Exemplo n.º 1
0
def get_wind_speed(ctx, city_name):
    '''
        Gets wind speed from an external service based on city

    :param str city_name: Name of a city to check wind speed
        for. Format is "<City>, <State Abbr.>".
    :rtype: int
    :returns: Wind speed in MPH
    '''
    ctx.logger.debug('Executing get_wind_speed(%s)' % city_name)
    url = 'https://query.yahooapis.com/v1/public/yql?q=' \
          'select wind from weather.forecast where woeid in ' \
          '(select woeid from geo.places(1) where text="%s")' \
          '&format=json&env=store://datatables.org/alltableswithkeys' \
          % city_name
    ctx.logger.debug('Querying URL "%s"' % url)
    res = requests.get(url)
    try:
        data = res.json()
        ctx.logger.debug('Response received: %s' % json.dumps(data, indent=2))
        speed = data.get('query', {}).get('results',
                                          {}).get('channel',
                                                  {}).get('wind',
                                                          {}).get('speed')
        if not speed:
            raise RecoverableError(
                'Missing wind speed data from weather service')
        return int(speed)
    except ValueError:
        raise RecoverableError('Unexpected response from weather service')
Exemplo n.º 2
0
    def operation_complete(self, op_info):
        '''
            Checks the status of an asynchronous operation

        :param dict op_info: Long-running operation headers
        :raises: :exc:`cloudify.exceptions.RecoverableError`,
                 :exc:`cloudify.exceptions.NonRecoverableError`,
                 :exc:`requests.RequestException`
        '''
        # Get the operation ID
        op_id = op_info.get('x-ms-request-id', 'not-reported')
        # Make the request
        self.log.info('Checking status of operation "{0}"'.format(op_id))
        op_url = op_info.get('location') or \
            op_info.get('azure-asyncoperation')
        res = self.client.request(method='get', url=op_url)
        # Convert headers from CaseInsensitiveDict to Dict
        headers = dict(res.headers)
        self.log.debug('headers: {0}'.format(
            utils.secure_logging_content(headers)))
        # HTTP 200 (OK) - Operation is successful and complete
        if res.status_code == httplib.OK:
            if self.validate_res_json(res) == 'InProgress':
                return ctx.operation.retry(
                    'Operation: "{0}" still pending'.format(
                        self.get_operation_id(headers)),
                    retry_after=self.get_retry_after(headers))
            self.ctx.instance.runtime_properties['async_op'] = None
            return
        # Clear the async state
        self.ctx.instance.runtime_properties['async_op'] = None
        # HTTP 202 (ACCEPTED) - Operation is still pending
        if res.status_code == httplib.ACCEPTED:
            if not headers.get('location'):
                raise RecoverableError(
                    'HTTP 202 ACCEPTED but no Location header present')
            self.ctx.instance.runtime_properties['async_op'] = headers
            return ctx.operation.retry(
                'Operation: "{0}" still pending'.format(
                    self.get_operation_id(headers)),
                retry_after=self.get_retry_after(headers))
        # HTTP 409 (CONFLICT) - Operation failed
        elif res.status_code == httplib.CONFLICT:
            if "AnotherOperationInProgress" in res.text:
                self.log.warn(
                    "Another Operation In Progress, let's wait: {0}".format(
                        headers))
                raise RecoverableError('Another Operation In Progress')
            raise NonRecoverableError(
                'Operation "{0}" failed. (code={1}, data={2})'.format(
                    op_id, res.status_code, res.text))
        # HTTP 500 (INTERNAL_SERVER_ERROR) - Operation time out
        elif res.status_code == httplib.INTERNAL_SERVER_ERROR:
            # Preserve op_info in case it's really just a time-out
            self.ctx.instance.runtime_properties['async_op'] = op_info
            return ctx.operation.retry(
                'Operation: "{0}" still pending'.format(
                    self.get_operation_id(headers)),
                retry_after=self.get_retry_after(headers))
        res.raise_for_status()
