add backward compatible SliceGetTicket and SliceTicketGet functions for Emulab during...
authorMark Huang <mlhuang@cs.princeton.edu>
Sat, 3 Feb 2007 23:35:06 +0000 (23:35 +0000)
committerMark Huang <mlhuang@cs.princeton.edu>
Sat, 3 Feb 2007 23:35:06 +0000 (23:35 +0000)
PLC/Methods/SliceGetTicket.py [new file with mode: 0644]
PLC/Methods/SliceTicketGet.py [new file with mode: 0644]
PLC/Methods/__init__.py

diff --git a/PLC/Methods/SliceGetTicket.py b/PLC/Methods/SliceGetTicket.py
new file mode 100644 (file)
index 0000000..33043ca
--- /dev/null
@@ -0,0 +1,249 @@
+import os
+import sys
+from subprocess import Popen, PIPE, call
+from tempfile import NamedTemporaryFile
+from xml.sax.saxutils import escape, quoteattr, XMLGenerator
+
+from PLC.Faults import *
+from PLC.Slices import Slice, Slices
+from PLC.Nodes import Node, Nodes
+from PLC.Persons import Person, Persons
+from PLC.SliceAttributes import SliceAttribute, SliceAttributes
+
+from PLC.Methods.GetSliceTicket import GetSliceTicket
+
+class PrettyXMLGenerator(XMLGenerator):
+    """
+    Adds indentation to the beginning and newlines to the end of
+    opening and closing tags.
+    """
+
+    def __init__(self, out = sys.stdout, encoding = "utf-8", indent = "", addindent = "", newl = ""):
+        XMLGenerator.__init__(self, out, encoding)
+        # XMLGenerator does not export _write()
+        self.write = self.ignorableWhitespace
+        self.indents = [indent]
+        self.addindent = addindent
+        self.newl = newl
+
+    def startDocument(self):
+        XMLGenerator.startDocument(self)
+
+    def startElement(self, name, attrs, indent = True, newl = True):
+        if indent:
+            self.ignorableWhitespace("".join(self.indents))
+        self.indents.append(self.addindent)
+
+        XMLGenerator.startElement(self, name, attrs)
+
+        if newl:
+            self.ignorableWhitespace(self.newl)
+
+    def characters(self, content):
+        # " to &quot;
+        # ' to &apos;
+        self.write(escape(content, {
+            '"': '&quot;',
+            "'": '&apos;',
+            }))
+
+    def endElement(self, name, indent = True, newl = True):
+        self.indents.pop()
+        if indent:
+            self.ignorableWhitespace("".join(self.indents))
+
+        XMLGenerator.endElement(self, name)
+
+        if newl:
+            self.ignorableWhitespace(self.newl)
+
+    def simpleElement(self, name, attrs = {}, indent = True, newl = True):
+        if indent:
+            self.ignorableWhitespace("".join(self.indents))
+
+        self.write('<' + name)
+        for (name, value) in attrs.items():
+            self.write(' %s=%s' % (name, quoteattr(value)))
+        self.write('/>')
+
+        if newl:
+            self.ignorableWhitespace(self.newl)
+
+class SliceGetTicket(GetSliceTicket):
+    """
+    Deprecated. See GetSliceTicket.
+
+    Warning: This function exists solely for backward compatibility
+    with the old public PlanetLab 3.0 Node Manager, which will be
+    removed from service by 2007. This call is not intended to be used
+    by any other PLC except the public PlanetLab.
+    """
+
+    status = "deprecated"
+
+    def call(self, auth, slice_id_or_name):
+        slices = Slices(self.api, [slice_id_or_name])
+        if not slices:
+            raise PLCInvalidArgument, "No such slice"
+        slice = slices[0]
+
+        # Allow peers to obtain tickets for their own slices
+        if slice['peer_id'] is not None:
+            raise PLCInvalidArgument, "Not a local slice"
+
+        if slice['instantiation'] != 'delegated':
+            raise PLCInvalidArgument, "Not in delegated state"
+
+        nodes = Nodes(self.api, slice['node_ids']).dict()
+        persons = Persons(self.api, slice['person_ids']).dict()
+        slice_attributes = SliceAttributes(self.api, slice['slice_attribute_ids']).dict()
+
+        ticket = NamedTemporaryFile()
+
+        xml = PrettyXMLGenerator(out = ticket, encoding = self.api.encoding, indent = "", addindent = "  ", newl = "\n")
+        xml.startDocument()
+
+        # <ticket>
+        xml.startElement('ticket', {})
+
+        # <slice name="site_slice" id="12345" expiry="1138712648">
+        xml.startElement('slice',
+                         {'id': str(slice['slice_id']),
+                          'name': unicode(slice['name']),
+                          'expiry': unicode(int(slice['expires']))})
+        
+        # <nodes>
+        xml.startElement('nodes', {})
+        for node_id in slice['node_ids']:
+            if not nodes.has_key(node_id):
+                continue
+            node = nodes[node_id]
+            # <node id="12345" hostname="node.site.domain"/>
+            xml.simpleElement('node',
+                              {'id': str(node['node_id']),
+                               'hostname': unicode(node['hostname'])})
+        # </nodes>
+        xml.endElement('nodes')
+
+        # <users>
+        xml.startElement('users', {})
+        for person_id in slice['person_ids']:
+            if not persons.has_key(person_id):
+                continue
+            user = persons[person_id]
+            # <user person_id="12345" email="user@site.domain"/>
+            xml.simpleElement('user',
+                              {'person_id': unicode(user['person_id']),
+                               'email': unicode(user['email'])})
+        # </users>
+        xml.endElement('users')
+
+        # <rspec>
+        xml.startElement('rspec', {})
+        for slice_attribute_id in slice['slice_attribute_ids']:
+            if not slice_attributes.has_key(slice_attribute_id):
+                continue
+            slice_attribute = slice_attributes[slice_attribute_id]
+
+            name = slice_attribute['name']
+            value = slice_attribute['value']
+
+            def kbps_to_bps(kbps):
+                bps = int(kbps) * 1000
+                return bps
+
+            def max_kbyte_to_bps(max_kbyte):
+                bps = int(max_kbyte) * 1000 * 8 / 24 / 60 / 60
+                return bps
+
+            # XXX Used to support multiple named values for each attribute type
+            name_type_cast = {
+                'cpu_share': ('nm_cpu_share', 'cpu_share', 'integer', int),
+
+                'net_share': ('nm_net_share', 'rate', 'integer', int),
+                'net_min_rate': ('nm_net_min_rate', 'rate', 'integer', int),
+                'net_max_rate': ('nm_net_max_rate', 'rate', 'integer', int),
+                'net_max_kbyte': ('nm_net_avg_rate', 'rate', 'integer', max_kbyte_to_bps),
+
+                'net_i2_share': ('nm_net_exempt_share', 'rate', 'integer', int),
+                'net_i2_min_rate': ('nm_net_exempt_min_rate', 'rate', 'integer', kbps_to_bps),
+                'net_i2_max_rate': ('nm_net_exempt_max_rate', 'rate', 'integer', kbps_to_bps),
+                'net_i2_max_kbyte': ('nm_net_exempt_avg_rate', 'rate', 'integer', max_kbyte_to_bps),
+
+                'disk_max': ('nm_disk_quota', 'quota', 'integer', int),
+                'plc_agent_version': ('plc_agent_version', 'version', 'string', str),
+                'plc_slice_type': ('plc_slice_type', 'type', 'string', str),
+                'plc_ticket_pubkey': ('plc_ticket_pubkey', 'key', 'string', str),
+                }
+
+            if name == 'initscript':
+                (attribute_name, value_name, type) = ('initscript', 'initscript_id', 'integer')
+                value = slice_attribute['slice_attribute_id']
+            elif name in name_type_cast:
+                (attribute_name, value_name, type, cast) = name_type_cast[name]
+                value = cast(value)
+            else:
+                attribute_name = value_name = name
+                type = "string"
+
+            # <resource name="slice_attribute_type">
+            xml.startElement('resource', {'name': unicode(attribute_name)})
+
+            # <value name="element_name" type="element_type">
+            xml.startElement('value',
+                             {'name': unicode(value_name),
+                              'type': type},
+                             newl = False)
+            # element value
+            xml.characters(unicode(value))
+            # </value>
+            xml.endElement('value', indent = False)
+
+            # </resource>
+            xml.endElement('resource')
+        # </rspec>
+        xml.endElement('rspec')
+
+        # </slice>
+        xml.endElement('slice')
+
+        # Add signature template
+        xml.startElement('Signature', {'xmlns': "http://www.w3.org/2000/09/xmldsig#"})
+        xml.startElement('SignedInfo', {})
+        xml.simpleElement('CanonicalizationMethod', {'Algorithm': "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"})
+        xml.simpleElement('SignatureMethod', {'Algorithm': "http://www.w3.org/2000/09/xmldsig#rsa-sha1"})
+        xml.startElement('Reference', {'URI': ""})
+        xml.startElement('Transforms', {})
+        xml.simpleElement('Transform', {'Algorithm': "http://www.w3.org/2000/09/xmldsig#enveloped-signature"})
+        xml.endElement('Transforms')
+        xml.simpleElement('DigestMethod', {'Algorithm': "http://www.w3.org/2000/09/xmldsig#sha1"})
+        xml.simpleElement('DigestValue', {})
+        xml.endElement('Reference')
+        xml.endElement('SignedInfo')
+        xml.simpleElement('SignatureValue', {})
+        xml.endElement('Signature')
+
+        xml.endElement('ticket')
+        xml.endDocument()
+
+        if not hasattr(self.api.config, 'PLC_API_TICKET_KEY') or \
+           not os.path.exists(self.api.config.PLC_API_TICKET_KEY):
+            raise PLCAPIError, "Slice ticket signing key not found"
+
+        ticket.flush()
+
+        # Sign the ticket
+        p = Popen(["xmlsec1", "--sign",
+                   "--privkey-pem", self.api.config.PLC_API_TICKET_KEY,
+                   ticket.name],
+                  stdin = PIPE, stdout = PIPE, stderr = PIPE)
+        signed_ticket = p.stdout.read()
+        err = p.stderr.read()
+        rc = p.wait()
+
+        ticket.close()
+
+        if rc:
+            raise PLCAPIError, err
+
+        return signed_ticket
diff --git a/PLC/Methods/SliceTicketGet.py b/PLC/Methods/SliceTicketGet.py
new file mode 100644 (file)
index 0000000..5b2b786
--- /dev/null
@@ -0,0 +1,13 @@
+from PLC.Methods.SliceGetTicket import SliceGetTicket
+
+class SliceTicketGet(SliceGetTicket):
+    """
+    Deprecated. See GetSliceTicket.
+
+    Warning: This function exists solely for backward compatibility
+    with the old public PlanetLab 3.0 Node Manager, which will be
+    removed from service by 2007. This call is not intended to be used
+    by any other PLC except the public PlanetLab.
+    """
+
+    status = "deprecated"
index 539fe24..08bf496 100644 (file)
@@ -1 +1 @@
-methods = 'AddAddressType AddAddressTypeToAddress AddBootState AddConfFile AddConfFileToNodeGroup AddConfFileToNode AddKeyType AddMessage AddNetworkMethod AddNetworkType AddNodeGroup AddNodeNetwork AddNode AddNodeToNodeGroup AddNodeToPCU AddPCU AddPeer AddPersonKey AddPerson AddPersonToSite AddPersonToSlice AddRole AddRoleToPerson AddSiteAddress AddSite AddSliceAttribute AddSliceAttributeType AddSliceInstantiation AddSlice AddSliceToNodes AdmAddAddressType AdmAddNodeGroup AdmAddNodeNetwork AdmAddNode AdmAddNodeToNodeGroup AdmAddPersonKey AdmAddPerson AdmAddPersonToSite AdmAddSitePowerControlUnit AdmAddSite AdmAssociateNodeToPowerControlUnitPort AdmAuthCheck AdmDeleteAddressType AdmDeleteAllPersonKeys AdmDeleteNodeGroup AdmDeleteNodeNetwork AdmDeleteNode AdmDeletePersonKeys AdmDeletePerson AdmDeleteSitePowerControlUnit AdmDeleteSite AdmDisassociatePowerControlUnitPort AdmGenerateNodeConfFile AdmGetAllAddressTypes AdmGetAllKeyTypes AdmGetAllNodeNetworks AdmGetAllRoles AdmGetNodeGroupNodes AdmGetNodeGroups AdmGetNodes AdmGetPersonKeys AdmGetPersonRoles AdmGetPersonSites AdmGetPersons AdmGetPowerControlUnitNodes AdmGetPowerControlUnits AdmGetSiteNodes AdmGetSitePersons AdmGetSitePIs AdmGetSitePowerControlUnits AdmGetSites AdmGetSiteTechContacts AdmGrantRoleToPerson AdmIsPersonInRole AdmQueryConfFile AdmQueryNode AdmQueryPerson AdmQueryPowerControlUnit AdmQuerySite AdmRebootNode AdmRemoveNodeFromNodeGroup AdmRemovePersonFromSite AdmRevokeRoleFromPerson AdmSetPersonEnabled AdmSetPersonPrimarySite AdmUpdateNodeGroup AdmUpdateNodeNetwork AdmUpdateNode AdmUpdatePerson AdmUpdateSitePowerControlUnit AdmUpdateSite AuthCheck BlacklistKey BootCheckAuthentication BootGetNodeDetails BootNotifyOwners BootUpdateNode DeleteAddress DeleteAddressTypeFromAddress DeleteAddressType DeleteBootState DeleteConfFileFromNodeGroup DeleteConfFileFromNode DeleteConfFile DeleteKey DeleteKeyType DeleteMessage DeleteNetworkMethod DeleteNetworkType DeleteNodeFromNodeGroup DeleteNodeFromPCU DeleteNodeGroup DeleteNodeNetwork DeleteNode DeletePCU DeletePeer DeletePersonFromSite DeletePersonFromSlice DeletePerson DeleteRoleFromPerson DeleteRole DeleteSession DeleteSite DeleteSliceAttribute DeleteSliceAttributeType DeleteSliceFromNodes DeleteSliceInstantiation DeleteSlice GetAddresses GetAddressTypes GetBootStates GetConfFiles GetEvents GetKeys GetKeyTypes GetMessages GetNetworkMethods GetNetworkTypes GetNodeGroups GetNodeNetworks GetNodes GetPCUs GetPeerData GetPeerName GetPeers GetPersons GetRoles GetSession GetSites GetSliceAttributes GetSliceAttributeTypes GetSliceInstantiations GetSlices GetSliceTicket GetSlivers NotifyPersons RebootNode RefreshPeer ResetPassword SetPersonPrimarySite SliceCreate SliceDelete SliceExtendedInfo SliceInfo SliceListNames SliceListUserSlices SliceNodesAdd SliceNodesDel SliceNodesList SliceRenew SliceUpdate SliceUserAdd SliceUserDel SliceUsersList UpdateAddress UpdateAddressType UpdateConfFile UpdateKey UpdateMessage UpdateNodeGroup UpdateNodeNetwork UpdateNode UpdatePCU UpdatePeer UpdatePerson UpdateSite UpdateSliceAttribute UpdateSliceAttributeType UpdateSlice VerifyPerson  system.listMethods  system.methodHelp  system.methodSignature  system.multicall'.split()
+methods = 'AddAddressType AddAddressTypeToAddress AddBootState AddConfFile AddConfFileToNodeGroup AddConfFileToNode AddKeyType AddMessage AddNetworkMethod AddNetworkType AddNodeGroup AddNodeNetwork AddNode AddNodeToNodeGroup AddNodeToPCU AddPCU AddPeer AddPersonKey AddPerson AddPersonToSite AddPersonToSlice AddRole AddRoleToPerson AddSiteAddress AddSite AddSliceAttribute AddSliceAttributeType AddSliceInstantiation AddSlice AddSliceToNodes AdmAddAddressType AdmAddNodeGroup AdmAddNodeNetwork AdmAddNode AdmAddNodeToNodeGroup AdmAddPersonKey AdmAddPerson AdmAddPersonToSite AdmAddSitePowerControlUnit AdmAddSite AdmAssociateNodeToPowerControlUnitPort AdmAuthCheck AdmDeleteAddressType AdmDeleteAllPersonKeys AdmDeleteNodeGroup AdmDeleteNodeNetwork AdmDeleteNode AdmDeletePersonKeys AdmDeletePerson AdmDeleteSitePowerControlUnit AdmDeleteSite AdmDisassociatePowerControlUnitPort AdmGenerateNodeConfFile AdmGetAllAddressTypes AdmGetAllKeyTypes AdmGetAllNodeNetworks AdmGetAllRoles AdmGetNodeGroupNodes AdmGetNodeGroups AdmGetNodes AdmGetPersonKeys AdmGetPersonRoles AdmGetPersonSites AdmGetPersons AdmGetPowerControlUnitNodes AdmGetPowerControlUnits AdmGetSiteNodes AdmGetSitePersons AdmGetSitePIs AdmGetSitePowerControlUnits AdmGetSites AdmGetSiteTechContacts AdmGrantRoleToPerson AdmIsPersonInRole AdmQueryConfFile AdmQueryNode AdmQueryPerson AdmQueryPowerControlUnit AdmQuerySite AdmRebootNode AdmRemoveNodeFromNodeGroup AdmRemovePersonFromSite AdmRevokeRoleFromPerson AdmSetPersonEnabled AdmSetPersonPrimarySite AdmUpdateNodeGroup AdmUpdateNodeNetwork AdmUpdateNode AdmUpdatePerson AdmUpdateSitePowerControlUnit AdmUpdateSite AuthCheck BlacklistKey BootCheckAuthentication BootGetNodeDetails BootNotifyOwners BootUpdateNode DeleteAddress DeleteAddressTypeFromAddress DeleteAddressType DeleteBootState DeleteConfFileFromNodeGroup DeleteConfFileFromNode DeleteConfFile DeleteKey DeleteKeyType DeleteMessage DeleteNetworkMethod DeleteNetworkType DeleteNodeFromNodeGroup DeleteNodeFromPCU DeleteNodeGroup DeleteNodeNetwork DeleteNode DeletePCU DeletePeer DeletePersonFromSite DeletePersonFromSlice DeletePerson DeleteRoleFromPerson DeleteRole DeleteSession DeleteSite DeleteSliceAttribute DeleteSliceAttributeType DeleteSliceFromNodes DeleteSliceInstantiation DeleteSlice GetAddresses GetAddressTypes GetBootStates GetConfFiles GetEvents GetKeys GetKeyTypes GetMessages GetNetworkMethods GetNetworkTypes GetNodeGroups GetNodeNetworks GetNodes GetPCUs GetPeerData GetPeerName GetPeers GetPersons GetRoles GetSession GetSites GetSliceAttributes GetSliceAttributeTypes GetSliceInstantiations GetSlices GetSliceTicket GetSlivers NotifyPersons RebootNode RefreshPeer ResetPassword SetPersonPrimarySite SliceCreate SliceDelete SliceExtendedInfo SliceGetTicket SliceInfo SliceListNames SliceListUserSlices SliceNodesAdd SliceNodesDel SliceNodesList SliceRenew SliceTicketGet SliceUpdate SliceUserAdd SliceUserDel SliceUsersList UpdateAddress UpdateAddressType UpdateConfFile UpdateKey UpdateMessage UpdateNodeGroup UpdateNodeNetwork UpdateNode UpdatePCU UpdatePeer UpdatePerson UpdateSite UpdateSliceAttribute UpdateSliceAttributeType UpdateSlice VerifyPerson  system.listMethods  system.methodHelp  system.methodSignature  system.multicall'.split()