Merge branch 'upstreammaster'
[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 Node
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                     tag_elem = node_elem.add_element(tag['tagname'])
84                     tag_elem.set_text(tag['value'])
85             SFAv1Sliver.add_slivers(node_elem, node.get('slivers', []))
86
87     @staticmethod 
88     def add_slivers(xml, slivers):
89         component_ids = []
90         for sliver in slivers:
91             filter = {}
92             if isinstance(sliver, str):
93                 filter['component_id'] = '*%s*' % sliver
94                 sliver = {}
95             elif 'component_id' in sliver and sliver['component_id']:
96                 filter['component_id'] = '*%s*' % sliver['component_id']
97             if not filter:
98                 continue 
99             nodes = SFAv1Node.get_nodes(xml, filter)
100             if not nodes:
101                 continue
102             node = nodes[0]
103             SFAv1Sliver.add_slivers(node, sliver)
104
105     @staticmethod
106     def remove_slivers(xml, hostnames):
107         for hostname in hostnames:
108             nodes = SFAv1Node.get_nodes(xml, {'component_id': '*%s*' % hostname})
109             for node in nodes:
110                 slivers = SFAv1Sliver.get_slivers(node.element)
111                 for sliver in slivers:
112                     node.element.remove(sliver.element)
113         
114     @staticmethod
115     def get_nodes(xml, filter={}):
116         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
117         node_elems = xml.xpath(xpath)
118         return SFAv1Node.get_node_objs(node_elems)
119
120     @staticmethod
121     def get_nodes_with_slivers(xml):
122         xpath = '//node[count(sliver)>0] | //default:node[count(default:sliver)>0]' 
123         node_elems = xml.xpath(xpath)
124         return SFAv1Node.get_node_objs(node_elems)
125
126
127     @staticmethod
128     def get_node_objs(node_elems):
129         nodes = []    
130         for node_elem in node_elems:
131             node = Node(node_elem.attrib, node_elem)
132             if 'site_id' in node_elem.attrib:
133                 node['authority_id'] = node_elem.attrib['site_id']
134             # get location
135             location_elems = node_elem.xpath('./default:location | ./location')
136             locations = [loc_elem.get_instance(Location) for loc_elem in location_elems]  
137             if len(locations) > 0:
138                 node['location'] = locations[0]
139             # get bwlimit
140             bwlimit_elems = node_elem.xpath('./default:bw_limit | ./bw_limit')
141             bwlimits = [bwlimit_elem.get_instance(BWlimit) for bwlimit_elem in bwlimit_elems]
142             if len(bwlimits) > 0:
143                 node['bwlimit'] = bwlimits[0]
144             # get interfaces
145             iface_elems = node_elem.xpath('./default:interface | ./interface')
146             ifaces = [iface_elem.get_instance(Interface) for iface_elem in iface_elems]
147             node['interfaces'] = ifaces
148             # get services
149             node['services'] = PGv2Services.get_services(node_elem) 
150             # get slivers
151             node['slivers'] = SFAv1Sliver.get_slivers(node_elem)
152             # get tags
153             node['tags'] =  SFAv1PLTag.get_pl_tags(node_elem, ignore=Node.fields+["hardware_type"])
154             # get hardware types
155             hardware_type_elems = node_elem.xpath('./default:hardware_type | ./hardware_type')
156             node['hardware_types'] = [hw_type.get_instance(HardwareType) for hw_type in hardware_type_elems]
157
158             # temporary... play nice with old slice manager rspec
159             if not node['component_name']:
160                 hostname_elem = node_elem.find("hostname")
161                 if hostname_elem != None:
162                     node['component_name'] = hostname_elem.text
163
164             nodes.append(node)
165         return nodes            
166