X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=planetstack%2Fopenstack%2Fdriver.py;h=a6addba2b24392a06d189e5ea2b9d599deb090c7;hb=0d5ea5c7e775695379b698e6b7357ae32d5cd182;hp=6b04b5d81bd1bb6cfe25f7430538771bf3b0b224;hpb=30fd4291ad7fdb809bb8ebbf738c3195436c2455;p=plstackapi.git diff --git a/planetstack/openstack/driver.py b/planetstack/openstack/driver.py index 6b04b5d..a6addba 100644 --- a/planetstack/openstack/driver.py +++ b/planetstack/openstack/driver.py @@ -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,22 +11,19 @@ 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 else: self.shell = OpenStackClient() - def create_role(self, name): + def create_role(self, name): roles = self.shell.keystone.roles.findall(name=name) if not roles: role = self.shell.keystone.roles.create(name) else: - role = roles[0] + role = roles[0] return role def delete_role(self, filter): @@ -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.name) + 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'] @@ -196,7 +210,7 @@ class OpenStackDriver: for snet in subnets: if snet['cidr'] == cidr_ip and snet['network_id'] == network_id: subnet = snet - + if not subnet: allocation_pools = [{'start': start, 'end': end}] subnet = {'subnet': {'name': name, @@ -204,9 +218,9 @@ class OpenStackDriver: 'ip_version': ip_version, 'cidr': cidr_ip, 'dns_nameservers': ['8.8.8.8', '8.8.4.4'], - 'allocation_pools': allocation_pools}} + '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,23 +236,129 @@ 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 and router.get('external_gateway_info'): + 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): keys = self.shell.nova.keypairs.findall(id=id) for key in keys: self.shell.nova.keypairs.delete(key) - return 1 + return 1 - def spawn_instance(self, name, key_name=None, hostname=None, image_id=None, security_group=None, pubkeys=[]): + def get_private_networks(self, tenant=None): + if not tenant: + tenant = self.shell.nova.tenant + tenant = self.shell.keystone.tenants.find(name=tenant) + search_opts = {"tenant_id": tenant.id, "shared": False} + private_networks = self.shell.quantum.list_networks(**search_opts) + return private_networks + + def get_shared_networks(self): + search_opts = {"shared": True} + shared_networks = self.shell.quantum.list_networks(**search_opts) + return shared_networks + + def get_network_subnet(self, network_id): + subnet_id = None + subnet = None + if network_id: + os_networks = self.shell.quantum.list_networks(id=network_id)["networks"] + if os_networks: + os_network = os_networks[0] + if os_network['subnets']: + subnet_id = os_network['subnets'][0] + os_subnets = self.shell.quantum.list_subnets(id=subnet_id)['subnets'] + if os_subnets: + subnet = os_subnets[0]['cidr'] + + return (subnet_id, subnet) + + def spawn_instance(self, name, key_name=None, hostname=None, image_id=None, security_group=None, pubkeys=[], networks=None): flavor_name = self.config.nova_default_flavor flavor = self.shell.nova.flavors.find(name=flavor_name) #if not image: @@ -246,9 +366,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 @@ -262,7 +382,8 @@ class OpenStackDriver: security_group = security_group, files=files, scheduler_hints=hints, - availability_zone=availability_zone) + availability_zone=availability_zone, + networks=networks) return server def destroy_instance(self, id):