Slice deployment deleter, refactored
[plstackapi.git] / planetstack / openstack_observer / steps / sync_slice_deployments.py
1 import os
2 import base64
3 from collections import defaultdict
4 from netaddr import IPAddress, IPNetwork
5 from django.db.models import F, Q
6 from planetstack.config import Config
7 from observer.openstacksyncstep import OpenStackSyncStep
8 from core.models.site import Deployment, SiteDeployments
9 from core.models.slice import Slice, SliceDeployments
10 from core.models.userdeployments import UserDeployments
11 from util.logger import Logger, logging
12
13 logger = Logger(level=logging.INFO)
14
15 class SyncSliceDeployments(OpenStackSyncStep):
16     provides=[SliceDeployments]
17     requested_interval=0
18
19     def fetch_pending(self, deleted):
20         if (deleted):
21             return SliceDeployments.deleted_objects.all()
22         else:
23             # slice deployments are not visible to users. We must ensure
24             # slices are deployed at all deploymets available to their site.
25             site_deployments = SiteDeployments.objects.all()
26             site_deploy_lookup = defaultdict(list)
27             for site_deployment in site_deployments:
28                 site_deploy_lookup[site_deployment.site].append(site_deployment.deployment)
29             
30             slice_deployments = SliceDeployments.objects.all()
31             slice_deploy_lookup = defaultdict(list)
32             for slice_deployment in slice_deployments:
33                 slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
34             
35             all_deployments = Deployment.objects.all() 
36             for slice in Slice.objects.all():
37                 # slices are added to all deployments for now
38                 expected_deployments = all_deployments
39                 #expected_deployments = site_deploy_lookup[slice.site]
40                 for expected_deployment in expected_deployments:
41                     if slice not in slice_deploy_lookup or \
42                        expected_deployment not in slice_deploy_lookup[slice]:
43                         sd = SliceDeployments(slice=slice, deployment=expected_deployment)
44                         sd.save()
45
46             # now we can return all slice deployments that need to be enacted   
47             return SliceDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
48
49     def get_next_subnet(self, deployment=None):
50         # limit ourself to 10.0.x.x for now
51         valid_subnet = lambda net: net.startswith('10.0')
52         driver = self.driver.admin_driver(deployment=deployment)
53         subnets = driver.shell.quantum.list_subnets()['subnets']
54         ints = [int(IPNetwork(subnet['cidr']).ip) for subnet in subnets \
55                 if valid_subnet(subnet['cidr'])]
56         ints.sort()
57         if ints:
58             last_ip = IPAddress(ints[-1])
59         else:
60             last_ip = IPAddress('10.0.0.1')
61         last_ip = IPAddress(ints[-1])
62         last_network = IPNetwork(str(last_ip) + "/24")
63         next_network = IPNetwork(str(IPAddress(last_network) + last_network.size) + "/24")
64         return next_network
65
66
67     def sync_record(self, slice_deployment):
68         logger.info("sync'ing slice deployment %s" % slice_deployment)
69         if not slice_deployment.tenant_id:
70             nova_fields = {'tenant_name': slice_deployment.slice.name,
71                    'description': slice_deployment.slice.description,
72                    'enabled': slice_deployment.slice.enabled}
73             driver = self.driver.admin_driver(deployment=slice_deployment.deployment.name)
74             tenant = driver.create_tenant(**nova_fields)
75             slice_deployment.tenant_id = tenant.id
76
77             # XXX give caller an admin role at the tenant they've created
78             deployment_users = UserDeployments.objects.filter(user=slice_deployment.slice.creator,
79                                                              deployment=slice_deployment.deployment)            
80             if not deployment_users:
81                 logger.info("slice createor %s has not accout at deployment %s" % (slice_deployment.slice.creator, slice_deployment.deployment.name))
82             else:
83                 deployment_user = deployment_users[0]
84                 # lookup user id at this deployment
85                 kuser= driver.shell.keystone.users.find(email=slice_deployment.slice.creator.email)
86
87                 # add required roles at the slice's tenant 
88                 driver.add_user_role(kuser.id, tenant.id, 'admin')
89                     
90                 # refresh credentials using this tenant
91                 client_driver = self.driver.client_driver(caller=deployment_user.user,
92                                                           tenant=tenant.name, 
93                                                           deployment=slice_deployment.deployment.name)
94
95
96         if slice_deployment.id and slice_deployment.tenant_id:
97             # update existing tenant
98             driver = self.driver.admin_driver(deployment=slice_deployment.deployment.name)
99             driver.update_tenant(slice_deployment.tenant_id,
100                                  description=slice_deployment.slice.description,
101                                  enabled=slice_deployment.slice.enabled)  
102
103         if slice_deployment.tenant_id:
104             # update slice/tenant quota
105             driver = self.driver.client_driver(deployment=slice_deployment.deployment.name, tenant=slice_deployment.slice.name)
106             driver.shell.nova.quotas.update(tenant_id=slice_deployment.tenant_id, instances=int(slice_deployment.slice.max_slivers)) 
107
108         slice_deployment.save()
109
110
111     def delete_record(self, slice_deployment):
112         user = User.objects.get(id=slice_deployment.slice.creator.id)
113         driver = OpenStackDriver().admin_driver(deployment=slice_deployment.deployment.name)
114         client_driver = driver.client_driver(caller=user,
115                                              tenant=slice_deployment.slice.name,
116                                              deployment=slice_deployment.deployment.name)
117
118         if slice_deployment.router_id and slice_deployment.subnet_id:
119             client_driver.delete_router_interface(slice_deployment.router_id, slice_deployment.subnet_id)
120         if slice_deployment.subnet_id:
121             client_driver.delete_subnet(slice_deployment.subnet_id)
122         if slice_deployment.router_id:    
123             client_driver.delete_router(slice_deployment.router_id)
124         if slice_deployment.network_id:
125             client_driver.delete_network(slice_deployment.network_id)
126         if slice_deployment.tenant_id:
127             driver.delete_tenant(slice_deployment.tenant_id)
128         # delete external route
129         #subnet = None
130         #subnets = client_driver.shell.quantum.list_subnets()['subnets']
131         #for snet in subnets:
132         #    if snet['id'] == slice_deployment.subnet_id:
133         #        subnet = snet
134         #if subnet:
135         #    driver.delete_external_route(subnet)