Package ganeti :: Package cmdlib :: Module operating_system
[hide private]
[frames] | no frames]

Source Code for Module ganeti.cmdlib.operating_system

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc. 
  5  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 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 
38 39 40 -class OsQuery(QueryBase):
41 FIELDS = query.OS_FIELDS 42
43 - def ExpandNames(self, lu):
44 # Lock all nodes in shared mode 45 # Temporary removal of locks, should be reverted later 46 # TODO: reintroduce locks when they are lighter-weight 47 lu.needed_locks = {} 48 #self.share_locks[locking.LEVEL_NODE] = 1 49 #self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET 50 51 # The following variables interact with _QueryBase._GetNames 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
59 - def DeclareLocks(self, lu, level):
60 pass
61 62 @staticmethod
63 - def _DiagnoseByOS(rlist):
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 # we build here the list of nodes that didn't fail the RPC (at RPC 81 # level), so that nodes with a non-responding node daemon don't 82 # make all OSes invalid 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 # build a list of nodes for this os containing empty lists 92 # for each node in node_list 93 all_os[name] = {} 94 for nuuid in good_node_uuids: 95 all_os[name][nuuid] = [] 96 # convert params from [name, help] to (name, help) 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
102 - def _GetQueryData(self, lu):
103 """Computes the list of nodes and their attributes. 104 105 """ 106 # Locking is not used 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 # First entry 137 variants.update(node_variants) 138 parameters.update(node_params) 139 api_versions.update(node_api) 140 else: 141 # Filter out inconsistent values 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 # Prepare data in requested order 153 return [data[name] for name in self._GetNames(lu, pol.keys(), None) 154 if name in data]
155
156 157 -class LUOsDiagnose(NoHooksLU):
158 """Logical unit for OS diagnose/query. 159 160 """ 161 REQ_BGL = False 162 163 @staticmethod
164 - def _BuildFilter(fields, names):
165 """Builds a filter for querying OSes. 166 167 """ 168 name_filter = qlang.MakeSimpleFilter("name", names) 169 170 # Legacy behaviour: Hide hidden, blacklisted or invalid OSes if the 171 # respective field is not requested 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
190 - def CheckArguments(self):
191 self.oq = OsQuery(self._BuildFilter(self.op.output_fields, self.op.names), 192 self.op.output_fields, False)
193
194 - def ExpandNames(self):
195 self.oq.ExpandNames(self)
196
197 - def Exec(self, feedback_fn):
198 return self.oq.OldStyleQuery(self)
199