Statistics
| Branch: | Tag: | Revision:

root / qa / rapi-workload.py @ e5351ee9

History | View | Annotate | Download (24.5 kB)

1 56803e14 Hrvoje Ribicic
#!/usr/bin/python -u
2 56803e14 Hrvoje Ribicic
#
3 56803e14 Hrvoje Ribicic
4 56803e14 Hrvoje Ribicic
# Copyright (C) 2013 Google Inc.
5 56803e14 Hrvoje Ribicic
#
6 56803e14 Hrvoje Ribicic
# This program is free software; you can redistribute it and/or modify
7 56803e14 Hrvoje Ribicic
# it under the terms of the GNU General Public License as published by
8 56803e14 Hrvoje Ribicic
# the Free Software Foundation; either version 2 of the License, or
9 56803e14 Hrvoje Ribicic
# (at your option) any later version.
10 56803e14 Hrvoje Ribicic
#
11 56803e14 Hrvoje Ribicic
# This program is distributed in the hope that it will be useful, but
12 56803e14 Hrvoje Ribicic
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 56803e14 Hrvoje Ribicic
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 56803e14 Hrvoje Ribicic
# General Public License for more details.
15 56803e14 Hrvoje Ribicic
#
16 56803e14 Hrvoje Ribicic
# You should have received a copy of the GNU General Public License
17 56803e14 Hrvoje Ribicic
# along with this program; if not, write to the Free Software
18 56803e14 Hrvoje Ribicic
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 56803e14 Hrvoje Ribicic
# 02110-1301, USA.
20 56803e14 Hrvoje Ribicic
21 56803e14 Hrvoje Ribicic
22 56803e14 Hrvoje Ribicic
"""Script for providing a large amount of RAPI calls to Ganeti.
23 56803e14 Hrvoje Ribicic

24 56803e14 Hrvoje Ribicic
"""
25 56803e14 Hrvoje Ribicic
26 56803e14 Hrvoje Ribicic
# pylint: disable=C0103
27 56803e14 Hrvoje Ribicic
# due to invalid name
28 56803e14 Hrvoje Ribicic
29 396c5dfb Hrvoje Ribicic
import inspect
30 56803e14 Hrvoje Ribicic
import sys
31 396c5dfb Hrvoje Ribicic
import types
32 56803e14 Hrvoje Ribicic
33 6b710ec0 Hrvoje Ribicic
import ganeti.constants as constants
34 c2e22e7b Hrvoje Ribicic
from ganeti.rapi.client import GanetiApiError, NODE_EVAC_PRI, NODE_EVAC_SEC
35 56803e14 Hrvoje Ribicic
36 56803e14 Hrvoje Ribicic
import qa_config
37 56803e14 Hrvoje Ribicic
import qa_node
38 56803e14 Hrvoje Ribicic
import qa_rapi
39 56803e14 Hrvoje Ribicic
40 56803e14 Hrvoje Ribicic
41 56803e14 Hrvoje Ribicic
# The purpose of this file is to provide a stable and extensive RAPI workload
42 56803e14 Hrvoje Ribicic
# that manipulates the cluster only using RAPI commands, with the assumption
43 56803e14 Hrvoje Ribicic
# that an empty cluster was set up beforehand. All the nodes that can be added
44 56803e14 Hrvoje Ribicic
# to the cluster should be a part of it, and no instances should be present.
45 56803e14 Hrvoje Ribicic
#
46 56803e14 Hrvoje Ribicic
# Its intended use is in RAPI compatibility tests, where different versions with
47 56803e14 Hrvoje Ribicic
# possibly vastly different QAs must be compared. Running the QA on both
48 56803e14 Hrvoje Ribicic
# versions of the cluster will produce RAPI calls, but there is no guarantee
49 56803e14 Hrvoje Ribicic
# that they will match, or that functions invoked in between will not change the
50 56803e14 Hrvoje Ribicic
# results.
51 56803e14 Hrvoje Ribicic
#
52 56803e14 Hrvoje Ribicic
# By using only RAPI functions, we are sure to be able to capture and log all
53 56803e14 Hrvoje Ribicic
# the changes in cluster state, and be able to compare them afterwards.
54 56803e14 Hrvoje Ribicic
#
55 56803e14 Hrvoje Ribicic
# The functionality of the QA is still used to generate a functioning,
56 56803e14 Hrvoje Ribicic
# RAPI-enabled cluster, and to set up a C{GanetiRapiClient} capable of issuing
57 56803e14 Hrvoje Ribicic
# commands to the cluster.
58 56803e14 Hrvoje Ribicic
#
59 56803e14 Hrvoje Ribicic
# Due to the fact that not all calls issued as a part of the workload might be
60 56803e14 Hrvoje Ribicic
# implemented in the different versions of Ganeti, the client does not halt or
61 56803e14 Hrvoje Ribicic
# produce a non-zero exit code upon encountering a RAPI error. Instead, it
62 56803e14 Hrvoje Ribicic
# reports it and moves on. Any utility comparing the requests should account for
63 56803e14 Hrvoje Ribicic
# this.
64 56803e14 Hrvoje Ribicic
65 56803e14 Hrvoje Ribicic
66 56803e14 Hrvoje Ribicic
def MockMethod(*_args, **_kwargs):
67 56803e14 Hrvoje Ribicic
  """ Absorbs all arguments, does nothing, returns None.
68 56803e14 Hrvoje Ribicic

69 56803e14 Hrvoje Ribicic
  """
70 56803e14 Hrvoje Ribicic
  return None
71 56803e14 Hrvoje Ribicic
72 56803e14 Hrvoje Ribicic
73 56803e14 Hrvoje Ribicic
RAPI_USERNAME = "ganeti-qa"
74 56803e14 Hrvoje Ribicic
75 56803e14 Hrvoje Ribicic
76 56803e14 Hrvoje Ribicic
class GanetiRapiClientWrapper(object):
77 56803e14 Hrvoje Ribicic
  """ Creates and initializes a GanetiRapiClient, and acts as a wrapper invoking
78 56803e14 Hrvoje Ribicic
  only the methods that the version of the client actually uses.
79 56803e14 Hrvoje Ribicic

80 56803e14 Hrvoje Ribicic
  """
81 56803e14 Hrvoje Ribicic
  def __init__(self):
82 56803e14 Hrvoje Ribicic
    self._client = qa_rapi.Setup(RAPI_USERNAME,
83 56803e14 Hrvoje Ribicic
                                 qa_rapi.LookupRapiSecret(RAPI_USERNAME))
84 56803e14 Hrvoje Ribicic
85 396c5dfb Hrvoje Ribicic
    self._method_invocations = {}
86 396c5dfb Hrvoje Ribicic
87 396c5dfb Hrvoje Ribicic
  def _RecordMethodInvocation(self, name, arg_dict):
88 396c5dfb Hrvoje Ribicic
    """ Records the invocation of a C{GanetiRAPIClient} method, noting the
89 396c5dfb Hrvoje Ribicic
    argument and the method names.
90 396c5dfb Hrvoje Ribicic

91 396c5dfb Hrvoje Ribicic
    """
92 396c5dfb Hrvoje Ribicic
    if name not in self._method_invocations:
93 396c5dfb Hrvoje Ribicic
      self._method_invocations[name] = set()
94 396c5dfb Hrvoje Ribicic
95 396c5dfb Hrvoje Ribicic
    for named_arg in arg_dict:
96 396c5dfb Hrvoje Ribicic
      self._method_invocations[name].add(named_arg)
97 396c5dfb Hrvoje Ribicic
98 396c5dfb Hrvoje Ribicic
  def _InvokerCreator(self, fn, name):