Exemplo n.º 3
0
def check_or_create_resource(headers,
                             resource_name,
                             resource_params,
                             check_resource_url,
                             create_resource_url,
                             resource_type,
                             save_response=False):
    if constants.REQUEST_ACCEPTED in ctx.instance.runtime_properties:
        if resource_was_created(headers, resource_name, check_resource_url,
                                save_response):
            ctx.logger.info(
                "check_or_create_resource resource {0} ({1}) is ready ".format(
                    resource_name, resource_type))
            return constants.CREATED_STATUS_CODE
        else:
            raise RecoverableError(
                "check_or_create_resource: resource {0} ({1}) is not ready yet"
                .format(resource_name, resource_type))
    elif create_resource(headers, resource_name, resource_params,
                         create_resource_url, resource_type):
        if resource_was_created(headers, resource_name, check_resource_url,
                                save_response):
            ctx.logger.info(
                "_create_resource resource {0} ({1}) is ready ".format(
                    resource_name, resource_type))
            return constants.CREATED_STATUS_CODE
        else:
            raise RecoverableError(
                "check_or_create_resource: resource {0} ({1}) is not ready yet"
                .format(resource_name, resource_type))
Exemplo n.º 4
0
def _make_call(ctx, request_method, url, data, operation_inputs):
    with _get_cert(ctx, operation_inputs) as cert:
        result = request_method(
            url,
            auth=_get_credentials(ctx, operation_inputs),
            json=data,
            verify=cert,
        )

    if result.status_code >= 500:
        raise RecoverableError('Server is currently unavailable. '
                               'Call was to {url}, and '
                               'response was {code}: {details}'.format(
                                   url=url,
                                   code=result.status_code,
                                   details=result.text,
                               ))
    elif result.status_code >= 400:
        raise RecoverableError('Parameters passed to server were incorrect, '
                               'or Nagios is still starting. '
                               'Call was to {url}, and '
                               'response was {code}: {details}'.format(
                                   url=url,
                                   code=result.status_code,
                                   details=result.text,
                               ))
    else:
        return result
Exemplo n.º 5
0
def validate_agent_amqp(current_amqp=True,
                        manager_ip=None,
                        manager_certificate=None,
                        **_):
    """
    Validate connectivity between a cloudify agent and an AMQP server
    :param current_amqp: If set to True, validation is done against the
    current manager's AMQP. If set to False, validation is done against the
    old manager's AMQP to which the agent is currently connected.
    Note: in case of an in-place upgrade, both AMQP servers should be identical
    :param manager_ip: the IP of the current leader (master) Manager, relevant
    only in HA cluster. This IP is used to validate that an agent is connected
    to the Manager's RabbitMQ.
    :param manager_certificate: the SSL certificate of the current leader
    (master) Manager.
    """
    if 'cloudify_agent' not in ctx.instance.runtime_properties:
        raise NonRecoverableError(
            'cloudify_agent key not available in runtime_properties')
    agent = ctx.instance.runtime_properties['cloudify_agent']
    _update_broker_config(agent, manager_ip, manager_certificate)

    validator = _validate_current_amqp if current_amqp else _validate_old_amqp
    result = validator(agent)

    result['timestamp'] = time.time()
    ctx.instance.runtime_properties['agent_status'] = result

    if current_amqp and not result['agent_alive']:
        raise RecoverableError(result['agent_alive_error'])
    if not current_amqp and not result['agent_alive_crossbroker']:
        raise RecoverableError(result['agent_alive_crossbroker_error'])
