Esempio n. 1
0
    def update(self, old_sfa_record, new_sfa_record, hrn, new_key):
        type = new_sfa_record['type']

        # new_key implemented for users only
        if new_key and type not in ['user']:
            raise UnknownSfaType(type)

        elif type == "slice":
            # can update project manager and description
            name = hrn_to_os_slicename(hrn)
            researchers = sfa_record.get('researchers', [])
            pis = sfa_record.get('pis', [])
            project_manager = None
            description = sfa_record.get('description', None)
            if pis:
                project_manager = Xrn(pis[0], 'user').get_leaf()
            elif researchers:
                project_manager = Xrn(researchers[0], 'user').get_leaf()
            self.shell.auth_manager.modify_project(name, project_manager,
                                                   description)

        elif type == "user":
            # can techinally update access_key and secret_key,
            # but that is not in our scope, so we do nothing.
            pass
        return True
Esempio n. 2
0
    def register_slice(self, sfa_record, hrn):
        # add slice description, name, researchers, PI
        name = hrn_to_os_tenant_name(hrn)
        description = sfa_record.get('description', None)
        self.shell.auth_manager.tenants.create(name, description)
        tenant = self.shell.auth_manager.tenants.find(name=name)
        auth_hrn = OSXrn(xrn=hrn, type='slice').get_authority_hrn()
        parent_tenant_name = OSXrn(xrn=auth_hrn,
                                   type='slice').get_tenant_name()
        parent_tenant = self.shell.auth_manager.tenants.find(
            name=parent_tenant_name)
        researchers = sfa_record.get('researchers', [])
        for researcher in researchers:
            name = Xrn(researcher).get_leaf()
            user = self.shell.auth_manager.users.find(name=name)
            self.shell.auth_manager.roles.add_user_role(user, 'Member', tenant)
            self.shell.auth_manager.roles.add_user_role(user, 'user', tenant)

        pis = sfa_record.get('pis', [])
        for pi in pis:
            name = Xrn(pi).get_leaf()
            user = self.shell.auth_manager.users.find(name=name)
            self.shell.auth_manager.roles.add_user_role(user, 'pi', tenant)
            self.shell.auth_manager.roles.add_user_role(
                user, 'pi', parent_tenant)

        return tenant
Esempio n. 3
0
 def test_void(self):
     void = Xrn(xrn='', type=None)
     expected = 'urn:publicid:IDN++'
     self.assertEqual(void.get_hrn(), '')
     self.assertEqual(void.get_type(), None)
     self.assertEqual(void.get_urn(), expected)
     loop = Xrn(xrn=expected)
     self.assertEqual(loop.get_hrn(), '')
     # xxx - this is not quite right as the first object has type None
     self.assertEqual(loop.get_type(), '')
Esempio n. 4
0
 def __hrn(self, h, t, exp_urn):
     if verbose: print 'testing (', h, t, ') expecting', exp_urn
     xrn = Xrn(h, type=t)
     if verbose: print xrn.dump_string()
     urn = xrn.get_urn()
     (h1, t1) = Xrn(urn).get_hrn_type()
     if h1 != h or t1 != t or urn != exp_urn:
         print "hrn->urn->hrn : MISMATCH with in=(%s,%s) -- out=(%s,%s) -- urn=%s" % (
             h, t, h1, t1, urn)
     self.assertEqual(h1, h)
     self.assertEqual(t1, t)
     self.assertEqual(urn, exp_urn)
Esempio n. 5
0
    def check_sliver_credentials(self, creds, urns):
        # build list of cred object hrns
        slice_cred_names = []
        for cred in creds:
            slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn()
            slice_cred_names.append(
                DummyXrn(xrn=slice_cred_hrn).dummy_slicename())

        # look up slice name of slivers listed in urns arg
        slice_ids = []
        for urn in urns:
            sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
            try:
                slice_ids.append(int(sliver_id_parts[0]))
            except ValueError:
                pass

        if not slice_ids:
            raise Forbidden("sliver urn not provided")

        slices = self.shell.GetSlices({'slice_ids': slice_ids})
        sliver_names = [slice['slice_name'] for slice in slices]

        # make sure we have a credential for every specified sliver ierd
        for sliver_name in sliver_names:
            if sliver_name not in slice_cred_names:
                msg = "Valid credential not found for target: %s" % sliver_name
                raise Forbidden(msg)