99 396c5dfb Hrvoje Ribicic
    """ Returns an invoker function that will invoke the given function
100 396c5dfb Hrvoje Ribicic
    with any arguments passed to the invoker at a later time, while
101 396c5dfb Hrvoje Ribicic
    catching any specific non-fatal errors we would like to know more
102 396c5dfb Hrvoje Ribicic
    about.
103 396c5dfb Hrvoje Ribicic

104 396c5dfb Hrvoje Ribicic
    @type fn arbitrary function
105 396c5dfb Hrvoje Ribicic
    @param fn The function to invoke later.
106 396c5dfb Hrvoje Ribicic
    @type name string
107 396c5dfb Hrvoje Ribicic
    @param name The name of the function, for debugging purposes.
108 396c5dfb Hrvoje Ribicic
    @rtype function
109 396c5dfb Hrvoje Ribicic

110 396c5dfb Hrvoje Ribicic
    """
111 396c5dfb Hrvoje Ribicic
    def decoratedFn(*args, **kwargs):
112 396c5dfb Hrvoje Ribicic
      result = None
113 396c5dfb Hrvoje Ribicic
      try:
114 396c5dfb Hrvoje Ribicic
        print "Using method %s" % name
115 396c5dfb Hrvoje Ribicic
        self._RecordMethodInvocation(name, kwargs)
116 396c5dfb Hrvoje Ribicic
        result = fn(*args, **kwargs)
117 396c5dfb Hrvoje Ribicic
      except GanetiApiError as e:
118 396c5dfb Hrvoje Ribicic
        print "RAPI error while performing function %s : %s" % \
119 396c5dfb Hrvoje Ribicic
              (name, str(e))
120 396c5dfb Hrvoje Ribicic
      return result
121 396c5dfb Hrvoje Ribicic
122 396c5dfb Hrvoje Ribicic
    return decoratedFn
123 396c5dfb Hrvoje Ribicic
124 56803e14 Hrvoje Ribicic
  def __getattr__(self, attr):
125 56803e14 Hrvoje Ribicic
    """ Fetches an attribute from the underlying client if necessary.
126 56803e14 Hrvoje Ribicic

127 56803e14 Hrvoje Ribicic
    """
128 56803e14 Hrvoje Ribicic
    # Assuming that this method exposes no public methods of its own,
129 56803e14 Hrvoje Ribicic
    # and that any private methods are named according to the style
130 56803e14 Hrvoje Ribicic
    # guide, this will stop infinite loops in attribute fetches.
131 56803e14 Hrvoje Ribicic
    if attr.startswith("_"):
132 56803e14 Hrvoje Ribicic
      return self.__getattribute__(attr)
133 396c5dfb Hrvoje Ribicic
134 396c5dfb Hrvoje Ribicic
    # We also want to expose non-methods
135 396c5dfb Hrvoje Ribicic
    if hasattr(self._client, attr) and \
136 396c5dfb Hrvoje Ribicic
       not isinstance(getattr(self._client, attr), types.MethodType):
137 396c5dfb Hrvoje Ribicic
      return getattr(self._client, attr)
138 396c5dfb Hrvoje Ribicic
139 56803e14 Hrvoje Ribicic
    try:
140 396c5dfb Hrvoje Ribicic
      return self._InvokerCreator(self._client.__getattribute__(attr), attr)
141 56803e14 Hrvoje Ribicic
    except AttributeError:
142 56803e14 Hrvoje Ribicic
      print "Missing method %s; supplying mock method" % attr
143 56803e14 Hrvoje Ribicic
      return MockMethod
144 56803e14 Hrvoje Ribicic
145 396c5dfb Hrvoje Ribicic
  def _OutputMethodInvocationDetails(self):
146 396c5dfb Hrvoje Ribicic
    """ Attempts to output as much information as possible about the methods
147 396c5dfb Hrvoje Ribicic
    that have and have not been invoked, including which arguments have not
148 396c5dfb Hrvoje Ribicic
    been used.
149 396c5dfb Hrvoje Ribicic

150 396c5dfb Hrvoje Ribicic
    """
151 396c5dfb Hrvoje Ribicic
    print "\nMethod usage:\n"
152 396c5dfb Hrvoje Ribicic
    for method in [n for n in dir(self._client)
153 396c5dfb Hrvoje Ribicic
                     if not n.startswith('_') and
154 396c5dfb Hrvoje Ribicic
                        isinstance(self.__getattr__(n), types.FunctionType)]:
155 396c5dfb Hrvoje Ribicic
      if method not in self._method_invocations:
156 396c5dfb Hrvoje Ribicic
        print "Method unused: %s" % method
157 396c5dfb Hrvoje Ribicic
      else:
158 396c5dfb Hrvoje Ribicic
        arg_spec, _, _, default_arg_spec = \
159 396c5dfb Hrvoje Ribicic
          inspect.getargspec(getattr(self._client, method))
160 396c5dfb Hrvoje Ribicic
        default_args = []
161 396c5dfb Hrvoje Ribicic
        if default_arg_spec is not None:
162 396c5dfb Hrvoje Ribicic
          default_args = arg_spec[-len(default_arg_spec):]
163 396c5dfb Hrvoje Ribicic
        used_arg_set = self._method_invocations[method]
164 396c5dfb Hrvoje Ribicic
        unused_args = [arg for arg in default_args if arg not in used_arg_set]
165 396c5dfb Hrvoje Ribicic
        if unused_args:
166 396c5dfb Hrvoje Ribicic
          print "Method %s used, but arguments unused: %s" % \
167 396c5dfb Hrvoje Ribicic
                (method, ", ".join(unused_args))
168 396c5dfb Hrvoje Ribicic
169 56803e14 Hrvoje Ribicic
170 b87948f5 Hrvoje Ribicic
def Finish(client, fn, *args, **kwargs):
171 b87948f5 Hrvoje Ribicic
  """ When invoked with a job-starting RAPI client method, it passes along any
172 b87948f5 Hrvoje Ribicic
  additional arguments and waits until its completion.
173 b87948f5 Hrvoje Ribicic

174 b87948f5 Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
175 b87948f5 Hrvoje Ribicic
  @param client The client wrapper.
176 b87948f5 Hrvoje Ribicic
  @type fn function
177 b87948f5 Hrvoje Ribicic
  @param fn A client method returning a job id.
178 b87948f5 Hrvoje Ribicic

179 e5351ee9 Hrvoje Ribicic
  @rtype tuple of bool, any object
180 e5351ee9 Hrvoje Ribicic
  @return The success status and the result of the operation, if any
181 e5351ee9 Hrvoje Ribicic

182 b87948f5 Hrvoje Ribicic
  """
183 b87948f5 Hrvoje Ribicic
  possible_job_id = fn(*args, **kwargs)
184 b87948f5 Hrvoje Ribicic
  try:
185 b87948f5 Hrvoje Ribicic
    # The job ids are returned as both ints and ints represented by strings.
186 b87948f5 Hrvoje Ribicic
    # This is a pythonic check to see if the content is an int.
187 b87948f5 Hrvoje Ribicic
    int(possible_job_id)
188 b87948f5 Hrvoje Ribicic
  except (ValueError, TypeError):
189 b87948f5 Hrvoje Ribicic
    # As a rule of thumb, failures will return None, and other methods are
190 b87948f5 Hrvoje Ribicic
    # expected to return at least something
191 b87948f5 Hrvoje Ribicic
    if possible_job_id is not None:
192 b87948f5 Hrvoje Ribicic
      print ("Finish called with a method not producing a job id, "
193 b87948f5 Hrvoje Ribicic
             "returning %s" % possible_job_id)
194 b87948f5 Hrvoje Ribicic
    return possible_job_id
195 b87948f5 Hrvoje Ribicic
196 b87948f5 Hrvoje Ribicic
  success = client.WaitForJobCompletion(possible_job_id)
197 b87948f5 Hrvoje Ribicic
198 b87948f5 Hrvoje Ribicic
  result = client.GetJobStatus(possible_job_id)["opresult"][0]
