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

Source Code for Module ganeti.client.gnt_os

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2010, 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  """OS scripts related commands""" 
 31   
 32  # pylint: disable=W0401,W0613,W0614,C0103 
 33  # W0401: Wildcard import ganeti.cli 
 34  # W0613: Unused argument, since all functions follow the same API 
 35  # W0614: Unused import %s from wildcard import (since we need cli) 
 36  # C0103: Invalid name gnt-os 
 37   
 38  from ganeti.cli import * 
 39  from ganeti import constants 
 40  from ganeti import opcodes 
 41  from ganeti import utils 
 42   
 43   
44 -def ListOS(opts, args):
45 """List the valid OSes in the cluster. 46 47 @param opts: the command line options selected by the user 48 @type args: list 49 @param args: should be an empty list 50 @rtype: int 51 @return: the desired exit code 52 53 """ 54 op = opcodes.OpOsDiagnose(output_fields=["name", "variants"], names=[]) 55 result = SubmitOpCode(op, opts=opts) 56 57 if not opts.no_headers: 58 headers = {"name": "Name"} 59 else: 60 headers = None 61 62 os_names = [] 63 for (name, variants) in result: 64 os_names.extend([[n] for n in CalculateOSNames(name, variants)]) 65 66 data = GenerateTable(separator=None, headers=headers, fields=["name"], 67 data=os_names, units=None) 68 69 for line in data: 70 ToStdout(line) 71 72 return 0
73 74
75 -def ShowOSInfo(opts, args):
76 """List detailed information about OSes in the cluster. 77 78 @param opts: the command line options selected by the user 79 @type args: list 80 @param args: should be an empty list 81 @rtype: int 82 @return: the desired exit code 83 84 """ 85 op = opcodes.OpOsDiagnose(output_fields=["name", "valid", "variants", 86 "parameters", "api_versions", 87 "blacklisted", "hidden"], 88 names=[]) 89 result = SubmitOpCode(op, opts=opts) 90 91 if result is None: 92 ToStderr("Can't get the OS list") 93 return 1 94 95 do_filter = bool(args) 96 97 for (name, valid, variants, parameters, api_versions, blk, hid) in result: 98 if do_filter: 99 if name not in args: 100 continue 101 else: 102 args.remove(name) 103 ToStdout("%s:", name) 104 ToStdout(" - valid: %s", valid) 105 ToStdout(" - hidden: %s", hid) 106 ToStdout(" - blacklisted: %s", blk) 107 if valid: 108 ToStdout(" - API versions:") 109 for version in sorted(api_versions): 110 ToStdout(" - %s", version) 111 ToStdout(" - variants:") 112 for vname in variants: 113 ToStdout(" - %s", vname) 114 ToStdout(" - parameters:") 115 for pname, pdesc in parameters: 116 ToStdout(" - %s: %s", pname, pdesc) 117 ToStdout("") 118 119 if args: 120 for name in args: 121 ToStdout("%s: ", name) 122 ToStdout("") 123 124 return 0
125 126
127 -def _OsStatus(status, diagnose):
128 """Beautifier function for OS status. 129 130 @type status: boolean 131 @param status: is the OS valid 132 @type diagnose: string 133 @param diagnose: the error message for invalid OSes 134 @rtype: string 135 @return: a formatted status 136 137 """ 138 if status: 139 return "valid" 140 else: 141 return "invalid - %s" % diagnose
142 143
144 -def DiagnoseOS(opts, args):
145 """Analyse all OSes on this cluster. 146 147 @param opts: the command line options selected by the user 148 @type args: list 149 @param args: should be an empty list 150 @rtype: int 151 @return: the desired exit code 152 153 """ 154 op = opcodes.OpOsDiagnose(output_fields=["name", "valid", "variants", 155 "node_status", "hidden", 156 "blacklisted"], names=[]) 157 result = SubmitOpCode(op, opts=opts) 158 159 if result is None: 160 ToStderr("Can't get the OS list") 161 return 1 162 163 has_bad = False 164 165 for os_name, _, os_variants, node_data, hid, blk in result: 166 nodes_valid = {} 167 nodes_bad = {} 168 nodes_hidden = {} 169 for node_name, node_info in node_data.iteritems(): 170 nodes_hidden[node_name] = [] 171 if node_info: # at least one entry in the per-node list 172 (fo_path, fo_status, fo_msg, fo_variants, 173 fo_params, fo_api) = node_info.pop(0) 174 fo_msg = "%s (path: %s)" % (_OsStatus(fo_status, fo_msg), fo_path) 175 if fo_api: 176 max_os_api = max(fo_api) 177 fo_msg += " [API versions: %s]" % utils.CommaJoin(fo_api) 178 else: 179 max_os_api = 0 180 fo_msg += " [no API versions declared]" 181 182 if max_os_api >= constants.OS_API_V15: 183 if fo_variants: 184 fo_msg += " [variants: %s]" % utils.CommaJoin(fo_variants) 185 else: 186 fo_msg += " [no variants]" 187 if max_os_api >= constants.OS_API_V20: 188 if fo_params: 189 fo_msg += (" [parameters: %s]" % 190 utils.CommaJoin([v[0] for v in fo_params])) 191 else: 192 fo_msg += " [no parameters]" 193 if fo_status: 194 nodes_valid[node_name] = fo_msg 195 else: 196 nodes_bad[node_name] = fo_msg 197 for hpath, hstatus, hmsg, _, _, _ in node_info: 198 nodes_hidden[node_name].append(" [hidden] path: %s, status: %s" % 199 (hpath, _OsStatus(hstatus, hmsg))) 200 else: 201 nodes_bad[node_name] = "OS not found" 202 203 # TODO: Shouldn't the global status be calculated by the LU? 204 if nodes_valid and not nodes_bad: 205 status = "valid" 206 elif not nodes_valid and nodes_bad: 207 status = "invalid" 208 has_bad = True 209 else: 210 status = "partial valid" 211 has_bad = True 212 213 def _OutputPerNodeOSStatus(msg_map): 214 map_k = utils.NiceSort(msg_map.keys()) 215 for node_name in map_k: 216 ToStdout(" Node: %s, status: %s", node_name, msg_map[node_name]) 217 for msg in nodes_hidden[node_name]: 218 ToStdout(msg)
219 220 st_msg = "OS: %s [global status: %s]" % (os_name, status) 221 if hid: 222 st_msg += " [hidden]" 223 if blk: 224 st_msg += " [blacklisted]" 225 ToStdout(st_msg) 226 if os_variants: 227 ToStdout(" Variants: [%s]" % utils.CommaJoin(os_variants)) 228 _OutputPerNodeOSStatus(nodes_valid) 229 _OutputPerNodeOSStatus(nodes_bad) 230 ToStdout("") 231 232 return int(has_bad) 233 234
235 -def ModifyOS(opts, args):
236 """Modify OS parameters for one OS. 237 238 @param opts: the command line options selected by the user 239 @type args: list 240 @param args: should be a list with one entry 241 @rtype: int 242 @return: the desired exit code 243 244 """ 245 os = args[0] 246 247 if opts.hvparams: 248 os_hvp = {os: dict(opts.hvparams)} 249 else: 250 os_hvp = None 251 252 if opts.osparams: 253 osp = {os: opts.osparams} 254 else: 255 osp = None 256 257 if opts.hidden is not None: 258 if opts.hidden: 259 ohid = [(constants.DDM_ADD, os)] 260 else: 261 ohid = [(constants.DDM_REMOVE, os)] 262 else: 263 ohid = None 264 265 if opts.blacklisted is not None: 266 if opts.blacklisted: 267 oblk = [(constants.DDM_ADD, os)] 268 else: 269 oblk = [(constants.DDM_REMOVE, os)] 270 else: 271 oblk = None 272 273 if not (os_hvp or osp or ohid or oblk): 274 ToStderr("At least one of OS parameters or hypervisor parameters" 275 " must be passed") 276 return 1 277 278 op = opcodes.OpClusterSetParams(os_hvp=os_hvp, 279 osparams=osp, 280 hidden_os=ohid, 281 blacklisted_os=oblk) 282 SubmitOrSend(op, opts) 283 284 return 0
285 286 287 commands = { 288 "list": ( 289 ListOS, ARGS_NONE, [NOHDR_OPT, PRIORITY_OPT], 290 "", "Lists all valid operating systems on the cluster"), 291 "diagnose": ( 292 DiagnoseOS, ARGS_NONE, [PRIORITY_OPT], 293 "", "Diagnose all operating systems"), 294 "info": ( 295 ShowOSInfo, [ArgOs()], [PRIORITY_OPT], 296 "", "Show detailed information about " 297 "operating systems"), 298 "modify": ( 299 ModifyOS, ARGS_ONE_OS, 300 [HVLIST_OPT, OSPARAMS_OPT, DRY_RUN_OPT, PRIORITY_OPT, 301 HID_OS_OPT, BLK_OS_OPT] + SUBMIT_OPTS, 302 "", "Modify the OS parameters"), 303 } 304 305 #: dictionary with aliases for commands 306 aliases = { 307 "show": "info", 308 } 309 310
311 -def Main():
312 return GenericMain(commands, aliases=aliases)
313