#panos: a new option to define the type of information about resources a user is interested in
parser.add_option("-i", "--info", dest="info",
help="optional component information", default=None)
+ # a new option to retreive or not reservation-oriented RSpecs (leases)
+ parser.add_option("-l", "--list_leases", dest="list_leases", type="choice",
+ help="Retreive or not reservation-oriented RSpecs ([resources]|leases|all )",
# 'create' does return the new rspec, makes sense to save that too
api_options['geni_slice_urn'] = hrn_to_urn(hrn, 'slice')
if options.info:
api_options['info'] = options.info
+ if options.list_leases:
+ api_options['list_leases'] = options.list_leases
if options.current:
if options.current == True:
api_options['cached'] = False
from sfa.rspecs.elements.interface import Interface
from sfa.rspecs.elements.services import Services
from sfa.rspecs.elements.pltag import PLTag
+from sfa.rspecs.elements.lease import Lease
+from sfa.rspecs.elements.granularity import Granularity
from sfa.rspecs.version_manager import VersionManager
-from sfa.planetlab.plxrn import PlXrn, hostname_to_urn, hrn_to_pl_slicename
+from sfa.planetlab.plxrn import PlXrn, hostname_to_urn, hrn_to_pl_slicename, slicename_to_hrn
from sfa.planetlab.vlink import get_tc_rate
from sfa.planetlab.topology import Topology
+import time
class PlAggregate:
filter.update({'peer_id': None})
nodes = self.driver.shell.GetNodes(filter)
+
+ # get the granularity in second for the reservation system
+ grain = self.driver.shell.GetLeaseGranularity()
site_ids = []
interface_ids = []
if site['longitude'] and site['latitude']:
location = Location({'longitude': site['longitude'], 'latitude': site['latitude'], 'country': 'unknown'})
rspec_node['location'] = location
+ # Granularity
+ granularity = Granularity({'grain': grain})
+ rspec_node['granularity'] = granularity
+
rspec_node['interfaces'] = []
if_count=0
for if_id in node['interface_ids']:
rspec_nodes.append(rspec_node)
return (rspec_nodes, links)
+
+ def get_leases(self, slice=None, options={}):
+ now = int(time.time())
+ filter={}
+ filter.update({'clip':now})
+ if slice:
+ filter.update({'name':slice['name']})
+ return_fields = ['lease_id', 'hostname', 'site_id', 'name', 't_from', 't_until']
+ leases = self.driver.shell.GetLeases(filter)
+
+ site_ids = []
+ for lease in leases:
+ site_ids.append(lease['site_id'])
+
+ # get sites
+ sites_dict = self.get_sites({'site_id': site_ids})
+
+ rspec_leases = []
+ for lease in leases:
+
+ rspec_lease = Lease()
+
+ # xxx how to retrieve site['login_base']
+ site_id=lease['site_id']
+ site=sites_dict[site_id]
+
+ rspec_lease['lease_id'] = lease['lease_id']
+ rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn, site['login_base'], lease['hostname'])
+ slice_hrn = slicename_to_hrn(self.driver.hrn, lease['name'])
+ slice_urn = hrn_to_urn(slice_hrn, 'slice')
+ rspec_lease['slice_id'] = slice_urn
+ rspec_lease['t_from'] = lease['t_from']
+ rspec_lease['t_until'] = lease['t_until']
+ rspec_leases.append(rspec_lease)
+ return rspec_leases
+
+
def get_rspec(self, slice_xrn=None, version = None, options={}):
version_manager = VersionManager()
if slice and 'expires' in slice:
rspec.xml.set('expires', datetime_to_string(utcparse(slice['expires'])))
- nodes, links = self.get_nodes_and_links(slice_xrn, slice, slivers)
- rspec.version.add_nodes(nodes)
- rspec.version.add_links(links)
+ if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'leases':
+ nodes, links = self.get_nodes_and_links(slice_xrn, slice, slivers)
+ rspec.version.add_nodes(nodes)
+ rspec.version.add_links(links)
+ # 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'])
- # 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'])
+ if not options.get('list_leases') or options.get('list_leases') and options['list_leases'] != 'resources':
+ leases = self.get_leases(slice)
+ rspec.version.add_leases(leases)
+
return rspec.toxml()
import sfa.planetlab.peers as peers
from sfa.planetlab.plaggregate import PlAggregate
from sfa.planetlab.plslices import PlSlices
-from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename
+from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, hrn_to_pl_login_base, xrn_to_hostname
def list_to_dict(recs, key):
#panos adding the info option to the caching key (can be improved)
if options.get('info'):
version_string = version_string + "_"+options.get('info', 'default')
+
+ # Adding the list_leases option to the caching key
+ if options.get('list_leases'):
+ version_string = version_string + "_"+options.get('list_leases', 'default')
# look in cache first
if cached_requested and self.cache and not slice_hrn:
# add/remove links links
slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
+
+ # add/remove leases
+ requested_leases = []
+ kept_leases = []
+ for lease in rspec.version.get_leases():
+ requested_lease = {}
+ if not lease.get('lease_id'):
+ requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
+ requested_lease['t_from'] = lease.get('t_from')
+ requested_lease['t_until'] = lease.get('t_until')
+ else:
+ kept_leases.append(int(lease['lease_id']))
+ if requested_lease.get('hostname'):
+ requested_leases.append(requested_lease)
+
+ leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
# handle MyPLC peer association.
# only used by plc and ple.
'UpdateSlice', 'UpdateSliceTag',
# also used as-is in importer
'GetSites','GetNodes',
+ # Lease management methods
+ 'GetLeases', 'GetLeaseGranularity', 'DeleteLeases','UpdateLeases',
+ 'AddLeases'
]
# support for other names - this is experimental
alias_calls = { 'get_authorities':'GetSites',
logger.debug('PlShell %s (%s) returned ... '%(name,actual_name))
return result
return func
+
return sfa_peer
+ def verify_slice_leases(self, slice, requested_leases, kept_leases, peer):
+
+ leases = self.driver.shell.GetLeases({'name':slice['name']}, ['lease_id'])
+ current_leases = [lease['lease_id'] for lease in leases]
+ deleted_leases = list(set(current_leases).difference(kept_leases))
+
+ try:
+ if peer:
+ self.driver.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer['shortname'])
+ deleted=self.driver.shell.DeleteLeases(deleted_leases)
+ for lease in requested_leases:
+ added=self.driver.shell.AddLeases(lease['hostname'], slice['name'], int(lease['t_from']), int(lease['t_until']))
+
+ except:
+ logger.log_exc('Failed to add/remove slice leases')
+
+ return leases
+
+
def verify_slice_nodes(self, slice, requested_slivers, peer):
nodes = self.driver.shell.GetNodes(slice['node_ids'], ['node_id', 'hostname', 'interface_ids'])
--- /dev/null
+from sfa.rspecs.elements.element import Element
+
+class Granularity(Element):
+
+ fields = [
+ 'grain',
+ ]
--- /dev/null
+from sfa.rspecs.elements.element import Element
+
+class Lease(Element):
+
+ fields = [
+ 'lease_id',
+ 'component_id',
+ 'slice_id'
+ 't_from',
+ 't_until',
+ ]
--- /dev/null
+from sfa.util.sfalogging import logger
+from sfa.util.xml import XpathFilter
+from sfa.util.xrn import Xrn
+
+from sfa.rspecs.elements.element import Element
+from sfa.rspecs.elements.node import Node
+from sfa.rspecs.elements.sliver import Sliver
+from sfa.rspecs.elements.location import Location
+from sfa.rspecs.elements.hardware_type import HardwareType
+from sfa.rspecs.elements.disk_image import DiskImage
+from sfa.rspecs.elements.interface import Interface
+from sfa.rspecs.elements.bwlimit import BWlimit
+from sfa.rspecs.elements.pltag import PLTag
+from sfa.rspecs.elements.versions.sfav1Sliver import SFAv1Sliver
+from sfa.rspecs.elements.versions.sfav1PLTag import SFAv1PLTag
+from sfa.rspecs.elements.versions.pgv2Services import PGv2Services
+from sfa.rspecs.elements.lease import Lease
+
+from sfa.planetlab.plxrn import xrn_to_hostname
+
+class SFAv1Lease:
+
+ @staticmethod
+ def add_leases(xml, leases):
+
+ 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
+
+ lease_elems = []
+ for lease in leases:
+ lease_fields = ['lease_id', 'component_id', 'slice_id', 't_from', 't_until']
+ lease_elem = network_elem.add_instance('lease', lease, lease_fields)
+ lease_elems.append(lease_elem)
+
+
+ @staticmethod
+ def get_leases(xml, filter={}):
+ xpath = '//lease%s | //default:lease%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
+ lease_elems = xml.xpath(xpath)
+ return SFAv1Lease.get_lease_objs(lease_elems)
+
+ @staticmethod
+ def get_lease_objs(lease_elems):
+ leases = []
+ for lease_elem in lease_elems:
+ lease = Lease(lease_elem.attrib, lease_elem)
+ if lease.get('lease_id'):
+ lease['lease_id'] = lease_elem.attrib['lease_id']
+ lease['component_id'] = lease_elem.attrib['component_id']
+ lease['slice_id'] = lease_elem.attrib['slice_id']
+ lease['t_from'] = lease_elem.attrib['t_from']
+ lease['t_until'] = lease_elem.attrib['t_until']
+
+ leases.append(lease)
+ return leases
+
if location:
node_elem.add_instance('location', location, Location.fields)
+ # add granularity of the reservation system
+ granularity = node.get('granularity')
+ if granularity:
+ node_elem.add_instance('granularity', granularity, granularity.fields)
+
+
if isinstance(node.get('interfaces'), list):
for interface in node.get('interfaces', []):
node_elem.add_instance('interface', interface, ['component_id', 'client_id', 'ipv4'])
SERVICES='SERVICES',
SLIVER='SLIVER',
SLIVER_TYPE='SLIVER_TYPE',
+ LEASE='LEASE',
+ GRANULARITY='GRANULARITY',
)
class RSpecElement:
from sfa.rspecs.elements.versions.pgv2Link import PGv2Link
from sfa.rspecs.elements.versions.sfav1Node import SFAv1Node
from sfa.rspecs.elements.versions.sfav1Sliver import SFAv1Sliver
+from sfa.rspecs.elements.versions.sfav1Lease import SFAv1Lease
class SFAv1(RSpecVersion):
enabled = True
self.xml.append(network.element)
current_networks.append(current_network)
+ # Leases
+
+ def get_leases(self, filter=None):
+ return SFAv1Lease.get_leases(self.xml, filter)
+
+ def add_leases(self, leases, network = None, no_dupes=False):
+ SFAv1Lease.add_leases(self.xml, leases)
+
if __name__ == '__main__':
from sfa.rspecs.rspec import RSpec
from sfa.rspecs.rspec_elements import *