Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-os @ 216fe2f3

History | View | Annotate | Download (5.5 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

    
22
import sys
23
from optparse import make_option
24

    
25
from ganeti.cli import *
26
from ganeti import opcodes
27
from ganeti import logger
28
from ganeti import objects
29
from ganeti import utils
30
from ganeti import errors
31

    
32
def _GetAllOS(rlist):
33
  """Remap an OpDiagnoseOS() return list into an a per-os per-node dictionary
34

    
35
    Args:
36
      rlist: a map with nodes as keys and diagnoseobjects as values
37

    
38
    Returns:
39
      map: a map with osnames as keys and as value another map, with nodes as
40
           keys and diagnoseobjects as values
41
           e.g. {"debian-etch": {"node1": <object>, "node2": <object>}}
42
  """
43

    
44
  all_os = {}
45
  for node_name, nr in rlist.iteritems():
46
    if not nr:
47
      continue
48
    for obj in nr:
49
      if _DiagnoseOSValid(obj):
50
        os_name = obj.name
51
      else:
52
        os_name = obj.args[0]
53
      if os_name not in all_os:
54
        all_os[os_name] = {}
55
      if node_name not in all_os[os_name]:
56
        all_os[os_name][node_name] = []
57
      all_os[os_name][node_name].append(obj)
58

    
59
  return all_os
60

    
61
def ListOS(opts, args):
62
  """List the OSes existing on this node.
63

    
64
  """
65
  op = opcodes.OpDiagnoseOS()
66
  result = SubmitOpCode(op)
67

    
68
  if not result:
69
    logger.ToStdout("Can't get the OS list")
70
    return 1
71

    
72
  node_data = result
73
  num_nodes = len(node_data)
74
  all_os = _GetAllOS(node_data)
75

    
76
  valid_os = []
77
  for os_name, os_node_data in all_os.iteritems():
78
    if len(os_node_data) != num_nodes:
79
      continue
80
    valid = True
81
    for l in os_node_data.values():
82
      if not _DiagnoseOSValid(l[0]):
83
        valid = False
84
        break
85
    if valid:
86
      valid_os.append(os_name)
87

    
88
  if not opts.no_headers:
89
    headers = {"name": "Name"}
90
  else:
91
    headers = None
92

    
93
  data = GenerateTable(separator=None, headers=headers, fields=["name"],
94
                       data=[[os] for os in valid_os])
95

    
96
  for line in data:
97
    logger.ToStdout(line)
98

    
99
  return 0
100

    
101
def _DiagnoseOSValid(obj):
102
  """Verify whether an OS diagnose object represents a valid OS
103

    
104
    Args:
105
      obj: an diagnostic object as returned by OpDiagnoseOS
106

    
107
    Returns:
108
      bool: OS validity status
109
  """
110

    
111
  if isinstance(obj, objects.OS):
112
    return True
113
  elif isinstance(obj, errors.InvalidOS):
114
    return False
115
  else:
116
    raise errors.ProgrammerError('unknown OS diagnose type')
117

    
118
def _DiagnoseOSStatus(obj):
119
  """Generate a status message for an OS diagnose object.
120

    
121
    Args:
122
      obj: an diagnostic object as returned by OpDiagnoseOS
123

    
124
    Returns:
125
      string: a description of the OS status
126
  """
127

    
128
  if _DiagnoseOSValid(obj):
129
    return "valid (path: %s)" % obj.path
130
  else:
131
    return "%s (path: %s)" % (obj.args[2], obj.args[1])
132

    
133
def DiagnoseOS(opts, args):
134
  """Analyse all OSes on this cluster.
135

    
136
  """
137
  op = opcodes.OpDiagnoseOS()
138
  result = SubmitOpCode(op)
139

    
140
  if not result:
141
    logger.ToStdout("Can't get the OS list")
142
    return 1
143

    
144
  node_data = result
145
  all_os = _GetAllOS(node_data)
146

    
147
  format = "%-*s %-*s %s"
148

    
149
  max_name = len('Name')
150
  if all_os:
151
    max_name = max(max_name, max([len(name) for name in all_os]))
152

    
153
  max_node = len('Status/Node')
154
  max_node = max(max_node, max([len(name) for name in node_data]))
155

    
156
  logger.ToStdout(format % (max_name, 'Name', max_node, 'Status/Node',
157
                            'Details'))
158

    
159
  for os_name in all_os:
160
    nodes_valid = {}
161
    nodes_bad = {}
162
    for node_name in node_data:
163
      if node_name in all_os[os_name]:
164
        first_os = all_os[os_name][node_name].pop(0)
165
        first_os_status = _DiagnoseOSStatus(first_os)
166
        if _DiagnoseOSValid(first_os):
167
          nodes_valid[node_name] = first_os_status
168
        else:
169
          nodes_bad[node_name] = first_os_status
170
      else:
171
        nodes_bad[node_name] = "OS not found"
172

    
173
    if nodes_valid and not nodes_bad:
174
      status = "valid"
175
    elif not nodes_valid and nodes_bad:
176
      status = "invalid"
177
    else:
178
      status = "partial valid"
179

    
180
    def _OutputNodeHiddenOSStatus(dobj_list):
181
      for dobj in dobj_list:
182
        logger.ToStdout(format % (max_name, "", max_node, "",
183
                                  "[hidden] %s" %
184
                                  _DiagnoseOSStatus(dobj)))
185

    
186
    def _OutputPerNodeOSStatus(status_map):
187
      map_k = utils.NiceSort(status_map.keys())
188
      for node_name in map_k:
189
        logger.ToStdout(format % (max_name, "", max_node,
190
                                  node_name, status_map[node_name]))
191
        if node_name in all_os[os_name]:
192
          _OutputNodeHiddenOSStatus(all_os[os_name][node_name])
193

    
194
    logger.ToStdout(format % (max_name, os_name, max_node, status, ""))
195
    _OutputPerNodeOSStatus(nodes_valid)
196
    _OutputPerNodeOSStatus(nodes_bad)
197

    
198

    
199
commands = {
200
  'list': (ListOS, ARGS_NONE, [DEBUG_OPT, NOHDR_OPT], "",
201
           "Lists all valid OSes on the master"),
202
  'diagnose': (DiagnoseOS, ARGS_NONE, [DEBUG_OPT], "",
203
               "Diagnose all OSes"),
204
  }
205

    
206
if __name__ == '__main__':
207
  sys.exit(GenericMain(commands))