PGv2 and GENIv3 Rspec: handle PL initscript and attribute exceptions
[sfa.git] / sfa / rspecs / elements / versions / pgv2Node.py
1 from sfa.util.xrn import Xrn, get_leaf
2 from sfa.util.xml import XpathFilter
3
4 from sfa.rspecs.elements.node import NodeElement
5 from sfa.rspecs.elements.sliver import Sliver
6 from sfa.rspecs.elements.location import Location
7 from sfa.rspecs.elements.hardware_type import HardwareType
8 from sfa.rspecs.elements.disk_image import DiskImage
9 from sfa.rspecs.elements.interface import Interface
10 from sfa.rspecs.elements.bwlimit import BWlimit
11 from sfa.rspecs.elements.pltag import PLTag
12 from sfa.rspecs.elements.versions.pgv2Services import PGv2Services     
13 from sfa.rspecs.elements.versions.pgv2SliverType import PGv2SliverType     
14 from sfa.rspecs.elements.versions.pgv2Interface import PGv2Interface     
15 from sfa.rspecs.elements.versions.sfav1PLTag import SFAv1PLTag
16 from sfa.rspecs.elements.granularity import Granularity
17 from sfa.rspecs.elements.attribute import Attribute
18
19
20 class PGv2Node:
21     @staticmethod
22     def add_nodes(xml, nodes, rspec_content_type=None):
23         node_elems = []
24         for node in nodes:
25             node_fields = ['component_manager_id', 'component_id', 'client_id', 'sliver_id', 'exclusive']
26             node_elem = xml.add_instance('node', node, node_fields)
27             node_elems.append(node_elem)
28             # set component name
29             if node.get('component_id'):
30                 component_name = Xrn.unescape(get_leaf(Xrn(node['component_id']).get_hrn()))
31                 node_elem.set('component_name', component_name)
32             # set hardware types
33             if node.get('hardware_types'):
34                 for hardware_type in node.get('hardware_types', []): 
35                     node_elem.add_instance('hardware_type', hardware_type, HardwareType.fields)
36             # set location
37             if node.get('location'):
38                 node_elem.add_instance('location', node['location'], Location.fields)       
39
40             # set granularity
41             if node.get('exclusive') == "true":
42                 granularity = node.get('granularity')
43                 node_elem.add_instance('granularity', granularity, granularity.fields)
44             # set interfaces
45             PGv2Interface.add_interfaces(node_elem, node.get('interfaces'))
46             #if node.get('interfaces'):
47             #    for interface in  node.get('interfaces', []):
48             #        node_elem.add_instance('interface', interface, ['component_id', 'client_id'])
49             # set available element
50             if node.get('available'):
51                 available_elem = node_elem.add_element('available', now=node['available'])
52             # add services
53             PGv2Services.add_services(node_elem, node.get('services', [])) 
54             # add slivers
55             slivers = node.get('slivers', [])
56             if not slivers:
57                 # we must still advertise the available sliver types
58                 slivers = Sliver({'type': 'plab-vserver'})
59                 # we must also advertise the available initscripts
60                 slivers['tags'] = []
61                 if node.get('pl_initscripts'): 
62                     for initscript in node.get('pl_initscripts', []):
63                         slivers['tags'].append({'name': 'initscript', 'value': initscript['name']})
64             PGv2SliverType.add_slivers(node_elem, slivers)
65
66             # advertise the node tags
67             tags = node.get('tags', [])
68             if tags:
69                for tag in tags:
70                     tag['name'] = tag.pop('tagname')
71                     node_elem.add_instance('{%s}attribute' % xml.namespaces['planetlab'], tag, ['name', 'value'])
72
73             # add sliver tag in Request Rspec
74             if rspec_content_type == "request":
75                 node_elem.add_instance('sliver', '', [])
76
77         return node_elems
78
79
80     @staticmethod
81     def get_nodes(xml, filter={}):
82         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
83         node_elems = xml.xpath(xpath)
84         return PGv2Node.get_node_objs(node_elems)
85
86     @staticmethod
87     def get_nodes_with_slivers(xml, filter={}):
88         xpath = '//node[count(sliver_type)>0] | //default:node[count(default:sliver_type) > 0]' 
89         node_elems = xml.xpath(xpath)        
90         return PGv2Node.get_node_objs(node_elems)
91
92     @staticmethod
93     def get_node_objs(node_elems):
94         nodes = []
95         for node_elem in node_elems:
96             node = NodeElement(node_elem.attrib, node_elem)
97             nodes.append(node) 
98             if 'component_id' in node_elem.attrib:
99                 node['authority_id'] = Xrn(node_elem.attrib['component_id']).get_authority_urn()
100             
101             # get hardware types
102             hardware_type_elems = node_elem.xpath('./default:hardware_type | ./hardware_type')
103             node['hardware_types'] = [dict(hw_type.get_instance(HardwareType)) for hw_type in hardware_type_elems]
104             
105             # get location
106             location_elems = node_elem.xpath('./default:location | ./location')
107             locations = [dict(location_elem.get_instance(Location)) for location_elem in location_elems]
108             if len(locations) > 0:
109                 node['location'] = locations[0]
110
111             # get granularity
112             granularity_elems = node_elem.xpath('./default:granularity | ./granularity')
113             if len(granularity_elems) > 0:
114                 node['granularity'] = granularity_elems[0].get_instance(Granularity)
115
116             # get interfaces
117             iface_elems = node_elem.xpath('./default:interface | ./interface')
118             node['interfaces'] = [dict(iface_elem.get_instance(Interface)) for iface_elem in iface_elems]
119
120             # get services
121             node['services'] = PGv2Services.get_services(node_elem)
122             
123             # get slivers
124             node['slivers'] = PGv2SliverType.get_slivers(node_elem)    
125             
126             # get boot state
127             available_elems = node_elem.xpath('./default:available | ./available')
128             if len(available_elems) > 0 and 'now' in available_elems[0].attrib:
129                 if available_elems[0].attrib.get('now', '').lower() == 'true': 
130                     node['boot_state'] = 'boot'
131                 else: 
132                     node['boot_state'] = 'disabled' 
133
134             # get initscripts
135             try:
136                node['pl_initscripts'] = []
137                initscript_elems = node_elem.xpath('./default:sliver_type/planetlab:initscript | ./sliver_type/initscript')
138                if len(initscript_elems) > 0:
139                    for initscript_elem in initscript_elems:
140                         if 'name' in initscript_elem.attrib:
141                             node['pl_initscripts'].append(dict(initscript_elem.attrib))
142             except:
143                pass
144
145             # get node tags
146             try:
147                tag_elems = node_elem.xpath('./planetlab:attribute | ./attribute')
148                node['tags'] = []
149                if len(tag_elems) > 0:
150                    for tag_elem in tag_elems:
151                         tag = dict(tag_elem.get_instance(Attribute))
152                         tag['tagname'] = tag.pop('name')
153                         node['tags'].append(tag)
154             except:
155                pass
156   
157         return nodes
158
159
160     @staticmethod
161     def add_slivers(xml, slivers):
162         component_ids = []
163         for sliver in slivers:
164             filter = {}
165             if isinstance(sliver, str):
166                 filter['component_id'] = '*%s*' % sliver
167                 sliver = {}
168             elif 'component_id' in sliver and sliver['component_id']:
169                 filter['component_id'] = '*%s*' % sliver['component_id']
170             if not filter: 
171                 continue
172             nodes = PGv2Node.get_nodes(xml, filter)
173             if not nodes:
174                 continue
175             node = nodes[0]
176             PGv2SliverType.add_slivers(node, sliver)
177
178     @staticmethod
179     def remove_slivers(xml, hostnames):
180         for hostname in hostnames:
181             nodes = PGv2Node.get_nodes(xml, {'component_id': '*%s*' % hostname})
182             for node in nodes:
183                 slivers = PGv2SliverType.get_slivers(node.element)
184                 for sliver in slivers:
185                     node.element.remove(sliver.element) 
186 if __name__ == '__main__':
187     from sfa.rspecs.rspec import RSpec
188     import pdb
189     r = RSpec('/tmp/emulab.rspec')
190     r2 = RSpec(version = 'ProtoGENI')
191     nodes = PGv2Node.get_nodes(r.xml)
192     PGv2Node.add_nodes(r2.xml.root, nodes)
193     #pdb.set_trace()
194         
195