Merging patch to support https proxies when running experiments using PlanetLab,...
[nepi.git] / src / nepi / testbeds / planetlab / plcapi.py
index c4aa111..d1d7980 100644 (file)
@@ -16,6 +16,7 @@ def _retry(fn):
     return rv
 
 class PLCAPI(object):
+
     _expected_methods = set(
         ['AddNodeTag', 'AddConfFile', 'DeletePersonTag', 'AddNodeType', 'DeleteBootState', 'SliceListNames', 'DeleteKey', 
          'SliceGetTicket', 'SliceUsersList', 'SliceUpdate', 'GetNodeGroups', 'SliceCreate', 'GetNetworkMethods', 'GetNodeFlavour', 
@@ -71,7 +72,7 @@ class PLCAPI(object):
      
     _required_methods = set()
 
-    def __init__(self, username=None, password=None, sessionkey=None,
+    def __init__(self, username=None, password=None, sessionkey=None, proxy=None,
             hostname = "www.planet-lab.eu",
             urlpattern = "https://%(hostname)s:443/PLCAPI/",
             localPeerName = "PLE"):
@@ -84,6 +85,21 @@ class PLCAPI(object):
         
         self._localPeerName = localPeerName
         self._url = urlpattern % {'hostname':hostname}
+        if (proxy is not None):
+            import urllib2
+            class HTTPSProxyTransport(xmlrpclib.Transport):
+                def __init__(self, proxy, use_datetime=0):
+                    opener = urllib2.build_opener(urllib2.ProxyHandler({"https" : proxy}))
+                    xmlrpclib.Transport.__init__(self, use_datetime)
+                    self.opener = opener
+                def request(self, host, handler, request_body, verbose=0):
+                    req = urllib2.Request('https://%s%s' % (host, handler), request_body)
+                    req.add_header('User-agent', self.user_agent)
+                    self.verbose = verbose
+                    return self.parse_response(self.opener.open(req))
+            self._proxyTransport = lambda : HTTPSProxyTransport(proxy)
+        else:
+            self._proxyTransport = lambda : None
         
         self.threadlocal = threading.local()
     
@@ -92,6 +108,7 @@ class PLCAPI(object):
         # Cannot reuse same proxy in all threads, py2.7 is not threadsafe
         return xmlrpclib.ServerProxy(
             self._url ,
+            transport = self._proxyTransport(),
             allow_none = True)
         
     @property
@@ -261,7 +278,6 @@ class PLCAPI(object):
             filters = kw.pop('filters',{})
             filters.update(kw)
             return _retry(self.mcapi.GetSliceTags)(self.auth, filters, *fieldstuple)
-        
     
     def GetInterfaces(self, interfaceIdOrIp=None, fields=None, **kw):
         if fields is not None:
@@ -289,7 +305,6 @@ class PLCAPI(object):
         
     def UpdateSlice(self, sliceIdOrName, **kw):
         return _retry(self.mcapi.UpdateSlice)(self.auth, sliceIdOrName, kw)
-        
 
     def StartMulticall(self):
         self.threadlocal.mc = xmlrpclib.MultiCall(self.mcapi)
@@ -298,3 +313,51 @@ class PLCAPI(object):
         mc = self.threadlocal.mc
         del self.threadlocal.mc
         return _retry(mc)()
+
+    def GetSliceNodes(self, slicename):
+        return self.GetSlices(slicename, ['node_ids'])[0]['node_ids']
+
+    def AddSliceNodes(self, slicename,  nodes = None):
+        self.UpdateSlice(slicename, nodes = nodes)
+
+    def GetNodeInfo(self, node_id):
+        self.StartMulticall()
+        info = self.GetNodes(node_id)
+        tags = self.GetNodeTags(node_id=node_id, fields=('tagname','value'))
+        info, tags = self.FinishMulticall()
+        return info, tags
+
+    def GetSliceId(self, slicename):
+        slice_id = None
+        slices = self.GetSlices(slicename, fields=('slice_id',))
+        if slices:
+            slice_id = slices[0]['slice_id']
+        # If it wasn't found, don't remember this failure, keep trying
+        return slice_id
+
+    def GetSliceVnetSysTag(self, slicename):
+        slicetags = self.GetSliceTags(
+            name = slicename,
+            tagname = 'vsys_vnet',
+            fields=('value',))
+        if slicetags:
+            return slicetags[0]['value']
+        else:
+            return None
+def plcapi(auth_user, auth_string, plc_host, plc_url, proxy):
+    api = None
+    if auth_user:
+        api = PLCAPI(
+            username = auth_user,
+            password = auth_string,
+            hostname = plc_host,
+            urlpattern = plc_url,
+            proxy = proxy
+        )
+    else:
+        # anonymous access - may not be enough for much
+        api = PLCAPI()
+    return api
+
+