Exemplo n.º 6
0
    def delete(self, name):
        '''
            Deletes an existing resource

        :param string name: Name of the existing resource
        :raises: :exc:`cloudify.exceptions.RecoverableError`,
                 :exc:`cloudify.exceptions.NonRecoverableError`,
                 :exc:`requests.RequestException`
        '''
        self.log.info('Deleting {0} "{1}"'.format(self.name, name))
        if self.ctx.instance._modifiable:
            self.ctx.instance.runtime_properties['async_op'] = None
        # Make the request
        res = self.client.request(method='delete',
                                  url='{0}/{1}'.format(self.endpoint, name))
        # Convert headers from CaseInsensitiveDict to Dict
        headers = dict(res.headers)
        self.log.debug('headers: {0}'.format(
            utils.secure_logging_content(headers)))
        # HTTP 200 (OK) - The operation is successful and complete
        if res.status_code == httplib.OK:
            return
        # HTTP 204 (NO_CONTENT) - The resource doesn't exist
        elif res.status_code == httplib.NO_CONTENT:
            return
        # HTTP 202 (ACCEPTED) - The operation has started but is asynchronous
        elif res.status_code == httplib.ACCEPTED:
            if not headers.get('location'):
                raise RecoverableError(
                    'HTTP 202 ACCEPTED but no Location header present')
            if not self.ctx.instance._modifiable:
                self.log.warn('Not retrying async operation, '
                              'because NodeInstanceContext is not modifiable. '
                              'headers: {0}'.format(headers))
                return
            self.ctx.instance.runtime_properties['async_op'] = headers
            return ctx.operation.retry(
                'Operation: "{0}" started'.format(
                    self.get_operation_id(headers)),
                retry_after=self.get_retry_after(headers))
        # HTTP 400 (BAD_REQUEST) - We're sending bad data
        elif res.status_code == httplib.BAD_REQUEST:
            self.log.info('BAD REQUEST: response: {}'.format(
                utils.secure_logging_content(res.content)))
            raise UnexpectedResponse('Recieved HTTP 400 BAD REQUEST',
                                     res.json())
        # HTTP 409 (CONFLICT) - Operation failed
        elif res.status_code == httplib.CONFLICT:
            raise NonRecoverableError(
                'Operation failed. (code={0}, data={1})'.format(
                    res.status_code, res.text))
        # All other errors will be treated as recoverable
        elif res.status_code != httplib.CREATED:
            raise RecoverableError(
                'Expected HTTP status code {0}, recieved {1}'.format(
                    httplib.CREATED, res.status_code))
Exemplo n.º 7
0
    def get(self, name=None):
        '''
            Gets details about an existing resource

        :param string name: Name of the existing resource
        :returns: Response data from the Azure API call
        :rtype: dict
        :raises: :exc:`cloudify.exceptions.RecoverableError`,
                 :exc:`cloudify.exceptions.NonRecoverableError`,
                 :exc:`requests.RequestException`
        '''
        self.log.info('Retrieving {0} "{1}"'.format(self.name, name))
        # Make the request
        if name:
            url = '{0}/{1}'.format(self.endpoint, name)
        else:
            url = self.endpoint
        res = self.client.request(
            method='get',
            url=url)
        self.log.debug('headers: {0}'.format(
            utils.secure_logging_content(dict(res.headers))))
        headers = self.lowercase_headers(res.headers)
        # Check the response
        # HTTP 202 (ACCEPTED) - The operation has started but is asynchronous
        if res.status_code == httplib.ACCEPTED:
            if not headers.get('location'):
                raise RecoverableError(
                    'HTTP 202 ACCEPTED but no Location header present')
            self.ctx.instance.runtime_properties['async_op'] = headers
            return ctx.operation.retry(
                'Operation: "{0}" started'
                .format(self.get_operation_id(headers)),
                retry_after=self.get_retry_after(headers))
        # HTTP 200 (OK) - The resource already exists
        elif res.status_code == httplib.OK:
            return res.json()
        # If Azure sent a 400, we're sending bad data
        if res.status_code == httplib.BAD_REQUEST:
            self.log.info('BAD REQUEST: response: {}'.format(res.content))
            raise UnexpectedResponse(
                'Recieved HTTP 400 BAD REQUEST', res.json())
        # If Azure sent a 404, the resource doesn't exist (yet?)
        if res.status_code == httplib.NOT_FOUND:
            raise RecoverableError(
                '{0} "{1}" doesn\'t exist (yet?)'
                .format(self.name, name))
        # All other errors will be treated as recoverable
        if res.status_code != httplib.CREATED:
            raise RecoverableError(
                'Expected HTTP status code {0}, recieved {1}'
                .format(httplib.CREATED, res.status_code))
        return res.json()
Exemplo n.º 8
0
def create():

    ctx.logger.info('Verifying that Salt is installed.')

    # Check if Salt is running
    salt_master_service = sudo('systemctl status salt-master.service')
    if salt_master_service.return_code == 0:
        ctx.logger.debug('Salt installed and running.')
    elif salt_master_service.return_code == 3:
        raise RecoverableError('Salt is installed, but is not running.')
    else:
        raise RecoverableError(
            'Salt is not installed and not running: {0}'.format(salt_master_service))
