Example #1
0
 def _update__preparse_kwargs(self, kwargs):
     kwargs.pop('authentication', None)
     rename_kwargs(kwargs, 'docker_port', 'port')
     rename_kwargs(kwargs, 'docker_host', 'host')
     rename_kwargs(kwargs, 'auth_user', 'username')
     rename_kwargs(kwargs, 'auth_password', 'password')
     host = kwargs.get('host', self.cloud.host)
     if host:
         host = sanitize_host(host)
         check_host(host)
Example #2
0
 def _update__preparse_kwargs(self, kwargs):
     rename_kwargs(kwargs, 'auth_url', 'url')
     rename_kwargs(kwargs, 'tenant_name', 'tenant')
     url = kwargs.get('url', self.cloud.url)
     if url:
         if url.endswith('/v2.0/'):
             url = url.split('/v2.0/')[0]
         elif url.endswith('/v2.0'):
             url = url.split('/v2.0')[0]
         kwargs['url'] = url.rstrip('/')
         check_host(sanitize_host(kwargs['url']))
Example #3
0
 def _add__preparse_kwargs(self, kwargs):
     rename_kwargs(kwargs, 'machine_hostname', 'host')
     rename_kwargs(kwargs, 'machine_user', 'username')
     rename_kwargs(kwargs, 'machine_key', 'key')
     rename_kwargs(kwargs, 'ssh_port', 'port')
     if kwargs.get('host'):
         kwargs['host'] = sanitize_host(kwargs['host'])
         check_host(kwargs['host'])
     if kwargs.get('key'):
         try:
             kwargs['key'] = Key.objects.get(owner=self.cloud.owner,
                                             id=kwargs['key'],
                                             deleted=None)
         except Key.DoesNotExist:
             raise NotFoundError("Key does not exist.")
Example #4
0
    def _update__preparse_kwargs(self, kwargs):
        username = kwargs.get('username', self.cloud.username) or ''
        organization = kwargs.pop('organization')

        if not organization:
            if '@' not in username:
                raise RequiredParameterMissingError('organization')
        else:
            if '@' in username:
                username = username.split('@')[0]
            kwargs['username'] = '******' % (username, organization)
        host = kwargs.get('host', self.cloud.host)
        if host:
            kwargs['host'] = sanitize_host(host)
            check_host(kwargs['host'])
Example #5
0
    def add_machine(self, name, host='',
                    ssh_user='******', ssh_port=22, ssh_key=None,
                    os_type='unix', rdp_port=3389, fail_on_error=True):
        """Add machine to this dummy Cloud

        This is a special method that exists only on this Cloud subclass.
        """

        old_machines = [m.as_dict() for m in
                        self.cloud.ctl.compute.list_cached_machines()]

        # FIXME: Move ssh command to Machine controller once it is migrated.
        from mist.api.methods import ssh_command

        try:
            ssh_port = int(ssh_port)
        except (ValueError, TypeError):
            ssh_port = 22
        try:
            rdp_port = int(rdp_port)
        except (ValueError, TypeError):
            rdp_port = 3389
        if ssh_key:
            ssh_key = Key.objects.get(owner=self.cloud.owner, id=ssh_key,
                                      deleted=None)

        from mist.api.machines.models import Machine
        # Create and save machine entry to database.
        machine = Machine(
            cloud=self.cloud,
            name=name,
            machine_id=uuid.uuid4().hex,
            os_type=os_type,
            ssh_port=ssh_port,
            rdp_port=rdp_port,
            last_seen=datetime.datetime.utcnow()
        )
        if host:
            # Sanitize inputs.
            host = sanitize_host(host)
            check_host(host)
            machine.hostname = host

            if is_private_subnet(socket.gethostbyname(host)):
                machine.private_ips = [host]
            else:
                machine.public_ips = [host]
        machine.save(write_concern={'w': 1, 'fsync': True})

        # Attempt to connect.
        if os_type == 'unix' and ssh_key:
            if not ssh_user:
                ssh_user = '******'
            # Try to connect. If it works, it will create the association.
            try:
                if not host:
                    raise BadRequestError("You have specified an SSH key but "
                                          "machine hostname is empty.")
                to_tunnel(self.cloud.owner, host)  # May raise VPNTunnelError
                ssh_command(
                    self.cloud.owner, self.cloud.id, machine.id, host,
                    'uptime', key_id=ssh_key.id, username=ssh_user,
                    port=ssh_port
                )
            except MachineUnauthorizedError as exc:
                if fail_on_error:
                    machine.delete()
                raise CloudUnauthorizedError(exc)
            except ServiceUnavailableError as exc:
                if fail_on_error:
                    machine.delete()
                raise MistError("Couldn't connect to host '%s'." % host)
            except:
                if fail_on_error:
                    machine.delete()
                raise

        if amqp_owner_listening(self.cloud.owner.id):
            new_machines = self.cloud.ctl.compute.list_cached_machines()
            self.cloud.ctl.compute.produce_and_publish_patch(
                old_machines, new_machines)

        return machine
