Package ganeti :: Package client :: Module gnt_group
[hide private]
[frames] | no frames]

Source Code for Module ganeti.client.gnt_group

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2010, 2011, 2012, 2013 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30  """Node group related commands""" 
 31   
 32  # pylint: disable=W0401,W0614 
 33  # W0401: Wildcard import ganeti.cli 
 34  # W0614: Unused import %s from wildcard import (since we need cli) 
 35   
 36  from cStringIO import StringIO 
 37   
 38  from ganeti.cli import * 
 39  from ganeti import constants 
 40  from ganeti import opcodes 
 41  from ganeti import utils 
 42  from ganeti import compat 
 43   
 44   
 45  #: default list of fields for L{ListGroups} 
 46  _LIST_DEF_FIELDS = ["name", "node_cnt", "pinst_cnt", "alloc_policy", "ndparams"] 
 47   
 48  _ENV_OVERRIDE = compat.UniqueFrozenset(["list"]) 
 49   
 50   
51 -def AddGroup(opts, args):
52 """Add a node group to the cluster. 53 54 @param opts: the command line options selected by the user 55 @type args: list 56 @param args: a list of length 1 with the name of the group to create 57 @rtype: int 58 @return: the desired exit code 59 60 """ 61 ipolicy = CreateIPolicyFromOpts( 62 minmax_ispecs=opts.ipolicy_bounds_specs, 63 ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio, 64 ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio, 65 ipolicy_disk_templates=opts.ipolicy_disk_templates, 66 group_ipolicy=True) 67 68 (group_name,) = args 69 diskparams = dict(opts.diskparams) 70 71 if opts.disk_state: 72 disk_state = utils.FlatToDict(opts.disk_state) 73 else: 74 disk_state = {} 75 hv_state = dict(opts.hv_state) 76 77 op = opcodes.OpGroupAdd(group_name=group_name, ndparams=opts.ndparams, 78 alloc_policy=opts.alloc_policy, 79 diskparams=diskparams, ipolicy=ipolicy, 80 hv_state=hv_state, 81 disk_state=disk_state) 82 SubmitOrSend(op, opts)
83 84
85 -def AssignNodes(opts, args):
86 """Assign nodes to a group. 87 88 @param opts: the command line options selected by the user 89 @type args: list 90 @param args: args[0]: group to assign nodes to; args[1:]: nodes to assign 91 @rtype: int 92 @return: the desired exit code 93 94 """ 95 group_name = args[0] 96 node_names = args[1:] 97 98 op = opcodes.OpGroupAssignNodes(group_name=group_name, nodes=node_names, 99 force=opts.force) 100 SubmitOrSend(op, opts)
101 102
103 -def _FmtDict(data):
104 """Format dict data into command-line format. 105 106 @param data: The input dict to be formatted 107 @return: The formatted dict 108 109 """ 110 if not data: 111 return "(empty)" 112 113 return utils.CommaJoin(["%s=%s" % (key, value) 114 for key, value in data.items()])
115 116
117 -def ListGroups(opts, args):
118 """List node groups and their properties. 119 120 @param opts: the command line options selected by the user 121 @type args: list 122 @param args: groups to list, or empty for all 123 @rtype: int 124 @return: the desired exit code 125 126 """ 127 desired_fields = ParseFields(opts.output, _LIST_DEF_FIELDS) 128 fmtoverride = { 129 "node_list": (",".join, False), 130 "pinst_list": (",".join, False), 131 "ndparams": (_FmtDict, False), 132 } 133 134 cl = GetClient(query=True) 135 136 return GenericList(constants.QR_GROUP, desired_fields, args, None, 137 opts.separator, not opts.no_headers, 138 format_override=fmtoverride, verbose=opts.verbose, 139 force_filter=opts.force_filter, cl=cl)
140 141
142 -def ListGroupFields(opts, args):
143 """List node fields. 144 145 @param opts: the command line options selected by the user 146 @type args: list 147 @param args: fields to list, or empty for all 148 @rtype: int 149 @return: the desired exit code 150 151 """ 152 cl = GetClient(query=True) 153 154 return GenericListFields(constants.QR_GROUP, args, opts.separator, 155 not opts.no_headers, cl=cl)
156 157
158 -def SetGroupParams(opts, args):
159 """Modifies a node group's parameters. 160 161 @param opts: the command line options selected by the user 162 @type args: list 163 @param args: should contain only one element, the node group name 164 165 @rtype: int 166 @return: the desired exit code 167 168 """ 169 allmods = [opts.ndparams, opts.alloc_policy, opts.diskparams, opts.hv_state, 170 opts.disk_state, opts.ipolicy_bounds_specs, 171 opts.ipolicy_vcpu_ratio, opts.ipolicy_spindle_ratio, 172 opts.diskparams, opts.ipolicy_disk_templates] 173 if allmods.count(None) == len(allmods): 174 ToStderr("Please give at least one of the parameters.") 175 return 1 176 177 if opts.disk_state: 178 disk_state = utils.FlatToDict(opts.disk_state) 179 else: 180 disk_state = {} 181 182 hv_state = dict(opts.hv_state) 183 184 diskparams = dict(opts.diskparams) 185 186 # create ipolicy object 187 ipolicy = CreateIPolicyFromOpts( 188 minmax_ispecs=opts.ipolicy_bounds_specs, 189 ipolicy_disk_templates=opts.ipolicy_disk_templates, 190 ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio, 191 ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio, 192 group_ipolicy=True, 193 allowed_values=[constants.VALUE_DEFAULT]) 194 195 op = opcodes.OpGroupSetParams(group_name=args[0], 196 ndparams=opts.ndparams, 197 alloc_policy=opts.alloc_policy, 198 hv_state=hv_state, 199 disk_state=disk_state, 200 diskparams=diskparams, 201 ipolicy=ipolicy) 202 203 result = SubmitOrSend(op, opts) 204 205 if result: 206 ToStdout("Modified node group %s", args[0]) 207 for param, data in result: 208 ToStdout(" - %-5s -> %s", param, data) 209 210 return 0
211 212
213 -def RemoveGroup(opts, args):
214 """Remove a node group from the cluster. 215 216 @param opts: the command line options selected by the user 217 @type args: list 218 @param args: a list of length 1 with the name of the group to remove 219 @rtype: int 220 @return: the desired exit code 221 222 """ 223 (group_name,) = args 224 op = opcodes.OpGroupRemove(group_name=group_name) 225 SubmitOrSend(op, opts)
226 227
228 -def RenameGroup(opts, args):
229 """Rename a node group. 230 231 @param opts: the command line options selected by the user 232 @type args: list 233 @param args: a list of length 2, [old_name, new_name] 234 @rtype: int 235 @return: the desired exit code 236 237 """ 238 group_name, new_name = args 239 op = opcodes.OpGroupRename(group_name=group_name, new_name=new_name) 240 SubmitOrSend(op, opts)
241 242
243 -def EvacuateGroup(opts, args):
244 """Evacuate a node group. 245 246 """ 247 (group_name, ) = args 248 249 cl = GetClient() 250 251 op = opcodes.OpGroupEvacuate(group_name=group_name, 252 iallocator=opts.iallocator, 253 target_groups=opts.to, 254 early_release=opts.early_release, 255 sequential=opts.sequential, 256 force_failover=opts.force_failover) 257 result = SubmitOrSend(op, opts, cl=cl) 258 259 # Keep track of submitted jobs 260 jex = JobExecutor(cl=cl, opts=opts) 261 262 for (status, job_id) in result[constants.JOB_IDS_KEY]: 263 jex.AddJobId(None, status, job_id) 264 265 results = jex.GetResults() 266 bad_cnt = len([row for row in results if not row[0]]) 267 if bad_cnt == 0: 268 ToStdout("All instances evacuated successfully.") 269 rcode = constants.EXIT_SUCCESS 270 else: 271 ToStdout("There were %s errors during the evacuation.", bad_cnt) 272 rcode = constants.EXIT_FAILURE 273 274 return rcode
275 276
277 -def _FormatGroupInfo(group):
278 (name, ndparams, custom_ndparams, diskparams, custom_diskparams, 279 ipolicy, custom_ipolicy) = group 280 return [ 281 ("Node group", name), 282 ("Node parameters", FormatParamsDictInfo(custom_ndparams, ndparams)), 283 ("Disk parameters", FormatParamsDictInfo(custom_diskparams, diskparams)), 284 ("Instance policy", FormatPolicyInfo(custom_ipolicy, ipolicy, False)), 285 ]
286 287
288 -def GroupInfo(_, args):
289 """Shows info about node group. 290 291 """ 292 cl = GetClient(query=True) 293 selected_fields = ["name", 294 "ndparams", "custom_ndparams", 295 "diskparams", "custom_diskparams", 296 "ipolicy", "custom_ipolicy"] 297 result = cl.QueryGroups(names=args, fields=selected_fields, 298 use_locking=False) 299 300 PrintGenericInfo([ 301 _FormatGroupInfo(group) for group in result 302 ])
303 304
305 -def _GetCreateCommand(group):
306 (name, ipolicy) = group 307 buf = StringIO() 308 buf.write("gnt-group add") 309 PrintIPolicyCommand(buf, ipolicy, True) 310 buf.write(" ") 311 buf.write(name) 312 return buf.getvalue()
313 314
315 -def ShowCreateCommand(opts, args):
316 """Shows the command that can be used to re-create a node group. 317 318 Currently it works only for ipolicy specs. 319 320 """ 321 cl = GetClient(query=True) 322 selected_fields = ["name"] 323 if opts.include_defaults: 324 selected_fields += ["ipolicy"] 325 else: 326 selected_fields += ["custom_ipolicy"] 327 result = cl.QueryGroups(names=args, fields=selected_fields, 328 use_locking=False) 329 330 for group in result: 331 ToStdout(_GetCreateCommand(group))
332 333 334 commands = { 335 "add": ( 336 AddGroup, ARGS_ONE_GROUP, 337 [DRY_RUN_OPT, ALLOC_POLICY_OPT, NODE_PARAMS_OPT, DISK_PARAMS_OPT, 338 HV_STATE_OPT, DISK_STATE_OPT, PRIORITY_OPT] 339 + SUBMIT_OPTS + INSTANCE_POLICY_OPTS, 340 "<group_name>", "Add a new node group to the cluster"), 341 "assign-nodes": ( 342 AssignNodes, ARGS_ONE_GROUP + ARGS_MANY_NODES, 343 [DRY_RUN_OPT, FORCE_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 344 "<group_name> <node>...", "Assign nodes to a group"), 345 "list": ( 346 ListGroups, ARGS_MANY_GROUPS, 347 [NOHDR_OPT, SEP_OPT, FIELDS_OPT, VERBOSE_OPT, FORCE_FILTER_OPT], 348 "[<group_name>...]", 349 "Lists the node groups in the cluster. The available fields can be shown" 350 " using the \"list-fields\" command (see the man page for details)." 351 " The default list is (in order): %s." % utils.CommaJoin(_LIST_DEF_FIELDS)), 352 "list-fields": ( 353 ListGroupFields, [ArgUnknown()], [NOHDR_OPT, SEP_OPT], "[fields...]", 354 "Lists all available fields for node groups"), 355 "modify": ( 356 SetGroupParams, ARGS_ONE_GROUP, 357 [DRY_RUN_OPT] + SUBMIT_OPTS + 358 [ALLOC_POLICY_OPT, NODE_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT, 359 DISK_PARAMS_OPT, PRIORITY_OPT] 360 + INSTANCE_POLICY_OPTS, 361 "<group_name>", "Alters the parameters of a node group"), 362 "remove": ( 363 RemoveGroup, ARGS_ONE_GROUP, [DRY_RUN_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 364 "[--dry-run] <group-name>", 365 "Remove an (empty) node group from the cluster"), 366 "rename": ( 367 RenameGroup, [ArgGroup(min=2, max=2)], 368 [DRY_RUN_OPT] + SUBMIT_OPTS + [PRIORITY_OPT], 369 "[--dry-run] <group-name> <new-name>", "Rename a node group"), 370 "evacuate": ( 371 EvacuateGroup, [ArgGroup(min=1, max=1)], 372 [TO_GROUP_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT, SEQUENTIAL_OPT, 373 FORCE_FAILOVER_OPT] 374 + SUBMIT_OPTS, 375 "[-I <iallocator>] [--to <group>]", 376 "Evacuate all instances within a group"), 377 "list-tags": ( 378 ListTags, ARGS_ONE_GROUP, [], 379 "<group_name>", "List the tags of the given group"), 380 "add-tags": ( 381 AddTags, [ArgGroup(min=1, max=1), ArgUnknown()], 382 [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 383 "<group_name> tag...", "Add tags to the given group"), 384 "remove-tags": ( 385 RemoveTags, [ArgGroup(min=1, max=1), ArgUnknown()], 386 [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 387 "<group_name> tag...", "Remove tags from the given group"), 388 "info": ( 389 GroupInfo, ARGS_MANY_GROUPS, [], "[<group_name>...]", 390 "Show group information"), 391 "show-ispecs-cmd": ( 392 ShowCreateCommand, ARGS_MANY_GROUPS, [INCLUDEDEFAULTS_OPT], 393 "[--include-defaults] [<group_name>...]", 394 "Show the command line to re-create a group"), 395 } 396 397
398 -def Main():
399 return GenericMain(commands, 400 override={"tag_type": constants.TAG_NODEGROUP}, 401 env_override=_ENV_OVERRIDE)
402