from plstackapi.planetstack.config import Config
from plstackapi.openstack.shell import OpenStackShell

class OpenStackDriver:

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

    def create_tenant(self, **kwds):
        """Create keystone tenant. Suggested fields: name, description, enabled"""  
        required_fields = ['tenant_name', 'enabled', 'description']
        for field in required_fields:
            if field not in kwds:
                raise Exception, "Must specify %s" % field

        tenants = self.shell.keystone.tenants.findall(name=kwds['tenant_name'])
        if not tenants:
            tenant = self.shell.keystone.tenants.create(**kwds)
        else:
            tenant = tenants[0]
        return tenant

    def update_tenant(self, id, **kwds):
        return self.shell.keystone.tenants.update(self.id, **kwds)

    def delete_tenant(self, id):
        tenant = self.shell.keystone.tenants.find(id=id)
        return self.shell.keystone.tenants.delete(tenant)

    def create_router(self, name):
        router = self.shell.quantum.create_router(name=name)
        # TODO: add router to external network
        return router

    def delete_router(self, name):
        return self.shell.quantum.delete_router(name=name)
    
    def create_network(self, name):
        return self.shell.quantum.create_network(name=name, admin_state_up=True)
    
    def delete_network(self, name):
        nets = self.shell.quantum.list_networks(name=name)
        for net in nets:
            # delete all subnets:
            #subnets = self.api.client_shell.quantum.list_subnets(network_id=net['network_id'])['subnets']
            for subnet_id in net['subnets']:
                self.delete_subnet(subnet_id)
            self.shell.quantum.delete_network(net['id'])
    
    def create_subnet(self, network_name, cidr_ip, ip_version, start, end):
        nets = self.shell.quantum.list_networks(name=network_name)
        if not nets:
            raise Exception, "No such network: %s" % network_name   
        nets = nets[0]

        subnets = self.shell.quantum.list_subnets(name=self.name)
        allocation_pools = [{'start': start, 'end': end}]
        subnet = self.shell.quantum.create_subnet(network_id=net['id'],
                                                ip_version=ip_version,
                                                cidr=cidr_ip,
                                                dns_nameservers=['8.8.8.8'],         
                                                allocation_pools=allocation_pools)

        # 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 delete_subnet(self, id):
        return self.client.quantum.delete_subnet(id=id)
     
    
    def create_keypair(self, name, key):
        keys = self.client.nova.keypairs.findall(name=name)
        if keys:
            raise Exception, "Key name already exists: %s" % name
        return self.client.nova.keypairs.create(name=name, public_key=key)

    def delete_keypair(self, name):
        keys = self.client.nova.keypairs.findall(name=name)
        for key in keys:
            self.client.nova.keypairs.delete(key) 

    def spawn_instance(self, name, key_name=None, hostname=None, flavor=None, image=None, security_group=None, pubkeys=[]):
        if not flavor:
            flavor = self.config.nova_default_flavor
        if not image:
            image = self.config.nova_default_imave
        if not security_group:
            security_group = self.config.nova_default_security_group 

        authorized_keys = "\n".join(pubkeys)
        files = {'/root/.ssh/authorized_keys': authorized_keys}
       
        flavor_id = self.shell.nova.flavors.find(name=flavor)
        images = self.shell.glance.get_images(name=image)
        if not images:
            raise Exception, "Image not found: " + image  
        image_id = images[0]['id']
        hints = {}
        if hostname:
            hints['force_hosts']= 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)
        return server
          
    def destroy_instance(self, name, id=None):
        args = {'name': name}
        if id:
            args['id'] = id
        servers = self.shell.nova.servers.findall(**args)
        for server in servers:
            if name == server.name:
                if not id or id == server.id:
                    self.shell.nova.servers.delete(server)
