예제 #1
0
def allocate(**_):
    """This allocates an Elastic IP in the connected account."""

    ec2_client = connection.EC2ConnectionClient().client()

    if _allocate_external_elasticip():
        return

    ctx.logger.debug('Attempting to allocate elasticip.')

    kw = {}
    if ctx.node.properties.get('domain'):
        kw['domain'] = ctx.node.properties['domain']

    try:
        address_object = ec2_client.allocate_address(**kw)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    if 'vpc' in address_object.domain:
        ctx.instance.runtime_properties[constants.ALLOCATION_ID] = \
            address_object.allocation_id

    utils.set_external_resource_id(address_object.public_ip,
                                   ctx.instance,
                                   external=False)
def create(**_):
    """Creates an EC2 security group.
    """

    ec2_client = connection.EC2ConnectionClient().client()

    for property_name in constants.SECURITY_GROUP_REQUIRED_PROPERTIES:
        utils.validate_node_property(property_name, ctx.node.properties)

    name = utils.get_resource_id()

    if _create_external_securitygroup(name):
        return

    ctx.logger.debug(
        'Creating Security Group: {0}'
        .format(name))

    create_args = dict(
        name=name,
        description=ctx.node.properties['description'],
        vpc_id=_get_connected_vpc()
    )

    try:
        group_object = ec2_client.create_security_group(**create_args)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    _create_group_rules(group_object)
    utils.set_external_resource_id(
        group_object.id, ctx.instance, external=False)
예제 #3
0
def stop(**_):
    ec2_client = connection.EC2ConnectionClient().client()

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

    if _stop_external_instance(instance_id):
        return

    ctx.logger.debug(
        'Attempting to stop EC2 Instance. {0}.)'.format(instance_id))

    try:
        ec2_client.stop_instances(instance_id)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    ctx.logger.debug('Attempted to stop instance {0}.'.format(instance_id))

    if _get_instance_state() == constants.INSTANCE_STATE_STOPPED:
        _unassign_runtime_properties(
            runtime_properties=constants.INSTANCE_INTERNAL_ATTRIBUTES,
            ctx_instance=ctx.instance)
        ctx.logger.info('Stopped instance {0}.'.format(instance_id))
    else:
        return ctx.operation.retry(
            message='Waiting server to stop. Retrying...')
예제 #4
0
def start(**_):
    ec2_client = connection.EC2ConnectionClient().client()

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

    if _start_external_instance(instance_id):
        return

    if _get_instance_state() == constants.INSTANCE_STATE_STARTED:
        _instance_started_assign_runtime_properties(instance_id)
        return

    ctx.logger.debug('Attempting to start instance: {0}.)'.format(instance_id))

    try:
        ec2_client.start_instances(instance_id)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    ctx.logger.debug('Attempted to start instance {0}.'.format(instance_id))

    if _get_instance_state() == constants.INSTANCE_STATE_STARTED:
        _instance_started_assign_runtime_properties(instance_id)
    else:
        return ctx.operation.retry(
            message='Waiting server to be running. Retrying...')
예제 #5
0
def create(args, **_):
    """Creates an EBS volume.
    """

    ec2_client = connection.EC2ConnectionClient().client()

    for property_name in constants.VOLUME_REQUIRED_PROPERTIES:
        utils.validate_node_property(property_name, ctx.node.properties)

    if _create_external_volume():
        return

    ctx.logger.debug('Creating EBS volume')

    create_volume_args = dict(size=ctx.node.properties['size'],
                              zone=ctx.node.properties['zone'])

    create_volume_args.update(args)

    try:
        new_volume = ec2_client.create_volume(**create_volume_args)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    utils.set_external_resource_id(new_volume.id, ctx.instance, external=False)
