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