Beispiel #1
0
    def _start_existing_instance(self, status):
        """
        Start a existing instance.

        Args:
            status (str): Status of the instance.
        """
        # Waiting for the instance stop if currently stopping
        if status == self.STATUS_STOPPING:
            with _utl.Timeout(self.TIMEOUT,
                              sleep=self._TIMEOUT_SLEEP) as timeout:
                while True:
                    # Get instance status
                    status = self._status()
                    if status != self.STATUS_STOPPING:
                        break
                    elif timeout.reached():
                        raise _exc.HostRuntimeException(
                            gen_msg=('timeout_status', 'stop', status))

        # If instance stopped, starts it
        if status == self.STATUS_STOPPED:
            with _exception_handler():
                self._instance.start()

        # If another status, raises error
        elif status != self.STATUS_RUNNING:
            raise _exc.HostRuntimeException(gen_msg=('unable_to_status',
                                                     'start', status))
Beispiel #2
0
    def _instance_request(self, action_name, status_desc='', **parameters):
        """
        Changes instance status. Does it in a retry loop to be sure
        to have the correct status when performing action.

        Getting status information seem to not always return an up to
        date information and is not reliable to perform requests without error.

        see "AlibabaCSP._request" for more information on requests and
        parameters.

        Args:
            action_name (str): Action name.
            status_desc (str): Status name for description
                (starting, stopping, ...)
            parameters: Request extra parameters.

        Returns:
            dict: Request response.
        """
        instance_id = parameters.pop('InstanceId', self._instance_id)
        with _utl.Timeout(self.TIMEOUT, sleep=self._TIMEOUT_SLEEP) as timeout:
            while True:
                # Tries to execute requests
                try:
                    return self._request(
                        action_name,
                        error_code_filter='IncorrectInstanceStatus',
                        InstanceId=instance_id, **parameters)

                # If incorrect instance status, waits and retries
                except _acs_exceptions.ServerException:
                    if timeout.reached():
                        raise _exc.HostRuntimeException(gen_msg=(
                            'timeout', status_desc))
Beispiel #3
0
    def _attach_instance_profile_role(self):
        """
        Attach IAM role to IAM instance profile.
        """
        # Attach role to instance profile
        with _exception_handler(filter_error_codes='LimitExceeded'):
            with _utl.Timeout(self.TIMEOUT,
                              sleep=self._TIMEOUT_SLEEP) as timeout:
                while True:
                    try:
                        self._iam_client.add_role_to_instance_profile(
                            InstanceProfileName=self._instance_profile_name,
                            RoleName=self._role)
                        break

                    # Some time, instance_profile is not ready immediately
                    except _ClientError as exception:
                        if (exception.response['Error']['Code'] ==
                                'NoSuchEntityException'):
                            if timeout.reached():
                                raise _exc.HostRuntimeException(gen_msg=(
                                    'timeout',
                                    'IAM instance_profile and role attachment'
                                ))
                            continue
                        raise

            _get_logger().debug(
                _utl.gen_msg('attached_to', 'IAM role', self._role,
                             'IAM instance profile',
                             self._instance_profile_name))
Beispiel #4
0
    def _get_private_ip(self):
        """
        Read current instance private IP from CSP instance.

        Returns:
            str: IP address
        """
        try:
            return self._get_instance()['PrivateIpAddress']['IpAddress'][0]
        except (KeyError, IndexError):
            raise _exc.HostRuntimeException(gen_msg='no_instance_ip')
Beispiel #5
0
    def _get_status(self):
        """
        Returns current status of current instance.

        Returns:
            str: Status
        """
        try:
            return self._get_instance()['Status']
        except KeyError:
            raise _exc.HostRuntimeException(
                gen_msg=('no_instance_id', self._instance_id))