199 b87948f5 Hrvoje Ribicic
  if success:
200 e5351ee9 Hrvoje Ribicic
    return success, result
201 b87948f5 Hrvoje Ribicic
  else:
202 b87948f5 Hrvoje Ribicic
    print "Error encountered while performing operation: "
203 b87948f5 Hrvoje Ribicic
    print result
204 e5351ee9 Hrvoje Ribicic
    return success, None
205 b87948f5 Hrvoje Ribicic
206 b87948f5 Hrvoje Ribicic
207 9f22ba9a Hrvoje Ribicic
def TestTags(client, get_fn, add_fn, delete_fn, *args):
208 9f22ba9a Hrvoje Ribicic
  """ Tests whether tagging works.
209 9f22ba9a Hrvoje Ribicic

210 9f22ba9a Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
211 9f22ba9a Hrvoje Ribicic
  @param client The client wrapper.
212 9f22ba9a Hrvoje Ribicic
  @type get_fn function
213 9f22ba9a Hrvoje Ribicic
  @param get_fn A Get*Tags function of the client.
214 9f22ba9a Hrvoje Ribicic
  @type add_fn function
215 9f22ba9a Hrvoje Ribicic
  @param add_fn An Add*Tags function of the client.
216 9f22ba9a Hrvoje Ribicic
  @type delete_fn function
217 9f22ba9a Hrvoje Ribicic
  @param delete_fn A Delete*Tags function of the client.
218 9f22ba9a Hrvoje Ribicic

219 9f22ba9a Hrvoje Ribicic
  To allow this method to work for all tagging functions of the client, use
220 9f22ba9a Hrvoje Ribicic
  named methods.
221 9f22ba9a Hrvoje Ribicic

222 9f22ba9a Hrvoje Ribicic
  """
223 9f22ba9a Hrvoje Ribicic
  get_fn(*args)
224 9f22ba9a Hrvoje Ribicic
225 9f22ba9a Hrvoje Ribicic
  tags = ["tag1", "tag2", "tag3"]
226 9f22ba9a Hrvoje Ribicic
  Finish(client, add_fn, *args, tags=tags, dry_run=True)
227 9f22ba9a Hrvoje Ribicic
  Finish(client, add_fn, *args, tags=tags)
228 9f22ba9a Hrvoje Ribicic
229 9f22ba9a Hrvoje Ribicic
  get_fn(*args)
230 9f22ba9a Hrvoje Ribicic
231 9f22ba9a Hrvoje Ribicic
  Finish(client, delete_fn, *args, tags=tags[:1], dry_run=True)
232 9f22ba9a Hrvoje Ribicic
  Finish(client, delete_fn, *args, tags=tags[:1])
233 9f22ba9a Hrvoje Ribicic
234 9f22ba9a Hrvoje Ribicic
  get_fn(*args)
235 9f22ba9a Hrvoje Ribicic
236 9f22ba9a Hrvoje Ribicic
  Finish(client, delete_fn, *args, tags=tags[1:])
237 9f22ba9a Hrvoje Ribicic
238 9f22ba9a Hrvoje Ribicic
  get_fn(*args)
239 9f22ba9a Hrvoje Ribicic
240 9f22ba9a Hrvoje Ribicic
241 a9e3e04d Hrvoje Ribicic
def TestGetters(client):
242 a9e3e04d Hrvoje Ribicic
  """ Tests the various get functions which only retrieve information about the
243 a9e3e04d Hrvoje Ribicic
  cluster.
244 56803e14 Hrvoje Ribicic

245 56803e14 Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
246 56803e14 Hrvoje Ribicic

247 56803e14 Hrvoje Ribicic
  """
248 94981c7a Hrvoje Ribicic
  client.GetVersion()
249 94981c7a Hrvoje Ribicic
  client.GetFeatures()
250 94981c7a Hrvoje Ribicic
  client.GetOperatingSystems()
251 94981c7a Hrvoje Ribicic
  client.GetInfo()
252 94981c7a Hrvoje Ribicic
  client.GetClusterTags()
253 94981c7a Hrvoje Ribicic
  client.GetInstances()
254 94981c7a Hrvoje Ribicic
  client.GetInstances(bulk=True)
255 94981c7a Hrvoje Ribicic
  client.GetJobs()
256 94981c7a Hrvoje Ribicic
  client.GetJobs(bulk=True)
257 94981c7a Hrvoje Ribicic
  client.GetNodes()
258 94981c7a Hrvoje Ribicic
  client.GetNodes(bulk=True)
259 94981c7a Hrvoje Ribicic
  client.GetNetworks()
260 94981c7a Hrvoje Ribicic
  client.GetNetworks(bulk=True)
261 94981c7a Hrvoje Ribicic
  client.GetGroups()
262 94981c7a Hrvoje Ribicic
  client.GetGroups(bulk=True)
263 94981c7a Hrvoje Ribicic
264 a9e3e04d Hrvoje Ribicic
265 9749bd5e Hrvoje Ribicic
def TestQueries(client, resource_name):
266 9749bd5e Hrvoje Ribicic
  """ Finds out which fields are present for a given resource type, and attempts
267 9749bd5e Hrvoje Ribicic
  to retrieve their values for all present resources.
268 9749bd5e Hrvoje Ribicic

269 9749bd5e Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
270 9749bd5e Hrvoje Ribicic
  @param client A wrapped RAPI client.
271 9749bd5e Hrvoje Ribicic
  @type resource_name string
272 9749bd5e Hrvoje Ribicic
  @param resource_name The name of the resource to use.
273 9749bd5e Hrvoje Ribicic

274 9749bd5e Hrvoje Ribicic
  """
275 9749bd5e Hrvoje Ribicic
276 9749bd5e Hrvoje Ribicic
  FIELDS_KEY = "fields"
277 9749bd5e Hrvoje Ribicic
278 9749bd5e Hrvoje Ribicic
  query_res = client.QueryFields(resource_name)
279 9749bd5e Hrvoje Ribicic
280 9749bd5e Hrvoje Ribicic
  if query_res is None or FIELDS_KEY not in query_res or \
281 9749bd5e Hrvoje Ribicic
    len(query_res[FIELDS_KEY]) == 0:
282 9749bd5e Hrvoje Ribicic
    return
283 9749bd5e Hrvoje Ribicic
284 9749bd5e Hrvoje Ribicic
  field_entries = query_res[FIELDS_KEY]
285 9749bd5e Hrvoje Ribicic
286 9749bd5e Hrvoje Ribicic
  fields = map(lambda e: e["name"], field_entries)
287 9749bd5e Hrvoje Ribicic
288 9749bd5e Hrvoje Ribicic
  client.Query(resource_name, fields)
289 9749bd5e Hrvoje Ribicic
290 9749bd5e Hrvoje Ribicic
291 4236968a Hrvoje Ribicic
def TestQueryFiltering(client, master_name):
292 4236968a Hrvoje Ribicic
  """ Performs queries by playing around with the only guaranteed resource, the
293 4236968a Hrvoje Ribicic
  master node.
294 4236968a Hrvoje Ribicic

295 4236968a Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
296 4236968a Hrvoje Ribicic
  @param client A wrapped RAPI client.
297 4236968a Hrvoje Ribicic
  @type master_name string
298 4236968a Hrvoje Ribicic
  @param master_name The hostname of the master node.
299 4236968a Hrvoje Ribicic

300 4236968a Hrvoje Ribicic
  """
301 4236968a Hrvoje Ribicic
  client.Query("node", ["name"],
302 4236968a Hrvoje Ribicic
               ["|",
303 4236968a Hrvoje Ribicic
                ["=", "name", master_name],
304 4236968a Hrvoje Ribicic
                [">", "dtotal", 0],
305 4236968a Hrvoje Ribicic
               ])
