Beispiel #1
0
def connect():
    try:
        conn = Client()
        conn.authenticate('123123aa')
        return { "error" : False, "conn" : conn}
    except Exception, e:
        return { "error" : True, "message" : "We have trouble connecting to the LXD daemon. LXC/LXD might not be installed or either daemon not initialised up properly !"}
Beispiel #2
0
 def get_client(self, system_id: str, context: dict):
     """Connect and return PyLXD client."""
     endpoint = self.get_url(context)
     password = context.get("password")
     try:
         client = Client(
             endpoint=endpoint,
             cert=(MAAS_CERTIFICATE, MAAS_PRIVATE_KEY),
             verify=False,
         )
         if not client.has_api_extension("virtual-machines"):
             raise LXDError(
                 "Please upgrade your LXD host to 3.19+ for virtual machine support."
             )
         if not client.trusted:
             if password:
                 client.authenticate(password)
             else:
                 raise LXDError(
                     f"{system_id}: Certificate is not trusted and no password was given."
                 )
         return client
     except ClientConnectionFailed:
         raise LXDError(
             f"{system_id}: Failed to connect to the LXD REST API.")
Beispiel #3
0
 def _get_client(self,
                 pod_id: int,
                 context: dict,
                 project: Optional[str] = None):
     """Connect PyLXD client."""
     if not project:
         project = context.get("project", "default")
     endpoint = self.get_url(context)
     try:
         client = Client(
             endpoint=endpoint,
             project=project,
             cert=get_maas_cert_tuple(),
             verify=False,
         )
         if not client.trusted:
             password = context.get("password")
             if password:
                 client.authenticate(password)
             else:
                 raise LXDPodError(
                     f"Pod {pod_id}: Certificate is not trusted and no password was given."
                 )
     except ClientConnectionFailed:
         raise LXDPodError(
             f"Pod {pod_id}: Failed to connect to the LXD REST API.")
     return client
Beispiel #4
0
def authenticate_host(host_id, pw):

    host = Host.objects.get(id=host_id)

    client = Client(endpoint=host.api_url, cert=(getattr(settings, "LXD_CRT"), getattr(settings, "LXD_KEY")),
                    verify=getattr(settings, "LXD_CA_CERT"), timeout=60)

    if not client.trusted:
        client.authenticate(pw)
 def creatClient(self):
     client = Client(endpoint=self.uri,
                     cert=(Config.cp_config["cert"],
                           Config.cp_config["key"]),
                     verify=False)
     client.authenticate(Config.cp_config["trustPassword"])
     if (client.trusted):
         return client
     else:
         return None
Beispiel #6
0
def authenticate(auth_endpoint: str, trust_password: str,
                 cert_location: str) -> LxdClient:
    _, _, cert_path, key_path = generate_certificates(
        cert_location=cert_location)
    client = LxdClient(endpoint=auth_endpoint,
                       cert=(cert_path, key_path),
                       verify=False,
                       timeout=5)
    try:
        client.authenticate(trust_password)
    except pylxd.exceptions.ClientConnectionFailed:
        logger.error("Error trying to connect to LXD")
        exit(3)
    if not client.trusted:
        logger.error("Problem connecting... you are not trusted!")
    return client
Beispiel #7
0
    def remote(self):
        try:
            conn = Client(endpoint='https://45.76.43.148:8443',
                          cert=(self.certfile, self.keyfile),
                          verify=False)
            conn.authenticate(self.password)

            return {"error": False, "conn": conn}

        except Exception as e:
            return {
                "error":
                True,
                "message":
                "We have trouble connecting to the LXD daemon. LXC/LXD might not be installed or either daemon not initialised up properly !\n{}"
                .format(e)
            }
Beispiel #8
0
class Server():
    def __init__(self, name, host, port, crt, key, password=None):
        self.containers = []
        self.name = name
        self.key = key
        self.ip = host
        self.port = port
        self.crt = crt
        self.endpoint = "https://" + self.ip + ":" + str(self.port)
        self.client = Client(endpoint=self.endpoint,
                             cert=(self.crt, self.key),
                             verify=False)
        if not (self.client.trusted):
            try:
                self.client.authenticate(password)
            except pylxd.exceptions.LXDAPIException:
                print("Introduces the trust password to Client.autheticate")

    def scan(self):
        self.containers = self.client.containers.all()

    @property
    def containers(self):
        return self.client.containers
