9 from geni.util.misc import *
10 from geni.util.rspec import *
11 from geni.util.specdict import *
12 from geni.util.faults import *
13 from geni.util.storage import *
14 from geni.util.debug import log
15 from geni.util.rspec import *
16 from geni.util.specdict import *
17 from geni.aggregate import Aggregates
18 from geni.util.policy import Policy
20 class Nodes(SimpleStorage):
22 def __init__(self, api, ttl = 1):
26 path = self.api.config.basepath
27 filename = ".".join([self.api.interface, self.api.hrn, "nodes"])
28 filepath = path + os.sep + filename
29 self.nodes_file = filepath
30 SimpleStorage.__init__(self, self.nodes_file)
31 self.policy = Policy(api)
37 Update the cached list of nodes
40 # Reload components list
41 now = datetime.datetime.now()
42 if not self.has_key('threshold') or not self.has_key('timestamp') or \
43 now > datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format))):
44 if self.api.interface in ['aggregate']:
45 self.refresh_nodes_aggregate()
46 elif self.api.interface in ['slicemgr']:
47 self.refresh_nodes_smgr()
50 def refresh_nodes_aggregate(self):
52 rspec.parseString(self.get_rspec())
54 # filter nodes according to policy
55 blist = self.policy['node_blacklist']
56 wlist = self.policy['node_whitelist']
57 rspec.filter('NodeSpec', 'name', blacklist=blist, whitelist=wlist)
59 # extract ifspecs from rspec to get ips'
61 ifspecs = rspec.getDictsByTagName('IfSpec')
62 for ifspec in ifspecs:
63 if ifspec.has_key('addr') and ifspec['addr']:
64 ips.append(ifspec['addr'])
66 # extract nodespecs from rspec to get dns names
68 nodespecs = rspec.getDictsByTagName('NodeSpec')
69 for nodespec in nodespecs:
70 if nodespec.has_key('name') and nodespec['name']:
71 hostnames.append(nodespec['name'])
73 # update timestamp and threshold
74 timestamp = datetime.datetime.now()
75 hr_timestamp = timestamp.strftime(self.api.time_format)
76 delta = datetime.timedelta(hours=self.ttl)
77 threshold = timestamp + delta
78 hr_threshold = threshold.strftime(self.api.time_format)
81 node_details['rspec'] = rspec.toxml()
82 node_details['ip'] = ips
83 node_details['dns'] = hostnames
84 node_details['timestamp'] = hr_timestamp
85 node_details['threshold'] = hr_threshold
87 self.update(node_details)
90 def refresh_nodes_smgr(self):
91 # convert and threshold to ints
92 if self.has_key('timestamp') and self['timestamp']:
93 hr_timestamp = self['timestamp']
94 timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(hr_timestamp, self.api.time_format)))
95 hr_threshold = self['threshold']
96 threshold = datetime.datetime.fromtimestamp(time.mktime(time.strptime(hr_threshold, self.api.time_format)))
98 timestamp = datetime.datetime.now()
99 hr_timestamp = timestamp.strftime(self.api.time_format)
100 delta = datetime.timedelta(hours=self.ttl)
101 threshold = timestamp + delta
102 hr_threshold = threshold.strftime(self.api.time_format)
104 start_time = int(timestamp.strftime("%s"))
105 end_time = int(threshold.strftime("%s"))
106 duration = end_time - start_time
108 aggregates = Aggregates(self.api)
112 credential = self.api.getCredential()
113 for aggregate in aggregates:
115 # get the rspec from the aggregate
116 agg_rspec = aggregates[aggregate].get_resources(credential)
117 # extract the netspec from each aggregates rspec
118 rspec.parseString(agg_rspec)
119 networks.extend([{'NetSpec': rspec.getDictsByTagName('NetSpec')}])
122 # XX print out to some error log
123 print >> log, "Error calling list nodes at aggregate %s" % aggregate
124 # create the rspec dict
125 resources = {'networks': networks, 'start_time': start_time, 'duration': duration}
126 resourceDict = {'Rspec': resources}
127 # convert rspec dict to xml
128 rspec.parseDict(resourceDict)
130 # filter according to policy
131 blist = self.policy['node_blacklist']
132 wlist = self.policy['node_whitelist']
133 rspec.filter('NodeSpec', 'name', blacklist=blist, whitelist=wlist)
135 # update timestamp and threshold
136 timestamp = datetime.datetime.now()
137 hr_timestamp = timestamp.strftime(self.api.time_format)
138 delta = datetime.timedelta(hours=self.ttl)
139 threshold = timestamp + delta
140 hr_threshold = threshold.strftime(self.api.time_format)
142 nodedict = {'rspec': rspec.toxml(),
143 'timestamp': hr_timestamp,
144 'threshold': hr_threshold}
146 self.update(nodedict)
150 def get_rspec(self, hrn = None):
152 Get resource information from PLC
155 # Get the required nodes
157 nodes = self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None})
158 try: linkspecs = self.api.plshell.GetLinkSpecs() # if call is supported
159 except: linkspecs = []
161 slicename = hrn_to_pl_slicename(hrn)
162 slices = self.api.plshell.GetSlices(self.api.plauth, [slicename])
167 node_ids = slice['node_ids']
168 nodes = self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None, 'node_id': node_ids})
170 # Filter out whitelisted nodes
171 public_nodes = lambda n: n.has_key('slice_ids_whitelist') and not n['slice_ids_whitelist']
172 nodes = filter(public_nodes, nodes)
174 # Get all network interfaces
177 # The field name has changed in plcapi 4.3
178 if self.api.plshell_version in ['4.2']:
179 interface_ids.extend(node['nodenetwork_ids'])
180 elif self.api.plshell_version in ['4.3']:
181 interface_ids.extend(node['interface_ids'])
183 raise GeniAPIError, "Unsupported plcapi version ", \
184 self.api.plshell_version
186 if self.api.plshell_version in ['4.2']:
187 interfaces = self.api.plshell.GetNodeNetworks(self.api.plauth, interface_ids)
188 elif self.api.plshell_version in ['4.3']:
189 interfaces = self.api.plshell.GetInterfaces(self.api.plauth, interface_ids)
191 raise GeniAPIError, "Unsupported plcapi version ", \
192 self.api.plshell_version
194 for interface in interfaces:
195 if self.api.plshell_version in ['4.2']:
196 interface_dict[interface['nodenetwork_id']] = interface
197 elif self.api.plshell_version in ['4.3']:
198 interface_dict[interface['interface_id']] = interface
200 raise GeniAPIError, "Unsupported plcapi version", \
201 self.api.plshell_version
203 # join nodes with thier interfaces
205 node['interfaces'] = []
206 if self.api.plshell_version in ['4.2']:
207 for nodenetwork_id in node['nodenetwork_ids']:
208 node['interfaces'].append(interface_dict[nodenetwork_id])
209 elif self.api.plshell_version in ['4.3']:
210 for interface_id in node['interface_ids']:
211 node['interfaces'].append(interface_dict[interface_id])
213 raise GeniAPIError, "Unsupported plcapi version", \
214 self.api.plshell_version
216 # convert and threshold to ints
217 if self.has_key('timestamp') and self['timestamp']:
218 timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['timestamp'], self.api.time_format)))
219 threshold = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format)))
221 timestamp = datetime.datetime.now()
222 delta = datetime.timedelta(hours=self.ttl)
223 threshold = timestamp + delta
225 start_time = int(timestamp.strftime("%s"))
226 end_time = int(threshold.strftime("%s"))
227 duration = end_time - start_time
229 # create the plc dict
230 networks = [{'nodes': nodes,
231 'name': self.api.hrn,
232 'start_time': start_time,
233 'duration': duration}]
235 networks[0]['links'] = linkspecs
236 resources = {'networks': networks, 'start_time': start_time, 'duration': duration}
238 # convert the plc dict to an rspec dict
239 resourceDict = RspecDict(resources)
240 # convert the rspec dict to xml
242 rspec.parseDict(resourceDict)