Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / operating_system.py @ 809a055b

History | View | Annotate | Download (6.4 kB)

1 1be6b00e Thomas Thrainer
#
2 1be6b00e Thomas Thrainer
#
3 1be6b00e Thomas Thrainer
4 1be6b00e Thomas Thrainer
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
5 1be6b00e Thomas Thrainer
#
6 1be6b00e Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 1be6b00e Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 1be6b00e Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 1be6b00e Thomas Thrainer
# (at your option) any later version.
10 1be6b00e Thomas Thrainer
#
11 1be6b00e Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 1be6b00e Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 1be6b00e Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 1be6b00e Thomas Thrainer
# General Public License for more details.
15 1be6b00e Thomas Thrainer
#
16 1be6b00e Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 1be6b00e Thomas Thrainer
# along with this program; if not, write to the Free Software
18 1be6b00e Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 1be6b00e Thomas Thrainer
# 02110-1301, USA.
20 1be6b00e Thomas Thrainer
21 1be6b00e Thomas Thrainer
22 1be6b00e Thomas Thrainer
"""Logical units dealing with OS."""
23 1be6b00e Thomas Thrainer
24 1be6b00e Thomas Thrainer
from ganeti import locking
25 1be6b00e Thomas Thrainer
from ganeti import qlang
26 1be6b00e Thomas Thrainer
from ganeti import query
27 5eacbcae Thomas Thrainer
from ganeti.cmdlib.base import QueryBase, NoHooksLU
28 1be6b00e Thomas Thrainer
29 1be6b00e Thomas Thrainer
30 5eacbcae Thomas Thrainer
class OsQuery(QueryBase):
31 1be6b00e Thomas Thrainer
  FIELDS = query.OS_FIELDS
32 1be6b00e Thomas Thrainer
33 1be6b00e Thomas Thrainer
  def ExpandNames(self, lu):
34 1be6b00e Thomas Thrainer
    # Lock all nodes in shared mode
35 1be6b00e Thomas Thrainer
    # Temporary removal of locks, should be reverted later
36 1be6b00e Thomas Thrainer
    # TODO: reintroduce locks when they are lighter-weight
37 1be6b00e Thomas Thrainer
    lu.needed_locks = {}
38 1be6b00e Thomas Thrainer
    #self.share_locks[locking.LEVEL_NODE] = 1
39 1be6b00e Thomas Thrainer
    #self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET
40 1be6b00e Thomas Thrainer
41 1be6b00e Thomas Thrainer
    # The following variables interact with _QueryBase._GetNames
42 1be6b00e Thomas Thrainer
    if self.names:
43 1be6b00e Thomas Thrainer
      self.wanted = self.names
44 1be6b00e Thomas Thrainer
    else:
45 1be6b00e Thomas Thrainer
      self.wanted = locking.ALL_SET
46 1be6b00e Thomas Thrainer
47 1be6b00e Thomas Thrainer
    self.do_locking = self.use_locking
48 1be6b00e Thomas Thrainer
49 1be6b00e Thomas Thrainer
  def DeclareLocks(self, lu, level):
50 1be6b00e Thomas Thrainer
    pass
51 1be6b00e Thomas Thrainer
52 1be6b00e Thomas Thrainer
  @staticmethod
53 1be6b00e Thomas Thrainer
  def _DiagnoseByOS(rlist):
54 a44114c9 Jose A. Lopes
    """Remaps a per-node return list into a per-os per-node dictionary
55 1be6b00e Thomas Thrainer

56 1be6b00e Thomas Thrainer
    @param rlist: a map with node names as keys and OS objects as values
57 1be6b00e Thomas Thrainer

58 1be6b00e Thomas Thrainer
    @rtype: dict
59 1be6b00e Thomas Thrainer
    @return: a dictionary with osnames as keys and as value another
60 1c3231aa Thomas Thrainer
        map, with node UUIDs as keys and tuples of (path, status, diagnose,
61 1be6b00e Thomas Thrainer
        variants, parameters, api_versions) as values, eg::
62 1be6b00e Thomas Thrainer

63 1c3231aa Thomas Thrainer
          {"debian-etch": {"node1-uuid": [(/usr/lib/..., True, "", [], []),
64 1c3231aa Thomas Thrainer
                                          (/srv/..., False, "invalid api")],
65 1c3231aa Thomas Thrainer
                           "node2-uuid": [(/srv/..., True, "", [], [])]}
66 1be6b00e Thomas Thrainer
          }
67 1be6b00e Thomas Thrainer

68 1be6b00e Thomas Thrainer
    """
69 1be6b00e Thomas Thrainer
    all_os = {}
70 1be6b00e Thomas Thrainer
    # we build here the list of nodes that didn't fail the RPC (at RPC
71 1be6b00e Thomas Thrainer
    # level), so that nodes with a non-responding node daemon don't
