Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-os @ ae5b1530

History | View | Annotate | Download (7.3 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2006, 2007 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21
"""OS scripts related commands"""
22

    
23
# pylint: disable-msg=W0401,W0613,W0614,C0103
24
# W0401: Wildcard import ganeti.cli
25
# W0613: Unused argument, since all functions follow the same API
26
# W0614: Unused import %s from wildcard import (since we need cli)
27
# C0103: Invalid name gnt-os
28

    
29
import sys
30

    
31
from ganeti.cli import *
32
from ganeti import opcodes
33
from ganeti import utils
34

    
35

    
36
def ListOS(opts, args):
37
  """List the valid OSes in the cluster.
38

    
39
  @param opts: the command line options selected by the user
40
  @type args: list
41
  @param args: should be an empty list
42
  @rtype: int
43
  @return: the desired exit code
44

    
45
  """
46
  op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants"],
47
                            names=[])
48
  result = SubmitOpCode(op, opts=opts)
49

    
50
  if not result:
51
    ToStderr("Can't get the OS list")
52
    return 1
53

    
54
  if not opts.no_headers:
55
    headers = {"name": "Name"}
56
  else:
57
    headers = None
58

    
59
  os_names = []
60
  for (name, valid, variants) in result:
61
    if valid:
62
      os_names.extend([[n] for n in CalculateOSNames(name, variants)])
63

    
64
  data = GenerateTable(separator=None, headers=headers, fields=["name"],
65
                       data=os_names, units=None)
66

    
67
  for line in data:
68
    ToStdout(line)
69

    
70
  return 0
71

    
72

    
73
def ShowOSInfo(opts, args):
74
  """List detailed information about OSes in the cluster.
75

    
76
  @param opts: the command line options selected by the user
77
  @type args: list
78
  @param args: should be an empty list
79
  @rtype: int
80
  @return: the desired exit code
81

    
82
  """
83
  op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants",
84
                                           "parameters", "api_versions"],
85
                            names=[])
86
  result = SubmitOpCode(op, opts=opts)
87

    
88
  if not result:
89
    ToStderr("Can't get the OS list")
90
    return 1
91

    
92
  do_filter = bool(args)
93

    
94
  for (name, valid, variants, parameters, api_versions) in result:
95
    if do_filter:
96
      if name not in args:
97
        continue
98
      else:
99
        args.remove(name)
100
    ToStdout("%s:", name)
101
    ToStdout("  - valid: %s", valid)
102
    if valid:
103
      ToStdout("  - API versions:")
104
      for version in sorted(api_versions):
105
        ToStdout("    - %s", version)
106
      ToStdout("  - variants:")
107
      for vname in variants:
108
        ToStdout("    - %s", vname)
109
      ToStdout("  - parameters:")
110
      for pname, pdesc in parameters:
111
        ToStdout("    - %s: %s", pname, pdesc)
112
    ToStdout("")
113

    
114
  if args:
115
    for name in args:
116
      ToStdout("%s: ", name)
117
      ToStdout("")
118

    
119
  return 0
120

    
121

    
122
def _OsStatus(status, diagnose):
123
  """Beautifier function for OS status.
124

    
125
  @type status: boolean
126
  @param status: is the OS valid
127
  @type diagnose: string
128
  @param diagnose: the error message for invalid OSes
129
  @rtype: string
130
  @return: a formatted status
131

    
132
  """
133
  if status:
134
    return "valid"
135
  else:
136
    return "invalid - %s" % diagnose
137

    
138
def DiagnoseOS(opts, args):
139
  """Analyse all OSes on this cluster.
140

    
141
  @param opts: the command line options selected by the user
142
  @type args: list
143
  @param args: should be an empty list
144
  @rtype: int
145
  @return: the desired exit code
146

    
147
  """
148
  op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants",
149
                                           "node_status"], names=[])
150
  result = SubmitOpCode(op, opts=opts)
151

    
152
  if not result:
153
    ToStderr("Can't get the OS list")
154
    return 1
155

    
156
  has_bad = False
157

    
158
  for os_name, _, os_variants, node_data in result:
