rspec.version.add_nodes take an extra arg to handle Request RSpec
[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={}):
129         xpath = '//node%s | //default:node%s' % (XpathFilter.xpath(filter), XpathFilter.xpath(filter))
130         node_elems = xml.xpath(xpath)
131         return SFAv1Node.get_node_objs(node_elems)
132
133     @staticmethod
134     def get_nodes_with_slivers(xml):
135         xpath = '//node[count(sliver)>0] | //default:node[count(default:sliver)>0]' 
136         node_elems = xml.xpath(xpath)
137         return SFAv1Node.get_node_objs(node_elems)
138
139
140     @staticmethod
141     def get_node_objs(node_elems):
142         nodes = []    
143         for node_elem in node_elems:
144             node = NodeElement(node_elem.attrib, node_elem)
145             if 'site_id' in node_elem.attrib:
146                 node['authority_id'] = node_elem.attrib['site_id']
147             # get location
148             location_elems = node_elem.xpath('./default:location | ./location')
149             locations = [dict(loc_elem.get_instance(Location)) for loc_elem in location_elems]  
150             if len(locations) > 0:
151                 node['location'] = locations[0]
152             # get bwlimit
153             bwlimit_elems = node_elem.xpath('./default:bw_limit | ./bw_limit')
154             bwlimits = [bwlimit_elem.get_instance(BWlimit) for bwlimit_elem in bwlimit_elems]
155             if len(bwlimits) > 0:
156                 node['bwlimit'] = bwlimits[0]
157             # get interfaces
158             iface_elems = node_elem.xpath('./default:interface | ./interface')
159             ifaces = [dict(iface_elem.get_instance(Interface)) for iface_elem in iface_elems]
160             node['interfaces'] = ifaces
161             # get services
162             node['services'] = PGv2Services.get_services(node_elem) 
163             # get slivers
164             node['slivers'] = SFAv1Sliver.get_slivers(node_elem)
165             # get tags
166             node['tags'] =  SFAv1PLTag.get_pl_tags(node_elem, ignore=NodeElement.fields+["hardware_type"])
167             # get hardware types
168             hardware_type_elems = node_elem.xpath('./default:hardware_type | ./hardware_type')
169             node['hardware_types'] = [dict(hw_type.get_instance(HardwareType)) for hw_type in hardware_type_elems]
170
171             # temporary... play nice with old slice manager rspec
172             if not node['component_name']:
173                 hostname_elem = node_elem.find("hostname")
174                 if hostname_elem != None:
175                     node['component_name'] = hostname_elem.text
176
177             nodes.append(node)
178         return nodes            
179