72 1be6b00e Thomas Thrainer
    # make all OSes invalid
73 1c3231aa Thomas Thrainer
    good_node_uuids = [node_uuid for node_uuid in rlist
74 1c3231aa Thomas Thrainer
                       if not rlist[node_uuid].fail_msg]
75 1c3231aa Thomas Thrainer
    for node_uuid, nr in rlist.items():
76 1be6b00e Thomas Thrainer
      if nr.fail_msg or not nr.payload:
77 1be6b00e Thomas Thrainer
        continue
78 1be6b00e Thomas Thrainer
      for (name, path, status, diagnose, variants,
79 a44114c9 Jose A. Lopes
           params, api_versions, trusted) in nr.payload:
80 1be6b00e Thomas Thrainer
        if name not in all_os:
81 1be6b00e Thomas Thrainer
          # build a list of nodes for this os containing empty lists
82 1be6b00e Thomas Thrainer
          # for each node in node_list
83 1be6b00e Thomas Thrainer
          all_os[name] = {}
84 1c3231aa Thomas Thrainer
          for nuuid in good_node_uuids:
85 1c3231aa Thomas Thrainer
            all_os[name][nuuid] = []
86 1be6b00e Thomas Thrainer
        # convert params from [name, help] to (name, help)
87 1be6b00e Thomas Thrainer
        params = [tuple(v) for v in params]
88 a44114c9 Jose A. Lopes
        all_os[name][node_uuid].append((path, status, diagnose, variants,
89 a44114c9 Jose A. Lopes
                                        params, api_versions, trusted))
90 1be6b00e Thomas Thrainer
    return all_os
91 1be6b00e Thomas Thrainer
92 1be6b00e Thomas Thrainer
  def _GetQueryData(self, lu):
93 1be6b00e Thomas Thrainer
    """Computes the list of nodes and their attributes.
94 1be6b00e Thomas Thrainer

95 1be6b00e Thomas Thrainer
    """
96 1c3231aa Thomas Thrainer
    valid_node_uuids = [node.uuid
97 1c3231aa Thomas Thrainer
                        for node in lu.cfg.GetAllNodesInfo().values()
98 1c3231aa Thomas Thrainer
                        if not node.offline and node.vm_capable]
99 1c3231aa Thomas Thrainer
    pol = self._DiagnoseByOS(lu.rpc.call_os_diagnose(valid_node_uuids))
100 1be6b00e Thomas Thrainer
    cluster = lu.cfg.GetClusterInfo()
101 1be6b00e Thomas Thrainer
102 1be6b00e Thomas Thrainer
    data = {}
103 1be6b00e Thomas Thrainer
104 1be6b00e Thomas Thrainer
    for (os_name, os_data) in pol.items():
105 1be6b00e Thomas Thrainer
      info = query.OsInfo(name=os_name, valid=True, node_status=os_data,
106 1be6b00e Thomas Thrainer
                          hidden=(os_name in cluster.hidden_os),
107 7f37f0ca Dimitris Bliablias
                          blacklisted=(os_name in cluster.blacklisted_os),
108 7f37f0ca Dimitris Bliablias
                          os_hvp={}, osparams={})
109 1be6b00e Thomas Thrainer
110 1be6b00e Thomas Thrainer
      variants = set()
111 1be6b00e Thomas Thrainer
      parameters = set()
112 1be6b00e Thomas Thrainer
      api_versions = set()
113 a44114c9 Jose A. Lopes
      trusted = True
114 1be6b00e Thomas Thrainer
115 1be6b00e Thomas Thrainer
      for idx, osl in enumerate(os_data.values()):
116 1be6b00e Thomas Thrainer
        info.valid = bool(info.valid and osl and osl[0][1])
117 1be6b00e Thomas Thrainer
        if not info.valid:
118 1be6b00e Thomas Thrainer
          break
119 1be6b00e Thomas Thrainer
120 a44114c9 Jose A. Lopes
        (node_variants, node_params, node_api, node_trusted) = osl[0][3:7]
121 1be6b00e Thomas Thrainer
        if idx == 0:
122 1be6b00e Thomas Thrainer
          # First entry
123 1be6b00e Thomas Thrainer
          variants.update(node_variants)
124 1be6b00e Thomas Thrainer
          parameters.update(node_params)
125 1be6b00e Thomas Thrainer
          api_versions.update(node_api)
126 1be6b00e Thomas Thrainer
        else:
127 1be6b00e Thomas Thrainer
          # Filter out inconsistent values
128 1be6b00e Thomas Thrainer
          variants.intersection_update(node_variants)
129 1be6b00e Thomas Thrainer
          parameters.intersection_update(node_params)
130 1be6b00e Thomas Thrainer
          api_versions.intersection_update(node_api)