예제 #6
0
def terminate(**_):
    ec2_client = connection.EC2ConnectionClient().client()

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

    if _terminate_external_instance(instance_id):
        return

    ctx.logger.debug(
        'Attempting to terminate EC2 Instance. {0}.)'.format(instance_id))

    try:
        ec2_client.terminate_instances(instance_id)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    ctx.logger.debug('Attemped to terminate instance {0}'.format(instance_id))

    if _get_instance_state() == \
            constants.INSTANCE_STATE_TERMINATED:
        ctx.logger.info('Terminated instance: {0}.'.format(instance_id))
        utils.unassign_runtime_property_from_resource(
            constants.EXTERNAL_RESOURCE_ID, ctx.instance)
    else:
        return ctx.operation.retry(
            message='Waiting server to terminate. Retrying...')
예제 #7
0
def _get_all_instances(list_of_instance_ids=None):
    """Returns a list of instance objects for a list of instance IDs.

    :returns a list of instance objects.
    :raises NonRecoverableError: If Boto errors.
    """

    ec2_client = connection.EC2ConnectionClient().client()

    try:
        reservations = ec2_client.get_all_reservations(list_of_instance_ids)
    except boto.exception.EC2ResponseError as e:
        if 'InvalidInstanceID.NotFound' in e:
            instances = [
                instance for res in ec2_client.get_all_reservations()
                for instance in res.instances
            ]
            utils.log_available_resources(instances)
        return None
    except boto.exception.BotoServerError as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    instances = []

    for reservation in reservations:
        for instance in reservation.instances:
            instances.append(instance)

    return instances
def associate(**_):
    """ Associates an Elastic IP created by Cloudify with an EC2 Instance
    that was also created by Cloudify.
    """

    ec2_client = connection.EC2ConnectionClient().client()

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

    if _associate_external_elasticip_or_instance(elasticip):
        return

    ctx.logger.debug(
        'Attempting to associate elasticip {0} and instance {1}.'.format(
            elasticip, instance_id))

    try:
        ec2_client.associate_address(instance_id=instance_id,
                                     public_ip=elasticip)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    ctx.logger.info('Associated Elastic IP {0} with instance {1}.'.format(
        elasticip, instance_id))
    ctx.source.instance.runtime_properties['public_ip_address'] = elasticip
예제 #9
0
def run_instances(**_):
    ec2_client = connection.EC2ConnectionClient().client()

    for property_name in constants.INSTANCE_REQUIRED_PROPERTIES:
        utils.validate_node_property(property_name, ctx.node.properties)

    if _create_external_instance():
        return

    instance_parameters = _get_instance_parameters()

    ctx.logger.info(
        'Attempting to create EC2 Instance with these API parameters: {0}.'.
        format(instance_parameters))

    instance_id = _run_instances_if_needed(ec2_client, instance_parameters)

    instance = _get_instance_from_id(instance_id)

    if instance is None:
        return ctx.operation.retry(
            message='Waiting to verify that instance {0} '
            'has been added to your account.'.format(instance_id))

    utils.set_external_resource_id(instance_id, ctx.instance, external=False)
def disassociate(**_):
    """ Disassocates an Elastic IP created by Cloudify from an EC2 Instance
    that was also created by Cloudify.
    """
    ec2_client = connection.EC2ConnectionClient().client()

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

    if _disassociate_external_elasticip_or_instance():
        return

    ctx.logger.debug('Disassociating Elastic IP {0}'.format(elasticip))

    try:
        ec2_client.disassociate_address(public_ip=elasticip)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    utils.unassign_runtime_property_from_resource('public_ip_address',
                                                  ctx.source.instance)

    ctx.logger.info('Disassociated Elastic IP {0} from instance {1}.'.format(
        elasticip, instance_id))
    def test_create_group_rules_both_src_group_id_cidr(self):
        """ This tests that either src_group_id or cidr_ip is
        error is raised when neither is given.
        """

        ec2_client = connection.EC2ConnectionClient().client()
        group = ec2_client.create_security_group(
            'test_create_group_rules_both_src_group_id_or_cidr',
            'this is test')
        test_properties = self.get_mock_properties()
        ctx = self.security_group_mock(
            'test_create_group_rules_both_src_group_id_or_cidr',
            test_properties)
        current_ctx.set(ctx=ctx)
        group_object = ec2_client.create_security_group(
            'dummy',
            'this is test')
        ctx.node.properties['rules'][0]['src_group_id'] = group_object
        ex = self.assertRaises(
            NonRecoverableError,
            securitygroup._create_group_rules,
            group)
        self.assertIn(
            'You need to pass either src_group_id OR cidr_ip.',
            ex.message)
