def sg_delete(name, force=False): """Deletes a security group. If you attempt to delete a security group that contains instances, or is referenced by another security group, the operation fails. Use the "force" flag to delete a security group that is referenced by another security group. :type name: string :param name: The name of the security group :type force: boolean :param force: Delete a security group even when it is referenced by another security group by deleting the referencing rules. """ connection = ec2_connect() target = sg_exists(name) if target: if force: instances = [x for x in ec2_list('sec:%s' % (target.name, ))] if instances: raise EC2LibraryError('%s is in use by %s.' % (target.name, ",".join(map(lambda x: x.name, instances)),)) _sg = connection.get_all_security_groups() for sg in filter(lambda x: x.name != target.name, _sg): _sg_revoke_all_rules(sg, target) connection.delete_security_group(target.name) # boto.ec2.connection.delete_security_group() raises boto.exception.EC2ResponseError # if the target security group is referenced by another security group return target else: raise EC2LibraryError('%s does not exist.' % (name, ))
def eip_release(public_ip=None, allocation_ip=None): """Free up an Elastic IP address. Pass a public IP address to release an EC2 Elastic IP address and an AllocationId to release a VPC Elastic IP address. You should only pass one value. This requires one of ``public_ip`` or ``allocation_id`` depending on if you're associating a VPC address or a plain EC2 address. When using an Allocation ID, make sure to pass ``None`` for ``public_ip`` as EC2 expects a single parameter and if ``public_ip`` is passed boto will preference that instead of ``allocation_id``. :type public_ip: string :param public_ip: The public IP address for EC2 elastic IPs. :type allocation_id: string :param allocation_id: The Allocation ID for VPC elastic IPs. :rtype: bool :return: True if successful """ connection = ec2_connect() _x = connection.release_address(public_ip, allocation_id) mico.output.info("released EIP: %s" % public_ip) return _x
def sg_delete(name, force=False): """Deletes a security group. If you attempt to delete a security group that contains instances, or is referenced by another security group, the operation fails. Use the "force" flag to delete a security group that is referenced by another security group. :type name: string :param name: The name of the security group :type force: boolean :param force: Delete a security group even when it is referenced by another security group by deleting the referencing rules. """ connection = ec2_connect() target = sg_exists(name) if target: if force: instances = [x for x in ec2_list('sec:%s' % (target.name, ))] if instances: raise EC2LibraryError('%s is in use by %s.' % ( target.name, ",".join(map(lambda x: x.name, instances)), )) _sg = connection.get_all_security_groups() for sg in filter(lambda x: x.name != target.name, _sg): _sg_revoke_all_rules(sg, target) connection.delete_security_group(target.name) # boto.ec2.connection.delete_security_group() raises boto.exception.EC2ResponseError # if the target security group is referenced by another security group return target else: raise EC2LibraryError('%s does not exist.' % (name, ))
def eip_release(public_ip=None, allocation_ip=None): """Free up an Elastic IP address. Pass a public IP address to release an EC2 Elastic IP address and an AllocationId to release a VPC Elastic IP address. You should only pass one value. This requires one of ``public_ip`` or ``allocation_id`` depending on if you're associating a VPC address or a plain EC2 address. When using an Allocation ID, make sure to pass ``None`` for ``public_ip`` as EC2 expects a single parameter and if ``public_ip`` is passed boto will preference that instead of ``allocation_id``. :type public_ip: string :param public_ip: The public IP address for EC2 elastic IPs. :type allocation_id: string :param allocation_id: The Allocation ID for VPC elastic IPs. :rtype: bool :return: True if successful """ connection = ec2_connect() _x = connection.release_address(public_ip, allocation_ip) mico.output.info("released EIP: %s" % public_ip) return _x
def ebs_exists(tags={}): """Returns if tagged volume already exists, if exists return the object, otherwise returns None. """ connection = ec2_connect() _x = connection.get_all_volumes( None, dict(map(lambda (x, y): ("tag:%s" % x, y), tags.items()))) return filter(lambda x: x.status == 'in-use', _x)
def ebs_exists(tags={}): """Returns if tagged volume already exists, if exists return the object, otherwise returns None. """ connection = ec2_connect() _x = connection.get_all_volumes(None, dict(map(lambda (x, y): ("tag:%s" % x, y), tags.items()))) return filter(lambda x: x.status == 'in-use', _x)
def eip_attach(address, instance): """Attach an address to an instance. :type address: string :param address: the address to be attached :type instace: instance object :param instance: the instance to be attached to. """ connection = ec2_connect() _x = connection.associate_address(instance.id, address) mico.output.info("attached EIP %s to %s" % (address, instance.id)) return _x
def eip_allocate(instance=None, force=False): """Allocate a new Elastic IP Address. :type instance: an instance object :param instance: if present check for eip tag in the instance, and try to allocate the same address. :type force: bool :param force: force the ip address resassociation. By default set to False. """ if instance is not None: if "public_ip" in instance.tags: ec2_connect().associate_address(instance, instace.tags["public_ip"]) mico.output.info("using existent EIP %s for %s" % ( instace.tags["public_ip"], instance) ) return instance.tags["public_ip"] else: address = ec2_connect().allocate_address().public_ip ec2_tag(instance, public_ip = address) ec2_connect().associate_address(instance.id, address) mico.output.info("created new EIP %s for %s" % ( address, instance.id )) return address else: return ec2_connect().allocate_address().public_ip
def eip_allocate(instance=None, force=False): """Allocate a new Elastic IP Address. :type instance: an instance object :param instance: if present check for eip tag in the instance, and try to allocate the same address. :type force: bool :param force: force the ip address resassociation. By default set to False. """ if instance is not None: if "public_ip" in instance.tags: ec2_connect().associate_address(instance, instance.tags["public_ip"]) mico.output.info("using existent EIP %s for %s" % (instance.tags["public_ip"], instance)) return instance.tags["public_ip"] else: address = ec2_connect().allocate_address().public_ip ec2_tag(instance, public_ip=address) ec2_connect().associate_address(instance.id, address) mico.output.info("created new EIP %s for %s" % (address, instance.id)) return address else: return ec2_connect().allocate_address().public_ip
def sg_exists(name): """Return the security group with name passed as argument for specified region or None if it does not exists. """ connection = ec2_connect() _sg = connection.get_all_security_groups() _sg = [g for g in _sg if g.name == name] if len(_sg) > 0: return _sg[0] else: return None
def as_list_instances(*args): """List autoscaling instances which are vinculated with specified autoscaling group passed as argument. For example:: as_list_instances('apaches-*') """ for ag in as_list(*args): for instance in ag.instances: res = ec2_connect().get_all_instances([instance.instance_id]) for insobj in [i for r in res for i in r.instances]: insobj.autoscaling_group = ag.name insobj.launch_config_name = instance.launch_config_name if "Name" in insobj.tags: insobj.name = insobj.tags["Name"] yield insobj
def eip_attach(address, instance): """Attach an address to an instance. :type address: string :param address: the address to be attached :type instace: instance object :param instance: the instance to be attached to. """ connection = ec2_connect() _x = connection.associate_address(instance.id, address) mico.output.info("attached EIP %s to %s" % ( address, instance.id )) return _x
def sg_ensure(name, description, vpc_id=None, rules=[], force=False): """Create a new EC2 security group according with parameters passed as arguments. :type name: string :param name: The name of the new security group :type description: string :param description: The description of the new security group :type vpc_id: string :param vpc_id: The ID of the VPC to create the security group in, if any. :type rules: list :param rules: a list of objects rules. """ connection = ec2_connect() _obj = sg_exists(name) if _obj: mico.output.info("use existent security group: %s" % name) if not force: return _obj elif not _obj: _obj = connection.create_security_group(name, description, vpc_id) mico.output.info("create security group: %s" % name) for rule in rules: for r in rule: try: _obj.authorize(**r) mico.output.info("add rule to security group %s: %s" % ( _obj.name, ",".join(map(lambda x: "%s=%s" % x, r.items())) )) except EC2ResponseError as e: if e.error_code == "InvalidPermission.Duplicate": mico.output.debug("skip add already exists rule to security group %s: %s" % ( _obj.name, ", ".join(map(lambda x: "%s=%s" % x, r.items())) )) except Exception as e: raise e return _obj
def sg_ensure(name, description, vpc_id=None, rules=[], force=False): """Create a new EC2 security group according with parameters passed as arguments. :type name: string :param name: The name of the new security group :type description: string :param description: The description of the new security group :type vpc_id: string :param vpc_id: The ID of the VPC to create the security group in, if any. :type rules: list :param rules: a list of objects rules. """ connection = ec2_connect() _obj = sg_exists(name) if _obj: mico.output.info("use existent security group: %s" % name) if not force: return _obj elif not _obj: _obj = connection.create_security_group(name, description, vpc_id) mico.output.info("create security group: %s" % name) for rule in rules: for r in rule: try: _obj.authorize(**r) mico.output.info("add rule to security group %s: %s" % (_obj.name, ",".join( map(lambda x: "%s=%s" % x, r.items())))) except EC2ResponseError as e: if e.error_code == "InvalidPermission.Duplicate": mico.output.debug( "skip add already exists rule to security group %s: %s" % (_obj.name, ", ".join( map(lambda x: "%s=%s" % x, r.items())))) except Exception as e: raise e return _obj
def ebs_detach(volumes, force=False): """Detach a number of volumes passed as arguments. :param volumes: a list of volumes ids or Volumes objects to be removed, or single string or object for detach unique volume. """ connection = ec2_connect() if not isinstance(volumes, list): volumes = [volumes] for x in volumes: if isinstance(x, str): connection.detach_volume(x, force) mico.output.info("Detached volume: %s" % x) else: connection.detach_volume(x.id, force) mico.output.info("Detached volume: %s" % x.id)
def ebs_delete(volumes): """Delete volumes passed as argument. :param volumes: a list of strings including volumes id, a list of Volumes object, or a string or a single Volume object for a unique volume to be deleted. """ connection = ec2_connect() if not isinstance(volumes, list): volumes = [volumes] for x in volumes: if isinstance(x, str): connection.delete_volume(x) mico.output.info("Remove volume: %s" % x) else: connection.delete_volume(x.id) mico.output.info("Remove volume: %s" % x.id)
def ebs_list(*args): """List volumes filtering with tag name, provided in arguments. Glob expressions are allowed in filters as multiple filters too, for example:: ebs_list('host-*', '*database*') """ conn = ec2_connect() vol = conn.get_all_volumes() ins = dict(map(lambda x:(x.id,x), [i for r in conn.get_all_instances() for i in r.instances])) args = args or ('*',) for x in vol: x.name = x.id for arg in args: if x.tags.get("Name",False) and fnmatch(x.tags["Name"], arg): x.device = x.attach_data.device x.instance_id = ("%s (%s)" % (ins[x.attach_data.instance_id].tags.get("Name",None), x.attach_data.instance_id)) \ if x.attach_data.id is not None else None yield x
def elb_ensure(name, listeners, check, zones=None, *args, **kwargs): """Create a new ELB :type name: string :param name: the name of the elb, if exists, the same object will be returned, unless force parameter if set to True :type listeners: a list of listener object :param listeners: the listeners of the ELB :type zones: list of strings :param zones: the availability zones where ELB must be span. :type check: a elb_check :param check: the health check to be used. """ _obj = elb_exists(name) if _obj: mico.output.info("using existent ELB: %s" % name) return _obj connection = elb_connect() if zones is None: ec2_conn = ec2_connect() zones = ec2_conn.get_all_zones() elb = connection.create_load_balancer( name=name, zones=zones, listeners=listeners, *args, **kwargs ) elb.configure_health_check(check) elb = elb_exists(name) mico.output.info("created new ELB: %s" % name) return elb
def ebs_list(*args): """List volumes filtering with tag name, provided in arguments. Glob expressions are allowed in filters as multiple filters too, for example:: ebs_list('host-*', '*database*') """ conn = ec2_connect() vol = conn.get_all_volumes() ins = dict( map(lambda x: (x.id, x), [i for r in conn.get_all_instances() for i in r.instances])) args = args or ('*', ) for x in vol: x.name = x.id for arg in args: if x.tags.get("Name", False) and fnmatch(x.tags["Name"], arg): x.device = x.attach_data.device x.instance_id = ("%s (%s)" % (ins[x.attach_data.instance_id].tags.get("Name",None), x.attach_data.instance_id)) \ if x.attach_data.id is not None else None yield x
def ebs_ensure(size, zone=None, instance=None, device=None, tags={}, force=False, **kwargs): """Create a new EBS volume :type size: int :param size: The size of the new volume, in GiB :type zone: string or :class:`boto.ec2.zone.Zone` :param zone: The availability zone in which the Volume will be created. :type snapshot: string or :class:`boto.ec2.snapshot.Snapshot` :param snapshot: The snapshot from which the new Volume will be created. :type volume_type: string :param volume_type: The type of the volume. (optional). Valid values are: standard | io1. :type iops: int :param iops: The provisioned IOPs you want to associate with this volume. (optional) :type tags: dict :param tags: a dictionary of tags for this volume. :type force: bool :param force: if set to True force the creation of the volumen tough already exists other volume with the same tags. """ if zone is None and instance is None: raise EC2LibraryError("volume require zone or instance to be created.") if zone is None: zone = instance.placement if not force and tags: _obj = ebs_exists(tags) elif not force: _tags = {} if instance is not None: if "Name" in instance.tags: _tags["Name"] = instance.tags["Name"] if device is not None: _tags["Device"] = device if _tags: _obj = ebs_exists(_tags) else: _obj = None else: _obj = None if _obj: mico.output.info("use existent volume: %s" % _obj[0].id) return _obj[0] connection = ec2_connect() _obj = connection.create_volume(size, zone, **kwargs) mico.output.info("create volume: %s (size=%s, zone=%s)" % (_obj.id, size, zone)) while _obj.status != "available": time.sleep(1) _obj.update() if tags: connection.create_tags([_obj.id], tags) if device and instance: connection.attach_volume(_obj.id, instance.id, device) ec2_tag_volumes(instance) mico.output.info("attach volume %s as device %s at instance %s" % (_obj.id, device, instance.id))
def eip_exists(public_ip): """Return the allocate Elastic IP object which match with public_ip passed as argument. """ return ec2_connect().get_all_addresses([public_ip])
def ebs_ensure(size, zone=None, instance=None, device=None, tags={}, force=False, **kwargs): """Create a new EBS volume :type size: int :param size: The size of the new volume, in GiB :type zone: string or :class:`boto.ec2.zone.Zone` :param zone: The availability zone in which the Volume will be created. :type snapshot: string or :class:`boto.ec2.snapshot.Snapshot` :param snapshot: The snapshot from which the new Volume will be created. :type volume_type: string :param volume_type: The type of the volume. (optional). Valid values are: standard | io1. :type iops: int :param iops: The provisioned IOPs you want to associate with this volume. (optional) :type tags: dict :param tags: a dictionary of tags for this volume. :type force: bool :param force: if set to True force the creation of the volumen tough already exists other volume with the same tags. """ if zone is None and instance is None: raise EC2LibraryError("volume require zone or instance to be created.") if zone is None: zone = instance.placement if not force and tags: _obj = ebs_exists(tags) elif not force: _tags = {} if instance is not None: if "Name" in instance.tags: _tags["Name"] = instance.tags["Name"] if device is not None: _tags["Device"] = device if _tags: _obj = ebs_exists(_tags) else: _obj = None else: _obj = None if _obj: mico.output.info("use existent volume: %s" % _obj[0].id) return _obj[0] connection = ec2_connect() _obj = connection.create_volume(size, zone, **kwargs) mico.output.info("create volume: %s (size=%s, zone=%s)" % ( _obj.id, size, zone )) while _obj.status != "available": time.sleep(1) _obj.update() if tags: connection.create_tags([_obj.id], tags) if device and instance: connection.attach_volume(_obj.id, instance.id, device) ec2_tag_volumes(instance) mico.output.info("attach volume %s as device %s at instance %s" % ( _obj.id, device, instance.id ))