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