Exemplo n.º 9
0
    def disassociate(self, args=None, **_):
        """ Disassocates an ENI created by Cloudify from an EC2 Instance
        that was also created by Cloudify.
        """

        attachment_id = \
            ctx.source.instance.runtime_properties.pop('attachment_id')

        detach_args = dict(attachment_id=attachment_id)

        detach_args = utils.update_args(detach_args, args)

        try:
            output = self.execute(self.client.detach_network_interface,
                                  detach_args,
                                  raise_on_falsy=True)
        except (exception.EC2ResponseError, exception.BotoServerError) as e:
            raise NonRecoverableError('{0}'.format(str(e)))

        if not output:
            ctx.source.instance.runtime_properties['attachment_id'] = \
                attachment_id
            raise RecoverableError('Failed to detach network interface {0} '
                                   'from instance {1}'.format(
                                       self.source_resource_id,
                                       self.target_resource_id))
        return output
Exemplo n.º 10
0
def create_agent_amqp(install_agent_timeout=300,
                      manager_ip=None,
                      manager_certificate=None,
                      stop_old_agent=False,
                      **_):
    """
    Installs a new agent on a host machine.
    :param install_agent_timeout: operation's timeout.
    :param manager_ip: the private IP of the current leader (master) Manager.
     This IP is used to connect to the Manager's RabbitMQ.
     (relevant only in HA cluster)
    :param manager_certificate: the SSL certificate of the current leader
    (master) Manager. (relevant only in HA cluster)
    :param stop_old_agent: if set, stop the old agent after successfully
    installing the new one
    """
    old_agent = _validate_agent()
    _update_broker_config(old_agent, manager_ip, manager_certificate)
    agents = _run_install_script(old_agent, install_agent_timeout)
    new_agent = agents['new']
    ctx.logger.info('Installed agent {0}'.format(new_agent['name']))

    result = _validate_current_amqp(new_agent)
    if not result['agent_alive']:
        raise RecoverableError('New agent did not start and connect')

    if stop_old_agent:
        _stop_old_diamond(old_agent, install_agent_timeout)
        _stop_old_agent(new_agent, old_agent, install_agent_timeout)

    # Setting old_cloudify_agent in order to uninstall it later.
    ctx.instance.runtime_properties['old_cloudify_agent'] = agents['old']
    update_agent_runtime_properties(new_agent)
    def wrapper(**kwargs):
        configuration_property = _retrieve_property(
            ctx.instance,
            NODE_PROPERTY_CONFIGURATION
        )

        authentication_property = _retrieve_property(
            ctx.instance,
            NODE_PROPERTY_AUTHENTICATION
        )

        try:
            kwargs['client'] = CloudifyKubernetesClient(
                ctx.logger,
                KubernetesApiConfigurationVariants(
                    ctx.logger,
                    configuration_property,
                    download_resource=ctx.download_resource
                ),
                KubernetesApiAuthenticationVariants(
                    ctx.logger,
                    authentication_property
                )
            )

            function(**kwargs)
        except KuberentesApiInitializationFailedError as e:
            _, exc_value, exc_traceback = sys.exc_info()
            raise RecoverableError(
                '{0}'.format(str(e)),
                causes=[exception_to_error_cause(exc_value, exc_traceback)]
            )
Exemplo n.º 12
0
    def _create_elb(self, args):

        create_args = self._create_elb_params()
        create_args = utils.update_args(create_args, args)

        try:
            lb = self.execute(self.client.create_load_balancer, create_args,
                              raise_on_falsy=True)
        except (exception.EC2ResponseError,
                exception.BotoServerError,
                exception.BotoClientError) as e:
            raise RecoverableError('Load Balancer not created '
                                   '{0}'.format(str(e)))

        if not lb:
            raise NonRecoverableError(
                'Load Balancer not created. While the create '
                'request was completed'
                ' successfully, verifying the load balancer '
                'afterwards has failed')

        ctx.instance.runtime_properties['elb_name'] = create_args['name']
        self.resource_id = create_args['name']

        return lb
Exemplo n.º 13
0
def raiseRecoverableError(msg):
    """
  Print a warning message and raise a RecoverableError exception.
  This is a handy endpoint to add other extended debugging calls.
  """
    warn(msg)
    raise RecoverableError(msg)
