Merge Master in geni-v3 conflict resolution
[sfa.git] / sfa / rspecs / elements / versions / sfav1Node.py
1 from sfa.util.sfalogging import logger
2 from sfa.util.xml import XpathFilter
3 from sfa.util.xrn import Xrn
4
5 from sfa.rspecs.elements.element import Element
6 from sfa.rspecs.elements.node import NodeElement
7 from sfa.rspecs.elements.sliver import Sliver
8 from sfa.rspecs.elements.location import Location
9 from sfa.rspecs.elements.hardware_type import HardwareType
10 from sfa.rspecs.elements.disk_image import DiskImage
11 from sfa.rspecs.elements.interface import Interface
12 from sfa.rspecs.elements.bwlimit import BWlimit
13 from sfa.rspecs.elements.pltag import PLTag
14 from sfa.rspecs.elements.versions.sfav1Sliver import SFAv1Sliver
15 from sfa.rspecs.elements.versions.sfav1PLTag import SFAv1PLTag
16 from sfa.rspecs.elements.versions.pgv2Services import PGv2Services
17
18 from sfa.planetlab.plxrn import xrn_to_hostname
19
20 class SFAv1Node:
21
22     @staticmethod
23     def add_nodes(xml, nodes):
24         network_elems = xml.xpath('//network')
25         if len(network_elems) > 0:
26             network_elem = network_elems[0]
27         elif len(nodes) > 0 and nodes[0].get('component_manager_id'):
28             network_urn = nodes[0]['component_manager_id']
29             network_elem = xml.add_element('network', name = Xrn(network_urn).get_hrn())
30         else:
31             network_elem = xml
32
33         node_elems = []       
34         for node in nodes:
35             node_fields = ['component_manager_id', 'component_id', 'boot_state']
36             node_elem = network_elem.add_instance('node', node, node_fields)
37             node_elems.append(node_elem)
38
39             # determine network hrn
40             network_hrn = None 
41             if 'component_manager_id' in node and node['component_manager_id']:
42                 network_hrn = Xrn(node['component_manager_id']).get_hrn()
43
44             # set component_name attribute and  hostname element
45             if 'component_id' in node and node['component_id']:
46                 component_name = xrn_to_hostname(node['component_id'])
47                 node_elem.set('component_name', component_name)
48                 hostname_elem = node_elem.add_element('hostname')
49                 hostname_elem.set_text(component_name)
50
51             # set site id
52             if 'authority_id' in node and node['authority_id']:
53                 node_elem.set('site_id', node['authority_id'])
54
55             # add locaiton
56             location = node.get('location')
57             if location:
58                 node_elem.add_instance('location', location, Location.fields)
59
60             # add exclusive tag to distinguish between Reservable and Shared nodes
61             exclusive_elem = node_elem.add_element('exclusive')
62             if node.get('exclusive') and node.get('exclusive') == 'true':
63                 exclusive_elem.set_text('TRUE')
64                 # add granularity of the reservation system
65                 granularity = node.get('granularity')
66                 if granularity:
67                     node_elem.add_instance('granularity', granularity, granularity.fields)
68             else:
69                 exclusive_elem.set_text('FALSE')
70
71
72             if isinstance(node.get('interfaces'), list):
73                 for interface in node.get('interfaces', []):
74                     node_elem.add_instance('interface', interface, ['component_id', 'client_id', 'ipv4']) 
75             
76             #if 'bw_unallocated' in node and node['bw_unallocated']:
77             #    bw_unallocated = etree.SubElement(node_elem, 'bw_unallocated', units='kbps').text = str(int(node['bw_unallocated'])/1000)
78
79             PGv2Services.add_services(node_elem, node.get('services', []))
80             tags = node.get('tags', [])
81             if tags:
82                 for tag in tags:
83                     # backdoor for FITeagle
84                     # Alexander Willner <alexander.willner@tu-berlin.de>
85                     if tag['tagname']=="fiteagle_settings":
86                         tag_elem = node_elem.add_element(tag['tagname'])
87                         for subtag in tag['value']:
88                             subtag_elem = tag_elem.add_element('setting')
89                             subtag_elem.set('name', str(subtag['tagname']))
90                             subtag_elem.set('description', str(subtag['description']))
91                             subtag_elem.set_text(subtag['value'])
92                     else:
93                         tag_elem = node_elem.add_element(tag['tagname'])
94                         tag_elem.set_text(tag['value'])
95             SFAv1Sliver.add_slivers(node_elem, node.get('slivers', []))
96
97     @staticmethod 
98     def add_slivers(xml, slivers):
99         component_ids = []
100         for sliver in slivers:
101             filter = {}
102             if isinstance(sliver, str):
103                 filter['component_id'] = '*%s*' % sliver
104                 sliver = {}
105             elif 'component_id' in sliver and sliver['component_id']:
106                 filter['component_id'] = '*%s*' % sliver['component_id']
107             if not filter:
108                 continue 
109             nodes = SFAv1Node.get_nodes(xml, filter)
110             if not nodes:
111                 continue
112             node = nodes[0]
113             SFAv1Sliver.add_slivers(node, sliver)
114
115     @staticmethod
116     def remove_slivers(xml, hostnames):
117         for hostname in hostnames:
118             nodes = SFAv1Node.get_nodes(xml, {'component_id': '*%s*' % hostname})
119             for node in nodes:
120                 slivers = SFAv1Sliver.get_slivers(node.element)
121                 for sliver in slivers:
122                     node.element.remove(sliver.element)
123         
124     @staticmethod
125     def get_nodes(xml, filter={}):
126         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
127         node_elems = xml.xpath(xpath)
128         return SFAv1Node.get_node_objs(node_elems)
129
130     @staticmethod
131     def get_nodes_with_slivers(xml):
132         xpath = '//node[count(sliver)>0] | //default:node[count(default:sliver)>0]' 
133         node_elems = xml.xpath(xpath)
134         return SFAv1Node.get_node_objs(node_elems)
135
136
137     @staticmethod
138     def get_node_objs(node_elems):
139         nodes = []    
140         for node_elem in node_elems:
141             node = NodeElement(node_elem.attrib, node_elem)
142             if 'site_id' in node_elem.attrib:
143                 node['authority_id'] = node_elem.attrib['site_id']
144             # get location
145             location_elems = node_elem.xpath('./default:location | ./location')
146             locations = [loc_elem.get_instance(Location) for loc_elem in location_elems]  
147             if len(locations) > 0:
148                 node['location'] = locations[0]
149             # get bwlimit
150             bwlimit_elems = node_elem.xpath('./default:bw_limit | ./bw_limit')
151             bwlimits = [bwlimit_elem.get_instance(BWlimit) for bwlimit_elem in bwlimit_elems]
152             if len(bwlimits) > 0:
153                 node['bwlimit'] = bwlimits[0]
154             # get interfaces
155             iface_elems = node_elem.xpath('./default:interface | ./interface')
156             ifaces = [iface_elem.get_instance(Interface) for iface_elem in iface_elems]
157             node['interfaces'] = ifaces
158             # get services
159             node['services'] = PGv2Services.get_services(node_elem) 
160             # get slivers
161             node['slivers'] = SFAv1Sliver.get_slivers(node_elem)
162             # get tags
163             node['tags'] =  SFAv1PLTag.get_pl_tags(node_elem, ignore=NodeElement.fields+["hardware_type"])
164             # get hardware types
165             hardware_type_elems = node_elem.xpath('./default:hardware_type | ./hardware_type')
166             node['hardware_types'] = [hw_type.get_instance(HardwareType) for hw_type in hardware_type_elems]
167
168             # temporary... play nice with old slice manager rspec
169             if not node['component_name']:
170                 hostname_elem = node_elem.find("hostname")
171                 if hostname_elem != None:
172                     node['component_name'] = hostname_elem.text
173
174             nodes.append(node)
175         return nodes            
176