1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """Logical units dealing with OS."""
32
33 from ganeti import compat
34 from ganeti import locking
35 from ganeti import qlang
36 from ganeti import query
37 from ganeti.cmdlib.base import QueryBase, NoHooksLU
41 FIELDS = query.OS_FIELDS
42
44
45
46
47 lu.needed_locks = {}
48
49
50
51
52 if self.names:
53 self.wanted = self.names
54 else:
55 self.wanted = locking.ALL_SET
56
57 self.do_locking = self.use_locking
58
61
62 @staticmethod
64 """Remaps a per-node return list into an a per-os per-node dictionary
65
66 @param rlist: a map with node names as keys and OS objects as values
67
68 @rtype: dict
69 @return: a dictionary with osnames as keys and as value another
70 map, with node UUIDs as keys and tuples of (path, status, diagnose,
71 variants, parameters, api_versions) as values, eg::
72
73 {"debian-etch": {"node1-uuid": [(/usr/lib/..., True, "", [], []),
74 (/srv/..., False, "invalid api")],
75 "node2-uuid": [(/srv/..., True, "", [], [])]}
76 }
77
78 """
79 all_os = {}
80
81
82
83 good_node_uuids = [node_uuid for node_uuid in rlist
84 if not rlist[node_uuid].fail_msg]
85 for node_uuid, nr in rlist.items():
86 if nr.fail_msg or not nr.payload:
87 continue
88 for (name, path, status, diagnose, variants,
89 params, api_versions) in nr.payload:
90 if name not in all_os:
91
92
93 all_os[name] = {}
94 for nuuid in good_node_uuids:
95 all_os[name][nuuid] = []
96
97 params = [tuple(v) for v in params]
98 all_os[name][node_uuid].append((path, status, diagnose,
99 variants, params, api_versions))
100 return all_os
101
103 """Computes the list of nodes and their attributes.
104
105 """
106
107 assert not (compat.any(lu.glm.is_owned(level)
108 for level in locking.LEVELS
109 if level != locking.LEVEL_CLUSTER) or
110 self.do_locking or self.use_locking)
111
112 valid_node_uuids = [node.uuid
113 for node in lu.cfg.GetAllNodesInfo().values()
114 if not node.offline and node.vm_capable]
115 pol = self._DiagnoseByOS(lu.rpc.call_os_diagnose(valid_node_uuids))
116 cluster = lu.cfg.GetClusterInfo()
117
118 data = {}
119
120 for (os_name, os_data) in pol.items():
121 info = query.OsInfo(name=os_name, valid=True, node_status=os_data,
122 hidden=(os_name in cluster.hidden_os),
123 blacklisted=(os_name in cluster.blacklisted_os))
124
125 variants = set()
126 parameters = set()
127 api_versions = set()
128
129 for idx, osl in enumerate(os_data.values()):
130 info.valid = bool(info.valid and osl and osl[0][1])
131 if not info.valid:
132 break
133
134 (node_variants, node_params, node_api) = osl[0][3:6]
135 if idx == 0:
136
137 variants.update(node_variants)
138 parameters.update(node_params)
139 api_versions.update(node_api)
140 else:
141
142 variants.intersection_update(node_variants)
143 parameters.intersection_update(node_params)
144 api_versions.intersection_update(node_api)
145
146 info.variants = list(variants)
147 info.parameters = list(parameters)
148 info.api_versions = list(api_versions)
149
150 data[os_name] = info
151
152
153 return [data[name] for name in self._GetNames(lu, pol.keys(), None)
154 if name in data]
155
158 """Logical unit for OS diagnose/query.
159
160 """
161 REQ_BGL = False
162
163 @staticmethod
165 """Builds a filter for querying OSes.
166
167 """
168 name_filter = qlang.MakeSimpleFilter("name", names)
169
170
171
172 status_filter = [[qlang.OP_NOT, [qlang.OP_TRUE, fname]]
173 for fname in ["hidden", "blacklisted"]
174 if fname not in fields]
175 if "valid" not in fields:
176 status_filter.append([qlang.OP_TRUE, "valid"])
177
178 if status_filter:
179 status_filter.insert(0, qlang.OP_AND)
180 else:
181 status_filter = None
182
183 if name_filter and status_filter:
184 return [qlang.OP_AND, name_filter, status_filter]
185 elif name_filter:
186 return name_filter
187 else:
188 return status_filter
189
191 self.oq = OsQuery(self._BuildFilter(self.op.output_fields, self.op.names),
192 self.op.output_fields, False)
193
196
197 - def Exec(self, feedback_fn):
199