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