12 except (socket.error, IOError, OSError):
19 _expected_methods = set(
20 ['AddNodeTag', 'AddConfFile', 'DeletePersonTag', 'AddNodeType', 'DeleteBootState', 'SliceListNames', 'DeleteKey',
21 'SliceGetTicket', 'SliceUsersList', 'SliceUpdate', 'GetNodeGroups', 'SliceCreate', 'GetNetworkMethods', 'GetNodeFlavour',
22 'DeleteNode', 'BootNotifyOwners', 'AddPersonKey', 'AddNode', 'UpdateNodeGroup', 'GetAddressTypes', 'AddIlink', 'DeleteNetworkType',
23 'GetInitScripts', 'GenerateNodeConfFile', 'AddSite', 'BindObjectToPeer', 'SliceListUserSlices', 'GetPeers', 'AddPeer', 'DeletePeer',
24 'AddRole', 'DeleteRole', 'SetPersonPrimarySite', 'AddSiteAddress', 'SliceDelete', 'NotifyPersons', 'GetKeyTypes', 'GetConfFiles',
25 'GetIlinks', 'AddTagType', 'GetNodes', 'DeleteNodeTag', 'DeleteSliceFromNodesWhitelist', 'UpdateAddress', 'ResetPassword',
26 'AddSliceToNodesWhitelist', 'AddRoleToTagType', 'AddLeases', 'GetAddresses', 'AddInitScript', 'RebootNode', 'GetPCUTypes',
27 'RefreshPeer', 'GetBootMedium', 'UpdateKey', 'UpdatePCU', 'GetSession', 'AddInterfaceTag', 'UpdatePCUType', 'GetInterfaces',
28 'SliceExtendedInfo', 'SliceNodesList', 'DeleteRoleFromTagType', 'DeleteSlice', 'GetSites', 'DeleteMessage', 'GetSliceFamily',
29 'GetPlcRelease', 'UpdateTagType', 'AddSliceInstantiation', 'ResolveSlices', 'GetSlices', 'DeleteRoleFromPerson', 'GetSessions',
30 'UpdatePeer', 'VerifyPerson', 'GetPersonTags', 'DeleteKeyType', 'AddSlice', 'SliceUserAdd', 'DeleteSession', 'GetMessages',
31 'DeletePCU', 'GetPeerData', 'DeletePersonFromSite', 'DeleteTagType', 'GetPCUs', 'UpdateLeases', 'AddMessage',
32 'DeletePCUProtocolType', 'DeleteInterfaceTag', 'AddPersonToSite', 'GetSlivers', 'SliceNodesDel', 'DeleteAddressTypeFromAddress',
33 'AddNodeGroup', 'GetSliceTags', 'DeleteSite', 'GetSiteTags', 'UpdateMessage', 'DeleteSliceFromNodes', 'SliceRenew',
34 'UpdatePCUProtocolType', 'DeleteSiteTag', 'GetPCUProtocolTypes', 'GetEvents', 'GetSliceTicket', 'AddPersonTag', 'BootGetNodeDetails',
35 'DeleteInterface', 'DeleteNodeGroup', 'AddPCUProtocolType', 'BootCheckAuthentication', 'AddSiteTag', 'AddAddressTypeToAddress',
36 'DeleteConfFile', 'DeleteInitScript', 'DeletePerson', 'DeleteIlink', 'DeleteAddressType', 'AddBootState', 'AuthCheck',
37 'NotifySupport', 'GetSliceInstantiations', 'AddPCUType', 'AddPCU', 'AddSession', 'GetEventObjects', 'UpdateSiteTag',
38 'UpdateNodeTag', 'AddPerson', 'BlacklistKey', 'UpdateInitScript', 'AddSliceToNodes', 'RebootNodeWithPCU', 'GetNodeTags',
39 'GetSliceKeys', 'GetSliceSshKeys', 'AddNetworkMethod', 'SliceNodesAdd', 'DeletePersonFromSlice', 'ReportRunlevel',
40 'GetNetworkTypes', 'UpdateSite', 'DeleteConfFileFromNodeGroup', 'UpdateNode', 'DeleteSliceInstantiation', 'DeleteSliceTag',
41 'BootUpdateNode', 'UpdatePerson', 'UpdateConfFile', 'SliceUserDel', 'DeleteLeases', 'AddConfFileToNodeGroup', 'UpdatePersonTag',
42 'DeleteConfFileFromNode', 'AddPersonToSlice', 'UnBindObjectFromPeer', 'AddNodeToPCU', 'GetLeaseGranularity', 'DeletePCUType',
43 'GetTagTypes', 'GetNodeTypes', 'UpdateInterfaceTag', 'GetRoles', 'UpdateSlice', 'UpdateSliceTag', 'AddSliceTag', 'AddNetworkType',
44 'AddInterface', 'AddAddressType', 'AddRoleToPerson', 'DeleteNodeType', 'GetLeases', 'UpdateInterface', 'SliceInfo', 'DeleteAddress',
45 'SliceTicketGet', 'GetPersons', 'GetWhitelist', 'AddKeyType', 'UpdateAddressType', 'GetPeerName', 'DeleteNetworkMethod',
46 'UpdateIlink', 'AddConfFileToNode', 'GetKeys', 'DeleteNodeFromPCU', 'GetInterfaceTags', 'GetBootStates', 'SetInterfaceSens', 'SetNodeLoadm',
47 'GetInterfaceRate', 'GetNodeLoadw', 'SetInterfaceKey', 'GetNodeSlices', 'GetNodeLoadm', 'SetSliceVref', 'GetInterfaceIwpriv', 'SetNodeLoadw',
48 'SetNodeSerial', 'GetNodePlainBootstrapfs', 'SetNodeMEMw', 'GetNodeResponse', 'SetInterfaceRate', 'SetSliceInitscript',
49 'SetNodeFcdistro', 'GetNodeLoady', 'SetNodeArch', 'SetNodeKargs', 'SetNodeMEMm', 'SetNodeBWy', 'SetNodeBWw',
50 'SetInterfaceSecurityMode', 'SetNodeBWm', 'SetNodeASType', 'GetNodeKargs', 'GetPersonColumnconf', 'GetNodeResponsem',
51 'GetNodeCPUy', 'GetNodeCramfs', 'SetNodeSlicesw', 'SetPersonColumnconf', 'SetNodeSlicesy', 'GetNodeCPUw', 'GetNodeBWy',
52 'GetNodeCPUm', 'GetInterfaceDriver', 'GetNodeLoad', 'GetInterfaceMode', 'GetNodeSerial', 'SetNodeSlicesm', 'SetNodeLoady',
53 'GetNodeReliabilityw', 'SetSliceFcdistro', 'GetNodeReliabilityy', 'SetInterfaceEssid', 'SetSliceInitscriptCode',
54 'GetNodeExtensions', 'GetSliceOmfControl', 'SetNodeCity', 'SetInterfaceIfname', 'SetNodeHrn', 'SetNodeNoHangcheck',
55 'GetNodeNoHangcheck', 'GetSliceFcdistro', 'SetNodeCountry', 'SetNodeKvariant', 'GetNodeKvariant', 'GetNodeMEMy',
56 'SetInterfaceIwpriv', 'GetNodeMEMw', 'SetInterfaceBackdoor', 'GetInterfaceFreq', 'SetInterfaceChannel', 'SetInterfaceNw',
57 'GetPersonShowconf', 'GetSliceInitscriptCode', 'SetNodeMEM', 'GetInterfaceEssid', 'GetNodeMEMm', 'SetInterfaceMode',
58 'SetInterfaceIwconfig', 'GetNodeSlicesm', 'GetNodeBWm', 'SetNodePlainBootstrapfs', 'SetNodeRegion', 'SetNodeCPU',
59 'GetNodeSlicesw', 'SetNodeBW', 'SetNodeSlices', 'SetNodeCramfs', 'GetNodeSlicesy', 'GetInterfaceKey', 'GetSliceInitscript',
60 'SetNodeCPUm', 'SetSliceArch', 'SetNodeLoad', 'SetNodeResponse', 'GetSliceSliverHMAC', 'GetNodeBWw', 'GetNodeRegion',
61 'SetNodeMEMy', 'GetNodeASType', 'SetNodePldistro', 'GetSliceArch', 'GetNodeCountry', 'SetSliceOmfControl', 'GetNodeHrn',
62 'GetNodeCity', 'SetInterfaceAlias', 'GetNodeBW', 'GetNodePldistro', 'GetSlicePldistro', 'SetNodeASNumber', 'GetSliceHmac',
63 'SetSliceHmac', 'GetNodeMEM', 'GetNodeASNumber', 'GetInterfaceAlias', 'GetSliceVref', 'GetNodeArch', 'GetSliceSshKey',
64 'GetInterfaceKey4', 'GetInterfaceKey2', 'GetInterfaceKey3', 'GetInterfaceKey1', 'GetInterfaceBackdoor', 'GetInterfaceIfname',
65 'SetSliceSliverHMAC', 'SetNodeReliability', 'GetNodeCPU', 'SetPersonShowconf', 'SetNodeExtensions', 'SetNodeCPUy',
66 'SetNodeCPUw', 'GetNodeResponsew', 'SetNodeResponsey', 'GetInterfaceSens', 'SetNodeResponsew', 'GetNodeResponsey',
67 'GetNodeReliability', 'GetNodeReliabilitym', 'SetNodeResponsem', 'SetInterfaceDriver', 'GetInterfaceSecurityMode',
68 'SetNodeDeployment', 'SetNodeReliabilitym', 'GetNodeFcdistro', 'SetInterfaceFreq', 'GetInterfaceNw', 'SetNodeReliabilityy',
69 'SetNodeReliabilityw', 'GetInterfaceIwconfig', 'SetSlicePldistro', 'SetSliceSshKey', 'GetNodeDeployment', 'GetInterfaceChannel',
70 'SetInterfaceKey2', 'SetInterfaceKey3', 'SetInterfaceKey1', 'SetInterfaceKey4'])
72 _required_methods = set()
74 def __init__(self, username=None, password=None, sessionkey=None,
75 hostname = "www.planet-lab.eu",
76 urlpattern = "https://%(hostname)s:443/PLCAPI/",
77 localPeerName = "PLE"):
78 if sessionkey is not None:
79 self.auth = dict(AuthMethod='session', session=sessionkey)
80 elif username is not None and password is not None:
81 self.auth = dict(AuthMethod='password', Username=username, AuthString=password)
83 self.auth = dict(AuthMethod='anonymous')
85 self._localPeerName = localPeerName
86 self._url = urlpattern % {'hostname':hostname}
88 self.threadlocal = threading.local()
92 # Cannot reuse same proxy in all threads, py2.7 is not threadsafe
93 return xmlrpclib.ServerProxy(
100 return self.threadlocal.mc
101 except AttributeError:
107 # validate XMLRPC server checking supported API calls
108 methods = set(_retry(self.mcapi.system.listMethods)())
109 if self._required_methods - methods:
110 warnings.warn("Unsupported REQUIRED methods: %s" % ( ", ".join(sorted(self._required_methods - methods)), ) )
112 if self._expected_methods - methods:
113 warnings.warn("Unsupported EXPECTED methods: %s" % ( ", ".join(sorted(self._expected_methods - methods)), ) )
117 network_types = _retry(self.mcapi.GetNetworkTypes)(self.auth)
118 except (xmlrpclib.ProtocolError, xmlrpclib.Fault),e:
119 warnings.warn(str(e))
125 def network_types(self):
127 return self._network_types
128 except AttributeError:
129 self._network_types = _retry(self.mcapi.GetNetworkTypes)(self.auth)
130 return self._network_types
135 return self._peer_map
136 except AttributeError:
137 peers = _retry(self.mcapi.GetPeers)(self.auth, {}, ['shortname','peername','peer_id'])
138 self._peer_map = dict(
139 (peer['shortname'], peer['peer_id'])
142 self._peer_map.update(
143 (peer['peername'], peer['peer_id'])
146 self._peer_map.update(
147 (peer['peer_id'], peer['shortname'])
150 self._peer_map[None] = self._localPeerName
151 return self._peer_map
154 def GetNodeFlavour(self, node):
156 Returns detailed information on a given node's flavour, i.e. its base installation.
158 This depends on the global PLC settings in the PLC_FLAVOUR area, optionnally overridden by any of the following tags if set on that node:
159 'arch', 'pldistro', 'fcdistro', 'deployment', 'extensions'
163 * node : int or string
164 - int, Node identifier
165 - string, Fully qualified hostname
170 * extensions : array of string, extensions to add to the base install
171 * fcdistro : string, the fcdistro this node should be based upon
172 * nodefamily : string, the nodefamily this node should be based upon
173 * plain : boolean, use plain bootstrapfs image if set (for tests)
175 if not isinstance(node, (str, int, long)):
176 raise ValueError, "Node must be either a non-unicode string or an int"
177 return _retry(self.mcapi.GetNodeFlavour)(self.auth, node)
179 def GetNodes(self, nodeIdOrName=None, fields=None, **kw):
181 Returns an array of structs containing details about nodes.
182 If nodeIdOrName is specified and is an array of node identifiers or hostnames,
183 or the filters keyword argument with struct of node attributes,
184 or node attributes by keyword argument,
185 only nodes matching the filter will be returned.
187 If fields is specified, only the specified details will be returned.
188 NOTE that if fields is unspecified, the complete set of native fields are returned,
189 which DOES NOT include tags at this time.
191 Some fields may only be viewed by admins.
195 fields: an optional list of fields to retrieve. The default is all.
197 filters: an optional mapping with custom filters, which is the only
198 way to support complex filters like negation and numeric comparisons.
200 peer: a string (or sequence of strings) with the name(s) of peers
201 to filter - or None for local nodes.
203 if fields is not None:
204 fieldstuple = (fields,)
207 if nodeIdOrName is not None:
208 return _retry(self.mcapi.GetNodes)(self.auth, nodeIdOrName, *fieldstuple)
210 filters = kw.pop('filters',{})
213 peer = kw.pop('peer')
215 nameToId = self.peer_map.get
217 if hasattr(peer, '__iter__'):
218 # we can't mix local and external nodes, so
219 # split and re-issue recursively in that case
220 if None in peer or self._localPeerName in peer:
223 if self._localPeerName in peer:
224 peer.remove(self._localPeerName)
226 self.GetNodes(nodeIdOrName, fields, filters=filters, peer=peer, **kw)
227 + self.GetNodes(nodeIdOrName, fields, filters=filters, peer=None, **kw)
230 peer_filter = map(nameToId, peer)
231 elif peer is None or peer == self._localPeerName:
234 peer_filter = nameToId(peer)
236 filters['peer_id'] = peer_filter
239 return _retry(self.mcapi.GetNodes)(self.auth, filters, *fieldstuple)
241 def GetNodeTags(self, nodeTagId=None, fields=None, **kw):
242 if fields is not None:
243 fieldstuple = (fields,)
246 if nodeTagId is not None:
247 return _retry(self.mcapi.GetNodeTags)(self.auth, nodeTagId, *fieldstuple)
249 filters = kw.pop('filters',{})
251 return _retry(self.mcapi.GetNodeTags)(self.auth, filters, *fieldstuple)
253 def GetSliceTags(self, sliceTagId=None, fields=None, **kw):
254 if fields is not None:
255 fieldstuple = (fields,)
258 if sliceTagId is not None:
259 return _retry(self.mcapi.GetSliceTags)(self.auth, sliceTagId, *fieldstuple)
261 filters = kw.pop('filters',{})
263 return _retry(self.mcapi.GetSliceTags)(self.auth, filters, *fieldstuple)
266 def GetInterfaces(self, interfaceIdOrIp=None, fields=None, **kw):
267 if fields is not None:
268 fieldstuple = (fields,)
271 if interfaceIdOrIp is not None:
272 return _retry(self.mcapi.GetInterfaces)(self.auth, interfaceIdOrIp, *fieldstuple)
274 filters = kw.pop('filters',{})
276 return _retry(self.mcapi.GetInterfaces)(self.auth, filters, *fieldstuple)
278 def GetSlices(self, sliceIdOrName=None, fields=None, **kw):
279 if fields is not None:
280 fieldstuple = (fields,)
283 if sliceIdOrName is not None:
284 return _retry(self.mcapi.GetSlices)(self.auth, sliceIdOrName, *fieldstuple)
286 filters = kw.pop('filters',{})
288 return _retry(self.mcapi.GetSlices)(self.auth, filters, *fieldstuple)
290 def UpdateSlice(self, sliceIdOrName, **kw):
291 return _retry(self.mcapi.UpdateSlice)(self.auth, sliceIdOrName, kw)
294 def StartMulticall(self):
295 self.threadlocal.mc = xmlrpclib.MultiCall(self.mcapi)
297 def FinishMulticall(self):
298 mc = self.threadlocal.mc
299 del self.threadlocal.mc