Merge branch 'master' of git://git.planet-lab.org/plstackapi
[plstackapi.git] / planetstack / openstack_observer / steps / sync_slivers.py
1 import os
2 import base64
3 from django.db.models import F, Q
4 from planetstack.config import Config
5 from observer.openstacksyncstep import OpenStackSyncStep
6 from core.models.sliver import Sliver
7 from core.models.slice import Slice, SlicePrivilege, ControllerSlices
8 from core.models.network import Network, NetworkSlice, ControllerNetworks
9 from util.logger import Logger, logging
10 from observer.ansible import *
11 import pdb
12
13 logger = Logger(level=logging.INFO)
14
15 def escape(s):
16     s = s.replace('\n',r'\n').replace('"',r'\"')
17     return s
18
19 class SyncSlivers(OpenStackSyncStep):
20     provides=[Sliver]
21     requested_interval=0
22
23     def get_userdata(self, sliver):
24         userdata = 'opencloud:\n   slicename: "%s"\n   hostname: "%s"\n' % (sliver.slice.name, sliver.node.name)
25         return userdata
26
27     def sync_record(self, sliver):
28         logger.info("sync'ing sliver:%s slice:%s controller:%s " % (sliver, sliver.slice.name, sliver.node.site_deployment.controller))
29
30         metadata_update = {}
31         if (sliver.numberCores):
32             metadata_update["cpu_cores"] = str(sliver.numberCores)
33
34         for tag in sliver.slice.tags.all():
35             if tag.name.startswith("sysctl-"):
36                 metadata_update[tag.name] = tag.value
37
38         # public keys
39         slice_memberships = SlicePrivilege.objects.filter(slice=sliver.slice)
40         pubkeys = set([sm.user.public_key for sm in slice_memberships if sm.user.public_key])
41         if sliver.creator.public_key:
42             pubkeys.add(sliver.creator.public_key)
43
44         if sliver.slice.creator.public_key:
45             pubkeys.add(sliver.slice.creator.public_key)
46
47         nics = []
48         networks = [ns.network for ns in NetworkSlice.objects.filter(slice=sliver.slice)]
49         controller_networks = ControllerNetworks.objects.filter(network__in=networks,
50                                                                 controller=sliver.node.site_deployment.controller)
51
52         for controller_network in controller_networks:
53             if controller_network.network.template.visibility == 'private' and \
54                controller_network.network.template.translation == 'none' and controller_network.net_id:
55                 nics.append(controller_network.net_id)
56
57         # now include network template
58         network_templates = [network.template.sharedNetworkName for network in networks \
59                              if network.template.sharedNetworkName]
60
61         #driver = self.driver.client_driver(caller=sliver.creator, tenant=sliver.slice.name, controller=sliver.controllerNetwork)
62         driver = self.driver.admin_driver(tenant='admin', controller=sliver.controllerNetwork)
63         nets = driver.shell.quantum.list_networks()['networks']
64         for net in nets:
65             if net['name'] in network_templates:
66                 nics.append(net['id'])
67
68         if (not nics):
69             for net in nets:
70                 if net['name']=='public':
71                     nics.append(net['id'])
72
73         # look up image id
74         controller_driver = self.driver.admin_driver(controller=sliver.controllerNetwork)
75         image_id = None
76         images = controller_driver.shell.glanceclient.images.list()
77         for image in images:
78             if image.name == sliver.image.name or not image_id:
79                 image_id = image.id
80
81         # look up key name at the controller
82         # create/fetch keypair
83         keyname = None
84         keyname = sliver.creator.email.lower().replace('@', 'AT').replace('.', '') +\
85                   sliver.slice.name
86         key_fields =  {'name': keyname,
87                        'public_key': sliver.creator.public_key}
88
89         try:
90             legacy = Config().observer_legacy
91         except:
92             legacy = False
93
94         if (legacy):
95             host_filter = sliver.node.name.split('.',1)[0]
96         else:
97             host_filter = sliver.node.name
98
99         availability_zone_filter = 'nova:%s'%host_filter
100         sliver_name = '%s-%d'%(sliver.slice.name,sliver.id)
101
102         userData = self.get_userdata(sliver)
103         if sliver.userData:
104             userData = sliver.userData
105
106         controller = sliver.controllerNetwork
107         tenant_fields = {'endpoint':controller.auth_url,
108                      'admin_user': sliver.creator.username,
109                      'admin_password': sliver.creator.password,
110                      'admin_tenant': sliver.slice.name,
111                      'tenant': sliver.slice.name,
112                      'tenant_description': sliver.slice.description,
113                      'name':sliver_name,
114                      'ansible_tag':sliver_name,
115                      'availability_zone': availability_zone_filter,
116                      'image_id':image_id,
117                      'key_name':keyname,
118                      'flavor_id':3,
119                      'nics':nics,
120                      'meta':metadata_update,
121                      'key':key_fields,
122                      'user_data':r'%s'%escape(userData)}
123
124         res = run_template('sync_slivers.yaml', tenant_fields,path='slivers')
125         if (len(res)!=2):
126             raise Exception('Could not sync sliver %s'%sliver.slice.name)
127         else:
128             sliver_id = res[1]['id'] # 0 is for the key
129
130             sliver.instance_id = sliver_id
131             sliver.instance_name = sliver_name
132             sliver.save()
133
134     def delete_record(self, sliver):
135         sliver_name = '@'.join([sliver.slice.name,sliver.node.name])
136         tenant_fields = {'name':sliver_name,
137                          'ansible_tag':sliver_name
138                         }
139         res = run_template('delete_slivers.yaml', tenant_fields, path='slivers')