예제 #12
0
    def test_validation_use_external_not_in_account(self):
        """ Tests that an error is raised if you use external,
        but the key pair doesn't exist in your account.
        """

        ctx = self.mock_ctx('test_validation_use_external_not_in_account')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair(
            'test_validation_use_external_not_in_account')
        ctx.node.properties['use_external_resource'] = True
        ctx.node.properties['resource_id'] = kp.name
        kp = ec2_client.delete_key_pair(
            'test_validation_use_external_not_in_account')
        key_path = \
            self.create_dummy_key_path(ctx=ctx)
        self.addCleanup(os.remove, key_path)
        with open(key_path, 'w') as dummy_key:
            dummy_key.write('test')
        ex = self.assertRaises(NonRecoverableError,
                               keypair.creation_validation,
                               ctx=ctx)
        self.assertIn('the key pair does not exist in the account', ex.message)
        self.assertIn('InvalidKeyPair.NotFound', ex.message)
    def test_aws_config_file_valid(self):
        client = connection.EC2ConnectionClient()
        config = client._get_aws_config_from_file()

        config_schema = constants.BOTO_CONFIG_SCHEMA
        for opt_group in config_schema.values():
            for opt in opt_group:
                self.assertIn(opt, config)
예제 #14
0
    def test_delete(self):
        """This tests that delete removes the runtime_properties"""

        test_properties = self.get_mock_properties()
        ctx = self.security_group_mock('test_delete', test_properties)
        current_ctx.set(ctx=ctx)
        ec2_client = connection.EC2ConnectionClient().client()
        group = ec2_client.create_security_group('test', 'this is test')
        ctx.instance.runtime_properties['aws_resource_id'] = group.id
        securitygroup.delete(ctx=ctx)
        self.assertNotIn('aws_resource_id', ctx.instance.runtime_properties)
예제 #15
0
    def test_get_key_pair_by_id(self):
        """ This tests that the _get_key_pair_by_id function
        returns the same keypair object.
        """

        ctx = self.mock_ctx('test_get_key_pair_by_id')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair('test_get_key_pair_by_id_bad_id')
        output = keypair._get_key_pair_by_id(kp.name)
        self.assertEqual(output.name, kp.name)
예제 #16
0
    def test_connect(self):
        """ this tests that a the correct region endpoint
        in returned by the connect function
        """

        ctx = self.get_mock_context('test_connect')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        self.assertTrue(type(ec2_client), EC2Connection)
        self.assertEqual(ec2_client.DefaultRegionEndpoint,
                         'ec2.us-east-1.amazonaws.com')
예제 #17
0
    def test_validation_use_external(self):
        ctx = self.mock_ctx('test_validation_use_external')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair('test_validation_use_external')
        ctx.node.properties['use_external_resource'] = True
        ctx.node.properties['resource_id'] = kp.name
        ex = self.assertRaises(NonRecoverableError,
                               keypair.creation_validation,
                               ctx=ctx)
        self.assertIn('but the key file does not exist locally.', ex.message)
예제 #18
0
    def test_save_key_pair_missing_property(self):
        """ This tests that _save_key_pair raises an error when
        private_key_path is not set.
        """

        ctx = self.mock_ctx('test_save_key_pair_missing_property')
        current_ctx.set(ctx=ctx)
        ec2_client = connection.EC2ConnectionClient().client()
        del (ctx.node.properties['private_key_path'])
        kp = ec2_client.create_key_pair('test_create_use_external')
        ex = self.assertRaises(NonRecoverableError, keypair._save_key_pair, kp)
        self.assertIn('Unable to get key file path, private_key_path not set',
                      ex.message)
