add slice_remap argument to RPC calls
[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                 interface = {"node_id": node_id,
162                              "ip": socket.gethostbyname(ps_node.name),
163                              "broadcast": None,
164                              "mac": "11:22:33:44:55:66",
165                              "bwlimit": None,
166                              "network": None,
167                              "is_primary": True,
168                              "dns1": None,
169                              "hostname": None,
170                              "netmask": None,
171                              "interface_tag_ids": [],
172                              "interface_id": node_id,     # assume each node has only one interface
173                              "gateway": None,
174                              "dns2": None,
175                              "type": "ipv4",
176                              "method": "dhcp"}
177                 interfaces.append(interface)
178     return interfaces
179
180 def GetConfiguration(name, slice_remap={}):
181     slicename = name["name"]
182     if "node_id" in name:
183         node_id = name["node_id"]
184     else:
185         node_id = 0
186
187     node_sliver_tags = GetTags(slicename, node_id)
188
189     slices = GetSlices({"name": slicename}, slice_remap=slice_remap)
190     perhost = {}
191     allinterfaces = {}
192     hostipmap = {}
193     nodes = []
194     if len(slices)==1:
195         slice = slices[0]
196         node_ids = slice['node_ids']
197         nodes = GetNodes(node_ids, ['hostname', 'node_id', 'site_id'], slice_remap=slice_remap)
198         nodemap = {}
199         for node in nodes:
200             nodemap[node['node_id']]=node['hostname']
201
202         interfaces = GetInterfaces(slice["planetstack_name"], node_ids)
203         print "XXX", interfaces
204         hostipmap = {}
205         for interface in interfaces:
206             if nodemap[interface['node_id']] not in allinterfaces:
207                 allinterfaces[nodemap[interface['node_id']]] = []
208             interface['interface_tags'] = []
209             allinterfaces[nodemap[interface['node_id']]].append(interface)
210             if interface['is_primary']:
211                 hostipmap[nodemap[interface['node_id']]] = interface['ip']
212
213         for nid in node_ids:
214             sliver_tags = GetTags(slicename,nid)
215             perhost[nodemap[nid]] = sliver_tags
216
217     slivers = GetSlices(slice_remap=slice_remap)
218     if node_id != 0:
219         slivers = [slice for slice in slivers if (node_id in slice.node_ids)]
220
221     sites = GetSites(slice_remap=slice_remap)
222     for site in sites:
223         site["site_tags"] = []
224
225     timestamp = int(time.time())
226     return {'version': 3,
227             'timestamp': timestamp,
228             'configuration': node_sliver_tags,
229             'allconfigurations':perhost,
230             'hostipmap':hostipmap,
231             'slivers': slivers,
232             'interfaces': allinterfaces,
233             'sites': sites,
234             'nodes': nodes}
235
236 DEFAULT_REMAP = {"princeton_vcoblitz2": ["princeton_vcoblitz", 70]}
237
238 def HandleGetConfiguration1():
239     configs={}
240     for slicename in ["princeton_vcoblitz"]:
241         configs[slicename] = GetConfiguration({"name": slicename}, DEFAULT_REMAP)
242     return configs
243
244 def HandleGetNodes1():
245     return GetNodes(slice_remap=DEFAULT_REMAP)
246
247 def HandleGetSlices1():
248     return GetSlices(slice_remap=DEFAULT_REMAP)
249
250 def HandleGetConfiguration2(name, slice_remap):
251     return GetConfiguration(name, slice_remap=slice_remap)
252
253 def HandleGetNodes2(slice_remap):
254     return GetNodes(slice_remap=slice_remap)
255
256 def HandleGetSlices2(slice_remap):
257     return GetSlices(slice_remap=slice_remap)
258
259 FUNCS = {"GetConfiguration": HandleGetConfiguration1,
260          "GetNodes": HandleGetNodes1,
261          "GetSlices": HandleGetSlices1,
262          "GetConfiguration2": HandleGetConfiguration2,
263          "GetNodes2": HandleGetNodes2,
264          "GetSlices2": HandleGetSlices2}
265
266 @csrf_exempt
267 def LegacyXMLRPC(request):
268     if request.method == "POST":
269         try:
270             (args, method) = xmlrpclib.loads(request.body)
271             result = None
272             if method in FUNCS:
273                 result = FUNCS[method](*args)
274             return HttpResponse(xmlrpclib.dumps((result,), methodresponse=True, allow_none=1))
275         except:
276             traceback.print_exc()
277             return HttpResponseServerError()
278     else:
279         return HttpResponse("Not Implemented")
280
281 if __name__ == '__main__':
282     slices = GetSlices(slice_remap = DEFAULT_REMAP)
283     nodes = GetNodes(slice_remap = DEFAULT_REMAP)
284
285     if ("-d" in sys.argv):
286         config = GetConfiguration({"name": "princeton_vcoblitz"}, slice_remap = DEFAULT_REMAP)
287         print config
288         print slices
289         print nodes
290     else:
291         configs={}
292         configs[slicename] = GetConfiguration({"name": "princeton_vcoblitz"})
293
294         file("planetstack_config","w").write(json.dumps(configs))
295         file("planetstack_slices","w").write(json.dumps(slices))
296         file("planetstack_nodes","w").write(json.dumps(nodes))