python3 - 2to3 + miscell obvious tweaks
[sfa.git] / sfa / dummy / dummyaggregate.py
index 4630033..fcdca5d 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 from sfa.util.xrn import Xrn, hrn_to_urn, urn_to_hrn
 from sfa.util.sfatime import utcparse, datetime_to_string
 from sfa.util.sfalogging import logger
@@ -19,8 +19,10 @@ from sfa.rspecs.version_manager import VersionManager
 
 from sfa.dummy.dummyxrn import DummyXrn, hostname_to_urn, hrn_to_dummy_slicename, slicename_to_hrn
 
+from sfa.storage.model import SliverAllocation
 import time
 
+
 class DummyAggregate:
 
     def __init__(self, driver):
@@ -41,86 +43,255 @@ class DummyAggregate:
         if not slices:
             return (slice, slivers)
         slice = slices[0]
-        
-        # sort slivers by node id 
+
+        # sort slivers by node id
         slice_nodes = []
-        if 'node_ids' in slice.keys():
-            slice_nodes = self.driver.shell.GetNodes({'node_ids': slice['node_ids']}) 
+        if 'node_ids' in list(slice.keys()):
+            slice_nodes = self.driver.shell.GetNodes(
+                {'node_ids': slice['node_ids']})
         for node in slice_nodes:
-            slivers[node['node_id']] = node  
+            slivers[node['node_id']] = node
 
         return (slice, slivers)
 
-    def get_nodes(self, slice_xrn, slice=None,slivers=[], options={}):
-        # if we are dealing with a slice that has no node just return 
-        # and empty list    
-        if slice_xrn:
-            if not slice or 'node_ids' not in slice.keys() or not slice['node_ids']:
-                return []
+    def get_nodes(self, options=None):
+        if options is None:
+            options = {}
+        filter = {}
+        nodes = self.driver.shell.GetNodes(filter)
+        return nodes
+
+    def get_slivers(self, urns, options=None):
+        if options is None:
+            options = {}
+        slice_names = set()
+        slice_ids = set()
+        node_ids = []
+        for urn in urns:
+            xrn = DummyXrn(xrn=urn)
+            if xrn.type == 'sliver':
+                 # id: slice_id-node_id
+                try:
+                    sliver_id_parts = xrn.get_sliver_id_parts()
+                    slice_id = int(sliver_id_parts[0])
+                    node_id = int(sliver_id_parts[1])
+                    slice_ids.add(slice_id)
+                    node_ids.append(node_id)
+                except ValueError:
+                    pass
+            else:
+                slice_names.add(xrn.dummy_slicename())
 
         filter = {}
-        if slice and 'node_ids' in slice and slice['node_ids']:
-            filter['node_ids'] = slice['node_ids']
+        if slice_names:
+            filter['slice_name'] = list(slice_names)
+        if slice_ids:
+            filter['slice_id'] = list(slice_ids)
+        # get slices
+        slices = self.driver.shell.GetSlices(filter)
+        if not slices:
+            return []
+        slice = slices[0]
+        slice['hrn'] = DummyXrn(auth=self.driver.hrn,
+                                slicename=slice['slice_name']).hrn
+
+        # get sliver users
+        users = []
+        user_ids = []
+        for slice in slices:
+            if 'user_ids' in list(slice.keys()):
+                user_ids.extend(slice['user_ids'])
+        if user_ids:
+            users = self.driver.shell.GetUsers({'user_ids': user_ids})
+
+        # construct user key info
+        users_list = []
+        for user in users:
+            name = user['email'][0:user['email'].index('@')]
+            user = {
+                'login': slice['slice_name'],
+                'user_urn': Xrn('%s.%s' % (self.driver.hrn, name), type='user').urn,
+                'keys': user['keys']
+            }
+            users_list.append(user)
 
