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 locking 
 34  from ganeti import qlang 
 35  from ganeti import query 
 36  from ganeti.cmdlib.base import QueryBase, NoHooksLU 
37 38 39 -class OsQuery(QueryBase):
40 FIELDS = query.OS_FIELDS 41
42 - def ExpandNames(self, lu):
43 # Lock all nodes in shared mode 44 # Temporary removal of locks, should be reverted later 45 # TODO: reintroduce locks when they are lighter-weight 46 lu.needed_locks = {} 47 #self.share_locks[locking.LEVEL_NODE] = 1 48 #self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET 49 50 # The following variables interact with _QueryBase._GetNames 51 if self.names: 52 self.wanted = self.names 53 else: 54 self.wanted = locking.ALL_SET 55 56 self.do_locking = self.use_locking
57
58 - def DeclareLocks(self, lu, level):
59 pass
60 61 @staticmethod
62 - def _DiagnoseByOS(rlist):
63 """Remaps a per-node return list into a per-os per-node dictionary 64 65 @param rlist: a map with node names as keys and OS objects as values 66 67 @rtype: dict 68 @return: a dictionary with osnames as keys and as value another 69 map, with node UUIDs as keys and tuples of (path, status, diagnose, 70 variants, parameters, api_versions) as values, eg:: 71 72 {"debian-etch": {"node1-uuid": [(/usr/lib/..., True, "", [], []), 73 (/srv/..., False, "invalid api")], 74 "node2-uuid": [(/srv/..., True, "", [], [])]} 75 } 76 77 """ 78 all_os = {} 79 # we build here the list of nodes that didn't fail the RPC (at RPC 80 # level), so that nodes with a non-responding node daemon don't 81 # make all OSes invalid 82 good_node_uuids = [node_uuid for node_uuid in rlist 83 if not rlist[node_uuid].fail_msg] 84 for node_uuid, nr in rlist.items(): 85 if nr.fail_msg or not nr.payload: 86 continue 87 for (name, path, status, diagnose, variants, 88 params, api_versions, trusted) in nr.payload: 89 if name not in all_os: 90 # build a list of nodes for this os containing empty lists 91 # for each node in node_list 92 all_os[name] = {} 93 for nuuid in good_node_uuids: 94 all_os[name][nuuid] = [] 95 # convert params from [name, help] to (name, help) 96 params = [tuple(v) for v in params] 97 all_os[name][node_uuid].append((path, status, diagnose, variants, 98 params, api_versions, trusted)) 99 return all_os
100
101 - def _GetQueryData(self, lu):
102 """Computes the list of nodes and their attributes. 103 104 """ 105 valid_node_uuids = [node.uuid 106 for node in lu.cfg.GetAllNodesInfo().values() 107 if not node.offline and node.vm_capable] 108 pol = self._DiagnoseByOS(lu.rpc.call_os_diagnose(valid_node_uuids)) 109 cluster = lu.cfg.GetClusterInfo() 110 111 data = {} 112 113 for (os_name, os_data) in pol.items(): 114 info = query.OsInfo(name=os_name, valid=True, node_status=os_data, 115 hidden=(os_name in cluster.hidden_os), 116 blacklisted=(os_name in cluster.blacklisted_os), 117 os_hvp={}, osparams={}) 118 119 variants = set() 120 parameters = set() 121 api_versions = set() 122 trusted = True 123 124 for idx, osl in enumerate(os_data.values()): 125 info.valid = bool(info.valid and osl and osl[0][1]) 126 if not info.valid: 127 break 128 129 (node_variants, node_params, node_api, node_trusted) = osl[0][3:7] 130 if idx == 0: 131 # First entry 132 variants.update(node_variants) 133 parameters.update(node_params) 134 api_versions.update(node_api) 135 else: 136 # Filter out inconsistent values 137 variants.intersection_update(node_variants) 138 parameters.intersection_update(node_params) 139 api_versions.intersection_update(node_api) 140 141 if not node_trusted: 142 trusted = False 143 144 info.variants = list(variants) 145 info.parameters = list(parameters) 146 info.api_versions = list(api_versions) 147 info.trusted = trusted 148 149 for variant in variants: 150 name = "+".join([os_name, variant]) 151 if name in cluster.os_hvp.keys(): 152 info.os_hvp[name] = cluster.os_hvp.get(name) 153 if name in cluster.osparams.keys(): 154 info.osparams[name] = cluster.osparams.get(name) 155 156 data[os_name] = info 157 158 # Prepare data in requested order 159 return [data[name] for name in self._GetNames(lu, pol.keys(), None) 160 if name in data]
161
162 163 -class LUOsDiagnose(NoHooksLU):
164 """Logical unit for OS diagnose/query. 165 166 """ 167 REQ_BGL = False 168 169 @staticmethod
170 - def _BuildFilter(fields, names):
171 """Builds a filter for querying OSes. 172 173 """ 174 name_filter = qlang.MakeSimpleFilter("name", names) 175 176 # Legacy behaviour: Hide hidden, blacklisted or invalid OSes if the 177 # respective field is not requested 178 status_filter = [[qlang.OP_NOT, [qlang.OP_TRUE, fname]] 179 for fname in ["hidden", "blacklisted"] 180 if fname not in fields] 181 if "valid" not in fields: 182 status_filter.append([qlang.OP_TRUE, "valid"]) 183 184 if status_filter: 185 status_filter.insert(0, qlang.OP_AND) 186 else: 187 status_filter = None 188 189 if name_filter and status_filter: 190 return [qlang.OP_AND, name_filter, status_filter] 191 elif name_filter: 192 return name_filter 193 else: 194 return status_filter
195
196 - def CheckArguments(self):
197 self.oq = OsQuery(self._BuildFilter(self.op.output_fields, self.op.names), 198 self.op.output_fields, False)
199
200 - def ExpandNames(self):
201 self.oq.ExpandNames(self)
202
203 - def Exec(self, feedback_fn):
204 return self.oq.OldStyleQuery(self)
205