Revision 8fada090 qa/qa_instance.py
b/qa/qa_instance.py | ||
---|---|---|
23 | 23 |
|
24 | 24 |
""" |
25 | 25 |
|
26 |
import operator |
|
27 | 26 |
import os |
28 | 27 |
import re |
29 | 28 |
|
... | ... | |
36 | 35 |
import qa_utils |
37 | 36 |
import qa_error |
38 | 37 |
|
39 |
from qa_utils import AssertIn, AssertCommand, AssertEqual
|
|
38 |
from qa_utils import AssertCommand, AssertEqual |
|
40 | 39 |
from qa_utils import InstanceCheck, INST_DOWN, INST_UP, FIRST_ARG, RETURN_VALUE |
40 |
from qa_instance_utils import CheckSsconfInstanceList, \ |
|
41 |
CreateInstanceDrbd8, \ |
|
42 |
CreateInstanceByDiskTemplate, \ |
|
43 |
CreateInstanceByDiskTemplateOneNode, \ |
|
44 |
GetGenericAddParameters |
|
41 | 45 |
|
42 | 46 |
|
43 | 47 |
def _GetDiskStatePath(disk): |
44 | 48 |
return "/sys/block/%s/device/state" % disk |
45 | 49 |
|
46 | 50 |
|
47 |
def _GetGenericAddParameters(inst, disk_template, force_mac=None): |
|
48 |
params = ["-B"] |
|
49 |
params.append("%s=%s,%s=%s" % (constants.BE_MINMEM, |
|
50 |
qa_config.get(constants.BE_MINMEM), |
|
51 |
constants.BE_MAXMEM, |
|
52 |
qa_config.get(constants.BE_MAXMEM))) |
|
53 |
|
|
54 |
if disk_template != constants.DT_DISKLESS: |
|
55 |
for idx, disk in enumerate(qa_config.GetDiskOptions()): |
|
56 |
size = disk.get("size") |
|
57 |
name = disk.get("name") |
|
58 |
diskparams = "%s:size=%s" % (idx, size) |
|
59 |
if name: |
|
60 |
diskparams += ",name=%s" % name |
|
61 |
params.extend(["--disk", diskparams]) |
|
62 |
|
|
63 |
# Set static MAC address if configured |
|
64 |
if force_mac: |
|
65 |
nic0_mac = force_mac |
|
66 |
else: |
|
67 |
nic0_mac = inst.GetNicMacAddr(0, None) |
|
68 |
|
|
69 |
if nic0_mac: |
|
70 |
params.extend(["--net", "0:mac=%s" % nic0_mac]) |
|
71 |
|
|
72 |
return params |
|
73 |
|
|
74 |
|
|
75 |
def _CreateInstanceByDiskTemplateRaw(nodes_spec, disk_template, fail=False): |
|
76 |
"""Creates an instance with the given disk template on the given nodes(s). |
|
77 |
Note that this function does not check if enough nodes are given for |
|
78 |
the respective disk template. |
|
79 |
|
|
80 |
@type nodes_spec: string |
|
81 |
@param nodes_spec: string specification of one node (by node name) or several |
|
82 |
nodes according to the requirements of the disk template |
|
83 |
@type disk_template: string |
|
84 |
@param disk_template: the disk template to be used by the instance |
|
85 |
@return: the created instance |
|
86 |
|
|
87 |
""" |
|
88 |
instance = qa_config.AcquireInstance() |
|
89 |
try: |
|
90 |
cmd = (["gnt-instance", "add", |
|
91 |
"--os-type=%s" % qa_config.get("os"), |
|
92 |
"--disk-template=%s" % disk_template, |
|
93 |
"--node=%s" % nodes_spec] + |
|
94 |
_GetGenericAddParameters(instance, disk_template)) |
|
95 |
cmd.append(instance.name) |
|
96 |
|
|
97 |
AssertCommand(cmd, fail=fail) |
|
98 |
|
|
99 |
if not fail: |
|
100 |
_CheckSsconfInstanceList(instance.name) |
|
101 |
instance.SetDiskTemplate(disk_template) |
|
102 |
|
|
103 |
return instance |
|
104 |
except: |
|
105 |
instance.Release() |
|
106 |
raise |
|
107 |
|
|
108 |
# Handle the case where creation is expected to fail |
|
109 |
assert fail |
|
110 |
instance.Release() |
|
111 |
return None |
|
112 |
|
|
113 |
|
|
114 |
def _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=False): |
|
115 |
"""Creates an instance using the given disk template for disk templates |
|
116 |
for which one given node is sufficient. These templates are for example: |
|
117 |
plain, diskless, file, sharedfile, blockdev, rados. |
|
118 |
|
|
119 |
@type nodes: list of nodes |
|
120 |
@param nodes: a list of nodes, whose first element is used to create the |
|
121 |
instance |
|
122 |
@type disk_template: string |
|
123 |
@param disk_template: the disk template to be used by the instance |
|
124 |
@return: the created instance |
|
125 |
|
|
126 |
""" |
|
127 |
assert len(nodes) > 0 |
|
128 |
return _CreateInstanceByDiskTemplateRaw(nodes[0].primary, disk_template, |
|
129 |
fail=fail) |
|
130 |
|
|
131 |
|
|
132 |
def _CreateInstanceDrbd8(nodes, fail=False): |
|
133 |
"""Creates an instance using disk template 'drbd' on the given nodes. |
|
134 |
|
|
135 |
@type nodes: list of nodes |
|
136 |
@param nodes: nodes to be used by the instance |
|
137 |
@return: the created instance |
|
138 |
|
|
139 |
""" |
|
140 |
assert len(nodes) > 1 |
|
141 |
return _CreateInstanceByDiskTemplateRaw( |
|
142 |
":".join(map(operator.attrgetter("primary"), nodes)), |
|
143 |
constants.DT_DRBD8, fail=fail) |
|
144 |
|
|
145 |
|
|
146 |
def CreateInstanceByDiskTemplate(nodes, disk_template, fail=False): |
|
147 |
"""Given a disk template, this function creates an instance using |
|
148 |
the template. It uses the required number of nodes depending on |
|
149 |
the disk template. This function is intended to be used by tests |
|
150 |
that don't care about the specifics of the instance other than |
|
151 |
that it uses the given disk template. |
|
152 |
|
|
153 |
Note: If you use this function, make sure to call |
|
154 |
'TestInstanceRemove' at the end of your tests to avoid orphaned |
|
155 |
instances hanging around and interfering with the following tests. |
|
156 |
|
|
157 |
@type nodes: list of nodes |
|
158 |
@param nodes: the list of the nodes on which the instance will be placed; |
|
159 |
it needs to have sufficiently many elements for the given |
|
160 |
disk template |
|
161 |
@type disk_template: string |
|
162 |
@param disk_template: the disk template to be used by the instance |
|
163 |
@return: the created instance |
|
164 |
|
|
165 |
""" |
|
166 |
if disk_template == constants.DT_DRBD8: |
|
167 |
return _CreateInstanceDrbd8(nodes, fail=fail) |
|
168 |
elif disk_template in [constants.DT_DISKLESS, constants.DT_PLAIN, |
|
169 |
constants.DT_FILE]: |
|
170 |
return _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail) |
|
171 |
else: |
|
172 |
# FIXME: This assumes that for all other disk templates, we only need one |
|
173 |
# node and no disk template specific parameters. This else-branch is |
|
174 |
# currently only used in cases where we expect failure. Extend it when |
|
175 |
# QA needs for these templates change. |
|
176 |
return _CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail) |
|
177 |
|
|
178 |
|
|
179 | 51 |
def _GetInstanceInfo(instance): |
180 | 52 |
"""Return information about the actual state of an instance. |
181 | 53 |
|
... | ... | |
378 | 250 |
def TestInstanceAddWithPlainDisk(nodes, fail=False): |
379 | 251 |
"""gnt-instance add -t plain""" |
380 | 252 |
if constants.DT_PLAIN in qa_config.GetEnabledDiskTemplates(): |
381 |
instance = _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_PLAIN,
|
|
253 |
instance = CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_PLAIN, |
|
382 | 254 |
fail=fail) |
383 | 255 |
if not fail: |
384 | 256 |
qa_utils.RunInstanceCheck(instance, True) |
... | ... | |
389 | 261 |
def TestInstanceAddWithDrbdDisk(nodes): |
390 | 262 |
"""gnt-instance add -t drbd""" |
391 | 263 |
if constants.DT_DRBD8 in qa_config.GetEnabledDiskTemplates(): |
392 |
return _CreateInstanceDrbd8(nodes)
|
|
264 |
return CreateInstanceDrbd8(nodes) |
|
393 | 265 |
|
394 | 266 |
|
395 | 267 |
@InstanceCheck(None, INST_UP, RETURN_VALUE) |
... | ... | |
397 | 269 |
"""gnt-instance add -t file""" |
398 | 270 |
assert len(nodes) == 1 |
399 | 271 |
if constants.DT_FILE in qa_config.GetEnabledDiskTemplates(): |
400 |
return _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_FILE)
|
|
272 |
return CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_FILE) |
|
401 | 273 |
|
402 | 274 |
|
403 | 275 |
@InstanceCheck(None, INST_UP, RETURN_VALUE) |
... | ... | |
405 | 277 |
"""gnt-instance add -t diskless""" |
406 | 278 |
assert len(nodes) == 1 |
407 | 279 |
if constants.DT_FILE in qa_config.GetEnabledDiskTemplates(): |
408 |
return _CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_DISKLESS)
|
|
280 |
return CreateInstanceByDiskTemplateOneNode(nodes, constants.DT_DISKLESS) |
|
409 | 281 |
|
410 | 282 |
|
411 | 283 |
@InstanceCheck(None, INST_DOWN, FIRST_ARG) |
... | ... | |
462 | 334 |
fail=True) |
463 | 335 |
|
464 | 336 |
|
465 |
def _ReadSsconfInstanceList(): |
|
466 |
"""Reads ssconf_instance_list from the master node. |
|
467 |
|
|
468 |
""" |
|
469 |
master = qa_config.GetMasterNode() |
|
470 |
|
|
471 |
ssconf_path = utils.PathJoin(pathutils.DATA_DIR, |
|
472 |
"ssconf_%s" % constants.SS_INSTANCE_LIST) |
|
473 |
|
|
474 |
cmd = ["cat", qa_utils.MakeNodePath(master, ssconf_path)] |
|
475 |
|
|
476 |
return qa_utils.GetCommandOutput(master.primary, |
|
477 |
utils.ShellQuoteArgs(cmd)).splitlines() |
|
478 |
|
|
479 |
|
|
480 |
def _CheckSsconfInstanceList(instance): |
|
481 |
"""Checks if a certain instance is in the ssconf instance list. |
|
482 |
|
|
483 |
@type instance: string |
|
484 |
@param instance: Instance name |
|
485 |
|
|
486 |
""" |
|
487 |
AssertIn(qa_utils.ResolveInstanceName(instance), |
|
488 |
_ReadSsconfInstanceList()) |
|
489 |
|
|
490 |
|
|
491 | 337 |
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG) |
492 | 338 |
def TestInstanceRenameAndBack(rename_source, rename_target): |
493 | 339 |
"""gnt-instance rename |
... | ... | |
496 | 342 |
name. |
497 | 343 |
|
498 | 344 |
""" |
499 |
_CheckSsconfInstanceList(rename_source)
|
|
345 |
CheckSsconfInstanceList(rename_source) |
|
500 | 346 |
|
501 | 347 |
# first do a rename to a different actual name, expecting it to fail |
502 | 348 |
qa_utils.AddToEtcHosts(["meeeeh-not-exists", rename_target]) |
503 | 349 |
try: |
504 | 350 |
AssertCommand(["gnt-instance", "rename", rename_source, rename_target], |
505 | 351 |
fail=True) |
506 |
_CheckSsconfInstanceList(rename_source)
|
|
352 |
CheckSsconfInstanceList(rename_source) |
|
507 | 353 |
finally: |
508 | 354 |
qa_utils.RemoveFromEtcHosts(["meeeeh-not-exists", rename_target]) |
509 | 355 |
|
... | ... | |
526 | 372 |
|
527 | 373 |
# and now rename instance to rename_target... |
528 | 374 |
AssertCommand(["gnt-instance", "rename", rename_source, rename_target]) |
529 |
_CheckSsconfInstanceList(rename_target)
|
|
375 |
CheckSsconfInstanceList(rename_target) |
|
530 | 376 |
qa_utils.RunInstanceCheck(rename_source, False) |
531 | 377 |
qa_utils.RunInstanceCheck(rename_target, False) |
532 | 378 |
|
... | ... | |
540 | 386 |
|
541 | 387 |
# and back |
542 | 388 |
AssertCommand(["gnt-instance", "rename", rename_target, rename_source]) |
543 |
_CheckSsconfInstanceList(rename_source)
|
|
389 |
CheckSsconfInstanceList(rename_source) |
|
544 | 390 |
qa_utils.RunInstanceCheck(rename_target, False) |
545 | 391 |
|
546 | 392 |
if (rename_source != rename_target and |
... | ... | |
1012 | 858 |
"--src-node=%s" % expnode.primary, |
1013 | 859 |
"--src-dir=%s/%s" % (pathutils.EXPORT_DIR, name), |
1014 | 860 |
"--node=%s" % node.primary] + |
1015 |
_GetGenericAddParameters(newinst, templ,
|
|
861 |
GetGenericAddParameters(newinst, templ, |
|
1016 | 862 |
force_mac=constants.VALUE_GENERATE)) |
1017 | 863 |
cmd.append(newinst.name) |
1018 | 864 |
AssertCommand(cmd) |
Also available in: Unified diff