import commands
from planetstack.config import Config
from openstack.client import OpenStackClient

class OpenStackDriver:

    def __init__(self, config = None, client=None): 
        if config:
            self.config = Config(config)
        else:
            self.config = Config() 

        self.admin_client = OpenStackClient()
        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):
        roles = self.shell.keystone.roles.findall(name=name)
        if not roles:
            role = self.shell.keystone.roles.create(name)
        else:
            role = roles[0]
        return role

    def delete_role(self, filter):
        roles = self.shell.keystone.roles.findall(**filter)
        for role in roles:
            self.shell.keystone.roles.delete(role)
        return 1

    def create_tenant(self, tenant_name, enabled, description):
        """Create keystone tenant. Suggested fields: name, description, enabled"""  
        tenants = self.shell.keystone.tenants.findall(name=tenant_name)
        if not tenants:
            fields = {'tenant_name': tenant_name, 'enabled': enabled, 
                      'description': description}  
            tenant = self.shell.keystone.tenants.create(**fields)
        else:
            tenant = tenants[0]

        # always give the admin user the admin role to any tenant created 
        # by the driver. 
        self.add_user_role(self.admin_user.id, tenant.id, 'admin')
        return tenant

    def update_tenant(self, id, **kwds):
        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

    def create_user(self, name, email, password, enabled):
        users = self.shell.keystone.users.findall(email=email)
        if not users:
            fields = {'name': name, 'email': email, 'password': password,
                      'enabled': enabled}
            user = self.shell.keystone.users.create(**fields)
        else: 
            user = users[0]
        return user

    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 

    def add_user_role(self, kuser_id, tenant_id, role_name):
        user = self.shell.keystone.users.find(id=kuser_id)
        tenant = self.shell.keystone.tenants.find(id=tenant_id)
        role = self.shell.keystone.roles.find(name=role_name)

        role_found = False
        user_roles = user.list_roles(tenant.id)
        for user_role in user_roles:
            if user_role.name == role.name:
                role_found = True
        if not role_found:
            tenant.add_user(user, role)

        return 1

    def delete_user_role(self, kuser_id, tenant_id, role_name):
        user = self.shell.keystone.users.find(id=kuser_id)
        tenant = self.shell.keystone.tenants.find(id=tenant_id)
        role = self.shell.keystone.roles.find(name=role_name)

        role_found = False
        user_roles = user.list_roles(tenant.id)
        for user_role in user_roles:
            if user_role.name == role.name:
                role_found = True
        if role_found:
            tenant.remove_user(user, role)

        return 1 

    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']
        if routers:
            router = routers[0]
        else:
            router = self.shell.quantum.create_router({'router': {'name': name}})['router']
        # add router to external network
        if set_gateway:
            nets = self.shell.quantum.list_networks()['networks']
            for net in nets:
                if net['router:external'] == True: 
                    self.shell.quantum.add_gateway_router(router['id'],
                                                          {'network_id': net['id']})
        
        return router

    def delete_router(self, id):
        routers = self.shell.quantum.list_routers(id=id)['routers']
        for router in routers:
            self.shell.quantum.delete_router(router['id'])
            # remove router form external network
            #nets = self.shell.quantum.list_networks()['networks']
            #for net in nets:
            #    if net['router:external'] == True:
            #        self.shell.quantum.remove_gateway_router(router['id'])

    def add_router_interface(self, router_id, subnet_id):
        router = self.shell.quantum.show_router(router_id)['router']
        subnet = self.shell.quantum.show_subnet(subnet_id)['subnet']
        if router and subnet:
            self.shell.quantum.add_interface_router(router_id, {'subnet_id': subnet_id})

    def delete_router_interface(self, router_id, subnet_id):
        router = self.shell.quantum.show_router(router_id)
        subnet = self.shell.quantum.show_subnet(subnet_id)
        if router and subnet:
            self.shell.quantum.remove_interface_router(router_id, {'subnet_id': subnet_id})
 
    def create_network(self, name):
        nets = self.shell.quantum.list_networks(name=name)['networks']
        if nets: 
            net = nets[0]
        else:
            net = self.shell.quantum.create_network({'network': {'name': name}})['network']
        return net
 
    def delete_network(self, id):
        nets = self.shell.quantum.list_networks()['networks']
        for net in nets:
            if net['id'] == id:
                # delete_all ports
                self.delete_network_ports(net['id'])
                # delete all subnets:
                for subnet_id in net['subnets']:
                    self.delete_subnet(subnet_id)
                self.shell.quantum.delete_network(net['id'])
        return 1

    def delete_network_ports(self, network_id):
        ports = self.shell.quantum.list_ports()['ports']
        for port in ports:
            if port['network_id'] == network_id:
                self.shell.quantum.delete_port(port['id'])
        return 1         

    def delete_subnet_ports(self, subnet_id):
        ports = self.shell.quantum.list_ports()['ports']
        for port in ports:
            delete = False
            for fixed_ip in port['fixed_ips']:
                if fixed_ip['subnet_id'] == subnet_id:
                    delete=True
                    break
            if delete:
                self.shell.quantum.delete_port(port['id'])
        return 1
 
    def create_subnet(self, name, network_id, cidr_ip, ip_version, start, end):
        #nets = self.shell.quantum.list_networks(name=network_name)['networks']
        #if not nets:
        #    raise Exception, "No such network: %s" % network_name   
        #net = nets[0]

        subnet = None 
        subnets = self.shell.quantum.list_subnets()['subnets']
        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,
                                 'network_id': network_id,
                                 'ip_version': ip_version,
                                 'cidr': cidr_ip,
                                 '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

    def update_subnet(self, id, fields):
        return self.shell.quantum.update_subnet(id, fields)

    def delete_subnet(self, id):
        #return self.shell.quantum.delete_subnet(id=id)
        # inefficient but fault tolerant
        subnets = self.shell.quantum.list_subnets()['subnets']
        for subnet in subnets:
            if subnet['id'] == id:
                self.delete_subnet_ports(subnet['id'])
                self.shell.quantum.delete_subnet(id)
                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, 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=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

    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 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:
        #    image = self.config.nova_default_imave
        if not security_group:
            security_group = self.config.nova_default_security_group 

        files = {}
        if pubkeys:    
            files['/root/.ssh/authorized_keys'] = "\n".join(pubkeys)
       
        hints = {}
        availability_zone = None
        if hostname:
            availability_zone = 'nova:%s' % hostname
        server = self.shell.nova.servers.create(
                                            name=name,
                                            key_name = key_name,
                                            flavor=flavor.id,
                                            image=image_id,
                                            security_group = security_group,
                                            files=files,
                                            scheduler_hints=hints,
                                            availability_zone=availability_zone,
                                            networks=networks)
        return server
          
    def destroy_instance(self, id):
        servers = self.shell.nova.servers.findall(id=id)
        for server in servers:
            self.shell.nova.servers.delete(server)

    def update_instance_metadata(self, id, metadata):
        servers = self.shell.nova.servers.findall(id=id)
        for server in servers:
            self.shell.nova.servers.set_meta(server, metadata)
            # note: set_meta() returns a broken Server() object. Don't try to
            # print it in the shell or it will fail in __repr__.

    def delete_instance_metadata(self, id, metadata):
        # note: metadata is a dict. Only the keys matter, not the values.
        servers = self.shell.nova.servers.findall(id=id)
        for server in servers:
            self.shell.nova.servers.delete_meta(server, metadata)

