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, 2014 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  from ganeti.client import base 
 44   
 45   
 46  #: default list of fields for L{ListGroups} 
 47  _LIST_DEF_FIELDS = ["name", "node_cnt", "pinst_cnt", "alloc_policy", "ndparams"] 
 48   
 49  _ENV_OVERRIDE = compat.UniqueFrozenset(["list"]) 
 50   
 51   
52 -def AddGroup(opts, args):
53 """Add a node group to the cluster. 54 55 @param opts: the command line options selected by the user 56 @type args: list 57 @param args: a list of length 1 with the name of the group to create 58 @rtype: int 59 @return: the desired exit code 60 61 """ 62 ipolicy = CreateIPolicyFromOpts( 63 minmax_ispecs=opts.ipolicy_bounds_specs, 64 ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio, 65 ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio, 66 ipolicy_memory_ratio=opts.ipolicy_memory_ratio, 67 ipolicy_disk_templates=opts.ipolicy_disk_templates, 68 group_ipolicy=True) 69 70 (group_name,) = args 71 diskparams = dict(opts.diskparams) 72 73 if opts.disk_state: 74 disk_state = utils.FlatToDict(opts.disk_state) 75 else: 76 disk_state = {} 77 hv_state = dict(opts.hv_state) 78 79 op = opcodes.OpGroupAdd(group_name=group_name, ndparams=opts.ndparams, 80 alloc_policy=opts.alloc_policy, 81 diskparams=diskparams, ipolicy=ipolicy, 82 hv_state=hv_state, 83 disk_state=disk_state) 84 return base.GetResult(None, opts, SubmitOrSend(op, opts))
85 86
87 -def AssignNodes(opts, args):
88 """Assign nodes to a group. 89 90 @param opts: the command line options selected by the user 91 @type args: list 92 @param args: args[0]: group to assign nodes to; args[1:]: nodes to assign 93 @rtype: int 94 @return: the desired exit code 95 96 """ 97 group_name = args[0] 98 node_names = args[1:] 99 100 op = opcodes.OpGroupAssignNodes(group_name=group_name, nodes=node_names, 101 force=opts.force) 102 SubmitOrSend(op, opts)
103 104
105 -def _FmtDict(data):
106 """Format dict data into command-line format. 107 108 @param data: The input dict to be formatted 109 @return: The formatted dict 110 111 """ 112 if not data: 113 return "(empty)" 114 115 return utils.CommaJoin(["%s=%s" % (key, value) 116 for key, value in data.items()])
117 118
119 -def ListGroups(opts, args):
120 """List node groups and their properties. 121 122 @param opts: the command line options selected by the user 123 @type args: list 124 @param args: groups to list, or empty for all 125 @rtype: int 126 @return: the desired exit code 127 128 """ 129 desired_fields = ParseFields(opts.output, _LIST_DEF_FIELDS) 130 fmtoverride = { 131 "node_list": (",".join, False), 132 "pinst_list": (",".join, False), 133 "ndparams": (_FmtDict, False), 134 } 135 136 cl = GetClient() 137 138 return GenericList(constants.QR_GROUP, desired_fields, args, None, 139 opts.separator, not opts.no_headers, 140 format_override=fmtoverride, verbose=opts.verbose, 141 force_filter=opts.force_filter, cl=cl)
142 143
144 -def ListGroupFields(opts, args):
145 """List node fields. 146 147 @param opts: the command line options selected by the user 148 @type args: list 149 @param args: fields to list, or empty for all 150 @rtype: int 151 @return: the desired exit code 152 153 """ 154 cl = GetClient() 155 156 return GenericListFields(constants.QR_GROUP, args, opts.separator, 157 not opts.no_headers, cl=cl)
158 159
160 -def SetGroupParams(opts, args):
161 """Modifies a node group's parameters. 162 163 @param opts: the command line options selected by the user 164 @type args: list 165 @param args: should contain only one element, the node group name 166 167 @rtype: int 168 @return: the desired exit code 169 170 """ 171 allmods = [opts.ndparams, opts.alloc_policy, opts.diskparams, opts.hv_state, 172 opts.disk_state, opts.ipolicy_bounds_specs, 173 opts.ipolicy_vcpu_ratio, opts.ipolicy_spindle_ratio, 174 opts.ipolicy_memory_ratio, opts.diskparams, 175 opts.ipolicy_disk_templates] 176 if allmods.count(None) == len(allmods): 177 ToStderr("Please give at least one of the parameters.") 178 return 1 179 180 if opts.disk_state: 181 disk_state = utils.FlatToDict(opts.disk_state) 182 else: 183 disk_state = {} 184 185 hv_state = dict(opts.hv_state) 186 187 diskparams = dict(opts.diskparams) 188 189 # create ipolicy object 190 ipolicy = CreateIPolicyFromOpts( 191 minmax_ispecs=opts.ipolicy_bounds_specs, 192 ipolicy_disk_templates=opts.ipolicy_disk_templates, 193 ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio, 194 ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio, 195 ipolicy_memory_ratio=opts.ipolicy_memory_ratio, 196 group_ipolicy=True, 197 allowed_values=[constants.VALUE_DEFAULT]) 198 199 op = opcodes.OpGroupSetParams(group_name=args[0], 200 ndparams=opts.ndparams, 201 alloc_policy=opts.alloc_policy, 202 hv_state=hv_state, 203 disk_state=disk_state, 204 diskparams=diskparams, 205 ipolicy=ipolicy) 206 207 result = SubmitOrSend(op, opts) 208 209 if result: 210 ToStdout("Modified node group %s", args[0]) 211 for param, data in result: 212 ToStdout(" - %-5s -> %s", param, data) 213 214 return 0
215 216
217 -def RemoveGroup(opts, args):
218 """Remove a node group from the cluster. 219 220 @param opts: the command line options selected by the user 221 @type args: list 222 @param args: a list of length 1 with the name of the group to remove 223 @rtype: int 224 @return: the desired exit code 225 226 """ 227 (group_name,) = args 228 op = opcodes.OpGroupRemove(group_name=group_name) 229 SubmitOrSend(op, opts)
230 231
232 -def RenameGroup(opts, args):
233 """Rename a node group. 234 235 @param opts: the command line options selected by the user 236 @type args: list 237 @param args: a list of length 2, [old_name, new_name] 238 @rtype: int 239 @return: the desired exit code 240 241 """ 242 group_name, new_name = args 243 op = opcodes.OpGroupRename(group_name=group_name, new_name=new_name) 244 SubmitOrSend(op, opts)
245 246
247 -def EvacuateGroup(opts, args):
248 """Evacuate a node group. 249 250 """ 251 (group_name, ) = args 252 253 cl = GetClient() 254 255 op = opcodes.OpGroupEvacuate(group_name=group_name, 256 iallocator=opts.iallocator, 257 target_groups=opts.to, 258 early_release=opts.early_release, 259 sequential=opts.sequential, 260 force_failover=opts.force_failover) 261 result = SubmitOrSend(op, opts, cl=cl) 262 263 # Keep track of submitted jobs 264 jex = JobExecutor(cl=cl, opts=opts) 265 266 for (status, job_id) in result[constants.JOB_IDS_KEY]: 267 jex.AddJobId(None, status, job_id) 268 269 results = jex.GetResults() 270 bad_cnt = len([row for row in results if not row[0]]) 271 if bad_cnt == 0: 272 ToStdout("All instances evacuated successfully.") 273 rcode = constants.EXIT_SUCCESS 274 else: 275 ToStdout("There were %s errors during the evacuation.", bad_cnt) 276 rcode = constants.EXIT_FAILURE 277 278 return rcode
279 280
281 -def _FormatGroupInfo(group):
282 (name, ndparams, custom_ndparams, diskparams, custom_diskparams, 283 ipolicy, custom_ipolicy) = group 284 return [ 285 ("Node group", name), 286 ("Node parameters", FormatParamsDictInfo(custom_ndparams, ndparams)), 287 ("Disk parameters", FormatParamsDictInfo(custom_diskparams, diskparams)), 288 ("Instance policy", FormatPolicyInfo(custom_ipolicy, ipolicy, False)), 289 ]
290 291
292 -def GroupInfo(_, args):
293 """Shows info about node group. 294 295 """ 296 cl = GetClient() 297 selected_fields = ["name", 298 "ndparams", "custom_ndparams", 299 "diskparams", "custom_diskparams", 300 "ipolicy", "custom_ipolicy"] 301 result = cl.QueryGroups(names=args, fields=selected_fields, 302 use_locking=False) 303 304 PrintGenericInfo([ 305 _FormatGroupInfo(group) for group in result 306 ])
307 308
309 -def _GetCreateCommand(group):
310 (name, ipolicy) = group 311 buf = StringIO() 312 buf.write("gnt-group add") 313 PrintIPolicyCommand(buf, ipolicy, True) 314 buf.write(" ") 315 buf.write(name) 316 return buf.getvalue()
317 318
319 -def ShowCreateCommand(opts, args):
320 """Shows the command that can be used to re-create a node group. 321 322 Currently it works only for ipolicy specs. 323 324 """ 325 cl = GetClient() 326 selected_fields = ["name"] 327 if opts.include_defaults: 328 selected_fields += ["ipolicy"] 329 else: 330 selected_fields += ["custom_ipolicy"] 331 result = cl.QueryGroups(names=args, fields=selected_fields, 332 use_locking=False) 333 334 for group in result: 335 ToStdout(_GetCreateCommand(group))
336 337 338 commands = { 339 "add": ( 340 AddGroup, ARGS_ONE_GROUP, 341 [DRY_RUN_OPT, ALLOC_POLICY_OPT, NODE_PARAMS_OPT, DISK_PARAMS_OPT, 342 HV_STATE_OPT, DISK_STATE_OPT, PRIORITY_OPT] 343 + SUBMIT_OPTS + INSTANCE_POLICY_OPTS, 344 "<group_name>", "Add a new node group to the cluster"), 345 "assign-nodes": ( 346 AssignNodes, ARGS_ONE_GROUP + ARGS_MANY_NODES, 347 [DRY_RUN_OPT, FORCE_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 348 "<group_name> <node>...", "Assign nodes to a group"), 349 "list": ( 350 ListGroups, ARGS_MANY_GROUPS, 351 [NOHDR_OPT, SEP_OPT, FIELDS_OPT, VERBOSE_OPT, FORCE_FILTER_OPT], 352 "[<group_name>...]", 353 "Lists the node groups in the cluster. The available fields can be shown" 354 " using the \"list-fields\" command (see the man page for details)." 355 " The default list is (in order): %s." % utils.CommaJoin(_LIST_DEF_FIELDS)), 356 "list-fields": ( 357 ListGroupFields, [ArgUnknown()], [NOHDR_OPT, SEP_OPT], "[fields...]", 358 "Lists all available fields for node groups"), 359 "modify": ( 360 SetGroupParams, ARGS_ONE_GROUP, 361 [DRY_RUN_OPT] + SUBMIT_OPTS + 362 [ALLOC_POLICY_OPT, NODE_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT, 363 DISK_PARAMS_OPT, PRIORITY_OPT] 364 + INSTANCE_POLICY_OPTS, 365 "<group_name>", "Alters the parameters of a node group"), 366 "remove": ( 367 RemoveGroup, ARGS_ONE_GROUP, [DRY_RUN_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 368 "[--dry-run] <group-name>", 369 "Remove an (empty) node group from the cluster"), 370 "rename": ( 371 RenameGroup, [ArgGroup(min=2, max=2)], 372 [DRY_RUN_OPT] + SUBMIT_OPTS + [PRIORITY_OPT], 373 "[--dry-run] <group-name> <new-name>", "Rename a node group"), 374 "evacuate": ( 375 EvacuateGroup, [ArgGroup(min=1, max=1)], 376 [TO_GROUP_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT, SEQUENTIAL_OPT, 377 FORCE_FAILOVER_OPT] 378 + SUBMIT_OPTS, 379 "[-I <iallocator>] [--to <group>]", 380 "Evacuate all instances within a group"), 381 "list-tags": ( 382 ListTags, ARGS_ONE_GROUP, [], 383 "<group_name>", "List the tags of the given group"), 384 "add-tags": ( 385 AddTags, [ArgGroup(min=1, max=1), ArgUnknown()], 386 [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 387 "<group_name> tag...", "Add tags to the given group"), 388 "remove-tags": ( 389 RemoveTags, [ArgGroup(min=1, max=1), ArgUnknown()], 390 [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS, 391 "<group_name> tag...", "Remove tags from the given group"), 392 "info": ( 393 GroupInfo, ARGS_MANY_GROUPS, [], "[<group_name>...]", 394 "Show group information"), 395 "show-ispecs-cmd": ( 396 ShowCreateCommand, ARGS_MANY_GROUPS, [INCLUDEDEFAULTS_OPT], 397 "[--include-defaults] [<group_name>...]", 398 "Show the command line to re-create a group"), 399 } 400 401
402 -def Main():
403 return GenericMain(commands, 404 override={"tag_type": constants.TAG_NODEGROUP}, 405 env_override=_ENV_OVERRIDE)
406