예제 #19
0
    def test_delete(self):
        """ this tests that keypair delete removes the keypair from
            the account
        """
        ctx = self.mock_ctx('test_delete')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair('test_delete')
        ctx.instance.runtime_properties['aws_resource_id'] = kp.name
        ctx.instance.runtime_properties['key_path'] = \
            self.create_dummy_key_path(ctx=ctx)
        keypair.delete(ctx=ctx)
        self.assertEquals(None, ec2_client.get_key_pair(kp.name))
예제 #20
0
def start(start_retry_interval=30, private_key_path=None, **_):
    ec2_client = connection.EC2ConnectionClient().client()

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

    if _start_external_instance(instance_id):
        return

    if _get_instance_state() == constants.INSTANCE_STATE_STARTED:
        if ctx.node.properties['use_password']:
            password_success = _retrieve_windows_pass(
                ec2_client=ec2_client,
                instance_id=instance_id,
                private_key_path=private_key_path)
            if not password_success:
                return ctx.operation.retry(
                    message='Waiting for server to post generated password',
                    retry_after=start_retry_interval)

        _instance_started_assign_runtime_properties_and_tag(instance_id)
        return

    ctx.logger.debug('Attempting to start instance: {0}.)'.format(instance_id))

    try:
        ec2_client.start_instances(instance_id)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    ctx.logger.debug('Attempted to start instance {0}.'.format(instance_id))

    if _get_instance_state() == constants.INSTANCE_STATE_STARTED:
        if ctx.node.properties['use_password']:
            password_success = _retrieve_windows_pass(
                ec2_client=ec2_client,
                instance_id=instance_id,
                private_key_path=private_key_path)
            if not password_success:
                return ctx.operation.retry(
                    message='Waiting for server to post generated password',
                    retry_after=start_retry_interval)
        _instance_started_assign_runtime_properties_and_tag(instance_id)
    else:
        return ctx.operation.retry(
            message='Waiting server to be running. Retrying...',
            retry_after=start_retry_interval)
예제 #21
0
    def test_create_existing(self):
        """This tests that create creates the runtime_properties"""

        test_properties = self.get_mock_properties()
        ctx = self.security_group_mock('test_create_duplicate',
                                       test_properties)
        current_ctx.set(ctx=ctx)
        name = ctx.node.properties.get('resource_id')
        description = ctx.node.properties.get('description')
        ec2_client = connection.EC2ConnectionClient().client()
        group = ec2_client.create_security_group(name, description)
        ctx.node.properties['use_external_resource'] = True
        securitygroup.create(ctx=ctx)
        self.assertEqual(ctx.instance.runtime_properties['aws_resource_id'],
                         group.id)
예제 #22
0
    def test_create_use_external(self):
        """ This tests that the create keypair function
            adds the key_pair_name to runtime properties.
        """

        ctx = self.mock_ctx('test_create_use_external')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair('test_create_use_external')
        ctx.node.properties['use_external_resource'] = True
        ctx.node.properties['resource_id'] = kp.name
        ex = self.assertRaises(NonRecoverableError, keypair.create, ctx=ctx)
        self.assertIn('External resource, but the key file does not exist',
                      ex.message)
예제 #23
0
    def test_get_all_groups(self):
        """ This tests that all created groups are returned
        by _get_all_security_groups
        """

        test_properties = self.get_mock_properties()
        ctx = self.security_group_mock('test_get_all_groups', test_properties)
        current_ctx.set(ctx=ctx)
        ec2_client = connection.EC2ConnectionClient().client()
        group = ec2_client.create_security_group('test_get_all_groups',
                                                 'this is test')
        ctx.instance.runtime_properties['aws_resource_id'] = group.id
        output = securitygroup._get_all_security_groups(
            list_of_group_ids=group.id)
        self.assertEqual(output[0].id, group.id)
예제 #24
0
    def test_delete_use_external(self):
        """ This tests that delete function removes the
        runtime_properties for external resource.
        """

        ctx = self.mock_ctx('test_delete_use_external')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair('test_delete_use_external')
        ctx.node.properties['use_external_resource'] = True
        ctx.node.properties['resource_id'] = kp.name
        ctx.instance.runtime_properties['aws_resource_id'] = kp.name
        keypair.delete(ctx=ctx)
        self.assertNotIn('aws_resource_id', ctx.instance.runtime_properties)
