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  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, but 
 12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 14  # General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 19  # 02110-1301, USA. 
 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 
29 30 31 -class OsQuery(QueryBase):
32 FIELDS = query.OS_FIELDS 33
34 - def ExpandNames(self, lu):
35 # Lock all nodes in shared mode 36 # Temporary removal of locks, should be reverted later 37 # TODO: reintroduce locks when they are lighter-weight 38 lu.needed_locks = {} 39 #self.share_locks[locking.LEVEL_NODE] = 1 40 #self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET 41 42 # The following variables interact with _QueryBase._GetNames 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
50 - def DeclareLocks(self, lu, level):
51 pass
52 53 @staticmethod
54 - def _DiagnoseByOS(rlist):
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 # we build here the list of nodes that didn't fail the RPC (at RPC 72 # level), so that nodes with a non-responding node daemon don't 73 # make all OSes invalid 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 # build a list of nodes for this os containing empty lists 83 # for each node in node_list 84 all_os[name] = {} 85 for nname in good_nodes: 86 all_os[name][nname] = [] 87 # convert params from [name, help] to (name, help) 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
93 - def _GetQueryData(self, lu):
94 """Computes the list of nodes and their attributes. 95 96 """ 97 # Locking is not used 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 # First entry 128 variants.update(node_variants) 129 parameters.update(node_params) 130 api_versions.update(node_api) 131 else: 132 # Filter out inconsistent values 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 # Prepare data in requested order 144 return [data[name] for name in self._GetNames(lu, pol.keys(), None) 145 if name in data]
146
147 148 -class LUOsDiagnose(NoHooksLU):
149 """Logical unit for OS diagnose/query. 150 151 """ 152 REQ_BGL = False 153 154 @staticmethod
155 - def _BuildFilter(fields, names):
156 """Builds a filter for querying OSes. 157 158 """ 159 name_filter = qlang.MakeSimpleFilter("name", names) 160 161 # Legacy behaviour: Hide hidden, blacklisted or invalid OSes if the 162 # respective field is not requested 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
181 - def CheckArguments(self):
182 self.oq = OsQuery(self._BuildFilter(self.op.output_fields, self.op.names), 183 self.op.output_fields, False)
184
185 - def ExpandNames(self):
186 self.oq.ExpandNames(self)
187
188 - def Exec(self, feedback_fn):
189 return self.oq.OldStyleQuery(self)
190