Example #6
0
 def _update__preparse_kwargs(self, kwargs):
     host = kwargs.get('host', self.cloud.host)
     if host:
         host = sanitize_host(host)
         check_host(host)
Example #7
0
    def add_machine(self, host, ssh_user='******', ssh_port=22, ssh_key=None,
                    **kwargs):
        try:
            ssh_port = int(ssh_port)
        except (ValueError, TypeError):
            ssh_port = 22

        if not ssh_key:
            raise RequiredParameterMissingError('machine_key')

        try:
            ssh_key = Key.objects.get(owner=self.cloud.owner, id=ssh_key,
                                      deleted=None)
        except Key.DoesNotExist:
            raise NotFoundError("Key does not exist.")

        images_location = kwargs.get('images_location',
                                     '/var/lib/libvirt/images')
        extra = {
            'images_location': images_location,
            'tags': {'type': 'hypervisor'},
            'username': ssh_user
        }

        from mist.api.machines.models import Machine
        # Create and save machine entry to database.
        # first check if the host has already been added to the cloud
        try:
            machine = Machine.objects.get(cloud=self.cloud,
                                          machine_id=host.replace('.', '-'))
            machine.name = kwargs.get('name') or host
            machine.ssh_port = ssh_port
            machine.extra = extra
            machine.last_seen = datetime.datetime.utcnow()
            machine.missing_since = None
        except me.DoesNotExist:
            machine = Machine(
                cloud=self.cloud,
                name=kwargs.get('name') or host,
                hostname=host,
                machine_id=host.replace('.', '-'),
                ssh_port=ssh_port,
                extra=extra,
                state=NodeState.RUNNING,
                last_seen=datetime.datetime.utcnow(),
            )

        # Sanitize inputs.
        host = sanitize_host(host)
        check_host(host)
        machine.hostname = host

        if is_private_subnet(socket.gethostbyname(host)):
            machine.private_ips = [host]
        else:
            machine.public_ips = [host]

        machine.save(write_concern={'w': 1, 'fsync': True})

        # associate key and attempt to connect
        try:
            machine.ctl.associate_key(ssh_key,
                                      username=ssh_user,
                                      port=ssh_port)
        except MachineUnauthorizedError as exc:
            log.error("Could not connect to host %s."
                      % host)
            machine.delete()
            raise CloudUnauthorizedError(exc)
        except ServiceUnavailableError as exc:
            log.error("Could not connect to host %s."
                      % host)
            machine.delete()
            raise MistError("Couldn't connect to host '%s'."
                            % host)

        if amqp_owner_listening(self.cloud.owner.id):
            old_machines = []
            for cached_machine in \
                    self.cloud.ctl.compute.list_cached_machines():
                # make sure that host just added becomes visible
                if cached_machine.id != machine.id:
                    old_machines.append(cached_machine)
            old_machines = [m.as_dict() for m in
                            old_machines]
            new_machines = self.cloud.ctl.compute.list_machines()
            self.cloud.ctl.compute.produce_and_publish_patch(
                old_machines, new_machines)

        return machine