Esempio n. 6
0
    def allocate(self, urn, rspec_string, expiration, options={}):
        xrn = Xrn(urn)
        aggregate = DummyAggregate(self)
        slices = DummySlices(self)
        slice_record = None
        users = options.get('geni_users', [])
        if users:
            slice_record = users[0].get('slice_record', {})

        # parse rspec
        rspec = RSpec(rspec_string)
        requested_attributes = rspec.version.get_slice_attributes()

        # ensure slice record exists
        slice = slices.verify_slice(xrn.hrn,
                                    slice_record,
                                    expiration=expiration,
                                    options=options)
        # ensure person records exists
        #persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options)

        # add/remove slice from nodes
        request_nodes = rspec.version.get_nodes_with_slivers()
        nodes = slices.verify_slice_nodes(urn, slice, request_nodes)

        return aggregate.describe([xrn.get_urn()], version=rspec.version)
Esempio n. 7
0
    def describe(self, urns, version=None, options={}):
        # update nova connection
        tenant_name = OSXrn(xrn=urns[0], type='slice').get_tenant_name()
        self.driver.shell.nova_manager.connect(tenant=tenant_name)
        instances = self.get_instances(urns)
        # lookup the sliver allocations
        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:
            sliver_allocation_dict[sliver_allocation.sliver_id] = sliver_allocation

        geni_slivers = []
        rspec_nodes = []
        for instance in instances:
            rspec_nodes.append(self.instance_to_rspec_node(instance))
            geni_sliver = self.instance_to_geni_sliver(instance, sliver_sllocation_dict)
            geni_slivers.append(geni_sliver)
        version_manager = VersionManager()
        version = version_manager.get_version(version)
        rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
        rspec = RSpec(version=rspec_version, user_options=options)
        rspec.xml.set('expires',  datetime_to_string(utcparse(time.time())))
        rspec.version.add_nodes(rspec_nodes)
        result = {'geni_urn': Xrn(urns[0]).get_urn(),
                  'geni_rspec': rspec.toxml(), 
                  'geni_slivers': geni_slivers}
        
        return result
Esempio n. 8
0
    def create_instance_key(self, slice_hrn, user):
        slice_name = Xrn(slice_hrn).leaf
        user_name = Xrn(user['urn']).leaf
        key_name = "%s_%s" % (slice_name, user_name)
        pubkey = user['keys'][0]
        key_found = False
        existing_keys = self.driver.shell.nova_manager.keypairs.findall(name=key_name)
        for existing_key in existing_keys:
            if existing_key.public_key != pubkey:
                self.driver.shell.nova_manager.keypairs.delete(existing_key)
            elif existing_key.public_key == pubkey:
                key_found = True

        if not key_found:
            self.driver.shell.nova_manager.keypairs.create(key_name, pubkey)
        return key_name       
Esempio n. 9
0
    def get_aggregate_nodes(self):
        zones = self.get_availability_zones()
        # available sliver/instance/vm types
        instances = self.driver.shell.nova_manager.flavors.list()
        if isinstance(instances, dict):
            instances = instances.values()
        # available images
        images = self.driver.shell.image_manager.get_images_detailed()
        disk_images  = [image_to_rspec_disk_image(img) for img in images if img['container_format'] in ['ami', 'ovf']]
        rspec_nodes = []
        for zone in zones:
            rspec_node = Node()
            xrn = OSXrn(zone, type='node')
            rspec_node['component_id'] = xrn.urn
            rspec_node['component_name'] = xrn.name
            rspec_node['component_manager_id'] = Xrn(self.driver.hrn, 'authority+cm').get_urn()
            rspec_node['exclusive'] = 'false'
            rspec_node['hardware_types'] = [HardwareType({'name': 'plos-pc'}),
                                                HardwareType({'name': 'pc'})]
            slivers = []
            for instance in instances:
                sliver = self.instance_to_sliver(instance)
                sliver['disk_image'] = disk_images
                slivers.append(sliver)
            rspec_node['available'] = 'true'
            rspec_node['slivers'] = slivers
            rspec_nodes.append(rspec_node) 

        return rspec_nodes 