306 4236968a Hrvoje Ribicic
307 4236968a Hrvoje Ribicic
  client.Query("instance", ["name"],
308 4236968a Hrvoje Ribicic
               ["|",
309 4236968a Hrvoje Ribicic
                ["=", "name", "NonexistentInstance"],
310 4236968a Hrvoje Ribicic
                [">", "oper_ram", 0],
311 4236968a Hrvoje Ribicic
               ])
312 4236968a Hrvoje Ribicic
313 4236968a Hrvoje Ribicic
314 a9e3e04d Hrvoje Ribicic
def RemoveAllInstances(client):
315 a9e3e04d Hrvoje Ribicic
  """ Queries for a list of instances, then removes them all.
316 a9e3e04d Hrvoje Ribicic

317 a9e3e04d Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
318 a9e3e04d Hrvoje Ribicic
  @param client A wrapped RAPI client.
319 a9e3e04d Hrvoje Ribicic

320 a9e3e04d Hrvoje Ribicic
  """
321 a9e3e04d Hrvoje Ribicic
  instances = client.GetInstances()
322 a9e3e04d Hrvoje Ribicic
  for inst in instances:
323 a9e3e04d Hrvoje Ribicic
    Finish(client, client.DeleteInstance, inst)
324 a9e3e04d Hrvoje Ribicic
325 a9e3e04d Hrvoje Ribicic
  instances = client.GetInstances()
326 a9e3e04d Hrvoje Ribicic
  assert len(instances) == 0
327 a9e3e04d Hrvoje Ribicic
328 a9e3e04d Hrvoje Ribicic
329 a9e3e04d Hrvoje Ribicic
def TestSingleInstance(client, instance_name, alternate_name, node_one,
330 a9e3e04d Hrvoje Ribicic
                       node_two):
331 a9e3e04d Hrvoje Ribicic
  """ Creates an instance, performs operations involving it, and then deletes
332 a9e3e04d Hrvoje Ribicic
  it.
333 a9e3e04d Hrvoje Ribicic

334 a9e3e04d Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
335 a9e3e04d Hrvoje Ribicic
  @param client A wrapped RAPI client.
336 a9e3e04d Hrvoje Ribicic
  @type instance_name string
337 a9e3e04d Hrvoje Ribicic
  @param instance_name The hostname to use.
338 a9e3e04d Hrvoje Ribicic
  @type instance_name string
339 a9e3e04d Hrvoje Ribicic
  @param instance_name Another valid hostname to use.
340 a9e3e04d Hrvoje Ribicic
  @type node_one string
341 a9e3e04d Hrvoje Ribicic
  @param node_one A node on which an instance can be added.
342 a9e3e04d Hrvoje Ribicic
  @type node_two string
343 a9e3e04d Hrvoje Ribicic
  @param node_two A node on which an instance can be added.
344 a9e3e04d Hrvoje Ribicic

345 a9e3e04d Hrvoje Ribicic
  """
346 a9e3e04d Hrvoje Ribicic
347 a9e3e04d Hrvoje Ribicic
  # Check that a dry run works, use string with size and unit
348 a9e3e04d Hrvoje Ribicic
  Finish(client, client.CreateInstance,
349 a9e3e04d Hrvoje Ribicic
         "create", instance_name, "plain", [{"size":"1gb"}], [], dry_run=True,
350 a9e3e04d Hrvoje Ribicic
          os="debian-image", pnode=node_one)
351 a9e3e04d Hrvoje Ribicic
352 a9e3e04d Hrvoje Ribicic
  # Another dry run, numeric size, should work, but still a dry run
353 a9e3e04d Hrvoje Ribicic
  Finish(client, client.CreateInstance,
354 a9e3e04d Hrvoje Ribicic
         "create", instance_name, "plain", [{"size": "1000"}], [{}],
355 a9e3e04d Hrvoje Ribicic
         dry_run=True, os="debian-image", pnode=node_one)
356 a9e3e04d Hrvoje Ribicic
357 a9e3e04d Hrvoje Ribicic
  # Create a smaller instance, and delete it immediately
358 a9e3e04d Hrvoje Ribicic
  Finish(client, client.CreateInstance,
359 a9e3e04d Hrvoje Ribicic
         "create", instance_name, "plain", [{"size":800}], [{}],
360 a9e3e04d Hrvoje Ribicic
         os="debian-image", pnode=node_one)
361 a9e3e04d Hrvoje Ribicic
362 a9e3e04d Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
363 a9e3e04d Hrvoje Ribicic
364 a9e3e04d Hrvoje Ribicic
  # Create one instance to use in further tests
365 a9e3e04d Hrvoje Ribicic
  Finish(client, client.CreateInstance,
366 a9e3e04d Hrvoje Ribicic
         "create", instance_name, "plain", [{"size":1200}], [{}],
367 a9e3e04d Hrvoje Ribicic
         os="debian-image", pnode=node_one)
368 a9e3e04d Hrvoje Ribicic
369 a9e3e04d Hrvoje Ribicic
  client.GetInstance(instance_name)
370 a9e3e04d Hrvoje Ribicic
371 a9e3e04d Hrvoje Ribicic
  Finish(client, client.GetInstanceInfo, instance_name)
372 a9e3e04d Hrvoje Ribicic
373 a9e3e04d Hrvoje Ribicic
  Finish(client, client.GetInstanceInfo, instance_name, static=True)
374 a9e3e04d Hrvoje Ribicic
375 9749bd5e Hrvoje Ribicic
  TestQueries(client, "instance")
376 9749bd5e Hrvoje Ribicic
377 a9e3e04d Hrvoje Ribicic
  TestTags(client, client.GetInstanceTags, client.AddInstanceTags,
378 a9e3e04d Hrvoje Ribicic
           client.DeleteInstanceTags, instance_name)
379 a9e3e04d Hrvoje Ribicic
380 a9e3e04d Hrvoje Ribicic
  Finish(client, client.GrowInstanceDisk,
381 a9e3e04d Hrvoje Ribicic
         instance_name, 0, 100, wait_for_sync=True)
382 a9e3e04d Hrvoje Ribicic
383 a9e3e04d Hrvoje Ribicic
  Finish(client, client.RebootInstance,
384 a9e3e04d Hrvoje Ribicic
         instance_name, "soft", ignore_secondaries=True, dry_run=True,
385 a9e3e04d Hrvoje Ribicic
         reason="Hulk smash gently!")
386 a9e3e04d Hrvoje Ribicic
387 a9e3e04d Hrvoje Ribicic
  Finish(client, client.ShutdownInstance,
388 a9e3e04d Hrvoje Ribicic
         instance_name, dry_run=True, no_remember=False,
389 a9e3e04d Hrvoje Ribicic
         reason="Hulk smash hard!")
390 a9e3e04d Hrvoje Ribicic
391 a9e3e04d Hrvoje Ribicic
  Finish(client, client.StartupInstance,
392 a9e3e04d Hrvoje Ribicic
         instance_name, dry_run=True, no_remember=False,
393 a9e3e04d Hrvoje Ribicic
         reason="Not hard enough!")
394 a9e3e04d Hrvoje Ribicic
395 a9e3e04d Hrvoje Ribicic
  Finish(client, client.RebootInstance,
396 a9e3e04d Hrvoje Ribicic
         instance_name, "soft", ignore_secondaries=True, dry_run=False)
397 a9e3e04d Hrvoje Ribicic
398 a9e3e04d Hrvoje Ribicic
  Finish(client, client.ShutdownInstance,
399 a9e3e04d Hrvoje Ribicic
         instance_name, dry_run=False, no_remember=False)
400 a9e3e04d Hrvoje Ribicic
401 a9e3e04d Hrvoje Ribicic
  Finish(client, client.ModifyInstance,
402 a9e3e04d Hrvoje Ribicic
         instance_name, disk_template="drbd", remote_node=node_two)
