blob: e14c1cb991bf5ba38ff2cf54de60c9967eadbbef [file] [log] [blame]
Matteo Scandoloede125b2017-08-08 13:05:25 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Scott Baker25467ff2016-08-04 09:50:22 -070017import os
18import json
19import socket
20import sys
21import time
22import traceback
23import xmlrpclib
24
25from core.models import Slice, Instance, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
26
27from django.http import HttpResponse
28from django.views.decorators.csrf import csrf_exempt
Scott Bakerc2a4d322016-08-09 09:16:57 -070029from rest_framework.views import APIView
Scott Baker25467ff2016-08-04 09:50:22 -070030
31def ps_id_to_pl_id(x):
32 # Since we don't want the XOS object IDs to conflict with existing
33 # PlanetLab object IDs in the CMI, just add 100000 to the XOS object
34 # IDs.
35 return 100000 + x
36
37def pl_id_to_ps_id(x):
38 return x - 100000
39
40# slice_remap is a dict of ps_slice_name -> (pl_slice_name, pl_slice_id)
41
42def pl_slice_id(slice, slice_remap={}):
43 if slice.name in slice_remap:
44 return int(slice_remap[slice.name][1])
45 else:
46 return ps_id_to_pl_id(slice.id)
47
48def pl_slicename(slice, slice_remap={}):
49 if slice.name in slice_remap:
50 return slice_remap[slice.name][0]
51 else:
52 return slice.name
53
54def filter_fields(src, fields):
55 dest = {}
56 for (key,value) in src.items():
57 if (not fields) or (key in fields):
58 dest[key] = value
59 return dest
60
61def GetSlices(filter={}, slice_remap={}):
62 #ps_slices = Slice.objects.filter(**filter)
63 ps_slices = Slice.objects.all()
64 slices = []
65 for ps_slice in ps_slices:
66 if (filter) and ("name" in filter):
67 remapped_name = slice_remap.get(ps_slice.name, (ps_slice.name,))[0]
68 if (remapped_name != filter["name"]):
69 continue
70
71 node_ids=[]
72 for ps_instance in ps_slice.instances.all():
73 node_ids.append(ps_id_to_pl_id(ps_instance.node.id))
74
75 slice = {"instantiation": "plc-instantiated",
76 "description": "XOS slice",
77 "slice_id": pl_slice_id(ps_slice, slice_remap),
78 "node_ids": node_ids,
79 "url": "xos",
80 "max_nodes": 1000,
81 "peer_slice_id": None,
82 "slice_tag_ids": [],
83 "peer_id": None,
84 "site_id": ps_id_to_pl_id(ps_slice.site_id),
85 "name": pl_slicename(ps_slice, slice_remap),
86 "planetstack_name": ps_slice.name} # keeping planetstack_name for now, to match the modified config.py
87
88 # creator_person_id, person_ids, expires, created
89
90 slices.append(slice)
91 return slices
92
93def GetNodes(node_ids=None, fields=None, slice_remap={}):
94 if node_ids:
95 ps_nodes = Node.objects.filter(id__in=[pl_id_to_ps_id(nid) for nid in node_ids])
96 else:
97 ps_nodes = Node.objects.all()
98 nodes = []
99 for ps_node in ps_nodes:
100 slice_ids=[]
101 for ps_instance in ps_node.instances.all():
102 slice_ids.append(pl_slice_id(ps_instance.slice, slice_remap))
103
104 node = {"node_id": ps_id_to_pl_id(ps_node.id),
105 "site_id": ps_id_to_pl_id(ps_node.site_id),
106 "node_type": "regular",
107 "peer_node_id": None,
108 "hostname": ps_node.name.lower(),
109 "conf_file_ids": [],
110 "slice_ids": slice_ids,
111 "model": "xos",
112 "peer_id": None,
113 "node_tag_ids": []}
114
115 # last_updated, key, boot_state, pcu_ids, node_type, session, last_boot,
116 # interface_ids, slice_ids_whitelist, run_level, ssh_rsa_key, last_pcu_reboot,
117 # nodegroup_ids, verified, last_contact, boot_nonce, version,
118 # last_pcu_configuration, last_download, date_created, ports
119
120 nodes.append(node)
121
122 nodes = [filter_fields(node, fields) for node in nodes]
123
124 return nodes
125
126def GetTags(slicename,node_id):
127 return {}
128
129def GetSites(slice_remap={}):
130 ps_sites = Site.objects.all()
131 sites = []
132 for ps_site in ps_sites:
133 slice_ids=[]
134 for ps_slice in ps_site.slices.all():
135 slice_ids.append(pl_slice_id(ps_slice, slice_remap))
136
137 node_ids=[]
138 for ps_node in ps_site.nodes.all():
139 node_ids.append(ps_id_to_pl_id(ps_node.id))
140
141 if ps_site.location:
142 longitude = ps_site.location.longitude
143 latitude = ps_site.location.latitude
144 else:
145 longitude = 0
146 latitude = 0
147
148 site = {"site_id": ps_id_to_pl_id(ps_site.id),
149 "node_ids": node_ids,
150 "pcu_ids": [],
151 "max_slices": 100,
152 "max_instances": 1000,
153 "is_public": False,
154 "peer_site_id": None,
155 "abbrebiated_name": ps_site.abbreviated_name,
156 "address_ids": [],
157 "name": ps_site.name,
158 "url": None,
159 "site_tag_ids": [],
160 "enabled": True,
161 "longitude": float(longitude),
162 "latitude": float(latitude),
163 "slice_ids": slice_ids,
164 "login_base": ps_site.login_base,
165 "peer_id": None}
166
167 # last_updated, ext_consortium_id, person_ids, date_created
168
169 sites.append(site)
170
171 return sites
172
173def GetInterfaces(slicename, node_ids, return_nat=False, return_private=False):
174 interfaces = []
175 ps_slices = Slice.objects.filter(name=slicename)
176 for ps_slice in ps_slices:
177 for ps_instance in ps_slice.instances.all():
178 node_id = ps_id_to_pl_id(ps_instance.node_id)
179 if node_id in node_ids:
180 ps_node = ps_instance.node
181
182 ip = socket.gethostbyname(ps_node.name.strip())
183
184 # If the slice has a network that's labeled for hpc_client, then
185 # return that network.
186 found_labeled_network = False
187 for port in ps_instance.ports.all():
188 if (not port.ip):
189 continue
190 if (port.network.owner != ps_slice):
191 continue
192 if port.network.labels and ("hpc_client" in port.network.labels):
193 ip=port.ip
194 found_labeled_network = True
195
196 if not found_labeled_network:
197 # search for a dedicated public IP address
198 for port in ps_instance.ports.all():
199 if (not port.ip):
200 continue
201 template = port.network.template
202 if (template.visibility=="public") and (template.translation=="none"):
203 ip=port.ip
204
205 if return_nat:
206 ip = None
207 for port in ps_instance.ports.all():
208 if (not port.ip):
209 continue
210 template = port.network.template
211 if (template.visibility=="private") and (template.translation=="NAT"):
212 ip=port.ip
213 if not ip:
214 continue
215
216 if return_private:
217 ip = None
218 for port in ps_instance.ports.all():
219 if (not port.ip):
220 continue
221 template = port.network.template
222 if (template.visibility=="private") and (template.translation=="none"):
223 ip=port.ip
224 if not ip:
225 continue
226
227 interface = {"node_id": node_id,
228 "ip": ip,
229 "broadcast": None,
230 "mac": "11:22:33:44:55:66",
231 "bwlimit": None,
232 "network": None,
233 "is_primary": True,
234 "dns1": None,
235 "hostname": None,
236 "netmask": None,
237 "interface_tag_ids": [],
238 "interface_id": node_id, # assume each node has only one interface
239 "gateway": None,
240 "dns2": None,
241 "type": "ipv4",
242 "method": "dhcp"}
243 interfaces.append(interface)
244 return interfaces
245
246def GetConfiguration(name, slice_remap={}):
247 slicename = name["name"]
248 if "node_id" in name:
249 node_id = name["node_id"]
250 else:
251 node_id = 0
252
253 node_instance_tags = GetTags(slicename, node_id)
254
255 slices = GetSlices({"name": slicename}, slice_remap=slice_remap)
256 perhost = {}
257 allinterfaces = {}
258 hostprivmap = {}
259 hostipmap = {}
260 hostnatmap = {}
261 nodes = []
262 if len(slices)==1:
263 slice = slices[0]
264 node_ids = slice['node_ids']
265 nodes = GetNodes(node_ids, ['hostname', 'node_id', 'site_id'], slice_remap=slice_remap)
266 nodemap = {}
267 for node in nodes:
268 nodemap[node['node_id']]=node['hostname']
269
270 interfaces = GetInterfaces(slice["planetstack_name"], node_ids)
271 hostipmap = {}
272 for interface in interfaces:
273 if nodemap[interface['node_id']] not in allinterfaces:
274 allinterfaces[nodemap[interface['node_id']]] = []
275 interface['interface_tags'] = []
276 allinterfaces[nodemap[interface['node_id']]].append(interface)
277 if interface['is_primary']:
278 hostipmap[nodemap[interface['node_id']]] = interface['ip']
279
280 hostnatmap = {}
281 interfaces = GetInterfaces(slice["planetstack_name"], node_ids, return_nat=True)
282 for interface in interfaces:
283 interface['interface_tags'] = []
284 hostnatmap[nodemap[interface['node_id']]] = interface['ip']
285
286 hostprivmap = {}
287 interfaces = GetInterfaces(slice["planetstack_name"], node_ids, return_private=True)
288 for interface in interfaces:
289 interface['interface_tags'] = []
290 hostprivmap[nodemap[interface['node_id']]] = interface['ip']
291
292 for nid in node_ids:
293 instance_tags = GetTags(slicename,nid)
294 perhost[nodemap[nid]] = instance_tags
295
296 instances = GetSlices(slice_remap=slice_remap)
297 if node_id != 0:
298 instances = [slice for slice in instances if (node_id in slice.node_ids)]
299
300 sites = GetSites(slice_remap=slice_remap)
301 for site in sites:
302 site["site_tags"] = []
303
304 timestamp = int(time.time())
305 return {'version': 3,
306 'timestamp': timestamp,
307 'configuration': node_instance_tags,
308 'allconfigurations':perhost,
309 'hostipmap':hostipmap,
310 'hostnatmap':hostnatmap,
311 'hostprivmap':hostprivmap,
312 'slivers': instances,
313 'interfaces': allinterfaces,
314 'sites': sites,
315 'nodes': nodes}
316
317DEFAULT_REMAP = {"princeton_vcoblitz2": ["princeton_vcoblitz", 70]}
318
319def HandleGetConfiguration1():
320 configs={}
321 for slicename in ["princeton_vcoblitz"]:
322 configs[slicename] = GetConfiguration({"name": slicename}, DEFAULT_REMAP)
323 return configs
324
325def HandleGetNodes1():
326 return GetNodes(slice_remap=DEFAULT_REMAP)
327
328def HandleGetSlices1():
329 return GetSlices(slice_remap=DEFAULT_REMAP)
330
331def HandleGetConfiguration2(name, slice_remap):
332 return GetConfiguration(name, slice_remap=slice_remap)
333
334def HandleGetNodes2(slice_remap):
335 return GetNodes(slice_remap=slice_remap)
336
337def HandleGetSlices2(slice_remap):
338 return GetSlices(slice_remap=slice_remap)
339
340FUNCS = {"GetConfiguration": HandleGetConfiguration1,
341 "GetNodes": HandleGetNodes1,
342 "GetSlices": HandleGetSlices1,
343 "GetConfiguration2": HandleGetConfiguration2,
344 "GetNodes2": HandleGetNodes2,
345 "GetSlices2": HandleGetSlices2}
346
Scott Bakerc2a4d322016-08-09 09:16:57 -0700347#@csrf_exempt
348class LegacyApi(APIView):
349 method_kind = "list"
350 method_name = "legacyapi"
351
352 def post(self, request, format=None):
Scott Baker25467ff2016-08-04 09:50:22 -0700353 try:
354 (args, method) = xmlrpclib.loads(request.body)
355 result = None
356 if method in FUNCS:
357 result = FUNCS[method](*args)
358 return HttpResponse(xmlrpclib.dumps((result,), methodresponse=True, allow_none=1))
359 except:
360 traceback.print_exc()
361 return HttpResponseServerError()
Scott Baker25467ff2016-08-04 09:50:22 -0700362
363if __name__ == '__main__':
364 slices = GetSlices(slice_remap = DEFAULT_REMAP)
365 nodes = GetNodes(slice_remap = DEFAULT_REMAP)
366
367 config = GetConfiguration({"name": "princeton_vcoblitz"}, slice_remap = DEFAULT_REMAP)
368 print config
369 print slices
370 print nodes
371