Exemplo n.º 14
0
def _execute_initial_state(minion_id):
    mgr = _instantiate_manager()

    ctx.logger.info('Connecting to Salt API...')
    resp, result = mgr.log_in()
    if not resp.ok:
        ctx.logger.error('Got response {0}'.format(resp))
        raise NonRecoverableError('Unable to connect with Salt API.')
    ctx.logger.info('Connected to Salt API.')

    ctx.logger.info('Pinging minion {0}...'.format(minion_id))
    for i in xrange(15):
        time.sleep(2)
        resp, result = mgr.ping(minion_id)
        if resp.ok and minion_id in result:
            break
    else:
        raise RecoverableError('{0} does not respond.'.format(minion_id))

    ctx.logger.info('Executing highstate on minion {0}...'.format(minion_id))
    resp, result = mgr.highstate(minion_id)
    if not resp.ok:
        ctx.logger.error('Got response {0}'.format(resp))
        raise NonRecoverableError(
            'Unable to execute highstate on minion {0}.'.format(minion_id))
    ctx.logger.info('Executed highstate on minion {0}.'.format(minion_id))

    resp, result = mgr.log_out()
    if resp.ok:
        ctx.logger.debug('Token has been cleared')
    else:
        ctx.logger.warn('Unable to clear token.')
    def test_image_delete(self, glance_m):
        glance_instance = glance_m.return_value
        server_ctx = self._simplectx()

        # still alive
        glance_instance.images.list = mock.Mock(return_value=[
            {
                'name': 'vm-server_id-snapshot_name-increment',
                'image_type': 'snapshot',
                'id': 'abc',
                'status': 'active'
            }
        ])

        server_ctx.operation.retry = mock.Mock(
            side_effect=RecoverableError())
        with self.assertRaises(RecoverableError):
            nova_plugin.server._image_delete(
                glance_instance,
                snapshot_name='vm-server_id-snapshot_name-increment',
                snapshot_incremental=True)
        server_ctx.operation.retry.assert_called_with(
            message='abc is still alive', retry_after=30)

        # removed
        glance_instance.images.list = mock.Mock(return_value=[])

        nova_plugin.server._image_delete(
            glance_instance, snapshot_name='snapshot_name',
            snapshot_incremental=True)
Exemplo n.º 16
0
 def delete(self, prev_kv=False, return_response=False):
     key = self.config.get('key')
     self.logger.debug('Attempting to delete the key: {}'.format(key))
     fail_on_overwrite = self.config.get('fail_on_overwrite')
     if fail_on_overwrite:
         predelete_value, existing_kvmetadata = self.connection.get(key)
         if self.config.get('value') != str(predelete_value):
             return
         response = self.connection.delete(key,
                                           prev_kv=True,
                                           return_response=True)
         if not response.deleted:
             raise RecoverableError(
                 'Key: {0} delete unsuccessful'.format(key))
         deleted_value = response.prev_kvs[-1].value
         if deleted_value != str(predelete_value):
             raise CommandExecutionError(
                 'etcd3 delete key',
                 'Deleted another value ({0}) than expected ({1}) for'
                 ' key: {2}'.format(deleted_value, predelete_value, key))
     else:
         response = self.connection.delete(key,
                                           prev_kv=prev_kv,
                                           return_response=return_response)
     # TODO: add some check if the deletion was successful
     self.logger.debug('Deleted key-value pair "{}" with result: {}'.format(
         key, response))
     return response
Exemplo n.º 17
0
def custom_resource_delete(client, api_mapping, resource_definition, **kwargs):
    try:
        read_response = _do_resource_read(client,
                                          api_mapping,
                                          _retrieve_id(ctx.instance),
                                          **kwargs)
        ctx.instance.runtime_properties[INSTANCE_RUNTIME_PROPERTY_KUBERNETES] \
            = read_response
    except KuberentesApiOperationError as e:
        if '"code":404' in str(e):
            ctx.logger.debug(
                'Ignoring error: {0}'.format(str(e)))
        else:
            raise RecoverableError(
                'Raising error: {0}'.format(str(e)))
    else:
        delete_response = _do_resource_delete(
            client,
            api_mapping,
            resource_definition,
            _retrieve_id(ctx.instance),
            **kwargs
        )

        raise OperationRetry(
            'Delete response: {0}'.format(delete_response))