403 a9e3e04d Hrvoje Ribicic
404 a9e3e04d Hrvoje Ribicic
  Finish(client, client.ModifyInstance,
405 a9e3e04d Hrvoje Ribicic
         instance_name, disk_template="plain")
406 a9e3e04d Hrvoje Ribicic
407 a9e3e04d Hrvoje Ribicic
  Finish(client, client.RenameInstance,
408 a9e3e04d Hrvoje Ribicic
         instance_name, alternate_name, ip_check=True, name_check=True)
409 a9e3e04d Hrvoje Ribicic
410 a9e3e04d Hrvoje Ribicic
  Finish(client, client.RenameInstance, alternate_name, instance_name)
411 a9e3e04d Hrvoje Ribicic
412 a9e3e04d Hrvoje Ribicic
  Finish(client, client.DeactivateInstanceDisks, instance_name)
413 a9e3e04d Hrvoje Ribicic
414 a9e3e04d Hrvoje Ribicic
  Finish(client, client.ActivateInstanceDisks, instance_name)
415 a9e3e04d Hrvoje Ribicic
416 89d52c9a Hrvoje Ribicic
  # Note that the RecreateInstanceDisks command will always fail, as there is
417 89d52c9a Hrvoje Ribicic
  # no way to induce the necessary prerequisites (removal of LV) via RAPI.
418 89d52c9a Hrvoje Ribicic
  # Keeping it around allows us to at least know that it still exists.
419 a9e3e04d Hrvoje Ribicic
  Finish(client, client.RecreateInstanceDisks,
420 a9e3e04d Hrvoje Ribicic
         instance_name, [0], [node_one])
421 a9e3e04d Hrvoje Ribicic
422 a9e3e04d Hrvoje Ribicic
  Finish(client, client.StartupInstance,
423 a9e3e04d Hrvoje Ribicic
         instance_name, dry_run=False, no_remember=False)
424 a9e3e04d Hrvoje Ribicic
425 a9e3e04d Hrvoje Ribicic
  client.GetInstanceConsole(instance_name)
426 a9e3e04d Hrvoje Ribicic
427 a9e3e04d Hrvoje Ribicic
  Finish(client, client.ReinstallInstance,
428 a9e3e04d Hrvoje Ribicic
         instance_name, os=None, no_startup=False, osparams={})
429 a9e3e04d Hrvoje Ribicic
430 a9e3e04d Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name, dry_run=True)
431 a9e3e04d Hrvoje Ribicic
432 a9e3e04d Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
433 a9e3e04d Hrvoje Ribicic
434 a9e3e04d Hrvoje Ribicic
435 6b710ec0 Hrvoje Ribicic
def MarkUnmarkNode(client, node, state):
436 6b710ec0 Hrvoje Ribicic
  """ Given a certain node state, marks a node as being in that state, and then
437 6b710ec0 Hrvoje Ribicic
  unmarks it.
438 6b710ec0 Hrvoje Ribicic

439 6b710ec0 Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
440 6b710ec0 Hrvoje Ribicic
  @param client A wrapped RAPI client.
441 6b710ec0 Hrvoje Ribicic
  @type node string
442 6b710ec0 Hrvoje Ribicic
  @type state string
443 6b710ec0 Hrvoje Ribicic

444 6b710ec0 Hrvoje Ribicic
  """
445 6b710ec0 Hrvoje Ribicic
  # pylint: disable=W0142
446 6b710ec0 Hrvoje Ribicic
  Finish(client, client.ModifyNode, node, **{state: True})
447 6b710ec0 Hrvoje Ribicic
  Finish(client, client.ModifyNode, node, **{state: False})
448 6b710ec0 Hrvoje Ribicic
  # pylint: enable=W0142
449 6b710ec0 Hrvoje Ribicic
450 6b710ec0 Hrvoje Ribicic
451 6b710ec0 Hrvoje Ribicic
def TestNodeOperations(client, non_master_node):
452 6b710ec0 Hrvoje Ribicic
  """ Tests various operations related to nodes only
453 6b710ec0 Hrvoje Ribicic

454 6b710ec0 Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
455 6b710ec0 Hrvoje Ribicic
  @param client A wrapped RAPI client.
456 6b710ec0 Hrvoje Ribicic
  @type non_master_node string
457 6b710ec0 Hrvoje Ribicic
  @param non_master_node The name of a non-master node in the cluster.
458 6b710ec0 Hrvoje Ribicic

459 6b710ec0 Hrvoje Ribicic
  """
460 6b710ec0 Hrvoje Ribicic
461 6b710ec0 Hrvoje Ribicic
  client.GetNode(non_master_node)
462 6b710ec0 Hrvoje Ribicic
463 6b710ec0 Hrvoje Ribicic
  old_role = client.GetNodeRole(non_master_node)
464 6b710ec0 Hrvoje Ribicic
465 6b710ec0 Hrvoje Ribicic
  # Should fail
466 6b710ec0 Hrvoje Ribicic
  Finish(client, client.SetNodeRole,
467 6b710ec0 Hrvoje Ribicic
         non_master_node, "master", False, auto_promote=True)
468 6b710ec0 Hrvoje Ribicic
469 6b710ec0 Hrvoje Ribicic
  Finish(client, client.SetNodeRole,
470 6b710ec0 Hrvoje Ribicic
         non_master_node, "regular", False, auto_promote=True)
471 6b710ec0 Hrvoje Ribicic
472 6b710ec0 Hrvoje Ribicic
  Finish(client, client.SetNodeRole,
473 6b710ec0 Hrvoje Ribicic
         non_master_node, "master-candidate", False, auto_promote=True)
474 6b710ec0 Hrvoje Ribicic
475 6b710ec0 Hrvoje Ribicic
  Finish(client, client.SetNodeRole,
476 6b710ec0 Hrvoje Ribicic
         non_master_node, "drained", False, auto_promote=True)
477 6b710ec0 Hrvoje Ribicic
478 6b710ec0 Hrvoje Ribicic
  Finish(client, client.SetNodeRole,
479 6b710ec0 Hrvoje Ribicic
         non_master_node, old_role, False, auto_promote=True)
480 6b710ec0 Hrvoje Ribicic
481 6b710ec0 Hrvoje Ribicic
  Finish(client, client.PowercycleNode,
482 6b710ec0 Hrvoje Ribicic
         non_master_node, force=False)
483 6b710ec0 Hrvoje Ribicic
484 6b710ec0 Hrvoje Ribicic
  storage_units_fields = [
485 6b710ec0 Hrvoje Ribicic
    "name", "allocatable", "free", "node", "size", "type", "used",
486 6b710ec0 Hrvoje Ribicic
  ]
487 6b710ec0 Hrvoje Ribicic
488 6b710ec0 Hrvoje Ribicic
  for storage_type in constants.STS_REPORT:
489 e5351ee9 Hrvoje Ribicic
    success, storage_units = Finish(client, client.GetNodeStorageUnits,
490 e5351ee9 Hrvoje Ribicic
                                    non_master_node, storage_type,
491 e5351ee9 Hrvoje Ribicic
                                    ",".join(storage_units_fields))
492 6b710ec0 Hrvoje Ribicic
493 e5351ee9 Hrvoje Ribicic
    if success and len(storage_units) > 0 and len(storage_units[0]) > 0:
494 6b710ec0 Hrvoje Ribicic
      # Name is the first entry of the first result, allocatable the other
495 6b710ec0 Hrvoje Ribicic
      unit_name = storage_units[0][0]
496 6b710ec0 Hrvoje Ribicic
      Finish(client, client.ModifyNodeStorageUnits,
497 6b710ec0 Hrvoje Ribicic
             non_master_node, storage_type, unit_name,
498 6b710ec0 Hrvoje Ribicic
             allocatable=not storage_units[0][1])