Esempio n. 10
0
    def check_sliver_credentials(self, creds, urns):
        # build list of cred object hrns
        slice_cred_names = []
        for cred in creds:
            slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn()
            slice_cred_names.append(OSXrn(xrn=slice_cred_hrn).get_slicename())

        # look up slice name of slivers listed in urns arg
        slice_ids = []
        for urn in urns:
            sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
            slice_ids.append(sliver_id_parts[0])

        if not slice_ids:
            raise Forbidden("sliver urn not provided")

        sliver_names = []
        for slice_id in slice_ids:
            slice = self.shell.auth_manager.tenants.find(slice_id)
            sliver_names.append(slice['name'])

        # make sure we have a credential for every specified sliver ierd
        for sliver_name in sliver_names:
            if sliver_name not in slice_cred_names:
                msg = "Valid credential not found for target: %s" % sliver_name
                raise Forbidden(msg)
Esempio n. 11
0
    def urn_to_properties(value):
        # urn:publicid:IDN+omf:paris.fit-nitos.fr+node+node38
        # node38.paris.fit-nitos.fr
        #import pdb
        #pdb.set_trace()
        urn = value['component_id']
        hrn = Xrn(urn).get_hrn()
        t_urn = urn.split('+')
        authority = t_urn[1]
        if ':' in authority:
            t_authority = authority.split(':')
            authority = t_authority[1]
        host = t_urn[-1]
        hostname = host + '.' + authority
        if value['type'] == 'node' and 'available.now' in value:
            if value['available.now'] == 'true':
                boot = "boot"
            else:
                boot = "disabled"

            return {
                'exclusive': True,
                'hostname': hostname,
                'hrn': hrn,
                'urn': urn,
                'boot_state': boot
            }
        else:
            return {
                'exclusive': True,
                'hostname': hostname,
                'hrn': hrn,
                'urn': urn
            }
Esempio n. 12
0
    def delete(self, urns, options={}):
        # collect sliver ids so we can update sliver allocation states after
        # we remove the slivers.
        aggregate = OSAggregate(self)
        instances = aggregate.get_instances(urns)
        sliver_ids = []
        for instance in instances:
            sliver_hrn = "%s.%s" % (self.driver.hrn, instance.id)
            sliver_ids.append(Xrn(sliver_hrn, type='sliver').urn)

            # delete the instance
            aggregate.delete_instance(instance)

        # delete sliver allocation states
        dbsession = self.api.dbsession()
        SliverAllocation.delete_allocations(sliver_ids, dbsession)

        # return geni_slivers
        geni_slivers = []
        for sliver_id in sliver_ids:
            geni_slivers.append({
                'geni_sliver_urn': sliver['sliver_id'],
                'geni_allocation_status': 'geni_unallocated',
                'geni_expires': None
            })
        return geni_slivers
Esempio n. 13
0
 def register_user(self, sfa_record, hrn, pub_key):
     # add person roles, projects and keys
     email = sfa_record.get('email', None)
     xrn = Xrn(hrn)
     name = xrn.get_leaf()
     auth_hrn = xrn.get_authority_hrn()
     tenant_name = OSXrn(xrn=auth_hrn, type='authority').get_tenant_name()
     tenant = self.shell.auth_manager.tenants.find(name=tenant_name)
     self.shell.auth_manager.users.create(name,
                                          email=email,
                                          tenant_id=tenant.id)
     user = self.shell.auth_manager.users.find(name=name)
     slices = sfa_records.get('slices', [])
     for slice in projects:
         slice_tenant_name = OSXrn(xrn=slice,
                                   type='slice').get_tenant_name()
         slice_tenant = self.shell.auth_manager.tenants.find(
             name=slice_tenant_name)
         self.shell.auth_manager.roles.add_user_role(
             user, slice_tenant, 'user')
     keys = sfa_records.get('keys', [])
     for key in keys:
         keyname = OSXrn(xrn=hrn, type='user').get_slicename()
         self.shell.nova_client.keypairs.create(keyname, key)
     return user
Esempio n. 14
0
    def allocate(self, urn, rspec_string, expiration, options={}):
        xrn = Xrn(urn)
        aggregate = OSAggregate(self)

        # assume first user is the caller and use their context
        # for the ec2/euca api connection. Also, use the first users
        # key as the project key.
        key_name = None
        if len(users) > 1:
            key_name = aggregate.create_instance_key(xrn.get_hrn(), users[0])

        # collect public keys
        users = options.get('geni_users', [])
        pubkeys = []
        for user in users:
            pubkeys.extend(user['keys'])

        rspec = RSpec(rspec_string)
        instance_name = hrn_to_os_slicename(slice_hrn)
        tenant_name = OSXrn(xrn=slice_hrn, type='slice').get_tenant_name()
        slivers = aggregate.run_instances(instance_name, tenant_name, \
                                          rspec_string, key_name, pubkeys)

        # update all sliver allocation states setting then to geni_allocated
        sliver_ids = [sliver.id for sliver in slivers]
        dbsession = self.api.dbsession()
        SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned',
                                         dbsession)

        return aggregate.describe(urns=[urn], version=rspec.version)
