53 |
53 |
import ganeti.masterd.instance # pylint: disable-msg=W0611
|
54 |
54 |
|
55 |
55 |
|
56 |
|
# need to define these here before the actual LUs
|
|
56 |
# Modifiable default values; need to define these here before the
|
|
57 |
# actual LUs
|
57 |
58 |
|
58 |
59 |
def _EmptyList():
|
59 |
60 |
"""Returns an empty list.
|
... | ... | |
69 |
70 |
return {}
|
70 |
71 |
|
71 |
72 |
|
|
73 |
# Some basic types
|
|
74 |
def _TNotNone(val):
|
|
75 |
"""Checks if the given value is not None.
|
|
76 |
|
|
77 |
"""
|
|
78 |
return val is not None
|
|
79 |
|
|
80 |
|
|
81 |
def _TNone(val):
|
|
82 |
"""Checks if the given value is None.
|
|
83 |
|
|
84 |
"""
|
|
85 |
return val is None
|
|
86 |
|
|
87 |
|
|
88 |
def _TBool(val):
|
|
89 |
"""Checks if the given value is a boolean.
|
|
90 |
|
|
91 |
"""
|
|
92 |
return isinstance(val, bool)
|
|
93 |
|
|
94 |
|
|
95 |
def _TInt(val):
|
|
96 |
"""Checks if the given value is an integer.
|
|
97 |
|
|
98 |
"""
|
|
99 |
return isinstance(val, int)
|
|
100 |
|
|
101 |
|
|
102 |
def _TFloat(val):
|
|
103 |
"""Checks if the given value is a float.
|
|
104 |
|
|
105 |
"""
|
|
106 |
return isinstance(val, float)
|
|
107 |
|
|
108 |
|
|
109 |
def _TString(val):
|
|
110 |
"""Checks if the given value is a string.
|
|
111 |
|
|
112 |
"""
|
|
113 |
return isinstance(val, basestring)
|
|
114 |
|
|
115 |
|
|
116 |
def _TTrue(val):
|
|
117 |
"""Checks if a given value evaluates to a boolean True value.
|
|
118 |
|
|
119 |
"""
|
|
120 |
return bool(val)
|
|
121 |
|
|
122 |
|
|
123 |
def _TElemOf(target_list):
|
|
124 |
"""Builds a function that checks if a given value is a member of a list.
|
|
125 |
|
|
126 |
"""
|
|
127 |
return lambda val: val in target_list
|
|
128 |
|
|
129 |
|
|
130 |
# Container types
|
|
131 |
def _TList(val):
|
|
132 |
"""Checks if the given value is a list.
|
|
133 |
|
|
134 |
"""
|
|
135 |
return isinstance(val, list)
|
|
136 |
|
|
137 |
|
|
138 |
def _TDict(val):
|
|
139 |
"""Checks if the given value is a dictionary.
|
|
140 |
|
|
141 |
"""
|
|
142 |
return isinstance(val, dict)
|
|
143 |
|
|
144 |
|
|
145 |
# Combinator types
|
|
146 |
def _TAnd(*args):
|
|
147 |
"""Combine multiple functions using an AND operation.
|
|
148 |
|
|
149 |
"""
|
|
150 |
def fn(val):
|
|
151 |
return compat.all(t(val) for t in args)
|
|
152 |
return fn
|
|
153 |
|
|
154 |
|
|
155 |
def _TOr(*args):
|
|
156 |
"""Combine multiple functions using an AND operation.
|
|
157 |
|
|
158 |
"""
|
|
159 |
def fn(val):
|
|
160 |
return compat.any(t(val) for t in args)
|
|
161 |
return fn
|
|
162 |
|
|
163 |
|
|
164 |
# Type aliases
|
|
165 |
|
|
166 |
# non-empty string
|
|
167 |
_TNEString = _TAnd(_TString, _TTrue)
|
|
168 |
|
|
169 |
|
|
170 |
# positive integer
|
|
171 |
_TPInt = _TAnd(_TInt, lambda v: v >= 0)
|
|
172 |
|
|
173 |
|
|
174 |
def _TListOf(my_type):
|
|
175 |
"""Checks if a given value is a list with all elements of the same type.
|
|
176 |
|
|
177 |
"""
|
|
178 |
return _TAnd(_TList,
|
|
179 |
lambda lst: compat.all(lst, my_type))
|
|
180 |
|
|
181 |
|
|
182 |
def _TDictOf(key_type, val_type):
|
|
183 |
"""Checks a dict type for the type of its key/values.
|
|
184 |
|
|
185 |
"""
|
|
186 |
return _TAnd(_TDict,
|
|
187 |
lambda my_dict: (compat.all(my_dict.keys(), key_type) and
|
|
188 |
compat.all(my_dict.values(), val_type)))
|
|
189 |
|
|
190 |
|
|
191 |
# End types
|
72 |
192 |
class LogicalUnit(object):
|
73 |
193 |
"""Logical Unit base class.
|
74 |
194 |
|
... | ... | |
138 |
258 |
dval = aval
|
139 |
259 |
setattr(self.op, aname, dval)
|
140 |
260 |
|
141 |
|
for attr_name in self._OP_REQP:
|
142 |
|
attr_val = getattr(op, attr_name, None)
|
143 |
|
if attr_val is None:
|
|
261 |
for attr_name, test in self._OP_REQP:
|
|
262 |
if not hasattr(op, attr_name):
|
144 |
263 |
raise errors.OpPrereqError("Required parameter '%s' missing" %
|
145 |
264 |
attr_name, errors.ECODE_INVAL)
|
|
265 |
attr_val = getattr(op, attr_name, None)
|
|
266 |
if not callable(test):
|
|
267 |
raise errors.ProgrammerError("Validation for parameter '%s' failed,"
|
|
268 |
" given type is not a proper type (%s)" %
|
|
269 |
(attr_name, test))
|
|
270 |
if not test(attr_val):
|
|
271 |
raise errors.OpPrereqError("Parameter '%s' has invalid type" %
|
|
272 |
attr_name, errors.ECODE_INVAL)
|
146 |
273 |
|
147 |
274 |
self.CheckArguments()
|
148 |
275 |
|
... | ... | |
466 |
593 |
@raise errors.ProgrammerError: if the nodes parameter is wrong type
|
467 |
594 |
|
468 |
595 |
"""
|
469 |
|
if not isinstance(nodes, list):
|
470 |
|
raise errors.OpPrereqError("Invalid argument type 'nodes'",
|
471 |
|
errors.ECODE_INVAL)
|
472 |
|
|
473 |
596 |
if not nodes:
|
474 |
597 |
raise errors.ProgrammerError("_GetWantedNodes should only be called with a"
|
475 |
598 |
" non-empty list of nodes whose name is to be expanded.")
|
... | ... | |
491 |
614 |
@raise errors.OpPrereqError: if any of the passed instances is not found
|
492 |
615 |
|
493 |
616 |
"""
|
494 |
|
if not isinstance(instances, list):
|
495 |
|
raise errors.OpPrereqError("Invalid argument type 'instances'",
|
496 |
|
errors.ECODE_INVAL)
|
497 |
|
|
498 |
617 |
if instances:
|
499 |
618 |
wanted = [_ExpandInstanceName(lu.cfg, name) for name in instances]
|
500 |
619 |
else:
|
... | ... | |
659 |
778 |
errors.ECODE_INVAL)
|
660 |
779 |
if storage_type == constants.ST_FILE:
|
661 |
780 |
_RequireFileStorage()
|
|
781 |
return True
|
662 |
782 |
|
663 |
783 |
|
664 |
784 |
def _GetClusterDomainSecret():
|
... | ... | |
685 |
805 |
(instance.name, reason), errors.ECODE_STATE)
|
686 |
806 |
|
687 |
807 |
|
688 |
|
def _CheckExportMode(mode):
|
689 |
|
"""Ensures that a given export mode is valid.
|
690 |
|
|
691 |
|
@param mode: the export mode to check
|
692 |
|
@raise errors.OpPrereqError: when the export mode is not valid
|
693 |
|
|
694 |
|
"""
|
695 |
|
if mode not in constants.EXPORT_MODES:
|
696 |
|
raise errors.OpPrereqError("Invalid export mode %r" % mode,
|
697 |
|
errors.ECODE_INVAL)
|
698 |
|
|
699 |
|
|
700 |
808 |
def _ExpandItemName(fn, name, kind):
|
701 |
809 |
"""Expand an item name.
|
702 |
810 |
|
... | ... | |
1126 |
1234 |
"""
|
1127 |
1235 |
HPATH = "cluster-verify"
|
1128 |
1236 |
HTYPE = constants.HTYPE_CLUSTER
|
1129 |
|
_OP_REQP = ["skip_checks", "verbose", "error_codes", "debug_simulate_errors"]
|
|
1237 |
_OP_REQP = [
|
|
1238 |
("skip_checks", _TListOf(_TElemOf(constants.VERIFY_OPTIONAL_CHECKS))),
|
|
1239 |
("verbose", _TBool),
|
|
1240 |
("error_codes", _TBool),
|
|
1241 |
("debug_simulate_errors", _TBool),
|
|
1242 |
]
|
1130 |
1243 |
REQ_BGL = False
|
1131 |
1244 |
|
1132 |
1245 |
TCLUSTER = "cluster"
|
... | ... | |
1800 |
1913 |
_ErrorIf(True, self.ENODERPC, node,
|
1801 |
1914 |
"node returned invalid LVM info, check LVM status")
|
1802 |
1915 |
|
1803 |
|
def CheckArguments(self):
|
1804 |
|
"""Check arguments.
|
1805 |
|
|
1806 |
|
Transform the list of checks we're going to skip into a set and check that
|
1807 |
|
all its members are valid.
|
1808 |
|
|
1809 |
|
"""
|
1810 |
|
self.skip_set = frozenset(self.op.skip_checks)
|
1811 |
|
if not constants.VERIFY_OPTIONAL_CHECKS.issuperset(self.skip_set):
|
1812 |
|
raise errors.OpPrereqError("Invalid checks to be skipped specified",
|
1813 |
|
errors.ECODE_INVAL)
|
1814 |
|
|
1815 |
1916 |
def BuildHooksEnv(self):
|
1816 |
1917 |
"""Build hooks env.
|
1817 |
1918 |
|
... | ... | |
2044 |
2145 |
feedback_fn("* Verifying orphan instances")
|
2045 |
2146 |
self._VerifyOrphanInstances(instancelist, node_image)
|
2046 |
2147 |
|
2047 |
|
if constants.VERIFY_NPLUSONE_MEM not in self.skip_set:
|
|
2148 |
if constants.VERIFY_NPLUSONE_MEM not in self.op.skip_checks:
|
2048 |
2149 |
feedback_fn("* Verifying N+1 Memory redundancy")
|
2049 |
2150 |
self._VerifyNPlusOneMemory(node_image, instanceinfo)
|
2050 |
2151 |
|
... | ... | |
2191 |
2292 |
"""Verifies the cluster disks sizes.
|
2192 |
2293 |
|
2193 |
2294 |
"""
|
2194 |
|
_OP_REQP = ["instances"]
|
|
2295 |
_OP_REQP = [("instances", _TListOf(_TNEString))]
|
2195 |
2296 |
REQ_BGL = False
|
2196 |
2297 |
|
2197 |
|
def CheckArguments(self):
|
2198 |
|
if not isinstance(self.op.instances, list):
|
2199 |
|
raise errors.OpPrereqError("Invalid argument type 'instances'",
|
2200 |
|
errors.ECODE_INVAL)
|
2201 |
|
|
2202 |
2298 |
def ExpandNames(self):
|
2203 |
2299 |
if self.op.instances:
|
2204 |
2300 |
self.wanted_names = []
|
... | ... | |
2314 |
2410 |
"""
|
2315 |
2411 |
HPATH = "cluster-rename"
|
2316 |
2412 |
HTYPE = constants.HTYPE_CLUSTER
|
2317 |
|
_OP_REQP = ["name"]
|
|
2413 |
_OP_REQP = [("name", _TNEString)]
|
2318 |
2414 |
|
2319 |
2415 |
def BuildHooksEnv(self):
|
2320 |
2416 |
"""Build hooks env.
|
... | ... | |
2414 |
2510 |
"""
|
2415 |
2511 |
HPATH = "cluster-modify"
|
2416 |
2512 |
HTYPE = constants.HTYPE_CLUSTER
|
2417 |
|
_OP_REQP = []
|
|
2513 |
_OP_REQP = [
|
|
2514 |
("hvparams", _TOr(_TDictOf(_TNEString, _TDict), _TNone)),
|
|
2515 |
("os_hvp", _TOr(_TDictOf(_TNEString, _TDict), _TNone)),
|
|
2516 |
("osparams", _TOr(_TDictOf(_TNEString, _TDict), _TNone)),
|
|
2517 |
("enabled_hypervisors",
|
|
2518 |
_TOr(_TAnd(_TListOf(_TElemOf(constants.HYPER_TYPES)), _TTrue), _TNone)),
|
|
2519 |
]
|
2418 |
2520 |
_OP_DEFS = [
|
2419 |
2521 |
("candidate_pool_size", None),
|
2420 |
2522 |
("uid_pool", None),
|
2421 |
2523 |
("add_uids", None),
|
2422 |
2524 |
("remove_uids", None),
|
|
2525 |
("hvparams", None),
|
|
2526 |
("ov_hvp", None),
|
2423 |
2527 |
]
|
2424 |
2528 |
REQ_BGL = False
|
2425 |
2529 |
|
... | ... | |
2539 |
2643 |
# hypervisor list/parameters
|
2540 |
2644 |
self.new_hvparams = new_hvp = objects.FillDict(cluster.hvparams, {})
|
2541 |
2645 |
if self.op.hvparams:
|
2542 |
|
if not isinstance(self.op.hvparams, dict):
|
2543 |
|
raise errors.OpPrereqError("Invalid 'hvparams' parameter on input",
|
2544 |
|
errors.ECODE_INVAL)
|
2545 |
2646 |
for hv_name, hv_dict in self.op.hvparams.items():
|
2546 |
2647 |
if hv_name not in self.new_hvparams:
|
2547 |
2648 |
self.new_hvparams[hv_name] = hv_dict
|
... | ... | |
2551 |
2652 |
# os hypervisor parameters
|
2552 |
2653 |
self.new_os_hvp = objects.FillDict(cluster.os_hvp, {})
|
2553 |
2654 |
if self.op.os_hvp:
|
2554 |
|
if not isinstance(self.op.os_hvp, dict):
|
2555 |
|
raise errors.OpPrereqError("Invalid 'os_hvp' parameter on input",
|
2556 |
|
errors.ECODE_INVAL)
|
2557 |
2655 |
for os_name, hvs in self.op.os_hvp.items():
|
2558 |
|
if not isinstance(hvs, dict):
|
2559 |
|
raise errors.OpPrereqError(("Invalid 'os_hvp' parameter on"
|
2560 |
|
" input"), errors.ECODE_INVAL)
|
2561 |
2656 |
if os_name not in self.new_os_hvp:
|
2562 |
2657 |
self.new_os_hvp[os_name] = hvs
|
2563 |
2658 |
else:
|
... | ... | |
2570 |
2665 |
# os parameters
|
2571 |
2666 |
self.new_osp = objects.FillDict(cluster.osparams, {})
|
2572 |
2667 |
if self.op.osparams:
|
2573 |
|
if not isinstance(self.op.osparams, dict):
|
2574 |
|
raise errors.OpPrereqError("Invalid 'osparams' parameter on input",
|
2575 |
|
errors.ECODE_INVAL)
|
2576 |
2668 |
for os_name, osp in self.op.osparams.items():
|
2577 |
|
if not isinstance(osp, dict):
|
2578 |
|
raise errors.OpPrereqError(("Invalid 'osparams' parameter on"
|
2579 |
|
" input"), errors.ECODE_INVAL)
|
2580 |
2669 |
if os_name not in self.new_osp:
|
2581 |
2670 |
self.new_osp[os_name] = {}
|
2582 |
2671 |
|
... | ... | |
2594 |
2683 |
# changes to the hypervisor list
|
2595 |
2684 |
if self.op.enabled_hypervisors is not None:
|
2596 |
2685 |
self.hv_list = self.op.enabled_hypervisors
|
2597 |
|
if not self.hv_list:
|
2598 |
|
raise errors.OpPrereqError("Enabled hypervisors list must contain at"
|
2599 |
|
" least one member",
|
2600 |
|
errors.ECODE_INVAL)
|
2601 |
|
invalid_hvs = set(self.hv_list) - constants.HYPER_TYPES
|
2602 |
|
if invalid_hvs:
|
2603 |
|
raise errors.OpPrereqError("Enabled hypervisors contains invalid"
|
2604 |
|
" entries: %s" %
|
2605 |
|
utils.CommaJoin(invalid_hvs),
|
2606 |
|
errors.ECODE_INVAL)
|
2607 |
2686 |
for hv in self.hv_list:
|
2608 |
2687 |
# if the hypervisor doesn't already exist in the cluster
|
2609 |
2688 |
# hvparams, we initialize it to empty, and then (in both
|
... | ... | |
2871 |
2950 |
"""Logical unit for OS diagnose/query.
|
2872 |
2951 |
|
2873 |
2952 |
"""
|
2874 |
|
_OP_REQP = ["output_fields", "names"]
|
|
2953 |
_OP_REQP = [
|
|
2954 |
("output_fields", _TListOf(_TNEString)),
|
|
2955 |
("names", _TListOf(_TNEString)),
|
|
2956 |
]
|
2875 |
2957 |
REQ_BGL = False
|
2876 |
2958 |
_FIELDS_STATIC = utils.FieldSet()
|
2877 |
2959 |
_FIELDS_DYNAMIC = utils.FieldSet("name", "valid", "node_status", "variants",
|
... | ... | |
2992 |
3074 |
"""
|
2993 |
3075 |
HPATH = "node-remove"
|
2994 |
3076 |
HTYPE = constants.HTYPE_NODE
|
2995 |
|
_OP_REQP = ["node_name"]
|
|
3077 |
_OP_REQP = [("node_name", _TNEString)]
|
2996 |
3078 |
|
2997 |
3079 |
def BuildHooksEnv(self):
|
2998 |
3080 |
"""Build hooks env.
|
... | ... | |
3085 |
3167 |
|
3086 |
3168 |
"""
|
3087 |
3169 |
# pylint: disable-msg=W0142
|
3088 |
|
_OP_REQP = ["output_fields", "names", "use_locking"]
|
|
3170 |
_OP_REQP = [
|
|
3171 |
("output_fields", _TListOf(_TNEString)),
|
|
3172 |
("names", _TListOf(_TNEString)),
|
|
3173 |
("use_locking", _TBool),
|
|
3174 |
]
|
3089 |
3175 |
REQ_BGL = False
|
3090 |
3176 |
|
3091 |
3177 |
_SIMPLE_FIELDS = ["name", "serial_no", "ctime", "mtime", "uuid",
|
... | ... | |
3238 |
3324 |
"""Logical unit for getting volumes on node(s).
|
3239 |
3325 |
|
3240 |
3326 |
"""
|
3241 |
|
_OP_REQP = ["nodes", "output_fields"]
|
|
3327 |
_OP_REQP = [
|
|
3328 |
("nodes", _TListOf(_TNEString)),
|
|
3329 |
("output_fields", _TListOf(_TNEString)),
|
|
3330 |
]
|
3242 |
3331 |
REQ_BGL = False
|
3243 |
3332 |
_FIELDS_DYNAMIC = utils.FieldSet("phys", "vg", "name", "size", "instance")
|
3244 |
3333 |
_FIELDS_STATIC = utils.FieldSet("node")
|
... | ... | |
3317 |
3406 |
"""Logical unit for getting information on storage units on node(s).
|
3318 |
3407 |
|
3319 |
3408 |
"""
|
3320 |
|
_OP_REQP = ["nodes", "storage_type", "output_fields"]
|
|
3409 |
_FIELDS_STATIC = utils.FieldSet(constants.SF_NODE)
|
|
3410 |
_OP_REQP = [
|
|
3411 |
("nodes", _TListOf(_TNEString)),
|
|
3412 |
("storage_type", _CheckStorageType),
|
|
3413 |
("output_fields", _TListOf(_TNEString)),
|
|
3414 |
]
|
3321 |
3415 |
_OP_DEFS = [("name", None)]
|
3322 |
3416 |
REQ_BGL = False
|
3323 |
|
_FIELDS_STATIC = utils.FieldSet(constants.SF_NODE)
|
3324 |
3417 |
|
3325 |
3418 |
def CheckArguments(self):
|
3326 |
|
_CheckStorageType(self.op.storage_type)
|
3327 |
|
|
3328 |
3419 |
_CheckOutputFields(static=self._FIELDS_STATIC,
|
3329 |
3420 |
dynamic=utils.FieldSet(*constants.VALID_STORAGE_FIELDS),
|
3330 |
3421 |
selected=self.op.output_fields)
|
... | ... | |
3404 |
3495 |
"""Logical unit for modifying a storage volume on a node.
|
3405 |
3496 |
|
3406 |
3497 |
"""
|
3407 |
|
_OP_REQP = ["node_name", "storage_type", "name", "changes"]
|
|
3498 |
_OP_REQP = [
|
|
3499 |
("node_name", _TNEString),
|
|
3500 |
("storage_type", _CheckStorageType),
|
|
3501 |
("name", _TNEString),
|
|
3502 |
("changes", _TDict),
|
|
3503 |
]
|
3408 |
3504 |
REQ_BGL = False
|
3409 |
3505 |
|
3410 |
3506 |
def CheckArguments(self):
|
3411 |
3507 |
self.op.node_name = _ExpandNodeName(self.cfg, self.op.node_name)
|
3412 |
3508 |
|
3413 |
|
_CheckStorageType(self.op.storage_type)
|
3414 |
|
|
3415 |
3509 |
storage_type = self.op.storage_type
|
3416 |
3510 |
|
3417 |
3511 |
try:
|
... | ... | |
3451 |
3545 |
"""
|
3452 |
3546 |
HPATH = "node-add"
|
3453 |
3547 |
HTYPE = constants.HTYPE_NODE
|
3454 |
|
_OP_REQP = ["node_name"]
|
|
3548 |
_OP_REQP = [
|
|
3549 |
("node_name", _TNEString),
|
|
3550 |
]
|
3455 |
3551 |
_OP_DEFS = [("secondary_ip", None)]
|
3456 |
3552 |
|
3457 |
3553 |
def CheckArguments(self):
|
... | ... | |
3682 |
3778 |
"""
|
3683 |
3779 |
HPATH = "node-modify"
|
3684 |
3780 |
HTYPE = constants.HTYPE_NODE
|
3685 |
|
_OP_REQP = ["node_name"]
|
|
3781 |
_OP_REQP = [("node_name", _TNEString)]
|
3686 |
3782 |
REQ_BGL = False
|
3687 |
3783 |
|
3688 |
3784 |
def CheckArguments(self):
|
... | ... | |
3843 |
3939 |
"""Powercycles a node.
|
3844 |
3940 |
|
3845 |
3941 |
"""
|
3846 |
|
_OP_REQP = ["node_name", "force"]
|
|
3942 |
_OP_REQP = [
|
|
3943 |
("node_name", _TNEString),
|
|
3944 |
("force", _TBool),
|
|
3945 |
]
|
3847 |
3946 |
REQ_BGL = False
|
3848 |
3947 |
|
3849 |
3948 |
def CheckArguments(self):
|
... | ... | |
3970 |
4069 |
"""Bring up an instance's disks.
|
3971 |
4070 |
|
3972 |
4071 |
"""
|
3973 |
|
_OP_REQP = ["instance_name"]
|
|
4072 |
_OP_REQP = [("instance_name", _TNEString)]
|
3974 |
4073 |
_OP_DEFS = [("ignore_size", False)]
|
3975 |
4074 |
REQ_BGL = False
|
3976 |
4075 |
|
... | ... | |
4114 |
4213 |
"""Shutdown an instance's disks.
|
4115 |
4214 |
|
4116 |
4215 |
"""
|
4117 |
|
_OP_REQP = ["instance_name"]
|
|
4216 |
_OP_REQP = [("instance_name", _TNEString)]
|
4118 |
4217 |
REQ_BGL = False
|
4119 |
4218 |
|
4120 |
4219 |
def ExpandNames(self):
|
... | ... | |
4277 |
4376 |
"""
|
4278 |
4377 |
HPATH = "instance-start"
|
4279 |
4378 |
HTYPE = constants.HTYPE_INSTANCE
|
4280 |
|
_OP_REQP = ["instance_name", "force"]
|
|
4379 |
_OP_REQP = [
|
|
4380 |
("instance_name", _TNEString),
|
|
4381 |
("force", _TBool),
|
|
4382 |
("beparams", _TDict),
|
|
4383 |
("hvparams", _TDict),
|
|
4384 |
]
|
4281 |
4385 |
_OP_DEFS = [
|
4282 |
4386 |
("beparams", _EmptyDict),
|
4283 |
4387 |
("hvparams", _EmptyDict),
|
... | ... | |
4287 |
4391 |
def CheckArguments(self):
|
4288 |
4392 |
# extra beparams
|
4289 |
4393 |
if self.op.beparams:
|
4290 |
|
if not isinstance(self.op.beparams, dict):
|
4291 |
|
raise errors.OpPrereqError("Invalid beparams passed: %s, expected"
|
4292 |
|
" dict" % (type(self.op.beparams), ),
|
4293 |
|
errors.ECODE_INVAL)
|
4294 |
4394 |
# fill the beparams dict
|
4295 |
4395 |
utils.ForceDictType(self.op.beparams, constants.BES_PARAMETER_TYPES)
|
4296 |
4396 |
|
4297 |
|
if self.op.hvparams:
|
4298 |
|
if not isinstance(self.op.hvparams, dict):
|
4299 |
|
raise errors.OpPrereqError("Invalid hvparams passed: %s, expected"
|
4300 |
|
" dict" % (type(self.op.hvparams), ),
|
4301 |
|
errors.ECODE_INVAL)
|
4302 |
|
|
4303 |
4397 |
def ExpandNames(self):
|
4304 |
4398 |
self._ExpandAndLockInstance()
|
4305 |
4399 |
|
... | ... | |
4380 |
4474 |
"""
|
4381 |
4475 |
HPATH = "instance-reboot"
|
4382 |
4476 |
HTYPE = constants.HTYPE_INSTANCE
|
4383 |
|
_OP_REQP = ["instance_name", "ignore_secondaries", "reboot_type"]
|
|
4477 |
_OP_REQP = [
|
|
4478 |
("instance_name", _TNEString),
|
|
4479 |
("ignore_secondaries", _TBool),
|
|
4480 |
("reboot_type", _TElemOf(constants.REBOOT_TYPES)),
|
|
4481 |
]
|
4384 |
4482 |
_OP_DEFS = [("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT)]
|
4385 |
4483 |
REQ_BGL = False
|
4386 |
4484 |
|
4387 |
|
def CheckArguments(self):
|
4388 |
|
if self.op.reboot_type not in constants.REBOOT_TYPES:
|
4389 |
|
raise errors.OpPrereqError("Invalid reboot type '%s', not one of %s" %
|
4390 |
|
(self.op.reboot_type,
|
4391 |
|
utils.CommaJoin(constants.REBOOT_TYPES)),
|
4392 |
|
errors.ECODE_INVAL)
|
4393 |
|
|
4394 |
4485 |
def ExpandNames(self):
|
4395 |
4486 |
self._ExpandAndLockInstance()
|
4396 |
4487 |
|
... | ... | |
4464 |
4555 |
"""
|
4465 |
4556 |
HPATH = "instance-stop"
|
4466 |
4557 |
HTYPE = constants.HTYPE_INSTANCE
|
4467 |
|
_OP_REQP = ["instance_name"]
|
|
4558 |
_OP_REQP = [("instance_name", _TNEString)]
|
4468 |
4559 |
_OP_DEFS = [("timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT)]
|
4469 |
4560 |
REQ_BGL = False
|
4470 |
4561 |
|
... | ... | |
4515 |
4606 |
"""
|
4516 |
4607 |
HPATH = "instance-reinstall"
|
4517 |
4608 |
HTYPE = constants.HTYPE_INSTANCE
|
4518 |
|
_OP_REQP = ["instance_name"]
|
|
4609 |
_OP_REQP = [("instance_name", _TNEString)]
|
4519 |
4610 |
_OP_DEFS = [
|
4520 |
4611 |
("os_type", None),
|
4521 |
4612 |
("force_variant", False),
|
... | ... | |
4588 |
4679 |
"""
|
4589 |
4680 |
HPATH = "instance-recreate-disks"
|
4590 |
4681 |
HTYPE = constants.HTYPE_INSTANCE
|
4591 |
|
_OP_REQP = ["instance_name", "disks"]
|
|
4682 |
_OP_REQP = [
|
|
4683 |
("instance_name", _TNEString),
|
|
4684 |
("disks", _TListOf(_TPInt)),
|
|
4685 |
]
|
4592 |
4686 |
REQ_BGL = False
|
4593 |
4687 |
|
4594 |
|
def CheckArguments(self):
|
4595 |
|
"""Check the arguments.
|
4596 |
|
|
4597 |
|
"""
|
4598 |
|
if not isinstance(self.op.disks, list):
|
4599 |
|
raise errors.OpPrereqError("Invalid disks parameter", errors.ECODE_INVAL)
|
4600 |
|
for item in self.op.disks:
|
4601 |
|
if (not isinstance(item, int) or
|
4602 |
|
item < 0):
|
4603 |
|
raise errors.OpPrereqError("Invalid disk specification '%s'" %
|
4604 |
|
str(item), errors.ECODE_INVAL)
|
4605 |
|
|
4606 |
4688 |
def ExpandNames(self):
|
4607 |
4689 |
self._ExpandAndLockInstance()
|
4608 |
4690 |
|
... | ... | |
4661 |
4743 |
"""
|
4662 |
4744 |
HPATH = "instance-rename"
|
4663 |
4745 |
HTYPE = constants.HTYPE_INSTANCE
|
4664 |
|
_OP_REQP = ["instance_name", "new_name"]
|
|
4746 |
_OP_REQP = [
|
|
4747 |
("instance_name", _TNEString),
|
|
4748 |
("new_name", _TNEString),
|
|
4749 |
]
|
4665 |
4750 |
_OP_DEFS = [("ignore_ip", False)]
|
4666 |
4751 |
|
4667 |
4752 |
def BuildHooksEnv(self):
|
... | ... | |
4752 |
4837 |
"""
|
4753 |
4838 |
HPATH = "instance-remove"
|
4754 |
4839 |
HTYPE = constants.HTYPE_INSTANCE
|
4755 |
|
_OP_REQP = ["instance_name", "ignore_failures"]
|
|
4840 |
_OP_REQP = [
|
|
4841 |
("instance_name", _TNEString),
|
|
4842 |
("ignore_failures", _TBool),
|
|
4843 |
]
|
4756 |
4844 |
_OP_DEFS = [("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT)]
|
4757 |
4845 |
REQ_BGL = False
|
4758 |
4846 |
|
... | ... | |
4836 |
4924 |
|
4837 |
4925 |
"""
|
4838 |
4926 |
# pylint: disable-msg=W0142
|
4839 |
|
_OP_REQP = ["output_fields", "names", "use_locking"]
|
|
4927 |
_OP_REQP = [
|
|
4928 |
("output_fields", _TListOf(_TNEString)),
|
|
4929 |
("names", _TListOf(_TNEString)),
|
|
4930 |
("use_locking", _TBool),
|
|
4931 |
]
|
4840 |
4932 |
REQ_BGL = False
|
4841 |
4933 |
_SIMPLE_FIELDS = ["name", "os", "network_port", "hypervisor",
|
4842 |
4934 |
"serial_no", "ctime", "mtime", "uuid"]
|
... | ... | |
5114 |
5206 |
"""
|
5115 |
5207 |
HPATH = "instance-failover"
|
5116 |
5208 |
HTYPE = constants.HTYPE_INSTANCE
|
5117 |
|
_OP_REQP = ["instance_name", "ignore_consistency"]
|
|
5209 |
_OP_REQP = [
|
|
5210 |
("instance_name", _TNEString),
|
|
5211 |
("ignore_consistency", _TBool),
|
|
5212 |
]
|
5118 |
5213 |
_OP_DEFS = [("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT)]
|
5119 |
5214 |
REQ_BGL = False
|
5120 |
5215 |
|
... | ... | |
5265 |
5360 |
"""
|
5266 |
5361 |
HPATH = "instance-migrate"
|
5267 |
5362 |
HTYPE = constants.HTYPE_INSTANCE
|
5268 |
|
_OP_REQP = ["instance_name", "live", "cleanup"]
|
|
5363 |
_OP_REQP = [
|
|
5364 |
("instance_name", _TNEString),
|
|
5365 |
("live", _TBool),
|
|
5366 |
("cleanup", _TBool),
|
|
5367 |
]
|
5269 |
5368 |
|
5270 |
5369 |
REQ_BGL = False
|
5271 |
5370 |
|
... | ... | |
5313 |
5412 |
"""
|
5314 |
5413 |
HPATH = "instance-move"
|
5315 |
5414 |
HTYPE = constants.HTYPE_INSTANCE
|
5316 |
|
_OP_REQP = ["instance_name", "target_node"]
|
|
5415 |
_OP_REQP = [
|
|
5416 |
("instance_name", _TNEString),
|
|
5417 |
("target_node", _TNEString),
|
|
5418 |
]
|
5317 |
5419 |
_OP_DEFS = [("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT)]
|
5318 |
5420 |
REQ_BGL = False
|
5319 |
5421 |
|
... | ... | |
5489 |
5591 |
"""
|
5490 |
5592 |
HPATH = "node-migrate"
|
5491 |
5593 |
HTYPE = constants.HTYPE_NODE
|
5492 |
|
_OP_REQP = ["node_name", "live"]
|
|
5594 |
_OP_REQP = [
|
|
5595 |
("node_name", _TNEString),
|
|
5596 |
("live", _TBool),
|
|
5597 |
]
|
5493 |
5598 |
REQ_BGL = False
|
5494 |
5599 |
|
5495 |
5600 |
def ExpandNames(self):
|
... | ... | |
6223 |
6328 |
"""
|
6224 |
6329 |
HPATH = "instance-add"
|
6225 |
6330 |
HTYPE = constants.HTYPE_INSTANCE
|
6226 |
|
_OP_REQP = ["instance_name", "disks",
|
6227 |
|
"mode", "start",
|
6228 |
|
"wait_for_sync", "ip_check", "nics",
|
6229 |
|
"hvparams", "beparams", "osparams"]
|
|
6331 |
_OP_REQP = [
|
|
6332 |
("instance_name", _TNEString),
|
|
6333 |
("mode", _TElemOf(constants.INSTANCE_CREATE_MODES)),
|
|
6334 |
("start", _TBool),
|
|
6335 |
("wait_for_sync", _TBool),
|
|
6336 |
("ip_check", _TBool),
|
|
6337 |
("disks", _TListOf(_TDict)),
|
|
6338 |
("nics", _TListOf(_TDict)),
|
|
6339 |
("hvparams", _TDict),
|
|
6340 |
("beparams", _TDict),
|
|
6341 |
("osparams", _TDict),
|
|
6342 |
]
|
6230 |
6343 |
_OP_DEFS = [
|
6231 |
6344 |
("name_check", True),
|
6232 |
6345 |
("no_install", False),
|
... | ... | |
6291 |
6404 |
|
6292 |
6405 |
self.adopt_disks = has_adopt
|
6293 |
6406 |
|
6294 |
|
# verify creation mode
|
6295 |
|
if self.op.mode not in constants.INSTANCE_CREATE_MODES:
|
6296 |
|
raise errors.OpPrereqError("Invalid instance creation mode '%s'" %
|
6297 |
|
self.op.mode, errors.ECODE_INVAL)
|
6298 |
|
|
6299 |
6407 |
# instance name verification
|
6300 |
6408 |
if self.op.name_check:
|
6301 |
6409 |
self.hostname1 = utils.GetHostInfo(self.op.instance_name)
|
... | ... | |
7128 |
7236 |
console.
|
7129 |
7237 |
|
7130 |
7238 |
"""
|
7131 |
|
_OP_REQP = ["instance_name"]
|
|
7239 |
_OP_REQP = [("instance_name", _TNEString)]
|
7132 |
7240 |
REQ_BGL = False
|
7133 |
7241 |
|
7134 |
7242 |
def ExpandNames(self):
|
... | ... | |
7179 |
7287 |
"""
|
7180 |
7288 |
HPATH = "mirrors-replace"
|
7181 |
7289 |
HTYPE = constants.HTYPE_INSTANCE
|
7182 |
|
_OP_REQP = ["instance_name", "mode", "disks"]
|
|
7290 |
_OP_REQP = [
|
|
7291 |
("instance_name", _TNEString),
|
|
7292 |
("mode", _TElemOf(constants.REPLACE_MODES)),
|
|
7293 |
("disks", _TListOf(_TPInt)),
|
|
7294 |
]
|
7183 |
7295 |
_OP_DEFS = [
|
7184 |
7296 |
("remote_node", None),
|
7185 |
7297 |
("iallocator", None),
|
... | ... | |
7920 |
8032 |
"""Repairs the volume group on a node.
|
7921 |
8033 |
|
7922 |
8034 |
"""
|
7923 |
|
_OP_REQP = ["node_name"]
|
|
8035 |
_OP_REQP = [("node_name", _TNEString)]
|
7924 |
8036 |
REQ_BGL = False
|
7925 |
8037 |
|
7926 |
8038 |
def CheckArguments(self):
|
... | ... | |
7985 |
8097 |
"""Computes the node evacuation strategy.
|
7986 |
8098 |
|
7987 |
8099 |
"""
|
7988 |
|
_OP_REQP = ["nodes"]
|
|
8100 |
_OP_REQP = [("nodes", _TListOf(_TNEString))]
|
7989 |
8101 |
_OP_DEFS = [
|
7990 |
8102 |
("remote_node", None),
|
7991 |
8103 |
("iallocator", None),
|
... | ... | |
8038 |
8150 |
"""
|
8039 |
8151 |
HPATH = "disk-grow"
|
8040 |
8152 |
HTYPE = constants.HTYPE_INSTANCE
|
8041 |
|
_OP_REQP = ["instance_name", "disk", "amount", "wait_for_sync"]
|
|
8153 |
_OP_REQP = [
|
|
8154 |
("instance_name", _TNEString),
|
|
8155 |
("disk", _TInt),
|
|
8156 |
("amount", _TInt),
|
|
8157 |
("wait_for_sync", _TBool),
|
|
8158 |
]
|
8042 |
8159 |
REQ_BGL = False
|
8043 |
8160 |
|
8044 |
8161 |
def ExpandNames(self):
|
... | ... | |
8132 |
8249 |
"""Query runtime instance data.
|
8133 |
8250 |
|
8134 |
8251 |
"""
|
8135 |
|
_OP_REQP = ["instances", "static"]
|
|
8252 |
_OP_REQP = [
|
|
8253 |
("instances", _TListOf(_TNEString)),
|
|
8254 |
("static", _TBool),
|
|
8255 |
]
|
8136 |
8256 |
REQ_BGL = False
|
8137 |
8257 |
|
8138 |
|
def CheckArguments(self):
|
8139 |
|
if not isinstance(self.op.instances, list):
|
8140 |
|
raise errors.OpPrereqError("Invalid argument type 'instances'",
|
8141 |
|
errors.ECODE_INVAL)
|
8142 |
|
|
8143 |
8258 |
def ExpandNames(self):
|
8144 |
8259 |
self.needed_locks = {}
|
8145 |
8260 |
self.share_locks = dict.fromkeys(locking.LEVELS, 1)
|
... | ... | |
8294 |
8409 |
"""
|
8295 |
8410 |
HPATH = "instance-modify"
|
8296 |
8411 |
HTYPE = constants.HTYPE_INSTANCE
|
8297 |
|
_OP_REQP = ["instance_name"]
|
|
8412 |
_OP_REQP = [("instance_name", _TNEString)]
|
8298 |
8413 |
_OP_DEFS = [
|
8299 |
8414 |
("nics", _EmptyList),
|
8300 |
8415 |
("disks", _EmptyList),
|
... | ... | |
8956 |
9071 |
"""Query the exports list
|
8957 |
9072 |
|
8958 |
9073 |
"""
|
8959 |
|
_OP_REQP = ['nodes']
|
|
9074 |
_OP_REQP = [("nodes", _TListOf(_TNEString))]
|
8960 |
9075 |
REQ_BGL = False
|
8961 |
9076 |
|
8962 |
9077 |
def ExpandNames(self):
|
... | ... | |
8993 |
9108 |
"""Prepares an instance for an export and returns useful information.
|
8994 |
9109 |
|
8995 |
9110 |
"""
|
8996 |
|
_OP_REQP = ["instance_name", "mode"]
|
|
9111 |
_OP_REQP = [
|
|
9112 |
("instance_name", _TNEString),
|
|
9113 |
("mode", _TElemOf(constants.EXPORT_MODES)),
|
|
9114 |
]
|
8997 |
9115 |
REQ_BGL = False
|
8998 |
9116 |
|
8999 |
|
def CheckArguments(self):
|
9000 |
|
"""Check the arguments.
|
9001 |
|
|
9002 |
|
"""
|
9003 |
|
_CheckExportMode(self.op.mode)
|
9004 |
|
|
9005 |
9117 |
def ExpandNames(self):
|
9006 |
9118 |
self._ExpandAndLockInstance()
|
9007 |
9119 |
|
... | ... | |
9053 |
9165 |
"""
|
9054 |
9166 |
HPATH = "instance-export"
|
9055 |
9167 |
HTYPE = constants.HTYPE_INSTANCE
|
9056 |
|
_OP_REQP = ["instance_name", "target_node", "shutdown"]
|
|
9168 |
_OP_REQP = [
|
|
9169 |
("instance_name", _TNEString),
|
|
9170 |
("target_node", _TNEString),
|
|
9171 |
("shutdown", _TBool),
|
|
9172 |
("mode", _TElemOf(constants.EXPORT_MODES)),
|
|
9173 |
]
|
9057 |
9174 |
_OP_DEFS = [
|
9058 |
9175 |
("shutdown_timeout", constants.DEFAULT_SHUTDOWN_TIMEOUT),
|
9059 |
9176 |
("remove_instance", False),
|
... | ... | |
9075 |
9192 |
raise errors.OpPrereqError("Can not remove instance without shutting it"
|
9076 |
9193 |
" down before")
|
9077 |
9194 |
|
9078 |
|
_CheckExportMode(self.op.mode)
|
9079 |
|
|
9080 |
9195 |
if self.op.mode == constants.EXPORT_MODE_REMOTE:
|
9081 |
9196 |
if not self.x509_key_name:
|
9082 |
9197 |
raise errors.OpPrereqError("Missing X509 key name for encryption",
|
... | ... | |
9339 |
9454 |
"""Remove exports related to the named instance.
|
9340 |
9455 |
|
9341 |
9456 |
"""
|
9342 |
|
_OP_REQP = ["instance_name"]
|
|
9457 |
_OP_REQP = [("instance_name", _TNEString)]
|
9343 |
9458 |
REQ_BGL = False
|
9344 |
9459 |
|
9345 |
9460 |
def ExpandNames(self):
|
... | ... | |
9418 |
9533 |
"""Returns the tags of a given object.
|
9419 |
9534 |
|
9420 |
9535 |
"""
|
9421 |
|
_OP_REQP = ["kind", "name"]
|
|
9536 |
_OP_REQP = [
|
|
9537 |
("kind", _TElemOf(constants.VALID_TAG_TYPES)),
|
|
9538 |
("name", _TNEString),
|
|
9539 |
]
|
9422 |
9540 |
REQ_BGL = False
|
9423 |
9541 |
|
9424 |
9542 |
def Exec(self, feedback_fn):
|
... | ... | |
9432 |
9550 |
"""Searches the tags for a given pattern.
|
9433 |
9551 |
|
9434 |
9552 |
"""
|
9435 |
|
_OP_REQP = ["pattern"]
|
|
9553 |
_OP_REQP = [("pattern", _TNEString)]
|
9436 |
9554 |
REQ_BGL = False
|
9437 |
9555 |
|
9438 |
9556 |
def ExpandNames(self):
|
... | ... | |
9472 |
9590 |
"""Sets a tag on a given object.
|
9473 |
9591 |
|
9474 |
9592 |
"""
|
9475 |
|
_OP_REQP = ["kind", "name", "tags"]
|
|
9593 |
_OP_REQP = [
|
|
9594 |
("kind", _TElemOf(constants.VALID_TAG_TYPES)),
|
|
9595 |
("name", _TNEString),
|
|
9596 |
("tags", _TListOf(objects.TaggableObject.ValidateTag)),
|
|
9597 |
]
|
9476 |
9598 |
REQ_BGL = False
|
9477 |
9599 |
|
9478 |
9600 |
def CheckPrereq(self):
|
... | ... | |
9501 |
9623 |
"""Delete a list of tags from a given object.
|
9502 |
9624 |
|
9503 |
9625 |
"""
|
9504 |
|
_OP_REQP = ["kind", "name", "tags"]
|
|
9626 |
_OP_REQP = [
|
|
9627 |
("kind", _TElemOf(constants.VALID_TAG_TYPES)),
|
|
9628 |
("name", _TNEString),
|
|
9629 |
("tags", _TListOf(objects.TaggableObject.ValidateTag)),
|
|
9630 |
]
|
9505 |
9631 |
REQ_BGL = False
|
9506 |
9632 |
|
9507 |
9633 |
def CheckPrereq(self):
|
... | ... | |
9538 |
9664 |
time.
|
9539 |
9665 |
|
9540 |
9666 |
"""
|
9541 |
|
_OP_REQP = ["duration", "on_master", "on_nodes"]
|
|
9667 |
_OP_REQP = [
|
|
9668 |
("duration", _TFloat),
|
|
9669 |
("on_master", _TBool),
|
|
9670 |
("on_nodes", _TListOf(_TNEString)),
|
|
9671 |
]
|
9542 |
9672 |
REQ_BGL = False
|
9543 |
9673 |
|
9544 |
9674 |
def CheckArguments(self):
|
... | ... | |
9918 |
10048 |
This LU runs the allocator tests
|
9919 |
10049 |
|
9920 |
10050 |
"""
|
9921 |
|
_OP_REQP = ["direction", "mode", "name"]
|
|
10051 |
_OP_REQP = [
|
|
10052 |
("direction", _TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS)),
|
|
10053 |
("mode", _TElemOf(constants.VALID_IALLOCATOR_MODES)),
|
|
10054 |
("name", _TNEString),
|
|
10055 |
("nics", _TOr(_TNone, _TListOf(
|
|
10056 |
_TDictOf(_TElemOf(["mac", "ip", "bridge"]), _TNEString)))),
|
|
10057 |
("disks", _TOr(_TNone, _TList)),
|
|
10058 |
]
|
9922 |
10059 |
_OP_DEFS = [
|
9923 |
10060 |
("hypervisor", None),
|
9924 |
10061 |
("allocator", None),
|
|
10062 |
("nics", None),
|
|
10063 |
("disks", None),
|
9925 |
10064 |
]
|
9926 |
10065 |
|
9927 |
10066 |
def CheckPrereq(self):
|
... | ... | |
9931 |
10070 |
|
9932 |
10071 |
"""
|
9933 |
10072 |
if self.op.mode == constants.IALLOCATOR_MODE_ALLOC:
|
9934 |
|
for attr in ["name", "mem_size", "disks", "disk_template",
|
|
10073 |
for attr in ["mem_size", "disks", "disk_template",
|
9935 |
10074 |
"os", "tags", "nics", "vcpus"]:
|
9936 |
10075 |
if not hasattr(self.op, attr):
|
9937 |
10076 |
raise errors.OpPrereqError("Missing attribute '%s' on opcode input" %
|
... | ... | |
9943 |
10082 |
if not isinstance(self.op.nics, list):
|
9944 |
10083 |
raise errors.OpPrereqError("Invalid parameter 'nics'",
|
9945 |
10084 |
errors.ECODE_INVAL)
|
9946 |
|
for row in self.op.nics:
|
9947 |
|
if (not isinstance(row, dict) or
|
9948 |
|
"mac" not in row or
|
9949 |
|
"ip" not in row or
|
9950 |
|
"bridge" not in row):
|
9951 |
|
raise errors.OpPrereqError("Invalid contents of the 'nics'"
|
9952 |
|
" parameter", errors.ECODE_INVAL)
|
9953 |
10085 |
if not isinstance(self.op.disks, list):
|
9954 |
10086 |
raise errors.OpPrereqError("Invalid parameter 'disks'",
|
9955 |
10087 |
errors.ECODE_INVAL)
|
... | ... | |
9964 |
10096 |
if self.op.hypervisor is None:
|
9965 |
10097 |
self.op.hypervisor = self.cfg.GetHypervisorType()
|
9966 |
10098 |
elif self.op.mode == constants.IALLOCATOR_MODE_RELOC:
|
9967 |
|
if not hasattr(self.op, "name"):
|
9968 |
|
raise errors.OpPrereqError("Missing attribute 'name' on opcode input",
|
9969 |
|
errors.ECODE_INVAL)
|
9970 |
10099 |
fname = _ExpandInstanceName(self.cfg, self.op.name)
|
9971 |
10100 |
self.op.name = fname
|
9972 |
10101 |
self.relocate_from = self.cfg.GetInstanceInfo(fname).secondary_nodes
|