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