+        if node_ids:
+            node_ids = [
+                node_id for node_id in node_ids if node_id in slice['node_ids']]
+            slice['node_ids'] = node_ids
+        nodes_dict = self.get_slice_nodes(slice, options)
+        slivers = []
+        for node in list(nodes_dict.values()):
+            node.update(slice)
+            sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
+                                       slice['slice_id'], node['node_id'])
+            node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn
+            node['urn'] = node['sliver_id']
+            node['services_user'] = users
+            slivers.append(node)
+        return slivers
+
+    def node_to_rspec_node(self, node, options=None):
+        if options is None:
+            options = {}
+        rspec_node = NodeElement()
+        site = self.driver.testbedInfo
+        rspec_node['component_id'] = hostname_to_urn(
+            self.driver.hrn, site['name'], node['hostname'])
+        rspec_node['component_name'] = node['hostname']
+        rspec_node['component_manager_id'] = Xrn(
+            self.driver.hrn, 'authority+cm').get_urn()
+        rspec_node['authority_id'] = hrn_to_urn(DummyXrn.site_hrn(
+            self.driver.hrn, site['name']), 'authority+sa')
+        # distinguish between Shared and Reservable nodes
+        rspec_node['exclusive'] = 'false'
+
+        rspec_node['hardware_types'] = [HardwareType({'name': 'dummy-pc'}),
+                                        HardwareType({'name': 'pc'})]
+        if site['longitude'] and site['latitude']:
+            location = Location({'longitude': site['longitude'], 'latitude': site[
+                                'latitude'], 'country': 'unknown'})
+            rspec_node['location'] = location
+        return rspec_node
+
+    def sliver_to_rspec_node(self, sliver, sliver_allocations):
+        rspec_node = self.node_to_rspec_node(sliver)
+        rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires']))
+        # add sliver info
+        rspec_sliver = Sliver({'sliver_id': sliver['urn'],
+                               'name': sliver['slice_name'],
+                               'type': 'dummy-vserver',
+                               'tags': []})
+        rspec_node['sliver_id'] = rspec_sliver['sliver_id']
+        if sliver['urn'] in sliver_allocations:
+            rspec_node['client_id'] = sliver_allocations[
+                sliver['urn']].client_id
+            if sliver_allocations[sliver['urn']].component_id:
+                rspec_node['component_id'] = sliver_allocations[
+                    sliver['urn']].component_id
+        rspec_node['slivers'] = [rspec_sliver]
+
+        # slivers always provide the ssh service
+        login = Login({'authentication': 'ssh-keys',
+                       'hostname': sliver['hostname'],
+                       'port': '22',
+                       'username': sliver['slice_name'],
+                       'login': sliver['slice_name']
+                       })
+        return rspec_node
+
+    def get_slice_nodes(self, slice, options=None):
+        if options is None:
+            options = {}
+        nodes_dict = {}
+        filter = {}
+        if slice and slice.get('node_ids'):
+            filter['node_ids'] = slice['node_ids']
+        else:
+            # there are no nodes to look up
+            return nodes_dict
         nodes = self.driver.shell.GetNodes(filter)
-        
+        for node in nodes:
+            nodes_dict[node['node_id']] = node
+        return nodes_dict
+
+    def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations=None):
+        if sliver_allocations is None:
+            sliver_allocations = {}
+        if rspec_node['sliver_id'] in sliver_allocations:
+            # set sliver allocation and operational status
+            sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
+            if sliver_allocation:
+                allocation_status = sliver_allocation.allocation_state
+                if allocation_status == 'geni_allocated':
+                    op_status = 'geni_pending_allocation'
+                elif allocation_status == 'geni_provisioned':
+                    op_status = 'geni_ready'
+                else:
+                    op_status = 'geni_unknown'
+            else:
+                allocation_status = 'geni_unallocated'
+        else:
+            allocation_status = 'geni_unallocated'
+            op_status = 'geni_failed'
+        # required fields
+        geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'],
+                       'geni_expires': rspec_node['expires'],
+                       'geni_allocation_status': allocation_status,
+                       'geni_operational_status': op_status,
+                       'geni_error': '',
+                       }
+        return geni_sliver
+
+    def list_resources(self, version=None, options=None):
+        if options is None:
+            options = {}
+
+        version_manager = VersionManager()
+        version = version_manager.get_version(version)
+        rspec_version = version_manager._get_version(
+            version.type, version.version, 'ad')
+        rspec = RSpec(version=rspec_version, user_options=options)
+
+        # get nodes
+        nodes = self.get_nodes(options)
+        nodes_dict = {}
+        for node in nodes:
+            nodes_dict[node['node_id']] = node
+
+        # convert nodes to rspec nodes
         rspec_nodes = []
         for node in nodes:
