From: Tony Mack Date: Mon, 21 Jan 2013 04:40:20 +0000 (-0500) Subject: include opstates in ad rspec. include ssh-user in manifest rspec X-Git-Tag: sfa-3.0-0~18 X-Git-Url: http://git.onelab.eu/?p=sfa.git;a=commitdiff_plain;h=e7b000568a55c9fc04ac4dc1783833447350f897 include opstates in ad rspec. include ssh-user in manifest rspec --- diff --git a/sfa/planetlab/plaggregate.py b/sfa/planetlab/plaggregate.py index 6ad1e471..1095f8d1 100644 --- a/sfa/planetlab/plaggregate.py +++ b/sfa/planetlab/plaggregate.py @@ -136,10 +136,42 @@ class PlAggregate: filter['name'] = list(names) if slice_ids: filter['slice_id'] = list(slice_ids) + # get slices slices = self.driver.shell.GetSlices(filter) if not slices: return [] - slice = slices[0] + slice = slices[0] + + # get sliver users + persons = [] + person_ids = [] + for slice in slices: + person_ids.extend(slice['person_ids']) + if person_ids: + persons = self.driver.shell.GetPersons(person_ids) + + # get user keys + keys = {} + key_ids = [] + for person in persons: + key_ids.extend(person['key_ids']) + + if key_ids: + key_list = self.driver.shell.GetKeys(key_ids) + for key in key_list: + keys[key['key_id']] = key + + # construct user key info + users = [] + for person in persons: + name = person['email'][0:person['email'].index('@')] + user = { + 'login': slice['name'], + 'user_urn': Xrn('%s.%s' % (self.driver.hrn, name), type='user').urn, + 'keys': [keys[k_id]['key'] for k_id in person['key_ids'] if k_id in keys] + } + users.append(user) + if node_ids: node_ids = [node_id for node_id in node_ids if node_id in slice['node_ids']] slice['node_ids'] = node_ids @@ -152,6 +184,7 @@ class PlAggregate: sliver_hrn = '%s.%s-%s' % (self.driver.hrn, slice['slice_id'], node['node_id']) node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn node['urn'] = node['sliver_id'] + node['services_user'] = users slivers.append(node) return slivers @@ -220,8 +253,14 @@ class PlAggregate: rspec_node['slivers'] = [rspec_sliver] # slivers always provide the ssh service - login = Login({'authentication': 'ssh-keys', 'hostname': sliver['hostname'], 'port':'22', 'username': sliver['name']}) - service = Services({'login': login}) + login = Login({'authentication': 'ssh-keys', + 'hostname': sliver['hostname'], + 'port':'22', + 'username': sliver['name'], + 'login': sliver['name'] + }) + service = Services({'login': login, + 'services_user': sliver['services_user']}) rspec_node['services'] = [service] return rspec_node diff --git a/sfa/rspecs/elements/login.py b/sfa/rspecs/elements/login.py index 99dc5c3b..51741a9b 100644 --- a/sfa/rspecs/elements/login.py +++ b/sfa/rspecs/elements/login.py @@ -5,5 +5,5 @@ class Login(Element): 'authentication', 'hostname', 'port', - 'username' + 'username', ] diff --git a/sfa/rspecs/elements/services.py b/sfa/rspecs/elements/services.py index df0546d4..e90b6455 100644 --- a/sfa/rspecs/elements/services.py +++ b/sfa/rspecs/elements/services.py @@ -6,5 +6,6 @@ class Services(Element): 'install', 'execute', 'login', + 'services_user', ] diff --git a/sfa/rspecs/elements/v3/__init__.py b/sfa/rspecs/elements/v3/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sfa/rspecs/elements/v3/node.py b/sfa/rspecs/elements/v3/node.py new file mode 100644 index 00000000..f8c0d012 --- /dev/null +++ b/sfa/rspecs/elements/v3/node.py @@ -0,0 +1,145 @@ +from sfa.util.xrn import Xrn +from sfa.util.xml import XpathFilter + +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.v3.services import Services +from sfa.rspecs.elements.versions.pgv2SliverType import PGv2SliverType +from sfa.rspecs.elements.versions.pgv2Interface import PGv2Interface + +from sfa.planetlab.plxrn import xrn_to_hostname + +class Node: + @staticmethod + def add_nodes(xml, nodes): + node_elems = [] + for node in nodes: + node_fields = ['component_manager_id', 'component_id', 'client_id', 'sliver_id', 'exclusive'] + node_elem = xml.add_instance('node', node, node_fields) + node_elems.append(node_elem) + # set component name + if node.get('component_id'): + component_name = xrn_to_hostname(node['component_id']) + node_elem.set('component_name', component_name) + # set hardware types + if node.get('hardware_types'): + for hardware_type in node.get('hardware_types', []): + node_elem.add_instance('hardware_type', hardware_type, HardwareType.fields) + # set location + if node.get('location'): + node_elem.add_instance('location', node['location'], Location.fields) + # set interfaces + PGv2Interface.add_interfaces(node_elem, node.get('interfaces')) + #if node.get('interfaces'): + # for interface in node.get('interfaces', []): + # node_elem.add_instance('interface', interface, ['component_id', 'client_id']) + # set available element + if node.get('available'): + available_elem = node_elem.add_element('available', now=node['available']) + # add services + Services.add_services(node_elem, node.get('services', [])) + # add slivers + slivers = node.get('slivers', []) + if not slivers: + # we must still advertise the available sliver types + slivers = Sliver({'type': 'plab-vserver'}) + # we must also advertise the available initscripts + slivers['tags'] = [] + if node.get('pl_initscripts'): + for initscript in node.get('pl_initscripts', []): + slivers['tags'].append({'name': 'initscript', 'value': initscript['name']}) + PGv2SliverType.add_slivers(node_elem, slivers) + + return node_elems + + @staticmethod + def get_nodes(xml, filter={}): + xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter)) + node_elems = xml.xpath(xpath) + return Node.get_node_objs(node_elems) + + @staticmethod + def get_nodes_with_slivers(xml, filter={}): + xpath = '//node[count(sliver_type)>0] | //default:node[count(default:sliver_type) > 0]' + node_elems = xml.xpath(xpath) + return Node.get_node_objs(node_elems) + + @staticmethod + def get_node_objs(node_elems): + nodes = [] + for node_elem in node_elems: + node = Node(node_elem.attrib, node_elem) + nodes.append(node) + if 'component_id' in node_elem.attrib: + node['authority_id'] = Xrn(node_elem.attrib['component_id']).get_authority_urn() + + # get hardware types + hardware_type_elems = node_elem.xpath('./default:hardware_type | ./hardware_type') + node['hardware_types'] = [hw_type.get_instance(HardwareType) for hw_type in hardware_type_elems] + + # get location + location_elems = node_elem.xpath('./default:location | ./location') + locations = [location_elem.get_instance(Location) for location_elem in location_elems] + if len(locations) > 0: + node['location'] = locations[0] + + # get interfaces + iface_elems = node_elem.xpath('./default:interface | ./interface') + node['interfaces'] = [iface_elem.get_instance(Interface) for iface_elem in iface_elems] + + # get services + node['services'] = Services.get_services(node_elem) + + # get slivers + node['slivers'] = PGv2SliverType.get_slivers(node_elem) + available_elems = node_elem.xpath('./default:available | ./available') + if len(available_elems) > 0 and 'name' in available_elems[0].attrib: + if available_elems[0].attrib.get('now', '').lower() == 'true': + node['boot_state'] = 'boot' + else: + node['boot_state'] = 'disabled' + return nodes + + + @staticmethod + def add_slivers(xml, slivers): + component_ids = [] + for sliver in slivers: + filter = {} + if isinstance(sliver, str): + filter['component_id'] = '*%s*' % sliver + sliver = {} + elif 'component_id' in sliver and sliver['component_id']: + filter['component_id'] = '*%s*' % sliver['component_id'] + if not filter: + continue + nodes = Node.get_nodes(xml, filter) + if not nodes: + continue + node = nodes[0] + PGv2SliverType.add_slivers(node, sliver) + + @staticmethod + def remove_slivers(xml, hostnames): + for hostname in hostnames: + nodes = Node.get_nodes(xml, {'component_id': '*%s*' % hostname}) + for node in nodes: + slivers = PGv2SliverType.get_slivers(node.element) + for sliver in slivers: + node.element.remove(sliver.element) +if __name__ == '__main__': + from sfa.rspecs.rspec import RSpec + import pdb + r = RSpec('/tmp/emulab.rspec') + r2 = RSpec(version = 'GENI') + nodes = Node.get_nodes(r.xml) + Node.add_nodes(r2.xml.root, nodes) + #pdb.set_trace() + + diff --git a/sfa/rspecs/elements/v3/services.py b/sfa/rspecs/elements/v3/services.py new file mode 100644 index 00000000..b4ac1cac --- /dev/null +++ b/sfa/rspecs/elements/v3/services.py @@ -0,0 +1,60 @@ +from sfa.rspecs.elements.element import Element +from sfa.rspecs.elements.execute import Execute +from sfa.rspecs.elements.install import Install +from sfa.rspecs.elements.services import Services +from sfa.rspecs.elements.login import Login + +class Services: + @staticmethod + def add_services(xml, services): + if not services: + return + for service in services: + service_elem = xml.add_element('services') + child_elements = {'install': Install.fields, + 'execute': Execute.fields, + 'login': Login.fields} + for (name, fields) in child_elements.items(): + child = service.get(name) + if not child: + continue + if isinstance(child, dict): + service_elem.add_instance(name, child, fields) + elif isinstance(child, list): + for obj in child: + service_elem.add_instance(name, obj, fields) + + # add ssh_users + if service['services_user']: + for ssh_user in service['services_user']: + ssh_user_elem = service_elem.add_element('{%s}services_user' % xml.namespaces['ssh-user'], + login=ssh_user['login'], + user_urn=ssh_user['user_urn']) + for key in ssh_user['keys']: + pkey_elem = ssh_user_elem.add_element('{%s}public_key' % xml.namespaces['ssh-user']) + pkey_elem.element.text=key + + + @staticmethod + def get_services(xml): + services = [] + for services_elem in xml.xpath('./default:services | ./services'): + service = Services(services_elem.attrib, services_elem) + # get install + install_elems = xml.xpath('./default:install | ./install') + service['install'] = [install_elem.get_instance(Install) for install_elem in install_elems] + # get execute + execute_elems = xml.xpath('./default:execute | ./execute') + service['execute'] = [execute_elem.get_instance(Execute) for execute_elem in execute_elems] + # get login + login_elems = xml.xpath('./default:login | ./login') + service['login'] = [login_elem.get_instance(Login) for login_elem in login_elems] + + ssh_user_elems = xml.xpath('./ssh-user:service_user | ./service_user') + service_users = [] + for ssh_user_elem in ssh_user_elems: + service_user = ssh_user_elem.get_instance(None, fields=['login', 'user_urn']) + service['services_user'] = service_user + services.append(service) + return services + diff --git a/sfa/rspecs/versions/pgv3.py b/sfa/rspecs/versions/pgv3.py index 47f0daed..43b744c2 100644 --- a/sfa/rspecs/versions/pgv3.py +++ b/sfa/rspecs/versions/pgv3.py @@ -1,4 +1,5 @@ from sfa.rspecs.versions.pgv2 import PGv2 +from sfa.rspecs.elements.v3.node import Node class GENIv3(PGv2): type = 'GENI' @@ -19,7 +20,34 @@ class GENIv3Ad(GENIv3): enabled = True content_type = 'ad' schema = 'http://www.geni.net/resources/rspec/3/ad.xsd' - template = '' + template = """ + + + + + + Boot the node + + VMs begin powered down or inactive. They + must be explicitly booted before use. + + + + + Booting takes a significant amount of time, so it + happens asynchronously while the node is in this + state. + + + The node is up and ready to use. + + + The node has failed and requires administrator + intervention before it can be used. Please contact support + for assistance. + + +""" class GENIv3Request(GENIv3): enabled = True @@ -31,5 +59,11 @@ class GENIv2Manifest(GENIv3): enabled = True content_type = 'manifest' schema = 'http://www.geni.net/resources/rspec/3/manifest.xsd' - template = '' - + template = '' + + + def add_nodes(self, nodes, check_for_dupes=False): + return Node.add_nodes(self.xml, nodes) + + def get_nodes(self, filter=None): + return Node.get_nodes(self.xml, filter)