def disassociate_elasticip(**_): """ Disassocates an Elastic IP created by Cloudify from an EC2 Instance that was also created by Cloudify. """ ec2_client = connection.EC2ConnectionClient().client() elasticip = \ utils.get_external_resource_id_or_raise( 'disassociate elasticip', ctx.target.instance) elasticip_object = _get_address_object_by_id(elasticip) if not elasticip_object: raise NonRecoverableError( 'no matching elastic ip in account: {0}'.format(elasticip)) disassociate_args = dict( public_ip=elasticip_object.public_ip, association_id=elasticip_object.association_id ) ctx.logger.debug('Disassociating Elastic IP {0}'.format(elasticip)) try: ec2_client.disassociate_address(**disassociate_args) 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) utils.unassign_runtime_property_from_resource( 'instance_id', ctx.target.instance)
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...')
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 post_delete(self): ec2_utils.unassign_runtime_property_from_resource(constants.EXTERNAL_RESOURCE_ID, ctx.instance) ctx.logger.info("Removed {0} {1} from Cloudify.".format(self.aws_resource_type, self.resource_id)) return True
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 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...')
def release(**_): """This releases an Elastic IP created by Cloudify in the connected account. """ elasticip = utils.get_external_resource_id_or_raise("release elasticip", ctx.instance) if _release_external_elasticip(): return address_object = _get_address_object_by_id(elasticip) if not address_object: raise NonRecoverableError("Unable to release elasticip. Elasticip not in account.") ctx.logger.debug("Attempting to release an Elastic IP.") try: deleted = address_object.delete() except (boto.exception.EC2ResponseError, boto.exception.BotoServerError) as e: raise NonRecoverableError("{0}".format(str(e))) if not deleted: raise NonRecoverableError( "Elastic IP {0} deletion failed for an unknown reason.".format(address_object.public_ip) ) address = _get_address_object_by_id(address_object.public_ip) if not address: for runtime_property in [constants.ALLOCATION_ID, constants.EXTERNAL_RESOURCE_ID]: utils.unassign_runtime_property_from_resource(runtime_property, ctx.instance) else: return ctx.operation.retry(message="Elastic IP not released. Retrying...")
def delete(**_): """ Deletes an EBS Volume. """ volume_id = utils.get_external_resource_id_or_raise( 'delete EBS volume', ctx.instance) if _delete_external_volume(): return ctx.logger.debug('Deleting EBS volume: {0}'.format(volume_id)) if not _delete_volume(volume_id): return ctx.operation.retry( message='Failed to delete volume {0}.' .format(volume_id)) utils.unassign_runtime_property_from_resource( constants.ZONE, ctx.instance) utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) ctx.logger.info( 'Deleted EBS volume: {0}.' .format(volume_id))
def delete_elb(**_): if ctx.node.properties['use_external_resource']: utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) return ctx.logger.info('Attempting to delete Load Balancer.') elb_name = ctx.node.properties['elb_name'] lb = _get_existing_elb(elb_name) try: lb.delete() except (boto.exception.EC2ResponseError, boto.exception.BotoServerError, boto.exception.BotoClientError) as e: raise NonRecoverableError('Load Balancer {0} not deleted.' .format(str(e))) ctx.logger.info( 'Load Balancer {0} deleted. ' .format(elb_name)) if 'elb_name' in ctx.instance.runtime_properties: ctx.instance.runtime_properties.pop('elb_name')
def _terminate_external_instance(instance_id): if not utils.use_external_resource(ctx.node.properties): return False ctx.logger.info("External resource. Not terminating instance {0}.".format(instance_id)) utils.unassign_runtime_property_from_resource(constants.EXTERNAL_RESOURCE_ID, ctx.instance) return True
def post_delete(self): ec2_utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) ctx.logger.info('Removed {0} {1} from Cloudify.'.format( self.aws_resource_type, self.resource_id)) return True
def _terminate_external_instance(instance_id): if not utils.use_external_resource(ctx.node.properties): return False ctx.logger.info( 'External resource. Not terminating instance {0}.'.format(instance_id)) utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) return True
def _release_external_elasticip(): """Pretends to release an Elastic IP but if it was not created by Cloudify, it just deletes runtime_properties and exits the operation. :return False: Cloudify resource. Continue operation. :return True: External resource. Unset runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.node.properties): return False utils.unassign_runtime_property_from_resource(constants.EXTERNAL_RESOURCE_ID, ctx.instance) return True
def _release_external_elasticip(): """Pretends to release an Elastic IP but if it was not created by Cloudify, it just deletes runtime_properties and exits the operation. :return False: Cloudify resource. Continue operation. :return True: External resource. Unset runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.node.properties): return False utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) return True
def _delete_external_volume(): """If use_external_resource is True, this will delete the runtime_properties, and then exit. :return False: Cloudify resource. Continue operation. :return True: External resource. Unset runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.node.properties): return False ctx.logger.info('External resource. Not deleting EBS volume from account.') utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) return True
def test_utils_unassign_runtime_property_from_resource(self): ctx = self.mock_ctx( 'test_utils_unassign_runtime_property_from_resource') current_ctx.set(ctx=ctx) ctx.instance.runtime_properties[constants.EXTERNAL_RESOURCE_ID] = \ 'test_utils_unassign_runtime_property_from_resource' utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) self.assertNotIn( constants.EXTERNAL_RESOURCE_ID, ctx.instance.runtime_properties)
def _delete_external_keypair(): """If use_external_resource is True, this will delete the runtime_properties, and then exit. :param ctx: The Cloudify context. :return False: Cloudify resource. Continue operation. :return True: External resource. Unset runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.node.properties): return False ctx.logger.info('External resource. Not deleting keypair.') utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) return True
def _disassociate_external_elasticip_or_instance(): """Pretends to disassociate an Elastic IP with an EC2 instance but if one was not created by Cloudify, it just deletes runtime_properties and exits the operation. :return False: At least one is a Cloudify resource. Continue operation. :return True: Both are External resources. Set runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.source.node.properties) or not utils.use_external_resource( ctx.target.node.properties ): return False ctx.logger.info("Either instance or elasticip is an external resource so not " "performing disassociate operation.") utils.unassign_runtime_property_from_resource("public_ip_address", ctx.source.instance) return True
def delete(**_): """ Deletes an EC2 security group. """ group_id = utils.get_external_resource_id_or_raise('delete security group', ctx.instance) if _delete_external_securitygroup(): return ctx.logger.debug('Deleting Security Group: {0}'.format(group_id)) _delete_security_group(group_id) utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) ctx.logger.info( 'Attempted to delete Security Group: {0}.'.format(group_id))
def release(**_): """This releases an Elastic IP created by Cloudify in the connected account. """ elasticip = \ utils.get_external_resource_id_or_raise( 'release elasticip', ctx.instance) if _release_external_elasticip(): return address_object = _get_address_object_by_id(elasticip) if not address_object: raise NonRecoverableError( 'Unable to release elasticip. Elasticip not in account.') ctx.logger.debug('Attempting to release an Elastic IP.') try: deleted = address_object.delete() except (boto.exception.EC2ResponseError, boto.exception.BotoServerError) as e: raise NonRecoverableError('{0}'.format(str(e))) if not deleted: raise NonRecoverableError( 'Elastic IP {0} deletion failed for an unknown reason.'.format( address_object.public_ip)) address = _get_address_object_by_id(address_object.public_ip) if not address: for runtime_property in \ [constants.ALLOCATION_ID, constants.EXTERNAL_RESOURCE_ID]: utils.unassign_runtime_property_from_resource( runtime_property, ctx.instance) else: return ctx.operation.retry( message='Elastic IP not released. Retrying...')
def delete(**_): """ Deletes an EBS Volume. """ volume_id = utils.get_external_resource_id_or_raise( 'delete EBS volume', ctx.instance) if _delete_external_volume(): return ctx.logger.debug('Deleting EBS volume: {0}'.format(volume_id)) if not _delete_volume(volume_id): return ctx.operation.retry( message='Failed to delete volume {0}.'.format(volume_id)) utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) ctx.logger.info('Deleted EBS volume: {0}.'.format(volume_id))
def delete(**_): """ Deletes an EC2 security group. """ group_id = utils.get_external_resource_id_or_raise( 'delete security group', ctx.instance) if _delete_external_securitygroup(): return ctx.logger.debug('Deleting Security Group: {0}'.format(group_id)) _delete_security_group(group_id) utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) ctx.logger.info( 'Attempted to delete Security Group: {0}.' .format(group_id))
def _detach_external_volume_or_instance(): """Pretends to detach an external EBC volume with an EC2 instance but if one was not created by Cloudify, it just sets runtime_properties and exits the operation. :return False: At least one is a Cloudify resource. Continue operation. :return True: Both are External resources. Set runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.source.node.properties) \ or not utils.use_external_resource( ctx.target.node.properties): return False utils.unassign_runtime_property_from_resource( 'instance_id', ctx.source.instance) ctx.logger.info( 'Either instance or EBS volume is an external resource so not ' 'performing detach operation.') return True
def _disassociate_external_elasticip_or_instance(): """Pretends to disassociate an Elastic IP with an EC2 instance but if one was not created by Cloudify, it just deletes runtime_properties and exits the operation. :return False: At least one is a Cloudify resource. Continue operation. :return True: Both are External resources. Set runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.source.node.properties) \ or not utils.use_external_resource( ctx.target.node.properties): return False ctx.logger.info( 'Either instance or elasticip is an external resource so not ' 'performing disassociate operation.') utils.unassign_runtime_property_from_resource('public_ip_address', ctx.source.instance) return True
def _detach_external_volume_or_instance(): """Pretends to detach an external EBC volume with an EC2 instance but if one was not created by Cloudify, it just sets runtime_properties and exits the operation. :return False: At least one is a Cloudify resource. Continue operation. :return True: Both are External resources. Set runtime_properties. Ignore operation. """ if not utils.use_external_resource(ctx.source.node.properties) \ or not utils.use_external_resource( ctx.target.node.properties): return False utils.unassign_runtime_property_from_resource('instance_id', ctx.source.instance) ctx.logger.info( 'Either instance or EBS volume is an external resource so not ' 'performing detach operation.') return True
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 elasticip_object = _get_address_object_by_id(elasticip) if not elasticip_object: raise NonRecoverableError("no matching elastic ip in account: {0}".format(elasticip)) disassociate_args = dict(public_ip=elasticip_object.public_ip, association_id=elasticip_object.association_id) ctx.logger.debug("Disassociating Elastic IP {0}".format(elasticip)) try: ec2_client.disassociate_address(**disassociate_args) 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) utils.unassign_runtime_property_from_resource("instance_id", ctx.target.instance) if ctx.source.instance.runtime_properties.get("vpc_id"): utils.unassign_runtime_property_from_resource("vpc_id", ctx.target.instance) ctx.logger.info("Disassociated Elastic IP {0} from instance {1}.".format(elasticip, instance_id))
def detach(args, **_): """ Detaches an EBS Volume created by Cloudify from an EC2 Instance that was also created by Cloudify. """ volume_id = \ utils.get_external_resource_id_or_raise( 'detach volume', ctx.source.instance) instance_id = \ utils.get_external_resource_id_or_raise( 'detach volume', ctx.target.instance) if _detach_external_volume_or_instance(): return ctx.logger.debug('Detaching EBS volume {0}'.format(volume_id)) volume_object = _get_volumes_from_id(volume_id) if not volume_object: raise NonRecoverableError( 'EBS volume {0} not found in account.'.format(volume_id)) try: detached = volume_object.detach(**args) except (boto.exception.EC2ResponseError, boto.exception.BotoServerError) as e: raise NonRecoverableError('{0}'.format(str(e))) if not detached: raise NonRecoverableError( 'Failed to detach volume {0} from instance {1}' .format(volume_id, instance_id)) utils.unassign_runtime_property_from_resource( 'instance_id', ctx.source.instance) ctx.logger.info( 'Detached volume {0} from instance {1}.' .format(volume_id, instance_id))
def detach(args, **_): """ Detaches an EBS Volume created by Cloudify from an EC2 Instance that was also created by Cloudify. """ volume_id = \ utils.get_external_resource_id_or_raise( 'detach volume', ctx.source.instance) instance_id = \ utils.get_external_resource_id_or_raise( 'detach volume', ctx.target.instance) if _detach_external_volume_or_instance(): return ctx.logger.debug('Detaching EBS volume {0}'.format(volume_id)) volume_object = _get_volumes_from_id(volume_id) if not volume_object: raise NonRecoverableError( 'EBS volume {0} not found in account.'.format(volume_id)) try: detached = volume_object.detach(**args) except (boto.exception.EC2ResponseError, boto.exception.BotoServerError) as e: raise NonRecoverableError('{0}'.format(str(e))) if not detached: raise NonRecoverableError( 'Failed to detach volume {0} from instance {1}'.format( volume_id, instance_id)) utils.unassign_runtime_property_from_resource('instance_id', ctx.source.instance) ctx.logger.info('Detached volume {0} from instance {1}.'.format( volume_id, instance_id))
def delete(**kwargs): """Deletes a keypair.""" ec2_client = connection.EC2ConnectionClient().client() key_pair_name = utils.get_external_resource_id_or_raise( 'delete key pair', ctx.instance) if _delete_external_keypair(): return ctx.logger.debug('Attempting to delete key pair from account.') try: ec2_client.delete_key_pair(key_pair_name) except (boto.exception.EC2ResponseError, boto.exception.BotoServerError) as e: raise NonRecoverableError('{0}'.format(str(e))) utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) _delete_key_file() ctx.logger.info('Deleted key pair: {0}.'.format(key_pair_name))
def delete_elb(**_): if ctx.node.properties['use_external_resource']: utils.unassign_runtime_property_from_resource( constants.EXTERNAL_RESOURCE_ID, ctx.instance) return ctx.logger.info('Attempting to delete Load Balancer.') elb_name = ctx.node.properties['elb_name'] lb = _get_existing_elb(elb_name) try: lb.delete() except (boto.exception.EC2ResponseError, boto.exception.BotoServerError, boto.exception.BotoClientError) as e: raise NonRecoverableError('Load Balancer {0} not deleted.'.format( str(e))) ctx.logger.info('Load Balancer {0} deleted. '.format(elb_name)) if 'elb_name' in ctx.instance.runtime_properties: ctx.instance.runtime_properties.pop('elb_name')
def _unassign_runtime_properties(runtime_properties, ctx_instance): for property_name in runtime_properties: utils.unassign_runtime_property_from_resource(property_name, ctx_instance)
def post_disassociate(self): ec2_utils.unassign_runtime_property_from_resource( 'association_id', ctx.source.instance)