예제 #25
0
    def test_validation_in_account(self):
        """ Tests that an error is raised if you don't use
        external, but the key does exist in your account.
        """

        ctx = self.mock_ctx('test_validation_in_account')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        kp = ec2_client.create_key_pair('test_validation_in_account')
        ctx.node.properties['use_external_resource'] = False
        ctx.node.properties['resource_id'] = kp.name
        ex = self.assertRaises(NonRecoverableError,
                               keypair.creation_validation,
                               ctx=ctx)
        self.assertIn('but the key pair exists in the account.', ex.message)
    def test_run_instances_external_resource(self):
        """ this tests that the instance create function adds
        the runtime_properties
        """
        ctx = self.mock_ctx('test_run_instances_external_resource')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        reservation = ec2_client.run_instances(
            TEST_AMI_IMAGE_ID, instance_type=TEST_INSTANCE_TYPE)
        instance_id = reservation.instances[0].id
        ctx.node.properties['use_external_resource'] = True
        ctx.node.properties['resource_id'] = instance_id
        instance.run_instances(ctx=ctx)
        self.assertIn('aws_resource_id',
                      ctx.instance.runtime_properties.keys())
    def test_get_private_dns_name(self):
        """ This checks that _get_instance_attribute
        sets the correct runtime property and it is an FQDN
        """

        ctx = self.mock_ctx('test_get_private_dns_name')
        current_ctx.set(ctx=ctx)

        ec2_client = connection.EC2ConnectionClient().client()
        reservation = ec2_client.run_instances(
            TEST_AMI_IMAGE_ID, instance_type=TEST_INSTANCE_TYPE)
        ctx.instance.runtime_properties['aws_resource_id'] = \
            reservation.instances[0].id
        property_name = 'private_dns_name'
        dns_name = instance._get_instance_attribute(property_name)
        self.assertRegexpMatches(dns_name, FQDN)
    def test_create_duplicate(self):
        """This tests that when you give a name of an existing
        resource, a NonRecoverableError is raised.
        """

        test_properties = self.get_mock_properties()
        ctx = self.security_group_mock(
            'test_create_duplicate', test_properties)
        current_ctx.set(ctx=ctx)
        name = ctx.node.properties.get('resource_id')
        description = ctx.node.properties.get('description')
        ec2_client = connection.EC2ConnectionClient().client()
        ec2_client.create_security_group(name, description)
        ex = self.assertRaises(
            NonRecoverableError, securitygroup.create, ctx=ctx)
        self.assertIn('InvalidGroup.Duplicate', ex.message)
예제 #29
0
def _get_key_pair_by_id(key_pair_id):
    """Returns the key pair object for a given key pair id.

    :param key_pair_id: The ID of a keypair.
    :returns The boto keypair object.
    :raises NonRecoverableError: If EC2 finds no matching key pairs.
    """

    ec2_client = connection.EC2ConnectionClient().client()

    try:
        key_pairs = ec2_client.get_all_key_pairs(keynames=key_pair_id)
    except (boto.exception.EC2ResponseError,
            boto.exception.BotoServerError) as e:
        raise NonRecoverableError('{0}'.format(str(e)))

    return key_pairs[0] if key_pairs else None
    def test_delete_deleted(self):
        """This tests that security group delete raises an
        error when the group is already deleted.
        """

        test_properties = self.get_mock_properties()
        ctx = self.security_group_mock(
            'test_delete_deleted', test_properties)
        current_ctx.set(ctx=ctx)
        ec2_client = connection.EC2ConnectionClient().client()
        group = ec2_client.create_security_group('test_delete_deleted',
                                                 'this is test')
        ctx.instance.runtime_properties['aws_resource_id'] = group.id
        ec2_client.delete_security_group(group_id=group.id)
        ex = self.assertRaises(
            NonRecoverableError, securitygroup.delete, ctx=ctx)
        self.assertIn('does not exist in the account', ex.message)