Beispiel #9
0
class LXCDriver(base.DriverBase):
    def __init__(self,
                 flavours,
                 provider_name='digital_ocean_provider',
                 profile_name='digital_ocean_profile',
                 host_ip='',
                 key_name='va_master_key',
                 key_path='/root/va_master_key',
                 datastore_handler=None,
                 ssl_path='/opt/va_master/ssl'):
        """ The standard issue init method. Borrows most of the functionality from the BaseDriver init method, but adds a self.regions attribute, specific for OpenStack hosts. """

        kwargs = {
            'driver_name': 'lxc',
            'provider_template': PROVIDER_TEMPLATE,
            'profile_template': PROFILE_TEMPLATE,
            'provider_name': provider_name,
            'profile_name': profile_name,
            'host_ip': host_ip,
            'key_name': key_name,
            'key_path': key_path,
            'datastore_handler': datastore_handler
        }
        self.ssl_path = ssl_path
        self.flavours = flavours
        super(LXCDriver, self).__init__(**kwargs)

    def get_cert(self, provider):
        cert_files = '%s/%s' % (self.ssl_path, provider['provider_name'])

        if not any([
                os.path.isfile(cert_files + file_type)
                for file_type in ['.csr', 'crt', 'key']
        ]):
            openssl_cmd = [
                'openssl', 'req', '-newkey', 'rsa:2048', '-nodes', '-keyout',
                cert_files + '.key', '-out', cert_files + '.csr', '-subj',
                '/C=MK/ST=MK/L=Skopje/O=Firma/OU=IT/CN=client'
            ]
            sign_cmd = [
                'openssl', 'x509', '-signkey', cert_files + '.key', '-in',
                cert_files + '.csr', '-req', '-days', '365', '-out',
                cert_files + '.crt'
            ]
            ssl = subprocess.call(openssl_cmd)
            keys = subprocess.call(sign_cmd)

        return (cert_files + '.crt', cert_files + '.key')

    def get_client(self, provider):
        cert = self.get_cert(provider)

        self.cl = Client(provider['provider_ip'], cert=cert, verify=False)
        self.cl.authenticate(provider['password'])

        return self.cl

    def get_server_addresses(self, s):
        if not s.get('network'):
            return ['']
        return [
            i.get('address') for i in s.get('network', {}).get('eth0', {}).get(
                'addresses', [{}]) if i.get('family', '') == 'inet'
        ] or ['']

    def get_server_usage(self, server, key):
        if type(server) != dict:
            server = server.state()
        if not server.get(key):
            return 0
        return server[key].get('usage', 0)

    @tornado.gen.coroutine
    def driver_id(self):
        """ Pretty simple. """
        raise tornado.gen.Return('lxc')

    @tornado.gen.coroutine
    def friendly_name(self):
        """ Pretty simple """
        raise tornado.gen.Return('LXC')

    @tornado.gen.coroutine
    def get_steps(self):
        """ Digital Ocean requires an access token in order to generate the provider conf.  """

        steps = yield super(LXCDriver, self).get_steps()
        steps[0].add_fields([
            ('provider_ip', 'IP of the lxc host.', 'str'),
        ])
        self.steps = steps
        raise tornado.gen.Return(steps)

    @tornado.gen.coroutine
    def get_networks(self):
        """ Gets the networks the salt-cloud method, at least for the moment. """
        networks = [x.name for x in self.cl.networks.all()]
        raise tornado.gen.Return(networks)

    @tornado.gen.coroutine
    def get_sec_groups(self):
        """ No security groups for lxc.  """
        sec_groups = ['No security groups. ']
        raise tornado.gen.Return(sec_groups)

    @tornado.gen.coroutine
    def get_images(self):
        """ Gets the images using salt-cloud. """
        images = [x.properties['description'] for x in self.cl.images.all()]
        raise tornado.gen.Return(images)

    @tornado.gen.coroutine
    def get_sizes(self):
        """ Gets the sizes using salt-cloud.  """
        sizes = self.flavours.keys()
        raise tornado.gen.Return(sizes)

    def get_cpus(self, container):
        cpu = self.get_server_usage(container, 'cpu')
        c = container['server']
        f = c.FilesManager(self.cl, c)
        number_cpus = len([
            x for x in f.get('/proc/cpuinfo').split('\n') if 'processor' in x
        ])
        return number_cpus

    def container_to_dict(self, container, provider_name):
        status_map = {
            'Running': 'ACTIVE',
            'Stopped': 'SHUTOFF',
        }
        print("I have container ----------", container)
        state = container.state().__dict__
        server = {
            'hostname': container.name,
            'ip': self.get_server_addresses(state)[0],
            'size': container.name,
            'used_disk': self.get_server_usage(state, 'disk') / float(2**20)
            or 1,
            'used_ram': self.get_server_usage(state, 'memory') / float(2**20),
            'status': status_map.get(
                container.status, container.status
            ),  #We try to get the status from the mapping, otherwise we just return the original status
            'cost': 0,  #TODO find way to calculate costs
            'estimated_cost': 0,
            'provider': provider_name,
            'provider_name': provider_name,  #Probably a bugfix
        }
        if container.status == 'ACTIVE':
            server['used_cpu'] = self.get_cpus(container)
        else:
            server['used_cpu'] = 0

        return server

    @tornado.gen.coroutine
    def get_servers(self, provider):
        cl = self.get_client(provider)
        servers = cl.containers.all()
        servers = [{'server': x, 'state': x.state().__dict__} for x in servers]

        servers = [
            self.container_to_dict(x['server'], provider['provider_name'])
            for x in servers
        ]

        raise tornado.gen.Return(servers)

    @tornado.gen.coroutine
    def get_provider_status(self, provider):
        """ TODO """
        try:
            cl = self.get_client(provider)
        except Exception as e:
            import traceback
            traceback.print_exc()
            raise tornado.gen.Return({'success': False, 'message': e.message})

        raise tornado.gen.Return({'success': True, 'message': ''})

    @tornado.gen.coroutine
    def get_provider_billing(self, provider):
        #TODO provide should have some sort of costing mechanism, and we multiply used stuff by some price.

        total_cost = 0
        servers = yield self.get_servers(provider)

        servers.append({
            'hostname': 'Other Costs',
            'ip': '',
            'size': '',
            'used_disk': 0,
            'used_ram': 0,
            'used_cpu': 0,
            'status': '',
            'cost': total_cost,
            'estimated_cost': 0,
            'provider': provider['provider_name'],
        })
        total_memory = sum(
            [x['used_ram']
             for x in servers if not type(x['used_ram']) == str]) * 2**20
        total_memory = int_to_bytes(total_memory)
        provider['memory'] = total_memory
        provider['hdd'] = '0.0 GB'

        for server in servers:
            server['used_ram'] = int_to_bytes(server['used_ram'] * (2**20))
            server['used_disk'] = int_to_bytes(server['used_disk'] * (2**30))

        billing_data = {
            'provider': provider,
            'servers': servers,
            'total_cost': total_cost
        }
        raise tornado.gen.Return(billing_data)

    @tornado.gen.coroutine
    def get_provider_data(self, provider, get_servers=True, get_billing=True):
        """ TODO """

        servers = yield self.get_servers(provider)

        get_sum = lambda x: sum(
            [s[x] for s in servers if not type(s[x]) == str])

        provider_usage = {
            'max_cpus': 0,
            'used_cpus': get_sum('used_cpu'),
            'free_cpus': 0,
            'max_ram': 0,
            'used_ram': get_sum('used_ram'),
            'free_ram': 0,
            'max_disk': 0,
            'used_disk': get_sum('used_disk'),
            'free_disk': 0,
            'max_servers': 0,
            'used_servers': len(servers),
            'free_servers': 0
        }

        provider_data = {
            'servers': servers,
            'provider_usage': provider_usage,
            'status': {
                'success': True,
                'message': ''
            }
        }
        raise tornado.gen.Return(provider_data)

    @tornado.gen.coroutine
    def get_driver_trigger_functions(self):
        conditions = []
        actions = []
        return {'conditions': conditions, 'actions': actions}

    @tornado.gen.coroutine
    def server_action(self, provider, server_name, action):
        """ Performs server actions using a nova client. """
        message = ''
        try:
            cl = self.get_client(provider)

            server = cl.containers.get(server_name)
            getattr(server, action)()
        except Exception as e:
            import traceback
            traceback.print_exc()

            raise Exception('Could not get server' + server_name + '. ' +
                            e.message)
        try:
            pass
            #TODO perform action
        except Exception as e:
            import traceback
            traceback.print_exc()

            raise Exception('Action ' + action + ' was not performed on ' +
                            server_name + '. Reason: ' + e.message)

        raise tornado.gen.Return({
            'success': True,
            'message': message,
            'data': {}
        })

    @tornado.gen.coroutine
    def validate_field_values(self, step_index, field_values):
        """ Uses the base driver method, but adds the region tenant and identity_url variables, used in the configurations. """
        if step_index == 0:
            self.field_values['provider_ip'] = field_values['provider_ip']
            cl = self.get_client(field_values)
        try:
            step_result = yield super(LXCDriver, self).validate_field_values(
                step_index, field_values)
        except:
            import traceback
            traceback.print_exc()
        raise tornado.gen.Return(step_result)

    #NOTE handler and dash_user are here to temporarily work with integraitons
    #I'd want to do away with it from host drivers, but we have a concept to prove
    #TODO find a way to streamline this
    @tornado.gen.coroutine
    def create_server(self, provider, data):
        try:
            lxc_config = {
                'name': data['server_name'],
                'source': {
                    'image': data['image'],
                    'network': data['network'],
                    'size': data['size']
                }
            }
            cl = self.get_client(provider)

            try:
                image = cl.images.get_by_alias(data['image'])
            except:
                raise Exception('No image ' + str(data['image']))

            network = cl.networks.get(data['network'])

            print(image.properties)
            lxc_config = {
                'name': data['server_name'],
                'source': {
                    'type': 'image',
                    'properties': {
                        'os': image.properties['os'],
                        'architecture': image.properties['architecture'],
                        'release': image.properties['release'],
                        'description': image.properties.get('description', '')
                    }
                }
            }
            new_container = cl.containers.create(lxc_config, wait=True)

            print('status is ', new_container.status)

            ssh_path = '/root/.ssh'
            keys_path = ssh_path + '/authorized_keys'

            with open(self.key_path + '.pub', 'r') as f:
                key = f.read()

            new_container.start(wait=True)

            new_container.execute(['mkdir', '-p', ssh_path])
            fm = new_container.FilesManager(cl, new_container)
            fm.put(keys_path, key)

            ip = []
            while not ip:
                addresses = new_container.state().network['eth0']['addresses']
                ip = [
                    x['address'] for x in addresses
                    if x.get('family', '') == 'inet'
                ]
            try:
                new_container.execute(
                    ['apt-get', '-y', 'install', 'openssh-server'])
            except:  #Sometimes there is a weird and cryptic "Not Found" exception. TODO: find it and pass only on it
                import traceback
                traceback.print_exc()
                pass
            ip = ip[0]
            print('IP is : ', ip)
            #                yield apps.add_minion_to_server(self.datastore_handler, data['server_name'], ip, data['role'], key_filename = '/root/.ssh/va-master.pem', username = '******')

            new_container = self.container_to_dict(new_container,
                                                   provider['provider_name'])
            print('New container : ', new_container)
            new_container['ip_address'] = ip
            print('Now is : ', new_container)
            raise tornado.gen.Return(new_container)
        except tornado.gen.Return:
            raise
        except:
            import traceback
            traceback.print_exc()