159
    nodes_valid = {}
160
    nodes_bad = {}
161
    nodes_hidden = {}
162
    for node_name, node_info in node_data.iteritems():
163
      nodes_hidden[node_name] = []
164
      if node_info: # at least one entry in the per-node list
165
        (first_os_path, first_os_status, first_os_msg,
166
         first_os_variants, _, first_os_api) = node_info.pop(0)
167
        if not first_os_variants:
168
          first_os_variants = []
169
        first_os_msg = ("%s (path: %s) [variants: %s] [api: %s]" %
170
                        (_OsStatus(first_os_status, first_os_msg),
171
                         first_os_path, utils.CommaJoin(first_os_variants),
172
                         utils.CommaJoin(first_os_api)))
173
        if first_os_status:
174
          nodes_valid[node_name] = first_os_msg
175
        else:
176
          nodes_bad[node_name] = first_os_msg
177
        for hpath, hstatus, hmsg, _, _, _ in node_info:
178
          nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
179
                                         (hpath, _OsStatus(hstatus, hmsg)))
180
      else:
181
        nodes_bad[node_name] = "OS not found"
182

    
183
    if nodes_valid and not nodes_bad:
184
      status = "valid"
185
    elif not nodes_valid and nodes_bad:
186
      status = "invalid"
187
      has_bad = True
188
    else:
189
      status = "partial valid"
190
      has_bad = True
191

    
192
    def _OutputPerNodeOSStatus(msg_map):
193
      map_k = utils.NiceSort(msg_map.keys())
194
      for node_name in map_k:
195
        ToStdout("  Node: %s, status: %s", node_name, msg_map[node_name])
196
        for msg in nodes_hidden[node_name]:
197
          ToStdout(msg)
198

    
199
    ToStdout("OS: %s [global status: %s]", os_name, status)
200
    if os_variants:
201
      ToStdout("  Variants: [%s]" % utils.CommaJoin(os_variants))
202
    _OutputPerNodeOSStatus(nodes_valid)
203
    _OutputPerNodeOSStatus(nodes_bad)
204
    ToStdout("")
205

    
206
  return int(has_bad)
207

    
208

    
209
def ModifyOS(opts, args):
210
  """Modify OS parameters for one OS.
211

    
212
  @param opts: the command line options selected by the user
213
  @type args: list
214
  @param args: should be a list with one entry
215
  @rtype: int
216
  @return: the desired exit code
217

    
218
  """
219
  os = args[0]
220

    
221
  if opts.hvparams:
222
    os_hvp = {os: dict(opts.hvparams)}
223
  else:
224
    os_hvp = None
225

    
226
  if opts.osparams:
227
    osp = {os: opts.osparams}
228
  else:
229
    osp = None
230

    
231
  if not (os_hvp or osp):
232
    ToStderr("At least one of OS parameters or hypervisor parameters"
233
             " must be passed")
234
    return 1
235

    
236
  op = opcodes.OpSetClusterParams(vg_name=None,
237
                                  enabled_hypervisors=None,
238
                                  hvparams=None,
239
                                  beparams=None,
240
                                  nicparams=None,
241
                                  candidate_pool_size=None,
242
                                  os_hvp=os_hvp,
243
                                  osparams=osp)
244
  SubmitOpCode(op)
245

    
246
  return 0
247

    
248

    
249
commands = {
250
  'list': (
251
    ListOS, ARGS_NONE, [NOHDR_OPT], "", "Lists all valid operating systems"
252
    " on the cluster"),
253
  'diagnose': (
254
    DiagnoseOS, ARGS_NONE, [], "", "Diagnose all operating systems"),
255
  'info': (
256
    ShowOSInfo, [ArgOs()], [], "", "Show detailed information about "
257
    "operating systems"),
258
  'modify': (
259
    ModifyOS, ARGS_ONE_OS, [HVLIST_OPT, OSPARAMS_OPT], "",
260
    "Modify the OS parameters"),
261
  }
262

    
263
if __name__ == '__main__':
264
  sys.exit(GenericMain(commands))