-            rspec_node = NodeElement()
-            # xxx how to retrieve site['login_base']
-            site=self.driver.testbedInfo
-            rspec_node['component_id'] = hostname_to_urn(self.driver.hrn, site['name'], node['hostname'])
-            rspec_node['component_name'] = node['hostname']
-            rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
-            rspec_node['authority_id'] = hrn_to_urn(DummyXrn.site_hrn(self.driver.hrn, site['name']), 'authority+sa')
-            rspec_node['exclusive'] = 'false'
-            rspec_node['hardware_types'] = [HardwareType({'name': 'plab-pc'}),
-                                            HardwareType({'name': 'pc'})]
-             # add site/interface info to nodes.
-            # assumes that sites, interfaces and tags have already been prepared.
-            if site['longitude'] and site['latitude']:  
-                location = Location({'longitude': site['longitude'], 'latitude': site['latitude'], 'country': 'unknown'})
-                rspec_node['location'] = location
-
-            if node['node_id'] in slivers:
-                # add sliver info
-                sliver = slivers[node['node_id']]
-                rspec_node['client_id'] = node['hostname']
-                rspec_node['slivers'] = [sliver]
-                
-                # slivers always provide the ssh service
-                login = Login({'authentication': 'ssh-keys', 'hostname': node['hostname'], 'port':'22', 'username': slice['slice_name']})
-                service = ServicesElement({'login': login})
-                rspec_node['services'] = [service]
+            rspec_node = self.node_to_rspec_node(node)
             rspec_nodes.append(rspec_node)
-        return rspec_nodes
-             
+        rspec.version.add_nodes(rspec_nodes)
 
-    
-    def get_rspec(self, slice_xrn=None, version = None, options={}):
+        return rspec.toxml()
 
+    def describe(self, urns, version=None, options=None):
+        if options is None:
+            options = {}
         version_manager = VersionManager()
         version = version_manager.get_version(version)
-        if not slice_xrn:
-            rspec_version = version_manager._get_version(version.type, version.version, 'ad')
+        rspec_version = version_manager._get_version(
+            version.type, version.version, 'manifest')
+        rspec = RSpec(version=rspec_version, user_options=options)
+
+        # get slivers
+        geni_slivers = []
+        slivers = self.get_slivers(urns, options)
+        if slivers:
+            rspec_expires = datetime_to_string(utcparse(slivers[0]['expires']))
         else:
-            rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
+            rspec_expires = datetime_to_string(utcparse(time.time()))
+        rspec.xml.set('expires',  rspec_expires)
 
-        slice, slivers = self.get_slice_and_slivers(slice_xrn)
-        rspec = RSpec(version=rspec_version, user_options=options)
-        if slice and 'expires' in slice:
-            rspec.xml.set('expires',  datetime_to_string(utcparse(slice['expires'])))
-
-        nodes = self.get_nodes(slice_xrn, slice, slivers, options)
-        rspec.version.add_nodes(nodes)
-        # add sliver defaults
-        default_sliver = slivers.get(None, [])
-        if default_sliver:
-            default_sliver_attribs = default_sliver.get('tags', [])
-            for attrib in default_sliver_attribs:
-                 logger.info(attrib)
-                 rspec.version.add_default_sliver_attribute(attrib['tagname'], attrib['value'])
-        
-        return rspec.toxml()
+        # lookup the sliver allocations
+        geni_urn = urns[0]
+        sliver_ids = [sliver['sliver_id'] for sliver in slivers]
+        constraint = SliverAllocation.sliver_id.in_(sliver_ids)
+        sliver_allocations = self.driver.api.dbsession().query(
+            SliverAllocation).filter(constraint)
+        sliver_allocation_dict = {}
+        for sliver_allocation in sliver_allocations:
+            geni_urn = sliver_allocation.slice_urn
+            sliver_allocation_dict[
+                sliver_allocation.sliver_id] = sliver_allocation
 
+        # add slivers
+        nodes_dict = {}
+        for sliver in slivers:
+            nodes_dict[sliver['node_id']] = sliver
+        rspec_nodes = []
+        for sliver in slivers:
+            rspec_node = self.sliver_to_rspec_node(
+                sliver, sliver_allocation_dict)
+            rspec_nodes.append(rspec_node)
+            geni_sliver = self.rspec_node_to_geni_sliver(
+                rspec_node, sliver_allocation_dict)
+            geni_slivers.append(geni_sliver)
+        rspec.version.add_nodes(rspec_nodes)
 
+        return {'geni_urn': geni_urn,
+                'geni_rspec': rspec.toxml(),
+                'geni_slivers': geni_slivers}