fix bugs
[plstackapi.git] / planetstack / openstack / driver.py
index 6b04b5d..c01fede 100644 (file)
@@ -1,7 +1,7 @@
+import commands
 from planetstack.config import Config
 from openstack.client import OpenStackClient
 
-has_openstack = False
 class OpenStackDriver:
 
     def __init__(self, config = None, client=None): 
@@ -11,10 +11,7 @@ class OpenStackDriver:
             self.config = Config() 
 
         self.admin_client = OpenStackClient()
-        if has_openstack:
-            self.admin_user = self.admin_client.keystone.users.find(name=self.admin_client.keystone.username)
-        else:
-            self.admin_user = None
+        self.admin_user = self.admin_client.keystone.users.find(name=self.admin_client.keystone.username)
 
         if client:
             self.shell = client
@@ -54,8 +51,17 @@ class OpenStackDriver:
         return self.shell.keystone.tenants.update(id, **kwds)
 
     def delete_tenant(self, id):
+        ctx = self.shell.nova_db.ctx
         tenants = self.shell.keystone.tenants.findall(id=id)
         for tenant in tenants:
+            # nova does not automatically delete the tenant's instances
+            # so we manually delete instances before deleteing the tenant   
+            instances = self.shell.nova_db.instance_get_all_by_filters(ctx, 
+                       {'project_id': tenant.id}, 'id', 'asc')
+            client = OpenStackClient(tenant=tenant)
+            driver = OpenStackDriver(client=client)
+            for instance in instances:
+                driver.destroy_instance(instance.id)
             self.shell.keystone.tenants.delete(tenant)
         return 1
 
@@ -72,6 +78,10 @@ class OpenStackDriver:
     def delete_user(self, id):
         users = self.shell.keystone.users.findall(id=id)
         for user in users:
+            # delete users keys
+            keys = self.shell.nova.keypairs.findall()
+            for key in keys:
+                self.shell.nova.keypairs.delete(key)
             self.shell.keystone.users.delete(user)
         return 1 
 
@@ -105,8 +115,12 @@ class OpenStackDriver:
 
         return 1 
 
-    def update_user(self, id, **kwds):
-        return self.shell.keystone.users.update(id, **kwds)
+    def update_user(self, id, fields):
+        if 'password' in fields:
+            self.shell.keystone.users.update_password(id, fields['password'])
+        if 'enabled' in fields:
+            self.shell.keystone.users.update_enabled(id, fields['enabled']) 
+        return 1 
 
     def create_router(self, name, set_gateway=True):
         routers = self.shell.quantum.list_routers(name=name)['routers']
@@ -206,7 +220,7 @@ class OpenStackDriver:
                                  'dns_nameservers': ['8.8.8.8', '8.8.4.4'],
                                  'allocation_pools': allocation_pools}}          
             subnet = self.shell.quantum.create_subnet(subnet)['subnet']
-
+            self.add_external_route(subnet)
         # TODO: Add route to external network
         # e.g. #  route add -net 10.0.3.0/24 dev br-ex gw 10.100.0.5 
         return subnet
@@ -222,14 +236,92 @@ class OpenStackDriver:
             if subnet['id'] == id:
                 self.delete_subnet_ports(subnet['id'])
                 self.shell.quantum.delete_subnet(id)
-        return
+                self.delete_external_route(subnet)
+        return 1
+
+    def get_external_routes(self):
+        status, output = commands.getstatusoutput('route')
+        routes = output.split('\n')[3:]
+        return routes
+
+    def add_external_route(self, subnet, routes=[]):
+        if not routes:
+            routes = self.get_external_routes()
+        ports = self.shell.quantum.list_ports()['ports']
+
+        gw_ip = subnet['gateway_ip']
+        subnet_id = subnet['id']
+
+        # 1. Find the port associated with the subnet's gateway
+        # 2. Find the router associated with that port
+        # 3. Find the port associated with this router and on the external net
+        # 4. Set up route to the subnet through the port from step 3
+        ip_address = None
+        for port in ports:
+            for fixed_ip in port['fixed_ips']:
+                if fixed_ip['subnet_id'] == subnet_id and fixed_ip['ip_address'] == gw_ip:
+                    gw_port = port
+                    router_id = gw_port['device_id']
+                    router = self.shell.quantum.show_router(router_id)['router']
+                    if router:
+                        ext_net = router['external_gateway_info']['network_id']
+                        for port in ports:
+                            if port['device_id'] == router_id and port['network_id'] == ext_net:
+                                ip_address = port['fixed_ips'][0]['ip_address']
+
+        if ip_address:
+            # check if external route already exists
+            route_exists = False
+            if routes:
+                for route in routes:
+                    if subnet['cidr'] in route and ip_address in route:
+                        route_exists = True
+            if not route_exists:
+                cmd = "route add -net %s dev br-ex gw %s" % (subnet['cidr'], ip_address)
+                s, o = commands.getstatusoutput(cmd)
+                #print cmd, "\n", s, o
+
+        return 1
+
+    def delete_external_route(self, subnet):
+        ports = self.shell.quantum.list_ports()['ports']
+
+        gw_ip = subnet['gateway_ip']
+        subnet_id = subnet['id']
+
+        # 1. Find the port associated with the subnet's gateway
+        # 2. Find the router associated with that port
+        # 3. Find the port associated with this router and on the external net
+        # 4. Set up route to the subnet through the port from step 3
+        ip_address = None
+        for port in ports:
+            for fixed_ip in port['fixed_ips']:
+                if fixed_ip['subnet_id'] == subnet_id and fixed_ip['ip_address'] == gw_ip:
+                    gw_port = port
+                    router_id = gw_port['device_id']
+                    router = self.shell.quantum.show_router(router_id)['router']
+                    ext_net = router['external_gateway_info']['network_id']
+                    for port in ports:
+                        if port['device_id'] == router_id and port['network_id'] == ext_net:
+                            ip_address = port['fixed_ips'][0]['ip_address']
+
+        if ip_address:
+            cmd = "route delete -net %s" % (subnet['cidr'])
+            commands.getstatusoutput(cmd)
+             
+        return 1
     
-    def create_keypair(self, name, key):
+    def create_keypair(self, name, public_key):
         keys = self.shell.nova.keypairs.findall(name=name)
         if keys:
             key = keys[0]
+            # update key     
+            if key.public_key != public_key:
+                self.delete_keypair(key.id)
+                key = self.shell.nova.keypairs.create(name=name, public_key=public_key)
         else:
-            key = self.shell.nova.keypairs.create(name=name, public_key=key)
+            key = self.shell.nova.keypairs.create(name=name, public_key=public_key)
         return key
 
     def delete_keypair(self, id):
@@ -246,9 +338,9 @@ class OpenStackDriver:
         if not security_group:
             security_group = self.config.nova_default_security_group 
 
-        #authorized_keys = "\n".join(pubkeys)
-        #files = {'/root/.ssh/authorized_keys': authorized_keys}
         files = {}
+        if pubkeys:    
+            files['/root/.ssh/authorized_keys'] = "\n".join(pubkeys)
        
         hints = {}
         availability_zone = None