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) |