499 6b710ec0 Hrvoje Ribicic
      Finish(client, client.ModifyNodeStorageUnits,
500 6b710ec0 Hrvoje Ribicic
             non_master_node, storage_type, unit_name,
501 6b710ec0 Hrvoje Ribicic
             allocatable=storage_units[0][1])
502 6b710ec0 Hrvoje Ribicic
      Finish(client, client.RepairNodeStorageUnits,
503 6b710ec0 Hrvoje Ribicic
             non_master_node, storage_type, unit_name)
504 6b710ec0 Hrvoje Ribicic
505 6b710ec0 Hrvoje Ribicic
  MarkUnmarkNode(client, non_master_node, "drained")
506 6b710ec0 Hrvoje Ribicic
  MarkUnmarkNode(client, non_master_node, "powered")
507 6b710ec0 Hrvoje Ribicic
  MarkUnmarkNode(client, non_master_node, "offline")
508 6b710ec0 Hrvoje Ribicic
509 9749bd5e Hrvoje Ribicic
  TestQueries(client, "node")
510 9749bd5e Hrvoje Ribicic
511 6b710ec0 Hrvoje Ribicic
512 1086027a Hrvoje Ribicic
def TestGroupOperations(client, node, another_node):
513 1086027a Hrvoje Ribicic
  """ Tests various operations related to groups only.
514 1086027a Hrvoje Ribicic

515 1086027a Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
516 1086027a Hrvoje Ribicic
  @param client A Ganeti RAPI client to use.
517 1086027a Hrvoje Ribicic
  @type node string
518 1086027a Hrvoje Ribicic
  @param node The name of a node in the cluster.
519 1086027a Hrvoje Ribicic
  @type another_node string
520 1086027a Hrvoje Ribicic
  @param another_node The name of another node in the cluster.
521 1086027a Hrvoje Ribicic

522 1086027a Hrvoje Ribicic
  """
523 1086027a Hrvoje Ribicic
524 1086027a Hrvoje Ribicic
  DEFAULT_GROUP_NAME = constants.INITIAL_NODE_GROUP_NAME
525 1086027a Hrvoje Ribicic
  TEST_GROUP_NAME = "TestGroup"
526 1086027a Hrvoje Ribicic
  ALTERNATE_GROUP_NAME = "RenamedTestGroup"
527 1086027a Hrvoje Ribicic
528 1086027a Hrvoje Ribicic
  Finish(client, client.CreateGroup,
529 1086027a Hrvoje Ribicic
         TEST_GROUP_NAME, alloc_policy=constants.ALLOC_POLICY_PREFERRED,
530 1086027a Hrvoje Ribicic
         dry_run=True)
531 1086027a Hrvoje Ribicic
532 1086027a Hrvoje Ribicic
  Finish(client, client.CreateGroup,
533 1086027a Hrvoje Ribicic
         TEST_GROUP_NAME, alloc_policy=constants.ALLOC_POLICY_PREFERRED)
534 1086027a Hrvoje Ribicic
535 1086027a Hrvoje Ribicic
  client.GetGroup(TEST_GROUP_NAME)
536 1086027a Hrvoje Ribicic
537 9749bd5e Hrvoje Ribicic
  TestQueries(client, "group")
538 9749bd5e Hrvoje Ribicic
539 1086027a Hrvoje Ribicic
  TestTags(client, client.GetGroupTags, client.AddGroupTags,
540 1086027a Hrvoje Ribicic
           client.DeleteGroupTags, TEST_GROUP_NAME)
541 1086027a Hrvoje Ribicic
542 1086027a Hrvoje Ribicic
  Finish(client, client.ModifyGroup,
543 1086027a Hrvoje Ribicic
         TEST_GROUP_NAME, alloc_policy=constants.ALLOC_POLICY_PREFERRED,
544 1086027a Hrvoje Ribicic
         depends=None)
545 1086027a Hrvoje Ribicic
546 1086027a Hrvoje Ribicic
  Finish(client, client.AssignGroupNodes,
547 1086027a Hrvoje Ribicic
         TEST_GROUP_NAME, [node, another_node], force=False, dry_run=True)
548 1086027a Hrvoje Ribicic
549 1086027a Hrvoje Ribicic
  Finish(client, client.AssignGroupNodes,
550 1086027a Hrvoje Ribicic
         TEST_GROUP_NAME, [another_node], force=False)
551 1086027a Hrvoje Ribicic
552 1086027a Hrvoje Ribicic
  Finish(client, client.RenameGroup,
553 1086027a Hrvoje Ribicic
         TEST_GROUP_NAME, ALTERNATE_GROUP_NAME)
554 1086027a Hrvoje Ribicic
555 1086027a Hrvoje Ribicic
  Finish(client, client.RenameGroup,
556 1086027a Hrvoje Ribicic
         ALTERNATE_GROUP_NAME, TEST_GROUP_NAME)
557 1086027a Hrvoje Ribicic
558 1086027a Hrvoje Ribicic
  Finish(client, client.AssignGroupNodes,
559 1086027a Hrvoje Ribicic
         DEFAULT_GROUP_NAME, [another_node], force=False)
560 1086027a Hrvoje Ribicic
561 1086027a Hrvoje Ribicic
  Finish(client, client.DeleteGroup, TEST_GROUP_NAME, dry_run=True)
562 1086027a Hrvoje Ribicic
563 1086027a Hrvoje Ribicic
  Finish(client, client.DeleteGroup, TEST_GROUP_NAME)
564 1086027a Hrvoje Ribicic
565 1086027a Hrvoje Ribicic
566 82a8bf3e Hrvoje Ribicic
def TestNetworkConnectDisconnect(client, network_name, mode, link):
567 82a8bf3e Hrvoje Ribicic
  """ Test connecting and disconnecting the network to a new node group.
568 82a8bf3e Hrvoje Ribicic

569 82a8bf3e Hrvoje Ribicic
  @type network_name string
570 82a8bf3e Hrvoje Ribicic
  @param network_name The name of an existing and unconnected network.
571 82a8bf3e Hrvoje Ribicic
  @type mode string
572 82a8bf3e Hrvoje Ribicic
  @param mode The network mode.
573 82a8bf3e Hrvoje Ribicic
  @type link string
574 82a8bf3e Hrvoje Ribicic
  @param link The network link.
575 82a8bf3e Hrvoje Ribicic

576 82a8bf3e Hrvoje Ribicic
  """
577 82a8bf3e Hrvoje Ribicic
  # For testing the connect/disconnect calls, a group is needed
578 82a8bf3e Hrvoje Ribicic
  TEST_GROUP_NAME = "TestGroup"
579 82a8bf3e Hrvoje Ribicic
  Finish(client, client.CreateGroup,
580 82a8bf3e Hrvoje Ribicic
         TEST_GROUP_NAME, alloc_policy=constants.ALLOC_POLICY_PREFERRED)
581 82a8bf3e Hrvoje Ribicic
582 82a8bf3e Hrvoje Ribicic
  Finish(client, client.ConnectNetwork,
583 82a8bf3e Hrvoje Ribicic
         network_name, TEST_GROUP_NAME, mode, link, dry_run=True)
584 82a8bf3e Hrvoje Ribicic
585 82a8bf3e Hrvoje Ribicic
  Finish(client, client.ConnectNetwork,
586 82a8bf3e Hrvoje Ribicic
         network_name, TEST_GROUP_NAME, mode, link)
587 82a8bf3e Hrvoje Ribicic
588 82a8bf3e Hrvoje Ribicic
  Finish(client, client.DisconnectNetwork,
589 82a8bf3e Hrvoje Ribicic
         network_name, TEST_GROUP_NAME, dry_run=True)