Esempio n. 15
0
    def instance_to_geni_sliver(self, instance, sliver_allocations = {}):
        sliver_hrn = '%s.%s' % (self.driver.hrn, instance.id)
        sliver_id = Xrn(sliver_hrn, type='sliver').urn
 
        # set sliver allocation and operational status
        sliver_allocation = sliver_allocations[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':
                state = instance.state.lower()
                if state == 'active':
                    op_status = 'geni_ready'
                elif state == 'building':
                    op_status = 'geni_notready'
                elif state == 'failed':
                    op_status =' geni_failed'
                else:
                    op_status = 'geni_unknown'
            else:
                allocation_status = 'geni_unallocated'    
        # required fields
        geni_sliver = {'geni_sliver_urn': sliver_id, 
                       'geni_expires': None,
                       'geni_allocation_status': allocation_status,
                       'geni_operational_status': op_status,
                       'geni_error': None,
                       'plos_created_at': datetime_to_string(utcparse(instance.created)),
                       'plos_sliver_type': self.shell.nova_manager.flavors.find(id=instance.flavor['id']).name,
                        }

        return geni_sliver
Esempio n. 16
0
 def GetVersion(self, api, options):
     # peers explicitly in aggregates.xml
     peers =dict ([ (peername,interface.get_url()) for (peername,interface) in api.aggregates.iteritems()
                    if peername != api.hrn])
     version_manager = VersionManager()
     ad_rspec_versions = []
     request_rspec_versions = []
     cred_types = [{'geni_type': 'geni_sfa', 'geni_version': str(i)} for i in range(4)[-2:]]
     for rspec_version in version_manager.versions:
         if rspec_version.content_type in ['*', 'ad']:
             ad_rspec_versions.append(rspec_version.to_dict())
         if rspec_version.content_type in ['*', 'request']:
             request_rspec_versions.append(rspec_version.to_dict())
     xrn=Xrn(api.hrn, 'authority+sm')
     version_more = {
         'interface':'slicemgr',
         'sfa': 2,
         'geni_api': 3,
         'geni_api_versions': {'3': 'http://%s:%s' % (api.config.SFA_SM_HOST, api.config.SFA_SM_PORT)},
         'hrn' : xrn.get_hrn(),
         'urn' : xrn.get_urn(),
         'peers': peers,
         'geni_single_allocation': 0, # Accept operations that act on as subset of slivers in a given state.
         'geni_allocate': 'geni_many',# Multiple slivers can exist and be incrementally added, including those which connect or overlap in some way.
         'geni_credential_types': cred_types,
         }
     sm_version=version_core(version_more)
     # local aggregate if present needs to have localhost resolved
     if api.hrn in api.aggregates:
         local_am_url=api.aggregates[api.hrn].get_url()
         sm_version['peers'][api.hrn]=local_am_url.replace('localhost',sm_version['hostname'])
     return sm_version
Esempio n. 17
0
    def _process_node(cls, node):
        node['type'] = 'node'
        node['network_hrn'] = Xrn(node['component_id']).authority[0] # network ? XXX
        node['hrn'] = urn_to_hrn(node['component_id'])[0]
        node['urn'] = node['component_id']
        node['hostname'] = node['component_name']
        node['initscripts'] = node.pop('pl_initscripts')

        # All Labora nodes are exclusive = true
        node['exclusive'] = 'true'

        if 'granularity' in node:
            node['granularity'] = node['granularity']['grain']

        # XXX This should use a MAP as before
        if 'position' in node: # iotlab
            node['x'] = node['position']['posx']
            node['y'] = node['position']['posy']
            node['z'] = node['position']['posz']
            del node['position']

        if 'location' in node:
            if node['location']:
                node['latitude'] = node['location']['latitude']
                node['longitude'] = node['location']['longitude']
            del node['location']

        # Flatten tags
        if 'tags' in node:
            if node['tags']:
                for tag in node['tags']:
                    node[tag['tagname']] = tag['value']
            del node['tags']

        return node
Esempio n. 18
0
 def sliver_to_slice_xrn(self, xrn):
     sliver_id_parts = Xrn(xrn).get_sliver_id_parts()
     slice = self.shell.auth_manager.tenants.find(id=sliver_id_parts[0])
     if not slice:
         raise Forbidden("Unable to locate slice record for sliver:  %s" %
                         xrn)
     slice_xrn = OSXrn(name=slice.name, type='slice')
     return slice_xrn
Esempio n. 19
0
 def provision(self, xrn):
     """Provision slivers"""
     xrn = Xrn(xrn, 'slice')
     slice_urn = xrn.get_urn()
     options = {}
     manifest = self.api.manager.provision(self.api, [slice_urn], [],
                                           options)
     print manifest
Esempio n. 20
0
 def allocate(self, xrn, rspec):
     """Allocate slivers"""
     xrn = Xrn(xrn, 'slice')
     slice_urn = xrn.get_urn()
     rspec_string = open(rspec).read()
     options = {}
     manifest = self.api.manager.Allocate(self.api, slice_urn, [],
                                          rspec_string, options)
     print manifest
Esempio n. 21
0
def xrn_to_hostname(xrn):
    """Returns a node's hostname from its xrn.
    :param xrn: The nodes xrn identifier.
    :type xrn: Xrn (from sfa.util.xrn)

    :returns: node's hostname.
    :rtype: string

    """
    return Xrn.unescape(Xrn(xrn=xrn, type='node').get_leaf())
Esempio n. 22
0
 def GetVersion(self, api, options):
     peers = dict ( [ (hrn,interface.get_url()) for (hrn,interface) in api.registries.iteritems()
                    if hrn != api.hrn])
     xrn=Xrn(api.hrn)
     return version_core({'interface':'registry',
                          'sfa': 2,
                          'geni_api': 2,
                          'hrn':xrn.get_hrn(),
                          'urn':xrn.get_urn(),
                          'peers':peers})
Esempio n. 23
0
def type_of_urn(urn):
    """
    Returns the type of the given urn (node, slice, sliver)
    
    :param urn: URN to discover the type
    :type string
    
    :returns type of the URN (node, slice, sliver, user, authority)
    """
    return Xrn(urn).get_type()
Esempio n. 24
0
 def remove(self, sfa_record):
     type = sfa_record['type']
     if type == 'user':
         name = Xrn(sfa_record['hrn']).get_leaf()
         if self.shell.auth_manager.get_user(name):
             self.shell.auth_manager.delete_user(name)
     elif type == 'slice':
         name = hrn_to_os_slicename(sfa_record['hrn'])
         if self.shell.auth_manager.get_project(name):
             self.shell.auth_manager.delete_project(name)
     return True
Esempio n. 25
0
def hrn_to_authname (hrn):
    """
    Gets the authority name from an HRN
    
    :param hrn: HRN whose authority is got
    :type string

    :returns: authority name name.
    :rtype: string
    """
    return Xrn(xrn=hrn).get_authority_hrn()
Esempio n. 26
0
 def CreateGid(self, api, xrn, cert):
     # get the authority
     authority = Xrn(xrn=xrn).get_authority_hrn()
     auth_info = api.auth.get_auth_info(authority)
     if not cert:
         pkey = Keypair(create=True)
     else:
         certificate = Certificate(string=cert)
         pkey = certificate.get_pubkey()
     gid = api.auth.hierarchy.create_gid(xrn, create_uuid(), pkey)
     return gid.save_to_string(save_parents=True)
Esempio n. 27
0
 def _record_dict(self,
                  xrn=None,
                  type=None,
                  url=None,
                  description=None,
                  email='',
                  key=None,
                  slices=[],
                  researchers=[],
                  pis=[],
                  extras={}):
     record_dict = {}
     if xrn:
         if type:
             xrn = Xrn(xrn, type)
         else:
             xrn = Xrn(xrn)
         record_dict['urn'] = xrn.get_urn()
         record_dict['hrn'] = xrn.get_hrn()
         record_dict['type'] = xrn.get_type()
     if url:
         record_dict['url'] = url
     if description:
         record_dict['description'] = description
     if key:
         try:
             pubkey = open(key, 'r').read()
         except IOError:
             pubkey = key
         record_dict['keys'] = [pubkey]
     if slices:
         record_dict['slices'] = slices
     if researchers:
         record_dict['researcher'] = researchers
     if email:
         record_dict['email'] = email
     if pis:
         record_dict['pi'] = pis
     if extras:
         record_dict.update(extras)
     return record_dict
Esempio n. 28
0
    def instance_to_sliver(self, instance, xrn=None):
        if xrn:
            sliver_hrn = '%s.%s' % (self.driver.hrn, instance.id)
            sliver_id = Xrn(sliver_hrn, type='sliver').urn

        sliver = Sliver({'sliver_id': sliver_id,
                         'name': instance.name,
                         'type': instance.name,
                         'cpus': str(instance.vcpus),
                         'memory': str(instance.ram),
                         'storage':  str(instance.disk)})
        return sliver   
Esempio n. 29
0
    def add_leases(xml, leases, channels):

        network_elems = xml.xpath('//network')
        if len(network_elems) > 0:
            network_elem = network_elems[0]
        elif len(leases) > 0:
            network_urn = Xrn(
                leases[0]['component_id']).get_authority_urn().split(':')[0]
            network_elem = xml.add_element('network', name=network_urn)
        else:
            network_elem = xml

        # group the leases by slice and timeslots
        grouped_leases = []

        while leases:
            slice_id = leases[0]['slice_id']
            start_time = leases[0]['start_time']
            duration = leases[0]['duration']
            group = []

            for lease in leases:
                if slice_id == lease['slice_id'] and start_time == lease[
                        'start_time'] and duration == lease['duration']:
                    group.append(lease)

            grouped_leases.append(group)

            for lease1 in group:
                leases.remove(lease1)

        lease_elems = []
        for lease in grouped_leases:
            #lease[0]['start_time'] = datetime_to_string(utcparse(lease[0]['start_time']))

            lease_fields = ['slice_id', 'start_time', 'duration']
            lease_elem = network_elem.add_instance('lease', lease[0],
                                                   lease_fields)
            lease_elems.append(lease_elem)

            # add nodes of this lease
            for node in lease:
                lease_elem.add_instance('node', node, ['component_id'])

            # add reserved channels of this lease
            #channels = [{'channel_id': 1}, {'channel_id': 2}]
            for channel in channels:
                #channel['start_time'] = datetime_to_string(utcparse(channel['start_time']))
                if channel['slice_id'] == lease[0]['slice_id'] and channel[
                        'start_time'] == lease[0]['start_time'] and channel[
                            'duration'] == lease[0]['duration']:
                    lease_elem.add_instance('channel', channel,
                                            ['component_id'])
Esempio n. 30
0
    def verify_slice_nodes(self, slice_urn, slice, rspec_nodes):

        slivers = {}
        for node in rspec_nodes:
            hostname = node.get('component_name')
            client_id = node.get('client_id')
            component_id = node.get('component_id').strip()
            if hostname:
                hostname = hostname.strip()
            elif component_id:
                hostname = xrn_to_hostname(component_id)
            if hostname:
                slivers[hostname] = {
                    'client_id': client_id,
                    'component_id': component_id
                }

        nodes = self.driver.shell.GetNodes(
            slice['node_ids'], ['node_id', 'hostname', 'interface_ids'])
        current_slivers = [node['hostname'] for node in nodes]

        # remove nodes not in rspec
        deleted_nodes = list(set(current_slivers).difference(slivers.keys()))

        # add nodes from rspec
        added_nodes = list(set(slivers.keys()).difference(current_slivers))

        try:
            self.driver.shell.AddSliceToNodes(slice['name'], added_nodes)
            self.driver.shell.DeleteSliceFromNodes(slice['name'],
                                                   deleted_nodes)

        except:
            logger.log_exc('Failed to add/remove slice from nodes')

        slices = self.driver.shell.GetSlices(slice['name'], ['node_ids'])
        resulting_nodes = self.driver.shell.GetNodes(slices[0]['node_ids'])

        # update sliver allocations
        for node in resulting_nodes:
            client_id = slivers[node['hostname']]['client_id']
            component_id = slivers[node['hostname']]['component_id']
            sliver_hrn = '%s.%s-%s' % (self.driver.hrn, slice['slice_id'],
                                       node['node_id'])
            sliver_id = Xrn(sliver_hrn, type='sliver').urn
            record = SliverAllocation(sliver_id=sliver_id,
                                      client_id=client_id,
                                      component_id=component_id,
                                      slice_urn=slice_urn,
                                      allocation_state='geni_allocated')
            record.sync(self.driver.api.dbsession())
        return resulting_nodes