Exemplo n.º 18
0
def get_config_content(filename):
    with open(filename, 'r') as outfile:
        try:
            return yaml.load(outfile)
        except yaml.YAMLError as e:
            raise RecoverableError('Unable to read file: {0}: {1}'.format(
                filename, str(e)))
Exemplo n.º 19
0
def stop(retry_interval, params, daemon_client=None, **_):
    """ cloudify.docker.container type stop lifecycle operation.
        Stops a container. Similar to the docker stop command.
        Any properties and runtime_properties set in the create
        and start lifecycle operations also available in stop.

    :param daemon_client: optional configuration for client creation
    :param timeout: Timeout in seconds to wait for the container to stop before
        sending a SIGKILL.
    """

    daemon_client = daemon_client or {}
    client = docker_client.get_client(daemon_client)

    container_id = ctx.instance.runtime_properties['container_id']
    ctx.logger.info('Stopping container: {}'.format(container_id))

    container_id = ctx.instance.runtime_properties['container_id']
    arguments = {'container': container_id}
    arguments.update(params)

    ctx.logger.info('Stop arguments: {0}'.format(arguments))

    try:
        client.stop(**arguments)
    except APIError as e:
        raise NonRecoverableError(
            'Failed to start container: {0}.'.format(str(e)))

    if 'Exited' not in utils.check_container_status(client):
        raise RecoverableError('Container still running. Retyring.',
                               retry_after=retry_interval)

    ctx.logger.info('Stopped container: {}'.format(container_id))
    def list_keys(self, name=None):
        '''
            Calls /listKeys

        :param string name: Name of the existing resource
        :returns: Response data from the Azure API call
        :rtype: dict
        :raises: :exc:`cloudify.exceptions.RecoverableError`
        '''
        # Get the resource name
        name = name or utils.get_resource_name(self.ctx)
        url = '{0}/{1}/listKeys'.format(self.endpoint, name)
        res = self.client.request(
            method='post',
            url=url)
        if res.status_code != httplib.OK:
            raise RecoverableError(
                'Unexpected status returned after calling '
                '/listKeys. Status={0}'.format(res.status_code))
        keys = res.json()
        ret = list()
        for key in keys:
            ret.append({
                'name': key,
                'key': keys[key]
            })
        return ret