590 82a8bf3e Hrvoje Ribicic
591 82a8bf3e Hrvoje Ribicic
  Finish(client, client.DisconnectNetwork,
592 82a8bf3e Hrvoje Ribicic
         network_name, TEST_GROUP_NAME)
593 82a8bf3e Hrvoje Ribicic
594 82a8bf3e Hrvoje Ribicic
  # Clean up the group
595 82a8bf3e Hrvoje Ribicic
  Finish(client, client.DeleteGroup, TEST_GROUP_NAME)
596 82a8bf3e Hrvoje Ribicic
597 82a8bf3e Hrvoje Ribicic
598 82a8bf3e Hrvoje Ribicic
def TestNetworks(client):
599 82a8bf3e Hrvoje Ribicic
  """ Add some networks of different sizes, using RFC5737 addresses like in the
600 82a8bf3e Hrvoje Ribicic
  QA.
601 82a8bf3e Hrvoje Ribicic

602 82a8bf3e Hrvoje Ribicic
  """
603 82a8bf3e Hrvoje Ribicic
604 82a8bf3e Hrvoje Ribicic
  NETWORK_NAME = "SurelyCertainlyNonexistentNetwork"
605 82a8bf3e Hrvoje Ribicic
606 82a8bf3e Hrvoje Ribicic
  Finish(client, client.CreateNetwork,
607 82a8bf3e Hrvoje Ribicic
         NETWORK_NAME, "192.0.2.0/30", tags=[], dry_run=True)
608 82a8bf3e Hrvoje Ribicic
609 82a8bf3e Hrvoje Ribicic
  Finish(client, client.CreateNetwork,
610 82a8bf3e Hrvoje Ribicic
         NETWORK_NAME, "192.0.2.0/30", tags=[])
611 82a8bf3e Hrvoje Ribicic
612 82a8bf3e Hrvoje Ribicic
  client.GetNetwork(NETWORK_NAME)
613 82a8bf3e Hrvoje Ribicic
614 82a8bf3e Hrvoje Ribicic
  TestTags(client, client.GetNetworkTags, client.AddNetworkTags,
615 82a8bf3e Hrvoje Ribicic
           client.DeleteNetworkTags, NETWORK_NAME)
616 82a8bf3e Hrvoje Ribicic
617 82a8bf3e Hrvoje Ribicic
  Finish(client, client.ModifyNetwork,
618 82a8bf3e Hrvoje Ribicic
         NETWORK_NAME, mac_prefix=None)
619 82a8bf3e Hrvoje Ribicic
620 82a8bf3e Hrvoje Ribicic
  TestQueries(client, "network")
621 82a8bf3e Hrvoje Ribicic
622 82a8bf3e Hrvoje Ribicic
  default_nicparams = qa_config.get("default-nicparams", None)
623 82a8bf3e Hrvoje Ribicic
624 82a8bf3e Hrvoje Ribicic
  # The entry might not be present in the QA config
625 82a8bf3e Hrvoje Ribicic
  if default_nicparams is not None:
626 82a8bf3e Hrvoje Ribicic
    mode = default_nicparams.get("mode", None)
627 82a8bf3e Hrvoje Ribicic
    link = default_nicparams.get("link", None)
628 82a8bf3e Hrvoje Ribicic
    if mode is not None and link is not None:
629 82a8bf3e Hrvoje Ribicic
      TestNetworkConnectDisconnect(client, NETWORK_NAME, mode, link)
630 82a8bf3e Hrvoje Ribicic
631 82a8bf3e Hrvoje Ribicic
  # Clean up the network
632 82a8bf3e Hrvoje Ribicic
  Finish(client, client.DeleteNetwork,
633 82a8bf3e Hrvoje Ribicic
         NETWORK_NAME, dry_run=True)
634 82a8bf3e Hrvoje Ribicic
635 82a8bf3e Hrvoje Ribicic
  Finish(client, client.DeleteNetwork, NETWORK_NAME)
636 82a8bf3e Hrvoje Ribicic
637 82a8bf3e Hrvoje Ribicic
638 c2e22e7b Hrvoje Ribicic
def CreateDRBDInstance(client, node_one, node_two, instance_name):
639 c2e22e7b Hrvoje Ribicic
  """ Creates a DRBD-enabled instance on the given nodes.
640 c2e22e7b Hrvoje Ribicic

641 c2e22e7b Hrvoje Ribicic
  """
642 c2e22e7b Hrvoje Ribicic
  Finish(client, client.CreateInstance,
643 c2e22e7b Hrvoje Ribicic
         "create", instance_name, "drbd", [{"size": "1000"}], [{}],
644 c2e22e7b Hrvoje Ribicic
         os="debian-image", pnode=node_one, snode=node_two)
645 c2e22e7b Hrvoje Ribicic
646 c2e22e7b Hrvoje Ribicic
647 c2e22e7b Hrvoje Ribicic
def TestInstanceMigrations(client, node_one, node_two, node_three,
648 c2e22e7b Hrvoje Ribicic
                           instance_name):
649 c2e22e7b Hrvoje Ribicic
  """ Test various operations related to migrating instances.
650 c2e22e7b Hrvoje Ribicic

651 c2e22e7b Hrvoje Ribicic
  @type node_one string
652 c2e22e7b Hrvoje Ribicic
  @param node_one The name of a node in the cluster.
653 c2e22e7b Hrvoje Ribicic
  @type node_two string
654 c2e22e7b Hrvoje Ribicic
  @param node_two The name of another node in the cluster.
655 c2e22e7b Hrvoje Ribicic
  @type node_three string
656 c2e22e7b Hrvoje Ribicic
  @param node_three The name of yet another node in the cluster.
657 c2e22e7b Hrvoje Ribicic
  @type instance_name string
658 c2e22e7b Hrvoje Ribicic
  @param instance_name An instance name that can be used.
659 c2e22e7b Hrvoje Ribicic

660 c2e22e7b Hrvoje Ribicic
  """
661 c2e22e7b Hrvoje Ribicic
662 c2e22e7b Hrvoje Ribicic
  CreateDRBDInstance(client, node_one, node_two, instance_name)
663 c2e22e7b Hrvoje Ribicic
  Finish(client, client.FailoverInstance, instance_name)
664 c2e22e7b Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
665 c2e22e7b Hrvoje Ribicic
666 c2e22e7b Hrvoje Ribicic
  CreateDRBDInstance(client, node_one, node_two, instance_name)
667 c2e22e7b Hrvoje Ribicic
  Finish(client, client.EvacuateNode,
668 c2e22e7b Hrvoje Ribicic
         node_two, early_release=False, mode=NODE_EVAC_SEC,
669 c2e22e7b Hrvoje Ribicic
         remote_node=node_three)
670 c2e22e7b Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
671 c2e22e7b Hrvoje Ribicic
672 c2e22e7b Hrvoje Ribicic
  CreateDRBDInstance(client, node_one, node_two, instance_name)
673 c2e22e7b Hrvoje Ribicic
  Finish(client, client.EvacuateNode,
674 c2e22e7b Hrvoje Ribicic
         node_one, early_release=False, mode=NODE_EVAC_PRI, iallocator="hail")
675 c2e22e7b Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
676 c2e22e7b Hrvoje Ribicic
677 c2e22e7b Hrvoje Ribicic
  CreateDRBDInstance(client, node_one, node_two, instance_name)
678 c2e22e7b Hrvoje Ribicic
  Finish(client, client.MigrateInstance,
679 c2e22e7b Hrvoje Ribicic
         instance_name, cleanup=True, target_node=node_two)
680 c2e22e7b Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
681 c2e22e7b Hrvoje Ribicic
682 c2e22e7b Hrvoje Ribicic
  CreateDRBDInstance(client, node_one, node_two, instance_name)
683 c2e22e7b Hrvoje Ribicic
  Finish(client, client.MigrateNode,
684 c2e22e7b Hrvoje Ribicic
         node_one, iallocator="hail", mode="non-live")
