-#
+#
# sfi.py - basic SFA command-line client
# the actual binary in sfa/clientbin essentially runs main()
# this module is used in sfascan
-#
+#
import sys
sys.path.append('.')
import datetime
import codecs
import pickle
+import json
from lxml import etree
from StringIO import StringIO
from optparse import OptionParser
# save methods
-def save_variable_to_file(var, filename, format="text"):
- f = open(filename, "w")
+def save_raw_to_file(var, filename, format="text", banner=None):
+ if filename == "-":
+ # if filename is "-", send it to stdout
+ f = sys.stdout
+ else:
+ f = open(filename, "w")
+ if banner:
+ f.write(banner+"\n")
if format == "text":
f.write(str(var))
elif format == "pickled":
f.write(pickle.dumps(var))
+ elif format == "json":
+ if hasattr(json, "dumps"):
+ f.write(json.dumps(var)) # python 2.6
+ else:
+ f.write(json.write(var)) # python 2.5
else:
# this should never happen
print "unknown output format", format
-
+ if banner:
+ f.write('\n'+banner+"\n")
def save_rspec_to_file(rspec, filename):
if not filename.endswith(".rspec"):
help="output file format ([xml]|xmllist|hrnlist)", default="xml",
choices=("xml", "xmllist", "hrnlist"))
- if command in ("status", "version"):
- parser.add_option("-o", "--output", dest="file",
- help="output dictionary to file", metavar="FILE", default=None)
- parser.add_option("-F", "--fileformat", dest="fileformat", type="choice",
- help="output file format ([text]|pickled)", default="text",
- choices=("text","pickled"))
-
if command in ("delegate"):
parser.add_option("-u", "--user",
action="store_true", dest="delegate_user", default=False,
help="root registry", metavar="URL", default=None)
parser.add_option("-s", "--sliceapi", dest="sm", default=None, metavar="URL",
help="slice API - in general a SM URL, but can be used to talk to an aggregate")
- parser.add_option("-R", "--raw", dest="raw", action="store_true", default=False,
- help="Display raw, unparsed server response")
+ parser.add_option("-R", "--raw", dest="raw", default=None,
+ help="Save raw, unparsed server response to a file")
+ parser.add_option("", "--rawformat", dest="rawformat", type="choice",
+ help="raw file format ([text]|pickled|json)", default="text",
+ choices=("text","pickled","json"))
+ parser.add_option("", "--rawbanner", dest="rawbanner", default=None,
+ help="text string to write before and after raw output")
parser.add_option("-d", "--dir", dest="sfi_dir",
help="config & working directory - default is %default",
metavar="PATH", default=Sfi.default_sfi_dir())
else:
self.logger.critical("No such registry record file %s"%record)
sys.exit(1)
-
+
#==========================================================================
# Following functions implement the commands
#
# Registry-related commands
#==========================================================================
-
+
def version(self, options, args):
"""
- display an SFA server version (GetVersion)
+ display an SFA server version (GetVersion)
or version information about sfi itself
"""
if options.version_local:
server = self.sliceapi()
result = server.GetVersion()
version = ReturnValue.get_value(result)
- pprinter = PrettyPrinter(indent=4)
- pprinter.pprint(version)
- if options.file:
- save_variable_to_file(version, options.file, options.fileformat)
+ if self.options.raw:
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+ else:
+ pprinter = PrettyPrinter(indent=4)
+ pprinter.pprint(version)
def list(self, options, args):
"""
result = server.ListSlices(creds, *self.ois(server,api_options))
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
display_list(value)
return
-
+
# show rspec for named slice
def resources(self, options, args):
"""
creds.append(self.my_credential_string)
if options.delegate:
creds.append(self.delegate_cred(cred, get_authority(self.authority)))
-
+
# no need to check if server accepts the options argument since the options has
- # been a required argument since v1 API
+ # been a required argument since v1 API
api_options = {}
# always send call_id to v2 servers
api_options ['call_id'] = unique_call_id()
# just request the version the client wants
api_options['geni_rspec_version'] = version_manager.get_version(options.rspec_version).to_dict()
else:
- api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
+ api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
else:
- api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
+ api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
result = server.ListResources (creds, api_options)
value = ReturnValue.get_value(result)
- if options.file is None:
- if self.options.raw:
- print result
- else:
- display_rspec(value, options.format)
- else:
+ if self.options.raw:
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+ if options.file is not None:
save_rspec_to_file(value, options.file)
+ if (self.options.raw is None) and (options.file is None):
+ display_rspec(value, options.format)
+
return
def create(self, options, args):
# delegated_cred = self.delegate_cred(slice_cred, server_version['hrn'])
#elif server_version.get('urn'):
# delegated_cred = self.delegate_cred(slice_cred, urn_to_hrn(server_version['urn']))
-
- # rspec
+
+ # rspec
rspec_file = self.get_rspec_file(args[1])
rspec = open(rspec_file).read()
rspec = RSpecConverter.to_pg_rspec(rspec.toxml(), content_type='request')
else:
users = sfa_users_arg(user_records, slice_record)
-
- # do not append users, keys, or slice tags. Anything
+
+ # do not append users, keys, or slice tags. Anything
# not contained in this request will be removed from the slice
# CreateSliver has supported the options argument for a while now so it should
result = server.CreateSliver(slice_urn, creds, rspec, users, *self.ois(server, api_options))
value = ReturnValue.get_value(result)
- if options.file is None:
- if self.options.raw:
- print result
- else:
- print value
- else:
+ if self.options.raw:
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+ if options.file is not None:
save_rspec_to_file (value, options.file)
+ if (self.options.raw is None) and (options.file is None):
+ print value
+
return value
def delete(self, options, args):
result = server.DeleteSliver(slice_urn, creds, *self.ois(server, api_options ) )
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
return value
result = server.SliverStatus(slice_urn, creds, *self.ois(server,api_options))
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
- if options.file:
- save_variable_to_file(value, options.file, options.fileformat)
def start(self, options, args):
"""
result = server.Start(slice_urn, creds)
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
return value
result = server.Stop(slice_urn, creds)
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
return value
result = server.reset_slice(creds, slice_urn)
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
return value
result = server.RenewSliver(slice_urn, creds, time, *self.ois(server,api_options))
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
return value
result = server.Shutdown(slice_urn, creds)
value = ReturnValue.get_value(result)
if self.options.raw:
- print result
+ save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
else:
print value
return value
from sfa.generic import Generic
import sfa.server.sfaapi
-import sfa.openstack.openstack_driver
+import sfa.openstack.nova_driver
import sfa.managers.registry_manager_openstack
+import sfa.managers.aggregate_manager
import sfa.managers.slice_manager
-import sfa.managers.aggregate_manager_openstack
# use pl as a model so we only redefine what's different
from sfa.generic.pl import pl
def registry_manager_class (self) :
return sfa.managers.registry_manager_openstack.RegistryManager
def aggregate_manager_class (self) :
- return sfa.managers.aggregate_manager_openstack.AggregateManager
+ return sfa.managers.aggregate_manager.AggregateManager
# driver class for server-side services, talk to the whole testbed
def driver_class (self):
- return sfa.openstack.openstack_driver.OpenstackDriver
+ return sfa.openstack.nova_driver.NovaDriver
from sfa.storage.alchemy import dbsession
from sfa.storage.model import RegRecord, RegAuthority, RegUser, RegSlice, RegNode
-from sfa.openstack.openstack_shell import OpenstackShell
+from sfa.openstack.nova_shell import NovaShell
def load_keys(filename):
keys = {}
config = Config ()
interface_hrn = config.SFA_INTERFACE_HRN
root_auth = config.SFA_REGISTRY_ROOT_AUTH
- shell = OpenstackShell (config)
+ shell = NovaShell (config)
# create dict of all existing sfa records
existing_records = {}
# essentially a union of the core version, the generic version (this code) and
# whatever the driver needs to expose
def GetVersion(self, api, options):
-
xrn=Xrn(api.hrn)
version = version_core()
version_generic = {
rights = api.auth.determine_user_rights(caller_hrn, record.__dict__)
# make sure caller has rights to this object
if rights.is_empty():
- raise PermissionError(caller_hrn + " has no rights to " + record.hrn)
-
+ raise PermissionError("%s has no rights to %s (%s)" % \
+ (caller_hrn, object_hrn, xrn))
object_gid = GID(string=record.gid)
new_cred = Credential(subject = object_gid.get_subject())
new_cred.set_gid_caller(caller_gid)
# the driver interface, mostly provides default behaviours
from sfa.managers.driver import Driver
-
-from sfa.openstack.openstack_shell import OpenstackShell
+from sfa.openstack.nova_shell import NovaShell
from sfa.openstack.osaggregate import OSAggregate
from sfa.plc.plslices import PlSlices
from sfa.util.osxrn import OSXrn
# can be sent as-is; it takes care of authentication
# from the global config
#
-class OpenstackDriver (Driver):
+class NovaDriver (Driver):
# the cache instance is a class member so it survives across incoming requests
cache = None
def __init__ (self, config):
Driver.__init__ (self, config)
- self.shell = OpenstackShell (config)
+ self.shell = NovaShell (config)
self.cache=None
if config.SFA_AGGREGATE_CACHING:
- if OpenstackDriver.cache is None:
- OpenstackDriver.cache = Cache()
- self.cache = OpenstackDriver.cache
+ if NovaDriver.cache is None:
+ NovaDriver.cache = Cache()
+ self.cache = NovaDriver.cache
########################################
########## registry oriented
name = Xrn(record['hrn']).get_leaf()
os_record = None
if record['type'] == 'user':
- os_record = self.shell.user_get(name)
+ os_record = self.shell.auth_manager.get_user(name)
+ projects = self.shell.db.project_get_by_user(name)
record['slices'] = [self.hrn + "." + proj.name for \
- proj in os_record.projects]
- record['roles'] = [role for role in os_record.roles]
- keys = self.shell.key_pair_get_all_by_user(name)
+ proj in projects]
+ record['roles'] = self.shell.db.user_get_roles(name)
+ keys = self.shell.db.key_pair_get_all_by_user(name)
record['keys'] = [key.public_key for key in keys]
elif record['type'] == 'slice':
- os_record = self.shell.project_get(name)
+ os_record = self.shell.auth_manager.get_project(name)
record['description'] = os_record.description
- record['PI'] = self.hrn + "." + os_record.project_manager
+ record['PI'] = [self.hrn + "." + os_record.project_manager.name]
record['geni_creator'] = record['PI']
- record['researcher'] = [self.hrn + "." + user.name for \
- user in os_record.members]
+ record['researcher'] = [self.hrn + "." + user for \
+ user in os_record.member_ids]
else:
continue
record['geni_urn'] = hrn_to_urn(record['hrn'], record['type'])
record['geni_certificate'] = record['gid']
record['name'] = os_record.name
- if os_record.created_at is not None:
- record['date_created'] = datetime_to_string(utcparse(os_record.created_at))
- if os_record.updated_at is not None:
- record['last_updated'] = datetime_to_string(utcparse(os_record.updated_at))
+ #if os_record.created_at is not None:
+ # record['date_created'] = datetime_to_string(utcparse(os_record.created_at))
+ #if os_record.updated_at is not None:
+ # record['last_updated'] = datetime_to_string(utcparse(os_record.updated_at))
return records
return slices
# get data from db
- slices = self.shell.project_get_all()
- slice_urns = [OSXrn(name, 'slice').urn for name in slice]
+ projs = self.shell.auth_manager.get_projects()
+ slice_urns = [OSXrn(proj.name, 'slice').urn for proj in projs]
# cache the result
if self.cache:
def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
- aggregate = PlAggregate(self)
- slices = PlSlices(self)
- peer = slices.get_peer(slice_hrn)
- sfa_peer = slices.get_sfa_peer(slice_hrn)
- slice_record=None
- if users:
- slice_record = users[0].get('slice_record', {})
-
+ aggregate = OSAggregate(self)
+ slicename = get_leaf(slice_hrn)
+
# parse rspec
rspec = RSpec(rspec_string)
requested_attributes = rspec.version.get_slice_attributes()
- # ensure site record exists
- site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer, options=options)
# ensure slice record exists
- slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer, options=options)
+ slice = aggregate.verify_slice(slicename, users, options=options)
# ensure person records exists
- persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer, options=options)
- # ensure slice attributes exists
- slices.verify_slice_attributes(slice, requested_attributes, options=options)
-
+ persons = aggregate.verify_slice_users(slicename, users, options=options)
# add/remove slice from nodes
- requested_slivers = [node.get('component_name') for node in rspec.version.get_nodes_with_slivers()]
- nodes = slices.verify_slice_nodes(slice, requested_slivers, peer)
+ slices.verify_instances(slicename, rspec)
- # add/remove links links
- slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
-
- # handle MyPLC peer association.
- # only used by plc and ple.
- slices.handle_peer(site, slice, persons, peer)
-
return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
def delete_sliver (self, slice_urn, slice_hrn, creds, options):
return 1
self.shell.DeleteSliceFromNodes(slicename, slice['node_ids'])
- instances = self.shell.instance_get_all_by_project(name)
+ instances = self.shell.db.instance_get_all_by_project(name)
for instance in instances:
- self.shell.instance_destroy(instance.instance_id)
+ self.shell.db.instance_destroy(instance.instance_id)
return 1
def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
def stop_slice (self, slice_urn, slice_hrn, creds):
name = OSXrn(xrn=slice_urn).name
- slice = self.shell.project_get(name)
- if not slice:
- return 1
-
- self.shell.DeleteSliceFromNodes(slicename, slice['node_ids'])
- instances = self.shell.instance_get_all_by_project(name)
+ slice = self.shell.get_project(name)
+ instances = self.shell.db.instance_get_all_by_project(name)
for instance in instances:
- self.shell.instance_stop(instance.instance_id)
+ self.shell.db.instance_stop(instance.instance_id)
return 1
def reset_slice (self, slice_urn, slice_hrn, creds):
from urlparse import urlparse
from sfa.util.sfalogging import logger
try:
- from nova import flags
- from nova import context
from nova import db
- has_nova = True
+ from nova import flags
+ from nova import context
+ from nova.auth.manager import AuthManager
+ from nova.compute.manager import ComputeManager
+ from nova.network.manager import NetworkManager
+ from nova.scheduler.manager import SchedulerManager
+ from nova.image.glance import GlanceImageService
+ has_nova = True
except:
has_nova = False
-
-class OpenstackShell:
+
+
+class InjectContext:
+ """
+ Wraps the module and injects the context when executing methods
+ """
+ def __init__(self, proxy, context):
+ self.proxy = proxy
+ self.context = context
+
+ def __getattr__(self, name):
+ def func(*args, **kwds):
+ result=getattr(self.proxy, name)(self.context, *args, **kwds)
+ return result
+ return func
+
+class NovaShell:
"""
A simple xmlrpc shell to a myplc instance
This class can receive all Openstack calls to the underlying testbed
def __init__ ( self, config ) :
url = config.SFA_PLC_URL
# try to figure if the url is local
+ is_local=False
hostname=urlparse(url).hostname
if hostname == 'localhost': is_local=True
# otherwise compare IP addresses;
if is_local and has_nova:
- logger.debug('openstack access - native')
+ logger.debug('nova access - native')
# load the config
flags.FLAGS(['foo', '--flagfile=/etc/nova/nova.conf', 'foo', 'foo'])
- self.auth = context.get_admin_context()
- self.proxy = db
+ # instantiate managers
+ self.auth_manager = AuthManager()
+ self.compute_manager = ComputeManager()
+ self.network_manager = NetworkManager()
+ self.scheduler_manager = SchedulerManager()
+ self.db = InjectContext(db, context.get_admin_context())
+ self.image_manager = InjectContext(GlanceImageService(), context.get_admin_context())
else:
self.auth = None
self.proxy = None
- logger.debug('openstack access - REST')
- raise SfaNotImplemented('openstack access - Rest')
-
- def __getattr__(self, name):
- def func(*args, **kwds):
- result=getattr(self.proxy, name)(self.auth, *args, **kwds)
- return result
- return func
+ logger.debug('nova access - REST')
+ raise SfaNotImplemented('nova access - Rest')
+
+from sfa.util.faults import SfaAPIError
from sfa.rspecs.rspec import RSpec
from sfa.rspecs.elements.hardware_type import HardwareType
from sfa.rspecs.elements.node import Node
from sfa.rspecs.elements.sliver import Sliver
from sfa.rspecs.elements.login import Login
+from sfa.rspecs.elements.disk_image import DiskImage
from sfa.rspecs.elements.services import Services
from sfa.util.xrn import Xrn
from sfa.util.osxrn import OSXrn
self.driver = driver
def instance_to_sliver(self, instance, slice_xrn=None):
- sliver_id = None
- name = None
- if slice_xrn:
- name = OSXrn(slice_xrn, 'slice').name
- sliver_id = xrn.sliver_id(instance.instance_id, "")
-
- # should include:
+ # should include?
# * instance.image_ref
# * instance.kernel_id
# * instance.ramdisk_id
+ import nova.db.sqlalchemy.models
name=None
- if hasattr(instance, 'name'):
- name = instance.name
- elif hasattr(instance, 'display_name'):
- name = instance.display_name
+ type=None
+ sliver_id = None
+ if isinstance(instance, dict):
+ # this is an isntance type dict
+ name = instance['name']
+ type = instance['name']
+ elif isinstance(instance, nova.db.sqlalchemy.models.Instance):
+ # this is an object that describes a running instance
+ name = instance.display_name
+ type = instance.instance_type.name
+ else:
+ raise SfaAPIError("instnace must be an instance_type dict or" + \
+ " a nova.db.sqlalchemy.models.Instance object")
+ if slice_xrn:
+ xrn = Xrn(slice_xrn, 'slice')
+ sliver_id = xrn.get_sliver_id(instance.project_id, instance.hostname, instance.id)
+
sliver = Sliver({'slice_id': sliver_id,
'name': name,
- 'type': 'plos-' + instance['name'],
+ 'type': 'plos-' + type,
'tags': []})
return sliver
- def get_rspec(self, slice_xrn=None, vsersion=None, options={}):
+ def get_rspec(self, slice_xrn=None, version=None, options={}):
version_manager = VersionManager()
version = version_manager.get_version(version)
if not slice_xrn:
else:
rspec_version = version_manager._get_version(version.type, version.version, 'manifest')
nodes = self.get_slice_nodes(slice_xrn)
-
+ rspec = RSpec(version=rspec_version, user_options=options)
rspec.version.add_nodes(nodes)
return rspec.toxml()
def get_slice_nodes(self, slice_xrn):
name = OSXrn(xrn = slice_xrn).name
- instances = self.driver.shell.instance_get_all_by_project(name)
+ instances = self.driver.shell.db.instance_get_all_by_project(name)
rspec_nodes = []
for instance in instances:
rspec_node = Node()
def get_aggregate_nodes(self):
- zones = self.driver.shell.zone_get_all()
+ zones = self.driver.shell.db.zone_get_all()
if not zones:
zones = ['cloud']
else:
zones = [zone.name for zone in zones]
+ # available sliver/instance/vm types
+ instances = self.driver.shell.db.instance_type_get_all().values()
+ # available images
+ images = self.driver.shell.image_manager.detail()
+ disk_images = []
+ for image in images:
+ if image['container_format'] == 'ami':
+ img = DiskImage()
+ img['name'] = image['name']
+ img['description'] = image['name']
+ img['os'] = image['name']
+ img['version'] = image['name']
+ disk_images.append(img)
+
rspec_nodes = []
for zone in zones:
rspec_node = Node()
rspec_node['exclusive'] = 'false'
rspec_node['hardware_types'] = [HardwareType({'name': 'plos-pc'}),
HardwareType({'name': 'pc'})]
- instances = self.driver.shell.instance_type_get_all().values()
- slivers = [self.instance_to_sliver(inst) for inst in instances]
+ slivers = []
+ for instance in instances:
+ sliver = self.instance_to_sliver(instance)
+ sliver['disk_images'] = disk_images
+ slivers.append(sliver)
+
rspec_node['slivers'] = slivers
rspec_nodes.append(rspec_node)
- return rspec_node
+ return rspec_nodes
+
+
+ def verify_slice(self, slicename, users, options={}):
+ """
+ Create the slice if it doesn't alredy exist
+ """
+ import nova.exception.ProjectNotFound
+ try:
+ slice = self.driver.shell.auth_manager.get_project(slicename)
+ except nova.exception.ProjectNotFound:
+ # convert urns to user names
+ usernames = [Xrn(user['urn']).get_leaf() for user in users]
+ # assume that the first user is the project manager
+ proj_manager = usernames[0]
+ self.driver.shell.auth_manager.create_project(slicename, proj_manager)
+
+ def verify_slice_users(self, slicename, users, options={}):
+ """
+ Add requested users to the specified slice.
+ """
+
+ # There doesn't seem to be an effcient way to
+ # look up all the users of a project, so lets not
+ # attempt to remove stale users . For now lets just
+ # ensure that the specified users exist
+ for user in users:
+ username = Xrn(user['urn']).get_leaf()
+ try:
+ self.driver.shell.auth_manager.get_user(username)
+ except nova.exception.UserNotFound:
+ self.driver.shell.auth_manager.create_user(username)
+ self.verify_user_keys(username, user['keys'], options)
+
+ def verify_user_keys(self, username, keys, options={}):
+ """
+ Add requested keys.
+ """
+ append = options.get('append', True)
+ existing_keys = self.driver.shell.db.key_pair_get_all_by_user(username)
+ existing_pub_keys = [key.public_key for key in existing_keys]
+ removed_pub_keys = set(existing_pub_keys).difference(keys)
+ added_pub_keys = set(keys).difference(existing_pub_keys)
+
+ # add new keys
+ for public_key in added_pub_keys:
+ key = {}
+ key['user_id'] = username
+ key['name'] = username
+ key['public'] = public_key
+ self.driver.shell.db.key_pair_create(key)
+
+ # remove old keys
+ if not append:
+ for key in existing_keys:
+ if key.public_key in removed_pub_keys:
+ self.driver.shell.db.key_pair_destroy(username, key.name)
+
+ def verify_instances(self, slicename, rspec):
+ rsepc = RSpec(rspec)
+ nodes = rspec.version.get_nodes_with_slivers()
+ old_instances = self.driver.shell.db.instance_get_all_by_project(name)
+ for node in nodes:
+ for slivers in node.get('slivers', []):
+ pass
+ # get instance type
+ # get image
+ # start instance
elif hasattr(self.element, name):
return getattr(self.element, name)
else:
- raise AttributeError, "class Element has not attribute %s" % name
+ raise AttributeError, "class Element has no attribute %s" % name
'name',
'type',
'tags',
+ 'disk_images',
]
--- /dev/null
+from sfa.rspecs.elements.element import Element
+from sfa.rspecs.elements.disk_image import DiskImage
+
+class PGv2DiskImage:
+
+ @staticmethod
+ def add_images(xml, images):
+ if not images:
+ return
+ if not isinstance(images, list):
+ images = [images]
+ for image in images:
+ xml.add_instance('disk_image', image, DiskImage.fields)
+
+ @staticmethod
+ def get_images(xml, filter={}):
+ xpath = './default:disk_image | ./disk_image'
+ image_elems = xml.xpath(xpath)
+ images = []
+ for image_elem in image_elems:
+ image = DiskImage(image_elem.attrib, image_elem)
+ images.append(image)
+ return images
+
from sfa.rspecs.elements.element import Element
from sfa.rspecs.elements.sliver import Sliver
+from sfa.rspecs.elements.versions.pgv2DiskImage import PGv2DiskImage
class PGv2SliverType:
if sliver.get('type'):
sliver_elem.set('name', sliver['type'])
if sliver.get('client_id'):
- sliver_elem.set('client_id', sliver['client_id'])
+ sliver_elem.set('client_id', sliver['client_id'])
+ images = sliver.get('disk_images')
+ if images and isinstance(images, list):
+ PGv2DiskImage.add_images(sliver_elem, images)
PGv2SliverType.add_sliver_attributes(sliver_elem, sliver.get('tags', []))
@staticmethod
sliver['component_id'] = xml.attrib['component_id']
if 'name' in sliver_elem.attrib:
sliver['type'] = sliver_elem.attrib['name']
+ sliver['images'] = PGv2DiskImage.get_images(sliver_elem)
slivers.append(sliver)
return slivers
if location:
node_elem.add_instance('location', location, Location.fields)
- for interface in node.get('interfaces', []):
- node_elem.add_instance('interface', interface, ['component_id', 'client_id', 'ipv4'])
+ if isinstance(node.get('interfaces'), list):
+ for interface in node.get('interfaces', []):
+ node_elem.add_instance('interface', interface, ['component_id', 'client_id', 'ipv4'])
#if 'bw_unallocated' in node and node['bw_unallocated']:
# bw_unallocated = etree.SubElement(node_elem, 'bw_unallocated', units='kbps').text = str(int(node['bw_unallocated'])/1000)
def hrn_authfor_hrn(parenthrn, hrn): return Xrn.hrn_is_auth_for_hrn(parenthrn, hrn)
def urn_to_sliver_id(urn, slice_id, node_id, index=0):
- return ":".join(map(str, [urn, slice_id, node_id, index]))
+ return Xrn(urn).get_sliver_id(slice_id, node_id, index)
class Xrn:
def get_authority_urn(self):
self._normalize()
return ':'.join( [Xrn.unescape(x) for x in self.authority] )
-
+
+ def get_sliver_id(self, slice_id, node_id, index=0):
+ self._normalize()
+ return ":".join(map(str, [self.get_urn(), slice_id, node_id, index]))
+
def urn_to_hrn(self):
"""
compute tuple (hrn, type) from urn