%define name sfa
%define version 1.0
-%define taglevel 26
+%define taglevel 27
%define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
%global python_sitearch %( python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)" )
[ "$1" -ge "1" ] && service sfa-cm restart || :
%changelog
+* Fri Jul 8 2011 Tony Mack <tmack@cs.princeton.edu> - sfa-1.0-27
+- ProtoGENI v2 RSpec updates.
+- Convert expiration timestamps with timezone info in credentials to utc.
+- Fixed redundant logging issue.
+- Improved SliceManager and SFI client logging.
+- Support aggregates that don't support the optional 'call_id' argument.
+- Only call get_trusted_certs() at aggreage interfaces that support the call.
+- CreateSliver() now handles MyPLC slice attributes/tags.
+- Cache now supports persistence.
+- Hide whitelisted nodes.
+
* Tue Jun 21 2011 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-1.0-26
- fixed issues with sup authority signing
- fixed bugs in remove_slivers and SliverStatus
from sqlobject import *
from sfa.util.faults import *
-from sfa.util.xrn import urn_to_hrn
+from sfa.util.xrn import urn_to_hrn, Xrn
from sfa.util.rspec import RSpec
from sfa.server.registry import Registries
from sfa.trust.credential import Credential
from sfa.plc.api import SfaAPI
from sfa.util.plxrn import hrn_to_pl_slicename, slicename_to_hrn
from sfa.util.callids import Callids
+from sfa.util.sfalogging import sfa_logger
+from sfa.rspecs.sfa_rspec import sfa_rspec_version
+from sfa.util.version import version_core
from threading import Thread
from time import sleep
# @param sliceHRN The hunman readable name of the slice.
# @return sting()
#
-def getKeysForSlice(sliceHRN):
- logger = logging.getLogger('EucaAggregate')
- try:
- # convert hrn to slice name
- plSliceName = hrn_to_pl_slicename(sliceHRN)
- except IndexError, e:
- logger.error('Invalid slice name (%s)' % sliceHRN)
+def getKeysForSlice(api, sliceHRN):
+ logger = logging.getLogger('EucaAggregate')
+ cred = api.getCredential()
+ registry = api.registries[api.hrn]
+ keys = []
+
+ # Get the slice record
+ records = registry.Resolve(sliceHRN, cred)
+ if not records:
+ logging.warn('Cannot find any record for slice %s' % sliceHRN)
return []
- # Get the slice's information
- sliceData = api.plshell.GetSlices(api.plauth, {'name':plSliceName})
- if not sliceData:
- logger.warn('Cannot get any data for slice %s' % plSliceName)
- return []
+ # Find who can log into this slice
+ persons = records[0]['persons']
- # It should only return a list with len = 1
- sliceData = sliceData[0]
+ # Extract the keys from persons records
+ for p in persons:
+ sliceUser = registry.Resolve(p, cred)
+ userKeys = sliceUser[0]['keys']
+ keys += userKeys
- keys = []
- person_ids = sliceData['person_ids']
- if not person_ids:
- logger.warn('No users in slice %s' % sliceHRN)
- return []
-
- persons = api.plshell.GetPersons(api.plauth, person_ids)
- for person in persons:
- pkeys = api.plshell.GetKeys(api.plauth, person['key_ids'])
- for key in pkeys:
- keys.append(key['key'])
-
return ''.join(keys)
##
# get hrn of the original caller
origin_hrn = options.get('origin_hrn', None)
if not origin_hrn:
- origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
+ origin_hrn = Credential(string=creds).get_gid_caller().get_hrn()
+ # origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
conn = getEucaConnection()
schemaXML = ET.parse(EUCALYPTUS_RSPEC_SCHEMA)
rspecValidator = ET.RelaxNG(schemaXML)
rspecXML = ET.XML(xml)
+ for network in rspecXML.iterfind("./network"):
+ if network.get('id') != cloud['name']:
+ # Throw away everything except my own RSpec
+ # sfa_logger().error("CreateSliver: deleting %s from rspec"%network.get('id'))
+ network.getparent().remove(network)
if not rspecValidator(rspecXML):
error = rspecValidator.error_log.last_error
message = '%s (line %s)' % (error.message, error.line)
pendingRmInst = []
for sliceInst in s.instances:
pendingRmInst.append(sliceInst.instance_id)
- existingInstGroup = rspecXML.findall('.//euca_instances')
+ existingInstGroup = rspecXML.findall(".//euca_instances")
for instGroup in existingInstGroup:
for existingInst in instGroup:
if existingInst.get('id') in pendingRmInst:
conn.terminate_instances(pendingRmInst)
# Process new instance requests
- requests = rspecXML.findall('.//request')
+ requests = rspecXML.findall(".//request")
if requests:
# Get all the public keys associate with slice.
- pubKeys = getKeysForSlice(s.slice_hrn)
+ pubKeys = getKeysForSlice(api, s.slice_hrn)
logger.debug('Passing the following keys to the instance:\n%s' % pubKeys)
for req in requests:
vmTypeElement = req.getparent()
dbInst.meta.pub_addr = ipData['pub_addr']
dbInst.meta.state = 'running'
+def GetVersion(api):
+ xrn=Xrn(api.hrn)
+ request_rspec_versions = [dict(sfa_rspec_version)]
+ ad_rspec_versions = [dict(sfa_rspec_version)]
+ version_more = {'interface':'aggregate',
+ 'testbed':'myplc',
+ 'hrn':xrn.get_hrn(),
+ 'request_rspec_versions': request_rspec_versions,
+ 'ad_rspec_versions': ad_rspec_versions,
+ 'default_ad_rspec': dict(sfa_rspec_version)
+ }
+ return version_core(version_more)
+
def main():
init_server()
#rspec = ListResources('euca', 'planetcloud.pc.test', 'planetcloud.pc.marcoy', 'test_euca')
#print rspec
- print getKeysForSlice('gc.gc.test1')
+
+ server_key_file = '/var/lib/sfa/authorities/server.key'
+ server_cert_file = '/var/lib/sfa/authorities/server.cert'
+ api = SfaAPI(key_file = server_key_file, cert_file = server_cert_file, interface='aggregate')
+ print getKeysForSlice(api, 'gc.gc.test1')
if __name__ == "__main__":
main()
from types import StringTypes
from sfa.util.faults import *
-from sfa.util.xrn import get_authority, hrn_to_urn, urn_to_hrn, Xrn
+from sfa.util.xrn import get_authority, hrn_to_urn, urn_to_hrn, Xrn, urn_to_sliver_id
from sfa.util.plxrn import slicename_to_hrn, hrn_to_pl_slicename, hostname_to_urn
from sfa.util.rspec import *
from sfa.util.specdict import *
api.logger.info(hrn)
slicename = hrn_to_pl_slicename(hrn)
- slices = api.plshell.GetSlices(api.plauth, [slicename], ['node_ids','person_ids','name','expires'])
+ slices = api.plshell.GetSlices(api.plauth, [slicename], ['slice_id', 'node_ids','person_ids','name','expires'])
if len(slices) == 0:
raise Exception("Slice %s not found (used %s as slicename internally)" % (slice_xrn, slicename))
slice = slices[0]
# report about the local nodes only
nodes = api.plshell.GetNodes(api.plauth, {'node_id':slice['node_ids'],'peer_id':None},
- ['hostname', 'site_id', 'boot_state', 'last_contact'])
+ ['node_id', 'hostname', 'site_id', 'boot_state', 'last_contact'])
site_ids = [node['site_id'] for node in nodes]
sites = api.plshell.GetSites(api.plauth, site_ids, ['site_id', 'login_base'])
sites_dict = dict ( [ (site['site_id'],site['login_base'] ) for site in sites ] )
top_level_status = 'unknown'
if nodes:
top_level_status = 'ready'
- result['geni_urn'] = Xrn(slice_xrn, 'slice').get_urn()
+ slice_urn = Xrn(slice_xrn, 'slice').get_urn()
+ result['geni_urn'] = slice_urn
result['pl_login'] = slice['name']
result['pl_expires'] = datetime.datetime.fromtimestamp(slice['expires']).ctime()
res['pl_last_contact'] = node['last_contact']
if node['last_contact'] is not None:
res['pl_last_contact'] = datetime.datetime.fromtimestamp(node['last_contact']).ctime()
- res['geni_urn'] = hostname_to_urn(api.hrn, sites_dict[node['site_id']], node['hostname'])
+ sliver_id = urn_to_sliver_id(slice_urn, slice['slice_id'], node['node_id'])
+ res['geni_urn'] = sliver_id
if node['boot_state'] == 'boot':
res['geni_status'] = 'ready'
else:
else:
existing_slice_attributes.append(slice_tag)
- #api.logger.debug("requested slice attributes: %s" % str(requested_slice_attributes))
- #api.logger.debug("removed slice attributes: %s" % str(removed_slice_attributes))
- #api.logger.debug("existing slice attributes: %s" % str(existing_slice_attributes))
try:
if peer:
api.plshell.UnBindObjectFromPeer(api.plauth, 'slice', slice['slice_id'], peer)
finally:
if peer:
- api.plshell.BindObjectToPeer(api.plauth, 'slice', slice.id, peer,
- slice.peer_id)
+ api.plshell.BindObjectToPeer(api.plauth, 'slice', slice['slice_id'], peer,
+ slice['peer_id'])
return aggregate.get_rspec(slice_xrn=slice_xrn, version=rspec.version)
start = RSpec
RSpec = element RSpec {
+ attribute expires { xsd:NMTOKEN },
+ attribute generated { xsd:NMTOKEN },
attribute type { xsd:NMTOKEN },
network
}
</start>
<define name="RSpec">
<element name="RSpec">
+ <attribute name="expires">
+ <data type="NMTOKEN"/>
+ </attribute>
+ <attribute name="generated">
+ <data type="NMTOKEN"/>
+ </attribute>
<attribute name="type">
<data type="NMTOKEN"/>
</attribute>
- <ref name="network"/>
+ <oneOrMore>
+ <ref name="network"/>
+ </oneOrMore>
</element>
</define>
<define name="network">
code_tag_parts = code_tag.split("-")
version_parts = code_tag_parts[0].split(".")
- major, minor = version_parts[0], version_parts[1]
+ major, minor = version_parts[0:2]
rev = code_tag_parts[1]
if int(major) > 1:
if int(minor) > 0 or int(rev) > 20:
def ListResources(api, creds, options, call_id):
- def _ListResources(server, credential, my_opts, call_id):
+ def _ListResources(server, credential, opts, call_id):
+
+ my_opts = copy(opts)
args = [credential, my_opts]
if _call_id_supported(api, server):
args.append(call_id)
+ version = api.get_cached_server_version(server)
+ # force ProtoGENI aggregates to give us a v2 RSpec
+ if 'sfa' not in version.keys():
+ my_opts['rspec_version'] = pg_rspec_ad_version
try:
return server.ListResources(*args)
except Exception, e:
# get slice's hrn from options
xrn = options.get('geni_slice_urn', '')
(hrn, type) = urn_to_hrn(xrn)
- my_opts = copy(options)
- my_opts['geni_compressed'] = False
- if 'rspec_version' in my_opts:
- del my_opts['rspec_version']
-
+ if 'geni_compressed' in options:
+ del(options['geni_compressed'])
+
# get the rspec's return format from options
rspec_version = RSpecVersion(options.get('rspec_version'))
version_string = "rspec_%s" % (rspec_version.get_version_name())
# unless the caller is the aggregate's SM
if caller_hrn == aggregate and aggregate != api.hrn:
continue
+
# get the rspec from the aggregate
server = api.aggregates[aggregate]
- #threads.run(server.ListResources, credentials, my_opts, call_id)
- threads.run(_ListResources, server, credentials, my_opts, call_id)
+ threads.run(_ListResources, server, credentials, options, call_id)
results = threads.get_results()
- rspec_version = RSpecVersion(my_opts.get('rspec_version'))
+ rspec_version = RSpecVersion(options.get('rspec_version'))
if rspec_version['type'] == pg_rspec_ad_version['type']:
rspec = PGRSpec()
else:
try:
rspec.merge(result)
except:
- api.logger.info("SM.ListResources: Failed to merge aggregate rspec")
+ api.logger.log_exc("SM.ListResources: Failed to merge aggregate rspec")
# cache the result
if caching and api.cache and not xrn:
# Need to call GetVersion at an aggregate to determine the supported
# rspec type/format beofre calling CreateSliver at an Aggregate.
server_version = api.get_cached_server_version(server)
- if 'sfa' not in aggregate_version and 'geni_api' in aggregate_version:
+ if 'sfa' not in server_version and 'geni_api' in server_version:
# sfa aggregtes support both sfa and pg rspecs, no need to convert
# if aggregate supports sfa rspecs. otherwise convert to pg rspec
rspec = RSpecConverter.to_pg_rspec(rspec)
args = [xrn, credential, rspec, users]
if _call_id_supported(api, server):
args.append(call_id)
- try:
- return server.CreateSliver(*args)
- except Exception, e:
- api.logger.warn("CreateSliver failed at %s: %s" %(server.url, str(e)))
+ return server.CreateSliver(*args)
except:
- logger.log_exc('Something wrong in _CreateSliver')
+ logger.log_exc('Something wrong in _CreateSliver with URL %s'%server.url)
if Callids().already_handled(call_id): return ""
# Validate the RSpec against PlanetLab's schema --disabled for now
def RenewSliver(api, xrn, creds, expiration_time, call_id):
def _RenewSliver(server, xrn, creds, expiration_time, call_id):
- server_version = _get_server_version(api, server)
+ server_version = api.get_cached_server_version(server)
args = [xrn, creds, expiration_time, call_id]
if _call_id_supported(api, server):
args.append(call_id)
def DeleteSliver(api, xrn, creds, call_id):
def _DeleteSliver(server, xrn, creds, call_id):
- server_version = _get_server_version(api, server)
+ server_version = api.get_cached_server_version(server)
args = [xrn, creds]
if _call_id_supported(api, server):
args.append(call_id)
# first draft at a merging SliverStatus
def SliverStatus(api, slice_xrn, creds, call_id):
def _SliverStatus(server, xrn, creds, call_id):
- server_version = _get_server_version(api, server)
+ server_version = api.get_cached_server_version(server)
args = [xrn, creds]
if _call_id_supported(api, server):
args.append(call_id)
#caching=False
def ListSlices(api, creds, call_id):
def _ListSlices(server, creds, call_id):
- server_version = _get_server_version(api, server)
+ server_version = api.get_cached_server_version(api, server)
args = [creds]
if _call_id_supported(api, server):
args.append(call_id)
start = RSpec
RSpec = element RSpec {
+ attribute expires { xsd:NMTOKEN },
+ attribute generated { xsd:NMTOKEN },
attribute type { xsd:NMTOKEN },
( network | request )
}
</start>
<define name="RSpec">
<element name="RSpec">
+ <attribute name="expires">
+ <data type="NMTOKEN"/>
+ </attribute>
+ <attribute name="generated">
+ <data type="NMTOKEN"/>
+ </attribute>
<attribute name="type">
<data type="NMTOKEN"/>
</attribute>
interfaces = {}
links = {}
node_tags = {}
+ pl_initscripts = {}
prepared=False
#panos new user options variable
user_options = {}
for node_tag in self.api.plshell.GetNodeTags(self.api.plauth):
self.node_tags[node_tag['node_tag_id']] = node_tag
+ def prepare_pl_initscripts(self, force=False):
+ if not self.pl_initscripts or force:
+ for initscript in self.api.plshell.GetInitScripts(self.api.plauth, {'enabled': True}):
+ self.pl_initscripts[initscript['initscript_id']] = initscript
+
def prepare(self, force=False):
if not self.prepared or force:
self.prepare_sites(force)
self.prepare_interfaces(force)
self.prepare_links(force)
self.prepare_node_tags(force)
+ self.prepare_pl_initscripts()
# add site/interface info to nodes
for node_id in self.nodes:
node = self.nodes[node_id]
else:
rspec = SfaRSpec(type=type, user_options=self.user_options)
-
- rspec.add_nodes(self.nodes.values())
- rspec.add_interfaces(self.interfaces.values())
- rspec.add_links(self.links.values())
-
+ # get slice details if specified
+ slice = None
if slice_xrn:
- # If slicename is specified then resulting rspec is a manifest.
- # Add sliver details to rspec and remove 'advertisement' elements
slice_hrn, _ = urn_to_hrn(slice_xrn)
slice_name = hrn_to_pl_slicename(slice_hrn)
slices = self.api.plshell.GetSlices(self.api.plauth, slice_name)
if slices:
- slice = slices[0]
- slivers = []
- tags = self.api.plshell.GetSliceTags(self.api.plauth, slice['slice_tag_ids'])
- for node_id in slice['node_ids']:
+ slice = slices[0]
+
+ # filter out nodes with a whitelist:
+ valid_nodes = []
+ for node in self.nodes.values():
+ # only doing this becuase protogeni rspec needs
+ # to advertise available initscripts
+ node['pl_initscripts'] = self.pl_initscripts
+ if not node['slice_ids_whitelist']:
+ valid_nodes.append(node)
+ elif slice and slice['slice_id'] in node['slice_ids_whitelist']:
+ valid_nodes.append(node)
+
+ rspec.add_nodes(valid_nodes)
+ rspec.add_interfaces(self.interfaces.values())
+ rspec.add_links(self.links.values())
+
+ # add slivers
+ if slice_xrn and slice:
+ slivers = []
+ tags = self.api.plshell.GetSliceTags(self.api.plauth, slice['slice_tag_ids'])
+ for node_id in slice['node_ids']:
+ try:
sliver = {}
sliver['hostname'] = self.nodes[node_id]['hostname']
+ sliver['node_id'] = node_id
+ sliver['slice_id'] = slice['slice_id']
sliver['tags'] = []
slivers.append(sliver)
for tag in tags:
tag_host = self.nodes[tag['node_id']]['hostname']
if tag_host == sliver['hostname']:
sliver['tags'].append(tag)
- rspec.add_slivers(slivers, sliver_urn=slice_xrn)
+ except:
+ self.api.logger.log_exc('unable to add sliver %s to node %s' % (slice['name'], node_id))
+ rspec.add_slivers(slivers, sliver_urn=slice_xrn)
return rspec.toxml(cleanup=True)
self.plauth = {'Username': self.config.SFA_PLC_USER,
'AuthMethod': 'password',
'AuthString': self.config.SFA_PLC_PASSWORD}
- try:
- sys.path.append(os.path.dirname(os.path.realpath("/usr/bin/plcsh")))
- self.plshell_type = 'direct'
- import PLC.Shell
- shell = PLC.Shell.Shell(globals = globals())
- except:
- self.plshell_type = 'xmlrpc'
- url = self.config.SFA_PLC_URL
- shell = xmlrpclib.Server(url, verbose = 0, allow_none = True)
+
+ # The native shell (PLC.Shell.Shell) is more efficient than xmlrpc,
+ # but it leaves idle db connections open. use xmlrpc until we can figure
+ # out why PLC.Shell.Shell doesn't close db connection properly
+ #try:
+ # sys.path.append(os.path.dirname(os.path.realpath("/usr/bin/plcsh")))
+ # self.plshell_type = 'direct'
+ # import PLC.Shell
+ # shell = PLC.Shell.Shell(globals = globals())
+ #except:
+ self.plshell_type = 'xmlrpc'
+ url = self.config.SFA_PLC_URL
+ shell = xmlrpclib.Server(url, verbose = 0, allow_none = True)
return shell
def getCredential(self):
auth_hrn = hrn
auth_info = self.auth.get_auth_info(auth_hrn)
table = self.SfaTable()
- records = table.findObjects(hrn)
+ records = table.findObjects({'hrn': hrn, 'type': 'authority+sa'})
if not records:
raise RecordNotFound
record = records[0]
from sfa.trust.hierarchy import *
from sfa.util.xrn import Xrn
from sfa.plc.api import *
-from sfa.util.sfalogging import logger
from sfa.trust.gid import create_uuid
from sfa.plc.sfaImport import sfaImport
# start importing
for site in sites:
site_hrn = interface_hrn + "." + site['login_base']
- logger.info("Importing site: %s" % site_hrn)
+ sfaImporter.logger.info("Importing site: %s" % site_hrn)
# import if hrn is not in list of existing hrns or if the hrn exists
# but its not a site record
class PGRSpec(RSpec):
xml = None
header = '<?xml version="1.0"?>\n'
- template = '<rspec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.protogeni.net/resources/rspec/2" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/%(rspec_type)s.xsd"/>'
+ template = '<rspec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.protogeni.net/resources/rspec/2" xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2 http://www.protogeni.net/resources/rspec/2/%(rspec_type)s.xsd" xmlns:flack="http://www.protogeni.net/resources/rspec/ext/flack/1" xmlns:planetlab="http://www.planet-lab.org/resources/ext/planetlab/1" />'
def __init__(self, rspec="", namespaces={}, type=None):
if not type:
self.template = self.template % {'rspec_type': rspec_type}
if not namespaces:
- self.namespaces = {'rspecv2': self.version['namespace']}
+ self.namespaces = {'rspecv2': self.version['namespace'],
+ 'flack': 'http://www.protogeni.net/resources/rspec/ext/flack/1',
+ 'planetlab': 'http://www.planet-lab.org/resources/ext/planetlab/1' }
+
else:
self.namespaces = namespaces
def get_network(self):
network = None
- nodes = self.xml.xpath('//rspecv2:node[@component_manager_uuid][1]', namespaces=self.namespaces)
+ nodes = self.xml.xpath('//rspecv2:node[@component_manager_id][1]', namespaces=self.namespaces)
if nodes:
- network = nodes[0].get('component_manager_uuid')
+ network = nodes[0].get('component_manager_id')
return network
def get_networks(self):
- networks = self.xml.xpath('//rspecv2:node[@component_manager_uuid]/@component_manager_uuid', namespaces=self.namespaces)
+ networks = self.xml.xpath('//rspecv2:node[@component_manager_id]/@component_manager_id', namespaces=self.namespaces)
return set(networks)
- def get_node_elements(self):
+ def get_node_element(self, hostname, network=None):
+ nodes = self.xml.xpath('//rspecv2:node[@component_id[contains(., "%s")]] | node[@component_id[contains(., "%s")]]' % (hostname, hostname), namespaces=self.namespaces)
+ if isinstance(nodes,list) and nodes:
+ return nodes[0]
+ else:
+ return None
+
+ def get_node_elements(self, network=None):
nodes = self.xml.xpath('//rspecv2:node | //node', namespaces=self.namespaces)
return nodes
def get_nodes_without_slivers(self, network=None):
return []
+
+ def get_sliver_attributes(self, hostname, network=None):
+ node = self.get_node_element(hostname, network)
+ sliver = node.xpath('./rspecv2:sliver_type', namespaces=self.namespaces)
+ if sliver is not None and isinstance(sliver, list):
+ sliver = sliver[0]
+ return self.attributes_list(sliver)
def get_slice_attributes(self, network=None):
- return []
+ slice_attributes = []
+ nodes_with_slivers = self.get_nodes_with_slivers(network)
+ # TODO: default sliver attributes in the PG rspec?
+ default_ns_prefix = self.namespaces['rspecv2']
+ for node in nodes_with_slivers:
+ sliver_attributes = self.get_sliver_attributes(node, network)
+ for sliver_attribute in sliver_attributes:
+ name=str(sliver_attribute[0])
+ text =str(sliver_attribute[1])
+ attribs = sliver_attribute[2]
+ # we currently only suppor the <initscript> and <flack> attributes
+ if 'info' in name:
+ attribute = {'name': 'flack_info', 'value': str(attribs), 'node_id': node}
+ slice_attributes.append(attribute)
+ elif 'initscript' in name:
+ if attribs is not None and 'name' in attribs:
+ value = attribs['name']
+ else:
+ value = text
+ attribute = {'name': 'initscript', 'value': value, 'node_id': node}
+ slice_attributes.append(attribute)
+
+ return slice_attributes
def attributes_list(self, elem):
opts = []
if elem is not None:
for e in elem:
- opts.append((e.tag, e.text))
+ opts.append((e.tag, e.text, e.attrib))
return opts
def get_default_sliver_attributes(self, network=None):
node_type_tag = etree.SubElement(node_tag, 'hardware_type', name='pc')
available_tag = etree.SubElement(node_tag, 'available', now='true')
sliver_type_tag = etree.SubElement(node_tag, 'sliver_type', name='plab-vnode')
+
+ pl_initscripts = node.get('pl_initscripts', {})
+ for pl_initscript in pl_initscripts.values():
+ etree.SubElement(sliver_type_tag, '{%s}initscript' % self.namespaces['planetlab'], name=pl_initscript['name'])
+
# protogeni uses the <sliver_type> tag to identify the types of
# vms available at the node.
# only add location tag if longitude and latitude are not null
# all nodes hould already be present in the rspec. Remove all
# nodes that done have slivers
slivers = self._process_slivers(slivers)
- sliver_hosts = [sliver['hostname'] for sliver in slivers]
+ slivers_dict = {}
+ for sliver in slivers:
+ slivers_dict[sliver['hostname']] = sliver
nodes = self.get_node_elements()
for node in nodes:
urn = node.get('component_id')
hostname = xrn_to_hostname(urn)
- if hostname not in sliver_hosts:
+ if hostname not in slivers_dict:
parent = node.getparent()
parent.remove(node)
else:
+ sliver_info = slivers_dict[hostname]
node.set('client_id', hostname)
if sliver_urn:
- node.set('sliver_id', sliver_urn)
+ slice_id = sliver_info.get('slice_id', -1)
+ node_id = sliver_info.get('node_id', -1)
+ sliver_id = urn_to_sliver_id(sliver_urn, slice_id, node_id)
+ node.set('sliver_id', sliver_id)
+
+ # remove existing sliver_type tags,it needs to be recreated
+ sliver_elem = node.xpath('./rspecv2:sliver_type | ./sliver_type', namespaces=self.namespaces)
+ if sliver_elem and isinstance(sliver_elem, list):
+ sliver_elem = sliver_elem[0]
+ node.remove(sliver_elem)
+
+ sliver_elem = etree.SubElement(node, 'sliver_type', name='plab-vnode')
+ for tag in sliver_info['tags']:
+ if tag['tagname'] == 'flack_info':
+ e = etree.SubElement(sliver_elem, '{%s}info' % self.namespaces['flack'], attrib=eval(tag['value']))
+ elif tag['tagname'] == 'initscript':
+ e = etree.SubElement(sliver_elem, '{%s}initscript' % self.namespaces['planetlab'], attrib={'name': tag['value']})
+
+
def add_default_sliver_attribute(self, name, value, network=None):
pass
nodes_with_slivers = pg_rspec.get_nodes_with_slivers()
i = 1
for pg_node_element in pg_nodes_elements:
- node_element = sfa_rspec.add_element('node', {'id': 'n'+str(i)}, parent=network_element)
- urn = pg_node_element.xpath('@component_uuid | @component_id')
+ attribs = dict(pg_node_element.attrib.items())
+ attribs['id'] = 'n'+str(i)
+
+ node_element = sfa_rspec.add_element('node', attribs, parent=network_element)
+ urn = pg_node_element.xpath('@component_id', namespaces=pg_rspec.namespaces)
if urn:
urn = urn[0]
hostname = Xrn.urn_split(urn)[-1]
--- /dev/null
+#
+## Extension for the "initscript" type for RSpecV2 on PlanetLab
+## Version 1
+##
+
+default namespace = "http://www.planet-lab.org/resources/ext/initscript/1"
+
+Node = element initscript {
+ attribute name { text }
+}
+
+start = Node
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Extension for the "initscript" type for RSpecV2 on PlanetLab
+ Version 1
+
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+elementFormDefault="qualified"
+targetNamespace="http://www.planet-lab.org/resources/ext/planetlab/1"
+xmlns:planetlab="http://www.planet-lab.org/resources/ext/planetlab/1">
+ <xs:element name="initscript">
+ <xs:complexType>
+ <xs:attribute name="name" use="required"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
elif rspec.version['type'] == pg_rspec_ad_version['type']:
return PGRSpecConverter.to_sfa_rspec(in_rspec)
else:
- return in_rspec
+ return in_rspec
@staticmethod
def to_pg_rspec(in_rspec):
if rspec.xml.xpath('//network'):
#out_rspec = SfaRSpec(in_rspec)
out_rspec = SfaRSpec()
+ out_rspec.type = 'SFA'
out_rspec.xml = rspec.xml
else:
#out_rspec = PGRSpec(in_rspec)
# TODO: determine if this is an ad or request
out_rspec = PGRSpec()
+ out_rspec.type = 'ProtoGENI'
out_rspec.xml = rspec.xml
return out_rspec
nodes = [node.strip() for node in nodes]
return nodes
+
def get_nodes_without_slivers(self, network=None):
xpath_nodes_without_slivers = '//node[not(sliver)]/hostname/text()'
xpath_nodes_without_slivers_in_network = '//network[@name="%s"]//node[not(sliver)]/hostname/text()'
node_tag = etree.SubElement(network_tag, 'node')
if 'network' in node:
- node_tag.set('component_manager_id', network)
+ node_tag.set('component_manager_id', hrn_to_urn(network, 'authority+sa'))
if 'urn' in node:
node_tag.set('component_id', node['urn'])
if 'site_urn' in node:
Merge contents for specified rspec with current rspec
"""
+ from sfa.rspecs.rspec_parser import parse_rspec
+ rspec = parse_rspec(in_rspec)
+ if rspec.type.lower() == 'protogeni':
+ from sfa.rspecs.rspec_converter import RSpecConverter
+ in_rspec = RSpecConverter.to_sfa_rspec(in_rspec)
+
# just copy over all networks
current_networks = self.get_networks()
rspec = SfaRSpec(rspec=in_rspec)
networks = rspec.get_network_elements()
for network in networks:
current_network = network.get('name')
- if not current_network in current_networks:
+ if current_network and current_network not in current_networks:
self.xml.append(network)
current_networks.append(current_network)
+
location = sfa_node_element.find('location')
if location != None:
location_attrs = {}
- location_attrs['country'] = locatiton.get('country', 'unknown')
+ location_attrs['country'] = location.get('country', 'unknown')
location_attrs['latitude'] = location.get('latitiue', 'None')
location_attrs['longitude'] = location.get('longitude', 'None')
pg_rspec.add_element('location', location_attrs, parent=node_element)
from sfa.util.sfatime import utcparse
from sfa.trust.certificate import Keypair
from sfa.trust.credential_legacy import CredentialLegacy
-from sfa.trust.rights import Right, Rights
+from sfa.trust.rights import Right, Rights, determine_rights
from sfa.trust.gid import GID
from sfa.util.xrn import urn_to_hrn
# Convert * into the default privileges for the credential's type
# Each inherits the delegatability from the * above
_ , type = urn_to_hrn(self.gidObject.get_urn())
- rl = rlist.determine_rights(type, self.gidObject.get_urn())
+ rl = determine_rights(type, self.gidObject.get_urn())
for r in rl.rights:
r.delegate = deleg
rlist.add(r)
if self.parent and dump_parents:
result += "\nPARENT"
- result += self.parent.dump(True)
+ result += self.parent.dump_string(True)
return result
print self.dump_string(*args,**kwargs)
def dump_string(self, indent=0, dump_parents=False):
- result="GID\n"
+ result=" "*(indent-2) + "GID\n"
result += " "*indent + "hrn:" + str(self.get_hrn()) +"\n"
result += " "*indent + "urn:" + str(self.get_urn()) +"\n"
result += " "*indent + "uuid:" + str(self.get_uuid()) + "\n"
elif type in ["sa", "authority+sa"]:
rl.add("authority")
rl.add("sa")
- elif type in ["ma", "authority+ma", "cm", "authority+cm"]:
+ elif type in ["ma", "authority+ma", "cm", "authority+cm", "sm", "authority+sm"]:
rl.add("authority")
rl.add("ma")
elif type == "authority":
return False
return True
-
-
- ##
- # Determine the rights that an object should have. The rights are entirely
- # dependent on the type of the object. For example, users automatically
- # get "refresh", "resolve", and "info".
- #
- # @param type the type of the object (user | sa | ma | slice | node)
- # @param name human readable name of the object (not used at this time)
- #
- # @return Rights object containing rights
-
- def determine_rights(self, type, name):
- rl = Rights()
-
- # rights seem to be somewhat redundant with the type of the credential.
- # For example, a "sa" credential implies the authority right, because
- # a sa credential cannot be issued to a user who is not an owner of
- # the authority
-
- if type == "user":
- rl.add("refresh")
- rl.add("resolve")
- rl.add("info")
- elif type in ["sa", "authority+sa"]:
- rl.add("authority")
- rl.add("sa")
- elif type in ["ma", "authority+ma", "cm", "authority+cm"]:
- rl.add("authority")
- rl.add("ma")
- elif type == "authority":
- rl.add("authority")
- rl.add("sa")
- rl.add("ma")
- elif type == "slice":
- rl.add("refresh")
- rl.add("embed")
- rl.add("bind")
- rl.add("control")
- rl.add("info")
- elif type == "component":
- rl.add("operator")
-
- return rl
-### $Id$
-### $URL$
+import os.path
+import glob
-import os
-
-from sfa.trust.gid import *
+from sfa.trust.gid import GID
class TrustedRootList:
def __init__(self, dir):
self.basedir = dir
-
- # create the directory to hold the files
- try:
+ # create the directory to hold the files, if not existing
+ if not os.path.isdir (self.basedir):
os.makedirs(self.basedir)
- # if the path already exists then pass
- except OSError, (errno, strerr):
- if errno == 17:
- pass
def add_gid(self, gid):
fn = os.path.join(self.basedir, gid.get_hrn() + ".gid")
-
gid.save_to_file(fn)
def get_list(self):
gid_list = []
- file_list = os.listdir(self.basedir)
- for gid_file in file_list:
- fn = os.path.join(self.basedir, gid_file)
- if os.path.isfile(fn):
- gid = GID(filename = fn)
+ pattern=os.path.join(self.basedir,"*.gid")
+ gid_files = glob.glob(pattern)
+ for gid_file in gid_files:
+ # ignore non-files
+ if os.path.isfile(gid_file):
+ gid = GID(filename = gid_file)
gid_list.append(gid)
return gid_list
def get_file_list(self):
gid_file_list = []
-
- file_list = os.listdir(self.basedir)
- for gid_file in file_list:
- fn = os.path.join(self.basedir, gid_file)
- if os.path.isfile(fn):
- gid_file_list.append(fn)
-
+ pattern=os.path.join(self.basedir,"*.gid")
+ gid_files = glob.glob(pattern)
+ for gid_file in gid_files:
+ # ignore non-files
+ if os.path.isfile(gid_file):
+ gid_file_list.append(gid_file)
return gid_file_list
# This is usually a permissions error becaue the file is
# owned by root, but httpd is trying to access it.
tmplogfile=os.getenv("TMPDIR", "/tmp") + os.path.sep + os.path.basename(logfile)
- handler=logging.handlers.RotatingFileHandler(tmplogfile,maxBytes=1000000, backupCount=5)
+ # In strange uses, 2 users on same machine might use same code,
+ # meaning they would clobber each others files
+ # We could (a) rename the tmplogfile, or (b)
+ # just log to the console in that case.
+ # Here we default to the console.
+ if os.path.exists(tmplogfile) and not os.access(tmplogfile,os.W_OK):
+ loggername = loggername + "-console"
+ handler = logging.StreamHandler()
+ else:
+ handler=logging.handlers.RotatingFileHandler(tmplogfile,maxBytes=1000000, backupCount=5)
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
self.logger=logging.getLogger(loggername)
self.logger.setLevel(level)
def warn(self, msg):
self.logger.warn(msg)
+
+ # some code is using logger.warn(), some is using logger.warning()
+ def warning(self, msg):
+ self.logger.warning(msg)
def error(self, msg):
self.logger.error(msg)
import traceback
import time
from Queue import Queue
+from sfa.util.sfalogging import logger
def ThreadedMethod(callable, results, errors):
"""
try:
results.put(callable(*args, **kwds))
except Exception, e:
+ logger.log_exc('ThreadManager: Error in thread: ')
errors.put(traceback.format_exc())
thread = ThreadInstance()
def urn_to_hrn(urn): xrn=Xrn(urn); return (xrn.hrn, xrn.type)
def hrn_to_urn(hrn,type): return Xrn(hrn, type=type).urn
+def urn_to_sliver_id(urn, slice_id, node_id, index=0):
+ urn = urn.replace('+slice+', '+sliver+')
+ return ":".join([urn, str(slice_id), str(node_id), str(index)])
+
class Xrn:
########## basic tools on HRNs