Exemplo n.º 21
0
def delete(ctx, **_):
    '''Deletes an AWS API Gateway REST API Deployment'''
    props = ctx.node.properties
    # Get a connection to the service
    client = APIGatewayConnection(ctx.node).client()
    # Get the parent API
    api_resource_id = props.get(
        'api_id', utils.get_ancestor_resource_id(ctx.instance, NODE_TYPE_API))
    # Get the resource ID (must exist at this point)
    resource_id = utils.get_resource_id()
    if not resource_id:
        ctx.logger.warn('Missing resource ID. Skipping workflow...')
        return
    # Delete the resource (if needed)
    if props['use_external_resource']:
        return
    if ctx.operation.retry_number == 0:
        stages = client.get_stages(restApiId=api_resource_id,
                                   deploymentId=resource_id)
        # There are stages left that must be removed
        if stages and 'item' in stages and len(stages['item']):
            for item in stages['item']:
                ctx.logger.debug('Removing deployment stage "%s"' %
                                 item['stageName'])
                client.delete_stage(restApiId=api_resource_id,
                                    stageName=item['stageName'])
        ctx.logger.info('Deleting Deployment "%s"' % resource_id)
        try:
            client.delete_deployment(restApiId=api_resource_id,
                                     deploymentId=resource_id)
            ctx.logger.debug('Deployment "%s" deleted' % resource_id)
        except ClientError as exc:
            raise RecoverableError('Error deleting Deployment: %s' % str(exc))
 def wrapper(**kwargs):
     try:
         kwargs['resource_definition'] = \
             retrieve_resource_definition(**kwargs)
         kwargs['api_mapping'] = retrieve_mapping(**kwargs)
         task(**kwargs)
     except (KuberentesMappingNotFoundError,
             KuberentesInvalidPayloadClassError,
             KuberentesInvalidApiClassError,
             KuberentesInvalidApiMethodError) as e:
         raise NonRecoverableError(str(e))
     except OperationRetry as e:
         _, exc_value, exc_traceback = sys.exc_info()
         raise OperationRetry(
             '{0}'.format(str(e)),
             retry_after=15,
             causes=[exception_to_error_cause(exc_value, exc_traceback)]
         )
     except NonRecoverableError as e:
         _, exc_value, exc_traceback = sys.exc_info()
         raise NonRecoverableError(
             '{0}'.format(str(e)),
             causes=[exception_to_error_cause(exc_value, exc_traceback)]
         )
     except Exception as e:
         _, exc_value, exc_traceback = sys.exc_info()
         raise RecoverableError(
             '{0}'.format(str(e)),
             causes=[exception_to_error_cause(exc_value, exc_traceback)]
         )
    def wrapper(**kwargs):
        configuration_property = _retrieve_property(
            ctx.instance,
            NODE_PROPERTY_CONFIGURATION
        )

        authentication_property = _retrieve_property(
            ctx.instance,
            NODE_PROPERTY_AUTHENTICATION
        )

        try:
            kwargs['client'] = CloudifyKubernetesClient(
                ctx.logger,
                KubernetesApiConfigurationVariants(
                    ctx.logger,
                    configuration_property,
                    download_resource=ctx.download_resource
                ),
                KubernetesApiAuthenticationVariants(
                    ctx.logger,
                    authentication_property
                )
            )

            function(**kwargs)
        except KuberentesApiInitializationFailedError as e:
            raise RecoverableError(e)
    def wrapper(**kwargs):

        node_property_definition = \
            ctx.node.properties[NODE_PROPERTY_DEFINITION]

        file_resource = \
            node_property_definition.pop('file', {})
        if file_resource:
            resource_definition = \
                _yaml_from_file(**file_resource)
        else:
            resource_definition = node_property_definition

        if 'kind' not in resource_definition.keys():
            node_type = \
                ctx.node.type if \
                isinstance(ctx.node.type, basestring) else ''
            resource_definition['kind'] = node_type.split('.')[-1]

        kwargs['resource_definition'] = \
            KubernetesResourceDefinition(
                **resource_definition)

        kwargs['mapping'] = KubernetesApiMapping(
            **ctx.node.properties[NODE_PROPERTY_API_MAPPING]
        )

        try:
            task(**kwargs)
        except (KuberentesInvalidPayloadClassError,
                KuberentesInvalidApiClassError,
                KuberentesInvalidApiMethodError) as e:
            raise NonRecoverableError(str(e))
        except Exception as e:
            raise RecoverableError(str(e))
Exemplo n.º 25
0
    def associate(self, args=None, **_):
        """ Associates an ENI created by Cloudify with an EC2 Instance
        that was also created by Cloudify.
        """

        network_interface_id = self.source_resource_id
        instance_id = self.target_resource_id

        attachment_args = dict(network_interface_id=network_interface_id,
                               instance_id=instance_id,
                               device_index=1)

        attachment_args = utils.update_args(attachment_args, args)

        try:
            output = self.execute(self.client.attach_network_interface,
                                  attachment_args,
                                  raise_on_falsy=True)
        except (exception.EC2ResponseError, exception.BotoServerError) as e:
            raise NonRecoverableError('{0}'.format(str(e)))

        if not output:
            raise RecoverableError(
                'Failed to attach eni    {0} to instance {1}'.format(
                    self.source_resource_id, self.target_resource_id))

        network_interface = self.get_source_resource()
        ctx.source.instance.runtime_properties['attachment_id'] = \
            network_interface.attachment.id

        return output
def remove_instance_from_elb(**_):

    elb_name = \
        utils.get_external_resource_id_or_raise(
            'elb_name', ctx.target.instance)

    instance_id = \
        utils.get_external_resource_id_or_raise(
            'instance_id', ctx.source.instance)

    instance_list = [instance_id]
    lb = _get_existing_elb(elb_name)

    ctx.logger.info('Attemping to remove instance: {0} from elb {1}'.format(
        instance_id, elb_name))

    try:
        lb.deregister_instances(instance_list)
    except (boto.exception.EC2ResponseError, boto.exception.BotoServerError,
            boto.exception.BotoClientError) as e:
        if instance_id in _get_instance_list():
            raise RecoverableError('Instance not removed from Load Balancer '
                                   '{0}'.format(str(e)))

    ctx.logger.info('Instance {0} removed from Load Balancer {1}.'.format(
        instance_id, elb_name))
    _remove_instance_from_elb_list_in_properties(instance_id)
