d7d77e4138449804e0c053cdf9aa467a2666286c
[plstackapi.git] / planetstack / core / views / legacyapi.py
1 import os
2 import json
3 import socket
4 import sys
5 import time
6 import traceback
7 import xmlrpclib
8
9 #  XXX for testing
10 #sys.path.append("/opt/planetstack")
11 #os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
12
13 from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
14
15 from django.http import HttpResponse
16 from django.views.decorators.csrf import csrf_exempt
17
18 def ps_id_to_pl_id(x):
19     # Since we don't want the PlanetStack object IDs to conflict with existing
20     # PlanetLab object IDs in the CMI, just add 100000 to the PlanetStack object
21     # IDs.
22     return 100000 + x
23
24 def pl_id_to_ps_id(x):
25     return x - 100000
26
27 # slice_remap is a dict of ps_slice_name -> (pl_slice_name, pl_slice_id)
28
29 def pl_slice_id(slice, slice_remap={}):
30     if slice.name in slice_remap:
31         return int(slice_remap[slice.name][1])
32     else:
33         return ps_id_to_pl_id(slice.id)
34
35 def pl_slicename(slice, slice_remap={}):
36     if slice.name in slice_remap:
37         return slice_remap[slice.name][0]
38     else:
39         return slice.name
40
41 def filter_fields(src, fields):
42     dest = {}
43     for (key,value) in src.items():
44         if (not fields) or (key in fields):
45             dest[key] = value
46     return dest
47
48 def GetSlices(filter={}, slice_remap={}):
49     #ps_slices = Slice.objects.filter(**filter)
50     ps_slices = Slice.objects.all()
51     slices = []
52     for ps_slice in ps_slices:
53         if (filter) and ("name" in filter):
54             remapped_name = slice_remap.get(ps_slice.name, (ps_slice.name,))[0]
55             if (remapped_name != filter["name"]):
56                 continue
57
58         node_ids=[]
59         for ps_sliver in ps_slice.slivers.all():
60             node_ids.append(ps_id_to_pl_id(ps_sliver.node.id))
61
62         slice = {"instantiation": "plc-instantiated",
63                  "description": "planetstack slice",
64                  "slice_id": pl_slice_id(ps_slice, slice_remap),
65                  "node_ids": node_ids,
66                  "url": "planetstack",
67                  "max_nodes": 1000,
68                  "peer_slice_id": None,
69                  "slice_tag_ids": [],
70                  "peer_id": None,
71                  "site_id": ps_id_to_pl_id(ps_slice.site_id),
72                  "name": pl_slicename(ps_slice, slice_remap),
73                  "planetstack_name": ps_slice.name}
74
75                  # creator_person_id, person_ids, expires, created
76
77         slices.append(slice)
78     return slices
79
80 def GetNodes(node_ids=None, fields=None, slice_remap={}):
81     if node_ids:
82         ps_nodes = Node.objects.filter(id__in=[pl_id_to_ps_id(nid) for nid in node_ids])
83     else:
84         ps_nodes = Node.objects.all()
85     nodes = []
86     for ps_node in ps_nodes:
87         slice_ids=[]
88         for ps_sliver in ps_node.slivers.all():
89             slice_ids.append(pl_slice_id(ps_sliver.slice, slice_remap))
90
91         node = {"node_id": ps_id_to_pl_id(ps_node.id),
92                 "site_id": ps_id_to_pl_id(ps_node.site_id),
93                 "node_type": "regular",
94                 "peer_node_id": None,
95                 "hostname": ps_node.name,
96                 "conf_file_ids": [],
97                 "slice_ids": slice_ids,
98                 "model": "planetstack",
99                 "peer_id": None,
100                 "node_tag_ids": []}
101
102                 # last_updated, key, boot_state, pcu_ids, node_type, session, last_boot,
103                 # interface_ids, slice_ids_whitelist, run_level, ssh_rsa_key, last_pcu_reboot,
104                 # nodegroup_ids, verified, last_contact, boot_nonce, version,
105                 # last_pcu_configuration, last_download, date_created, ports
106
107         nodes.append(node)
108
109     nodes = [filter_fields(node, fields) for node in nodes]
110
111     return nodes
112
113 def GetTags(slicename,node_id):
114     return {}
115
116 def GetSites(slice_remap={}):
117     ps_sites = Site.objects.all()
118     sites = []
119     for ps_site in ps_sites:
120         slice_ids=[]
121         for ps_slice in ps_site.slices.all():
122             slice_ids.append(pl_slice_id(ps_slice, slice_remap))
123
124         node_ids=[]
125         for ps_node in ps_site.nodes.all():
126             node_ids.append(ps_id_to_pl_id(ps_node.id))
127
128         site = {"site_id": ps_id_to_pl_id(ps_site.id),
129                 "node_ids": node_ids,
130                 "pcu_ids": [],
131                 "max_slices": 100,
132                 "max_slivers": 1000,
133                 "is_public": False,
134                 "peer_site_id": None,
135                 "abbrebiated_name": ps_site.abbreviated_name,
136                 "address_ids": [],
137                 "name": ps_site.name,
138                 "url": None,
139                 "site_tag_ids": [],
140                 "enabled": True,
141                 "longitude": float(ps_site.location.longitude),
142                 "latitude": float(ps_site.location.latitude),
143                 "slice_ids": slice_ids,
144                 "login_base": ps_site.login_base,
145                 "peer_id": None}
146
147                 # last_updated, ext_consortium_id, person_ids, date_created
148
149         sites.append(site)
150
151     return sites
152
153 def GetInterfaces(slicename, node_ids):
154     interfaces = []
155     ps_slices = Slice.objects.filter(name=slicename)
156     for ps_slice in ps_slices:
157         for ps_sliver in ps_slice.slivers.all():
158             node_id = ps_id_to_pl_id(ps_sliver.node_id)
159             if node_id in node_ids:
160                 ps_node = ps_sliver.node
161
162                 ip = socket.gethostbyname(ps_node.name)
163
164                 # search for a dedicated public IP address
165                 for networkSliver in ps_sliver.networksliver_set.all():
166                     if (not networkSliver.ip):
167                         continue
168                     template = networkSliver.network.template
169                     if (template.visibility=="public") and (template.translation=="none"):
170                         ip=networkSliver.ip
171
172                 interface = {"node_id": node_id,
173                              "ip": ip,
174                              "broadcast": None,
175                              "mac": "11:22:33:44:55:66",
176                              "bwlimit": None,
177                              "network": None,
178                              "is_primary": True,
179                              "dns1": None,
180                              "hostname": None,
181                              "netmask": None,
182                              "interface_tag_ids": [],
183                              "interface_id": node_id,     # assume each node has only one interface
184                              "gateway": None,
185                              "dns2": None,
186                              "type": "ipv4",
187                              "method": "dhcp"}
188                 interfaces.append(interface)
189     return interfaces
190
191 def GetConfiguration(name, slice_remap={}):
192     slicename = name["name"]
193     if "node_id" in name:
194         node_id = name["node_id"]
195     else:
196         node_id = 0
197
198     node_sliver_tags = GetTags(slicename, node_id)
199
200     slices = GetSlices({"name": slicename}, slice_remap=slice_remap)
201     perhost = {}
202     allinterfaces = {}
203     hostipmap = {}
204     nodes = []
205     if len(slices)==1:
206         slice = slices[0]
207         node_ids = slice['node_ids']
208         nodes = GetNodes(node_ids, ['hostname', 'node_id', 'site_id'], slice_remap=slice_remap)
209         nodemap = {}
210         for node in nodes:
211             nodemap[node['node_id']]=node['hostname']
212
213         interfaces = GetInterfaces(slice["planetstack_name"], node_ids)
214         print "XXX", interfaces
215         hostipmap = {}
216         for interface in interfaces:
217             if nodemap[interface['node_id']] not in allinterfaces:
218                 allinterfaces[nodemap[interface['node_id']]] = []
219             interface['interface_tags'] = []
220             allinterfaces[nodemap[interface['node_id']]].append(interface)
221             if interface['is_primary']:
222                 hostipmap[nodemap[interface['node_id']]] = interface['ip']
223
224         for nid in node_ids:
225             sliver_tags = GetTags(slicename,nid)
226             perhost[nodemap[nid]] = sliver_tags
227
228     slivers = GetSlices(slice_remap=slice_remap)
229     if node_id != 0:
230         slivers = [slice for slice in slivers if (node_id in slice.node_ids)]
231
232     sites = GetSites(slice_remap=slice_remap)
233     for site in sites:
234         site["site_tags"] = []
235
236     timestamp = int(time.time())
237     return {'version': 3,
238             'timestamp': timestamp,
239             'configuration': node_sliver_tags,
240             'allconfigurations':perhost,
241             'hostipmap':hostipmap,
242             'slivers': slivers,
243             'interfaces': allinterfaces,
244             'sites': sites,
245             'nodes': nodes}
246
247 DEFAULT_REMAP = {"princeton_vcoblitz2": ["princeton_vcoblitz", 70]}
248
249 def HandleGetConfiguration1():
250     configs={}
251     for slicename in ["princeton_vcoblitz"]:
252         configs[slicename] = GetConfiguration({"name": slicename}, DEFAULT_REMAP)
253     return configs
254
255 def HandleGetNodes1():
256     return GetNodes(slice_remap=DEFAULT_REMAP)
257
258 def HandleGetSlices1():
259     return GetSlices(slice_remap=DEFAULT_REMAP)
260
261 def HandleGetConfiguration2(name, slice_remap):
262     return GetConfiguration(name, slice_remap=slice_remap)
263
264 def HandleGetNodes2(slice_remap):
265     return GetNodes(slice_remap=slice_remap)
266
267 def HandleGetSlices2(slice_remap):
268     return GetSlices(slice_remap=slice_remap)
269
270 FUNCS = {"GetConfiguration": HandleGetConfiguration1,
271          "GetNodes": HandleGetNodes1,
272          "GetSlices": HandleGetSlices1,
273          "GetConfiguration2": HandleGetConfiguration2,
274          "GetNodes2": HandleGetNodes2,
275          "GetSlices2": HandleGetSlices2}
276
277 @csrf_exempt
278 def LegacyXMLRPC(request):
279     if request.method == "POST":
280         try:
281             (args, method) = xmlrpclib.loads(request.body)
282             result = None
283             if method in FUNCS:
284                 result = FUNCS[method](*args)
285             return HttpResponse(xmlrpclib.dumps((result,), methodresponse=True, allow_none=1))
286         except:
287             traceback.print_exc()
288             return HttpResponseServerError()
289     else:
290         return HttpResponse("Not Implemented")
291
292 if __name__ == '__main__':
293     slices = GetSlices(slice_remap = DEFAULT_REMAP)
294     nodes = GetNodes(slice_remap = DEFAULT_REMAP)
295
296     if ("-d" in sys.argv):
297         config = GetConfiguration({"name": "princeton_vcoblitz"}, slice_remap = DEFAULT_REMAP)
298         print config
299         print slices
300         print nodes
301     else:
302         configs={}
303         configs[slicename] = GetConfiguration({"name": "princeton_vcoblitz"})
304
305         file("planetstack_config","w").write(json.dumps(configs))
306         file("planetstack_slices","w").write(json.dumps(slices))
307         file("planetstack_nodes","w").write(json.dumps(nodes))