Beispiel #6
0
    def _get_instance(self):
        """
        Returns current instance.

        Returns:
            dict: Instance description
        """
        response = self._request(
            'DescribeInstances', InstanceIds=[self._instance_id])
        try:
            return response['Instances']['Instance'][0]
        except (KeyError, IndexError):
            raise _exc.HostRuntimeException(
                gen_msg=('no_instance_id', self._instance_id))
Beispiel #7
0
    def _status(self):
        """
        Returns current status of current instance.

        Returns:
            str: Status

        Raises:
            apyfal.exceptions.HostRuntimeException:
                No instance from which get status.
        """
        if self._instance_id is None:
            raise _exc.HostRuntimeException(gen_msg='no_instance')

        # Update instance
        self._instance = self._get_instance()

        if self._instance is None:
            raise _exc.HostRuntimeException(gen_msg=('no_instance_id',
                                                     self._instance_id))

        # Read instance status
        return self._get_status()
Beispiel #8
0
    def private_ip(self):
        """
        Private IP of the current instance.

        Returns:
            str: IP address

        Raises:
            apyfal.exceptions.HostRuntimeException:
                No instance from which get IP.
        """
        if self._instance is None:
            raise _exc.HostRuntimeException(gen_msg='no_instance')
        return self._get_private_ip()
Beispiel #9
0
    def _get_public_ip(self):
        """
        Read current instance public IP from CSP instance.

        Returns:
            str: IP address
        """
        with _utl.Timeout(self.TIMEOUT, sleep=self._TIMEOUT_SLEEP) as timeout:
            while True:
                for address in list(
                        self._get_instance().addresses.values())[0]:
                    if address['version'] == 4:
                        return address['addr']
                if timeout.reached():
                    raise _exc.HostRuntimeException(gen_msg='no_instance_ip')
Beispiel #10
0
    def _wait_instance_ready(self):
        """
        Waits until instance is ready.
        """
        warned = False
        # Waiting for the instance provisioning
        with _utl.Timeout(self.TIMEOUT, sleep=self._TIMEOUT_SLEEP) as timeout:
            while True:
                # Get instance status
                status = self._status()
                if status == self.STATUS_RUNNING:
                    return
                elif status == self.STATUS_ERROR:
                    raise _exc.HostRuntimeException(
                        gen_msg=('unable_to_status', "provision", status))
                elif timeout.reached():
                    raise _exc.HostRuntimeException(gen_msg=('timeout_status',
                                                             "provisioning",
                                                             status))

                elif not warned:
                    # Avoid to show message if already booted
                    warned = True
                    _get_logger().info("Waiting instance provisioning...")
Beispiel #11
0
    def _wait_instance_ready(self):
        """
        Waits until instance is ready.
        """
        try:
            _CSPHost._wait_instance_ready(self)
        except _exc.HostException as exception:
            # Get extra information about error if possible
            try:
                raise _exc.HostRuntimeException(
                    exception.args[0],
                    exc=self._get_instance().fault['message'])

            # If not extra information, re raise previous error
            except (AttributeError, _nova_exc.ClientException):
                raise exception
Beispiel #12
0
def _exception_handler(to_catch=_ClientError,
                       to_raise=None,
                       filter_error_codes=None,
                       exception_msg=None,
                       **exc_kwargs):
    """
    Context manager that catch AWS EC2 exceptions and raises
    Apyfal exceptions.

    Args:
        to_catch (Exception sub class or tuple of Exception): Exception to catch.
            ClientError if not specified.
        to_raise (apyfal.exception.AcceleratorException subclass):
            Exception to raise. apyfal.exceptions.HostRuntimeException if not
            specified.
        filter_error_codes (str or tuple of str):
            Don't raise exception if error code in this argument.
        exception_msg (str): Exception message.
        exc_kwargs: Exception to raise arguments.
    """
    # Performs operation
    try:
        yield

    # Catch specified exceptions
    except to_catch as exception:
        # Try to get error code and message
        try:
            error_dict = exception.response['Error']
            error_code = error_dict['Code']
        except (AttributeError, KeyError):
            raise _exc.HostRuntimeException(exception_msg, exc=exception)

        # Converts single str to tuple
        if filter_error_codes is None:
            filter_error_codes = ()
        elif isinstance(filter_error_codes, str):
            filter_error_codes = (filter_error_codes, )

        # Raises if not in filter
        if error_code not in filter_error_codes:
            exception = to_raise or _exc.HostRuntimeException
            raise exception(exception_msg,
                            exc=error_dict['Message'],
                            **exc_kwargs)