131 1be6b00e Thomas Thrainer
132 a44114c9 Jose A. Lopes
        if not node_trusted:
133 a44114c9 Jose A. Lopes
          trusted = False
134 a44114c9 Jose A. Lopes
135 1be6b00e Thomas Thrainer
      info.variants = list(variants)
136 1be6b00e Thomas Thrainer
      info.parameters = list(parameters)
137 1be6b00e Thomas Thrainer
      info.api_versions = list(api_versions)
138 a44114c9 Jose A. Lopes
      info.trusted = trusted
139 1be6b00e Thomas Thrainer
140 7f37f0ca Dimitris Bliablias
      for variant in variants:
141 7f37f0ca Dimitris Bliablias
        name = "+".join([os_name, variant])
142 7f37f0ca Dimitris Bliablias
        if name in cluster.os_hvp.keys():
143 7f37f0ca Dimitris Bliablias
          info.os_hvp[name] = cluster.os_hvp.get(name)
144 7f37f0ca Dimitris Bliablias
        if name in cluster.osparams.keys():
145 7f37f0ca Dimitris Bliablias
          info.osparams[name] = cluster.osparams.get(name)
146 7f37f0ca Dimitris Bliablias
147 1be6b00e Thomas Thrainer
      data[os_name] = info
148 1be6b00e Thomas Thrainer
149 1be6b00e Thomas Thrainer
    # Prepare data in requested order
150 1be6b00e Thomas Thrainer
    return [data[name] for name in self._GetNames(lu, pol.keys(), None)
151 1be6b00e Thomas Thrainer
            if name in data]
152 1be6b00e Thomas Thrainer
153 1be6b00e Thomas Thrainer
154 1be6b00e Thomas Thrainer
class LUOsDiagnose(NoHooksLU):
155 1be6b00e Thomas Thrainer
  """Logical unit for OS diagnose/query.
156 1be6b00e Thomas Thrainer

157 1be6b00e Thomas Thrainer
  """
158 1be6b00e Thomas Thrainer
  REQ_BGL = False
159 1be6b00e Thomas Thrainer
160 1be6b00e Thomas Thrainer
  @staticmethod
161 1be6b00e Thomas Thrainer
  def _BuildFilter(fields, names):
162 1be6b00e Thomas Thrainer
    """Builds a filter for querying OSes.
163 1be6b00e Thomas Thrainer

164 1be6b00e Thomas Thrainer
    """
165 1be6b00e Thomas Thrainer
    name_filter = qlang.MakeSimpleFilter("name", names)
166 1be6b00e Thomas Thrainer
167 1be6b00e Thomas Thrainer
    # Legacy behaviour: Hide hidden, blacklisted or invalid OSes if the
168 1be6b00e Thomas Thrainer
    # respective field is not requested
169 1be6b00e Thomas Thrainer
    status_filter = [[qlang.OP_NOT, [qlang.OP_TRUE, fname]]
170 1be6b00e Thomas Thrainer
                     for fname in ["hidden", "blacklisted"]
171 1be6b00e Thomas Thrainer
                     if fname not in fields]
172 1be6b00e Thomas Thrainer
    if "valid" not in fields:
173 1be6b00e Thomas Thrainer
      status_filter.append([qlang.OP_TRUE, "valid"])
174 1be6b00e Thomas Thrainer
175 1be6b00e Thomas Thrainer
    if status_filter:
176 1be6b00e Thomas Thrainer
      status_filter.insert(0, qlang.OP_AND)
177 1be6b00e Thomas Thrainer
    else:
178 1be6b00e Thomas Thrainer
      status_filter = None
179 1be6b00e Thomas Thrainer
180 1be6b00e Thomas Thrainer
    if name_filter and status_filter:
181 1be6b00e Thomas Thrainer
      return [qlang.OP_AND, name_filter, status_filter]
182 1be6b00e Thomas Thrainer
    elif name_filter:
183 1be6b00e Thomas Thrainer
      return name_filter
184 1be6b00e Thomas Thrainer
    else:
185 1be6b00e Thomas Thrainer
      return status_filter
186 1be6b00e Thomas Thrainer
187 1be6b00e Thomas Thrainer
  def CheckArguments(self):
188 5eacbcae Thomas Thrainer
    self.oq = OsQuery(self._BuildFilter(self.op.output_fields, self.op.names),
189 a44114c9 Jose A. Lopes
                      self.op.output_fields, False)
190 1be6b00e Thomas Thrainer
191 1be6b00e Thomas Thrainer
  def ExpandNames(self):
192 1be6b00e Thomas Thrainer
    self.oq.ExpandNames(self)
193 1be6b00e Thomas Thrainer
194 1be6b00e Thomas Thrainer
  def Exec(self, feedback_fn):
195 1be6b00e Thomas Thrainer
    return self.oq.OldStyleQuery(self)