Example #8
0
    def add(self, fail_on_error=True, fail_on_invalid_params=False, **kwargs):
        from mist.api.machines.models import Machine
        if not kwargs.get('hosts'):
            raise RequiredParameterMissingError('hosts')
        try:
            self.cloud.save()
        except me.ValidationError as exc:
            raise BadRequestError({'msg': str(exc),
                                   'errors': exc.to_dict()})
        except me.NotUniqueError:
            raise CloudExistsError("Cloud with name %s already exists"
                                   % self.cloud.title)
        total_errors = {}

        for _host in kwargs['hosts']:
            self._add__preparse_kwargs(_host)
            errors = {}
            for key in list(_host.keys()):
                if key not in ('host', 'alias', 'username', 'port', 'key',
                               'images_location'):
                    error = "Invalid parameter %s=%r." % (key, _host[key])
                    if fail_on_invalid_params:
                        self.cloud.delete()
                        raise BadRequestError(error)
                    else:
                        log.warning(error)
                        _host.pop(key)

            for key in ('host', 'key'):
                if key not in _host or not _host.get(key):
                    error = "Required parameter missing: %s" % key
                    errors[key] = error
                    if fail_on_error:
                        self.cloud.delete()
                        raise RequiredParameterMissingError(key)
                    else:
                        log.warning(error)
                        total_errors.update({key: error})

            if not errors:
                try:
                    ssh_port = int(_host.get('ssh_port', 22))
                except (ValueError, TypeError):
                    ssh_port = 22

                images_location = _host.get('images_location',
                                            '/var/lib/libvirt/images')
                extra = {
                    'images_location': images_location,
                    'tags': {'type': 'hypervisor'},
                    'username': _host.get('username')
                }
                # Create and save machine entry to database.
                machine = Machine(
                    cloud=self.cloud,
                    machine_id=_host.get('host').replace('.', '-'),
                    name=_host.get('alias') or _host.get('host'),
                    ssh_port=ssh_port,
                    last_seen=datetime.datetime.utcnow(),
                    hostname=_host.get('host'),
                    state=NodeState.RUNNING,
                    extra=extra
                )
                # Sanitize inputs.
                host = sanitize_host(_host.get('host'))
                check_host(_host.get('host'))
                machine.hostname = host

                if is_private_subnet(socket.gethostbyname(_host.get('host'))):
                    machine.private_ips = [_host.get('host')]
                else:
                    machine.public_ips = [_host.get('host')]

                try:
                    machine.save(write_concern={'w': 1, 'fsync': True})
                except me.NotUniqueError:
                    error = 'Duplicate machine entry. Maybe the same \
                            host has been added twice?'
                    if fail_on_error:
                        self.cloud.delete()
                        raise MistError(error)
                    else:
                        total_errors.update({_host.get('host'): error})
                        continue

                # associate key and attempt to connect
                try:
                    machine.ctl.associate_key(_host.get('key'),
                                              username=_host.get('username'),
                                              port=ssh_port)
                except MachineUnauthorizedError as exc:
                    log.error("Could not connect to host %s."
                              % _host.get('host'))
                    machine.delete()
                    if fail_on_error:
                        self.cloud.delete()
                        raise CloudUnauthorizedError(exc)
                except ServiceUnavailableError as exc:
                    log.error("Could not connect to host %s."
                              % _host.get('host'))
                    machine.delete()
                    if fail_on_error:
                        self.cloud.delete()
                        raise MistError("Couldn't connect to host '%s'."
                                        % _host.get('host'))

        # check if host was added successfully
        # if not, delete the cloud and raise
        if Machine.objects(cloud=self.cloud):
            if amqp_owner_listening(self.cloud.owner.id):
                old_machines = [m.as_dict() for m in
                                self.cloud.ctl.compute.list_cached_machines()]
                new_machines = self.cloud.ctl.compute.list_machines()
                self.cloud.ctl.compute.produce_and_publish_patch(
                    old_machines, new_machines)

            self.cloud.errors = total_errors

        else:
            self.cloud.delete()
            raise BadRequestError(total_errors)