def _create_elb():

    ctx.logger.info('Attempting to Create Load Balancer.')

    params_dict = _create_elb_params()
    elb_client = connection.ELBConnectionClient().client()

    try:
        lb = elb_client.create_load_balancer(**params_dict)
    except (boto.exception.EC2ResponseError, boto.exception.BotoServerError,
            boto.exception.BotoClientError) as e:
        raise RecoverableError('Load Balancer not created '
                               '{0}'.format(str(e)))

    if not lb:
        raise NonRecoverableError(
            'Load Balancer not created. While the create request was completed'
            ' successfully, verifying the load balancer afterwards has failed')

    ctx.logger.info('Load Balancer Created.')

    utils.set_external_resource_id(params_dict['name'],
                                   ctx.instance,
                                   external=False)

    ctx.instance.runtime_properties['elb_name'] = params_dict['name']

    return lb
Exemplo n.º 28
0
def attach_volume(nova_client, cinder_client, status_attempts,
                  status_timeout, **kwargs):
    server_id = get_openstack_id(ctx.target)
    volume_id = get_openstack_id(ctx.source)

    if is_external_relationship_not_conditionally_created(ctx):
        ctx.logger.info('Validating external volume and server '
                        'are connected')
        attachment = volume.get_attachment(cinder_client=cinder_client,
                                           volume_id=volume_id,
                                           server_id=server_id)
        if attachment:
            return
        else:
            raise NonRecoverableError(
                'Expected external resources server {0} and volume {1} to be '
                'connected'.format(server_id, volume_id))

    # Note: The 'device_name' property should actually be a property of the
    # relationship between a server and a volume; It'll move to that
    # relationship type once relationship properties are better supported.
    device = ctx.source.node.properties[volume.DEVICE_NAME_PROPERTY]
    nova_client.volumes.create_server_volume(
        server_id,
        volume_id,
        device if device != 'auto' else None)
    try:
        vol, wait_succeeded = volume.wait_until_status(
            cinder_client=cinder_client,
            volume_id=volume_id,
            status=volume.VOLUME_STATUS_IN_USE,
            num_tries=status_attempts,
            timeout=status_timeout
        )
        if not wait_succeeded:
            raise RecoverableError(
                'Waiting for volume status {0} failed - detaching volume and '
                'retrying..'.format(volume.VOLUME_STATUS_IN_USE))
        if device == 'auto':
            # The device name was assigned automatically so we
            # query the actual device name
            attachment = volume.get_attachment(
                cinder_client=cinder_client,
                volume_id=volume_id,
                server_id=server_id
            )
            device_name = attachment['device']
            ctx.logger.info('Detected device name for attachment of volume '
                            '{0} to server {1}: {2}'
                            .format(volume_id, server_id, device_name))
            ctx.source.instance.runtime_properties[
                volume.DEVICE_NAME_PROPERTY] = device_name
    except Exception, e:
        if not isinstance(e, NonRecoverableError):
            _prepare_attach_volume_to_be_repeated(
                nova_client, cinder_client, server_id, volume_id,
                status_attempts, status_timeout)
        raise
Exemplo n.º 29
0
    def wrapper(*args, **kwargs):
        _put_api_in_kwargs('fco_api', kwargs)

        try:
            return f(*args, **kwargs)
        except fco_exceptions.NonRecoverableError as e:
            raise NonRecoverableError(str(e))
        except fco_exceptions.RecoverableError as e:
            raise RecoverableError(str(e), retry_after=e.retry_after)
Exemplo n.º 30
0
def _re_raise(e, recoverable, retry_after=None):
    exc_type, exc, traceback = sys.exc_info()
    if recoverable:
        if retry_after == 0:
            retry_after = None
        raise RecoverableError(message=e.message,
                               retry_after=retry_after), None, traceback
    else:
        raise NonRecoverableError(e.message), None, traceback