Beispiel #13
0
    def _wait_instance_boot(self):
        """
        Waits until instance has booted and webservice is OK

        Raises:
            apyfal.exceptions.HostRuntimeException:
                Timeout while booting.
        """
        if not self.ALLOW_PORTS or _utl.check_port(self.host_ip, 80):
            # Avoid to show message if already booted or not
            return

        _get_logger().info("Waiting instance boot...")
        _sleep(self._TIMEOUT_SLEEP)
        if not _utl.check_port(
                self.host_ip, 80, timeout=self.TIMEOUT,
                sleep=self._TIMEOUT_SLEEP):
            raise _exc.HostRuntimeException(gen_msg=('timeout', "boot"))
Beispiel #14
0
    def _get_status(self):
        """
        Returns current status of current instance.

        Returns:
            str: Status
        """
        with _utl.Timeout(1, sleep=0.01) as timeout:
            while True:
                # Check Timeout
                if timeout.reached():
                    raise _exc.HostRuntimeException(
                        gen_msg=('no_instance_id', self._instance_id))

                # Get status
                with _exception_handler(
                        filter_error_codes='InvalidInstanceID.NotFound'):
                    return self._instance.state["Name"]
Beispiel #15
0
    def start(self,
              accelerator=None,
              accel_parameters=None,
              stop_mode=None,
              image_id=None,
              instance_type=None):
        """
        Start instance if not already started. Create instance if necessary.

        Needs "accel_client" or "accel_parameters".

        Args:
            accelerator (str): Name of the accelerator.
            accel_parameters (dict): Can override parameters from accelerator
                client.
            image_id (str): Force the use of specified image ID.
            instance_type (str): Force the use of specified instance type.
            stop_mode (str or int): See "stop_mode" property for more
                information.
        """
        # Updates stop mode
        self.stop_mode = stop_mode

        # Starts instance only if not already started
        if self._host_ip is None:

            # Get parameters from accelerator
            self._set_accelerator_requirements(
                accelerator=accelerator,
                accel_parameters=accel_parameters,
                image_id=image_id,
                instance_type=instance_type)

            # Checks CSP credential
            self._check_credential()

            # Creates and starts instance if not exists
            if self.instance_id is None:
                _get_logger().info("Configuring host on %s instance...",
                                   self._host_type)

                with self._stop_silently_on_exception():
                    self._create_instance()

                with self._stop_silently_on_exception():
                    self._instance, self._instance_id = \
                        self._start_new_instance()

                _get_logger().debug(
                    _utl.gen_msg('created_named', 'instance',
                                 self._instance_id))

            # If exists, starts it directly
            else:
                self._start_existing_instance(self._status())

            # Waiting for instance provisioning
            with self._stop_silently_on_exception():
                self._wait_instance_ready()

            # Update instance URL
            self._host_ip = self.host_ip
            self._url = _utl.format_url(self._host_ip,
                                        force_secure=bool(self._ssl_cert_crt))

            # Waiting for the instance to boot
            self._wait_instance_boot()

            _get_logger().info("Host ready")

        # If Host IP exists exists, checks if reachable
        elif self.ALLOW_PORTS and not _utl.check_port(self.host_ip, 80):
            raise _exc.HostRuntimeException(gen_msg=('unable_reach_port',
                                                     self.host_ip, 80))