aa2c22f07bbb0d686cb7c3987ba6393dfbbee4ea
[plstackapi.git] / plstackapi / openstack / manager.py
1 from plstackapi.planetstack import settings
2 from django.core import management
3 management.setup_environ(settings)
4 try:
5     from plstackapi.openstack.client import OpenStackClient
6     from plstackapi.openstack.driver import OpenStackDriver
7     from plstackapi.planetstack.config import Config
8     from plstackapi.core.models import * 
9     has_openstack = True
10 except:
11     has_openpstack = False
12
13 manager_enabled = Config().api_nova_enabled
14
15 def require_enabled(callable):
16     def wrapper(*args, **kwds):
17         if manager_enabled and has_openstack:
18             return callable(*args, **kwds)
19         else:
20             return None
21     return wrapper
22
23
24 class OpenStackManager:
25
26     def __init__(self, auth={}, caller=None):
27         self.client = None
28         self.driver = None
29         self.caller = None
30         self.has_openstack = has_openstack       
31         self.enabled = manager_enabled
32
33         if has_openstack and manager_enabled:
34             if auth:
35                 self.client = OpenStackClient(**auth)
36             else:
37                 self.client = OpenStackClient()
38             self.driver = OpenStackDriver(client=self.client) 
39             
40             if caller:
41                 self.caller = caller
42             else:
43                 self.caller = self.driver.admin_user
44                 self.caller.user_id = self.caller.id 
45
46     @require_enabled
47     def save_role(self, role):
48         if not role.role_id:
49             keystone_role = self.driver.create_role(role.role_type)
50             role.role_id = keystone_role.id
51
52     @require_enabled
53     def delete_role(self, role):
54         if role.role_id:
55             self.driver.delete_role({'id': role.role_id})
56
57     @require_enabled
58     def save_key(self, key):
59         if not key.key_id:
60             key_fields = {'name': key.name,
61                           'key': key.key}
62             nova_key = self.driver.create_keypair(**key_fields)
63             key.key_id = nova_key.id        
64
65     @require_enabled
66     def delete_key(self, key):
67         if key.key_id:
68             self.driver.delete_keypair(key.key_id)
69
70     @require_enabled
71     def save_user(self, user):
72         if not user.user_id:
73             name = user.email[:user.email.find('@')]
74             user_fields = {'name': name,
75                            'email': user.email,
76                            'password': user.password,
77                            'enabled': True}
78             keystone_user = self.driver.create_user(**user_fields)
79             user.user_id = keystone_user.id
80     
81     @require_enabled
82     def delete_user(self, user):
83         if user.user_id:
84             self.driver.delete_user(user.user_id)        
85     
86
87     
88     @require_enabled
89     def save_site(self, site, add_role=True):
90         if not site.tenant_id:
91             tenant = self.driver.create_tenant(tenant_name=site.login_base,
92                                                description=site.name,
93                                                enabled=site.enabled)
94             site.tenant_id = tenant.id
95             # give caller an admin role at the tenant they've created
96             self.driver.add_user_role(self.caller.user_id, tenant.id, 'admin')
97
98         # update the record
99         if site.id and site.tenant_id:
100             self.driver.update_tenant(site.tenant_id,
101                                       description=site.name,
102                                       enabled=site.enabled)
103
104     @require_enabled
105     def delete_site(self, site):
106         if site.tenant_id:
107             self.driver.delete_tenant(site.tenant_id)
108                
109     @require_enabled
110     def save_slice(self, slice):
111         if not slice.tenant_id:
112             nova_fields = {'tenant_name': slice.name,
113                    'description': slice.description,
114                    'enabled': slice.enabled}
115             tenant = self.driver.create_tenant(**nova_fields)
116             slice.tenant_id = tenant.id
117
118             # give caller an admin role at the tenant they've created
119             self.driver.add_user_role(self.caller.user_id, tenant.id, 'admin')
120
121             # refresh credentials using this tenant
122             self.driver.shell.connect(username=self.driver.shell.keystone.username,
123                                       password=self.driver.shell.keystone.password,
124                                       tenant=tenant.name)
125
126             # create network
127             network = self.driver.create_network(slice.name)
128             slice.network_id = network['id']
129
130             # create router
131             router = self.driver.create_router(slice.name)
132             slice.router_id = router['id']
133
134         if slice.id and slice.tenant_id:
135             self.driver.update_tenant(slice.tenant_id,
136                                       description=slice.description,
137                                       enabled=slice.enabled)    
138
139     @require_enabled
140     def delete_slice(self, slice):
141         if slice.tenant_id:
142             self.driver.delete_router(slice.router_id)
143             self.driver.delete_network(slice.network_id)
144             self.driver.delete_tenant(slice.tenant_id)
145
146     @require_enabled
147     def save_subnet(self, subnet):    
148         if not subnet.subnet_id:
149             quantum_subnet = self.driver.create_subnet(name= subnet.slice.name,
150                                           network_id=subnet.slice.network_id,
151                                           cidr_ip = subnet.cidr,
152                                           ip_version=subnet.ip_version,
153                                           start = subnet.start,
154                                           end = subnet.end)
155             subnet.subnet_id = quantum_subnet['id']
156             # add subnet as interface to slice's router
157             self.driver.add_router_interface(subnet.slice.router_id, subnet.subnet_id)
158             #add_route = 'route add -net %s dev br-ex gw 10.100.0.5' % self.cidr
159             #commands.getstatusoutput(add_route)
160
161     
162     @require_enabled
163     def delete_subnet(self, subnet):
164         if subnet.subnet_id:
165             self.driver.delete_router_interface(subnet.slice.router_id, subnet.subnet_id)
166             self.driver.delete_subnet(subnet.subnet_id)
167             #del_route = 'route del -net %s' % self.cidr
168             #commands.getstatusoutput(del_route)
169     
170     @require_enabled
171     def save_sliver(self, sliver):
172         if not sliver.instance_id:
173             instance = self.driver.spawn_instance(name=sliver.name,
174                                    key_name = sliver.key.name,
175                                    image_id = sliver.image.image_id,
176                                    hostname = sliver.node.name )
177             sliver.instance_id = instance.id
178             sliver.instance_name = getattr(instance, 'OS-EXT-SRV-ATTR:instance_name')
179
180     @require_enabled
181     def delete_sliver(self, sliver):
182         if sliver.instance_id:
183             self.driver.destroy_instance(sliver.instance_id) 
184     
185
186     def refresh_nodes(self):
187         # collect local nodes
188         nodes = Node.objects.all()
189         nodes_dict = {}
190         for node in nodes:
191             if 'viccidev10' not in node.name:
192                 nodes_dict[node.name] = node 
193         
194         deployment = DeploymentNetwork.objects.filter(name='VICCI')[0]
195         login_bases = ['princeton', 'stanford', 'gt', 'uw', 'mpisws']
196         sites = Site.objects.filter(login_base__in=login_bases)
197         # collect nova nodes:
198         compute_nodes = self.client.nova.hypervisors.list()
199
200         compute_nodes_dict = {}
201         for compute_node in compute_nodes:
202             compute_nodes_dict[compute_node.hypervisor_hostname] = compute_node
203
204         # add new nodes:
205         new_node_names = set(compute_nodes_dict.keys()).difference(nodes_dict.keys())
206         i = 0
207         max = len(sites)
208         for name in new_node_names:
209             if i == max:
210                 i = 0
211             site = sites[i]
212             node = Node(name=compute_nodes_dict[name].hypervisor_hostname,
213                         site=site,
214                         deploymentNetwork=deployment)
215             node.save()
216             i+=1
217
218         # remove old nodes
219         old_node_names = set(nodes_dict.keys()).difference(compute_nodes_dict.keys())
220         Node.objects.filter(name__in=old_node_names).delete()
221
222     def refresh_images(self):
223         # collect local images
224         images = Image.objects.all()
225         images_dict = {}    
226         for image in images:
227             images_dict[image.name] = image
228
229         # collect glance images
230         glance_images = self.client.glance.get_images()
231         glance_images_dict = {}
232         for glance_image in glance_images:
233             glance_images_dict[glance_image['name']] = glance_image
234
235         # add new images
236         new_image_names = set(glance_images_dict.keys()).difference(images_dict.keys())
237         for name in new_image_names:
238             image = Image(image_id=glance_images_dict[name]['id'],
239                           name=glance_images_dict[name]['name'],
240                           disk_format=glance_images_dict[name]['disk_format'],
241                           container_format=glance_images_dict[name]['container_format'])
242             image.save()
243
244         # remove old images
245         old_image_names = set(images_dict.keys()).difference(glance_images_dict.keys())
246         Image.objects.filter(name__in=old_image_names).delete()
247
248