685 c2e22e7b Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
686 c2e22e7b Hrvoje Ribicic
687 c2e22e7b Hrvoje Ribicic
  CreateDRBDInstance(client, node_one, node_two, instance_name)
688 c2e22e7b Hrvoje Ribicic
  Finish(client, client.MigrateNode,
689 c2e22e7b Hrvoje Ribicic
         node_one, target_node=node_two, mode="non-live")
690 c2e22e7b Hrvoje Ribicic
  Finish(client, client.DeleteInstance, instance_name)
691 c2e22e7b Hrvoje Ribicic
692 c2e22e7b Hrvoje Ribicic
693 a9e3e04d Hrvoje Ribicic
def Workload(client):
694 a9e3e04d Hrvoje Ribicic
  """ The actual RAPI workload used for tests.
695 a9e3e04d Hrvoje Ribicic

696 a9e3e04d Hrvoje Ribicic
  @type client C{GanetiRapiClientWrapper}
697 a9e3e04d Hrvoje Ribicic
  @param client A wrapped RAPI client.
698 a9e3e04d Hrvoje Ribicic

699 a9e3e04d Hrvoje Ribicic
  """
700 a9e3e04d Hrvoje Ribicic
701 a9e3e04d Hrvoje Ribicic
  # First just the simple information retrievals
702 a9e3e04d Hrvoje Ribicic
  TestGetters(client)
703 a9e3e04d Hrvoje Ribicic
704 a9e3e04d Hrvoje Ribicic
  # Then the only remaining function which is parameter-free
705 b87948f5 Hrvoje Ribicic
  Finish(client, client.RedistributeConfig)
706 56803e14 Hrvoje Ribicic
707 9f22ba9a Hrvoje Ribicic
  TestTags(client, client.GetClusterTags, client.AddClusterTags,
708 9f22ba9a Hrvoje Ribicic
           client.DeleteClusterTags)
709 9f22ba9a Hrvoje Ribicic
710 9f22ba9a Hrvoje Ribicic
  # Generously assume the master is present
711 9f22ba9a Hrvoje Ribicic
  node = qa_config.AcquireNode()
712 9f22ba9a Hrvoje Ribicic
  TestTags(client, client.GetNodeTags, client.AddNodeTags,
713 9f22ba9a Hrvoje Ribicic
           client.DeleteNodeTags, node.primary)
714 9f22ba9a Hrvoje Ribicic
  node.Release()
715 9f22ba9a Hrvoje Ribicic
716 a9e3e04d Hrvoje Ribicic
  # Instance tests
717 a9e3e04d Hrvoje Ribicic
718 a9e3e04d Hrvoje Ribicic
  # First remove all instances the QA might have created
719 a9e3e04d Hrvoje Ribicic
  RemoveAllInstances(client)
720 a9e3e04d Hrvoje Ribicic
721 a9e3e04d Hrvoje Ribicic
  nodes = qa_config.AcquireManyNodes(2)
722 c2e22e7b Hrvoje Ribicic
  instances = qa_config.AcquireManyInstances(2)
723 c2e22e7b Hrvoje Ribicic
  TestSingleInstance(client, instances[0].name, instances[1].name,
724 a9e3e04d Hrvoje Ribicic
                     nodes[0].primary, nodes[1].primary)
725 c2e22e7b Hrvoje Ribicic
  qa_config.ReleaseManyInstances(instances)
726 a9e3e04d Hrvoje Ribicic
  qa_config.ReleaseManyNodes(nodes)
727 a9e3e04d Hrvoje Ribicic
728 9749bd5e Hrvoje Ribicic
  # Test all the queries which involve resources that do not have functions
729 9749bd5e Hrvoje Ribicic
  # of their own
730 9749bd5e Hrvoje Ribicic
  TestQueries(client, "lock")
731 9749bd5e Hrvoje Ribicic
  TestQueries(client, "job")
732 9749bd5e Hrvoje Ribicic
  TestQueries(client, "export")
733 9749bd5e Hrvoje Ribicic
734 6b710ec0 Hrvoje Ribicic
  node = qa_config.AcquireNode(exclude=qa_config.GetMasterNode())
735 6b710ec0 Hrvoje Ribicic
  TestNodeOperations(client, node.primary)
736 4236968a Hrvoje Ribicic
  TestQueryFiltering(client, node.primary)
737 6b710ec0 Hrvoje Ribicic
  node.Release()
738 82a8bf3e Hrvoje Ribicic
739 1086027a Hrvoje Ribicic
  nodes = qa_config.AcquireManyNodes(2)
740 1086027a Hrvoje Ribicic
  TestGroupOperations(client, nodes[0].primary, nodes[1].primary)
741 1086027a Hrvoje Ribicic
  qa_config.ReleaseManyNodes(nodes)
742 1086027a Hrvoje Ribicic
743 82a8bf3e Hrvoje Ribicic
  TestNetworks(client)
744 82a8bf3e Hrvoje Ribicic
745 c2e22e7b Hrvoje Ribicic
  nodes = qa_config.AcquireManyNodes(3)
746 c2e22e7b Hrvoje Ribicic
  instance = qa_config.AcquireInstance()
747 c2e22e7b Hrvoje Ribicic
  TestInstanceMigrations(client, nodes[0].primary, nodes[1].primary,
748 c2e22e7b Hrvoje Ribicic
                         nodes[2].primary, instance.name)
749 c2e22e7b Hrvoje Ribicic
  instance.Release()
750 c2e22e7b Hrvoje Ribicic
  qa_config.ReleaseManyNodes(nodes)
751 c2e22e7b Hrvoje Ribicic
752 56803e14 Hrvoje Ribicic
753 56803e14 Hrvoje Ribicic
def Usage():
754 56803e14 Hrvoje Ribicic
  sys.stderr.write("Usage:\n\trapi-workload.py qa-config-file")
755 56803e14 Hrvoje Ribicic
756 56803e14 Hrvoje Ribicic
757 56803e14 Hrvoje Ribicic
def Main():
758 56803e14 Hrvoje Ribicic
  if len(sys.argv) < 2:
759 56803e14 Hrvoje Ribicic
    Usage()
760 56803e14 Hrvoje Ribicic
761 56803e14 Hrvoje Ribicic
  qa_config.Load(sys.argv[1])
762 56803e14 Hrvoje Ribicic
763 56803e14 Hrvoje Ribicic
  # Only the master will be present after a fresh QA cluster setup, so we have
764 56803e14 Hrvoje Ribicic
  # to invoke this to get all the other nodes.
765 56803e14 Hrvoje Ribicic
  qa_node.TestNodeAddAll()
766 56803e14 Hrvoje Ribicic
767 56803e14 Hrvoje Ribicic
  client = GanetiRapiClientWrapper()
768 56803e14 Hrvoje Ribicic
769 56803e14 Hrvoje Ribicic
  Workload(client)
770 56803e14 Hrvoje Ribicic
771 56803e14 Hrvoje Ribicic
  qa_node.TestNodeRemoveAll()
772 56803e14 Hrvoje Ribicic
773 396c5dfb Hrvoje Ribicic
  # The method invoked has the naming of the protected method, and pylint does
774 396c5dfb Hrvoje Ribicic
  # not like this. Disabling the warning is healthier than explicitly adding and
775 396c5dfb Hrvoje Ribicic
  # maintaining an exception for this method in the wrapper.
776 396c5dfb Hrvoje Ribicic
  # pylint: disable=W0212
777 396c5dfb Hrvoje Ribicic
  client._OutputMethodInvocationDetails()
778 396c5dfb Hrvoje Ribicic
  # pylint: enable=W0212
779 56803e14 Hrvoje Ribicic
780 56803e14 Hrvoje Ribicic
if __name__ == "__main__":
781 56803e14 Hrvoje Ribicic
  Main()