예제 #1
0
파일: test_elb.py 프로젝트: Affirm/moto
def test_connection_draining_attribute():
    conn = boto.connect_elb()
    ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
    lb = conn.create_load_balancer('my-lb', [], ports)

    connection_draining = ConnectionDrainingAttribute()
    connection_draining.enabled = True
    connection_draining.timeout = 60

    conn.modify_lb_attribute(
        "my-lb", "ConnectionDraining", connection_draining)
    attributes = lb.get_attributes(force=True)
    attributes.connection_draining.enabled.should.be.true
    attributes.connection_draining.timeout.should.equal(60)

    connection_draining.timeout = 30
    conn.modify_lb_attribute(
        "my-lb", "ConnectionDraining", connection_draining)
    attributes = lb.get_attributes(force=True)
    attributes.connection_draining.timeout.should.equal(30)

    connection_draining.enabled = False
    conn.modify_lb_attribute(
        "my-lb", "ConnectionDraining", connection_draining)
    attributes = lb.get_attributes(force=True)
    attributes.connection_draining.enabled.should.be.false
예제 #2
0
파일: models.py 프로젝트: Affirm/moto
    def get_default_attributes(cls):
        attributes = LbAttributes()

        cross_zone_load_balancing = CrossZoneLoadBalancingAttribute()
        cross_zone_load_balancing.enabled = False
        attributes.cross_zone_load_balancing = cross_zone_load_balancing

        connection_draining = ConnectionDrainingAttribute()
        connection_draining.enabled = False
        attributes.connection_draining = connection_draining

        access_log = AccessLogAttribute()
        access_log.enabled = False
        attributes.access_log = access_log

        connection_settings = ConnectionSettingAttribute()
        connection_settings.idle_timeout = 60
        attributes.connecting_settings = connection_settings

        return attributes
예제 #3
0
    def modify_load_balancer_attributes(self):
        load_balancer_name = self._get_param('LoadBalancerName')
        load_balancer = self.elb_backend.get_load_balancer(load_balancer_name)

        cross_zone = self._get_dict_param(
            "LoadBalancerAttributes.CrossZoneLoadBalancing.")
        if cross_zone:
            attribute = CrossZoneLoadBalancingAttribute()
            attribute.enabled = cross_zone["enabled"] == "true"
            self.elb_backend.set_cross_zone_load_balancing_attribute(
                load_balancer_name, attribute)

        access_log = self._get_dict_param("LoadBalancerAttributes.AccessLog.")
        if access_log:
            attribute = AccessLogAttribute()
            attribute.enabled = access_log["enabled"] == "true"
            attribute.s3_bucket_name = access_log['s3_bucket_name']
            attribute.s3_bucket_prefix = access_log['s3_bucket_prefix']
            attribute.emit_interval = access_log["emit_interval"]
            self.elb_backend.set_access_log_attribute(load_balancer_name,
                                                      attribute)

        connection_draining = self._get_dict_param(
            "LoadBalancerAttributes.ConnectionDraining.")
        if connection_draining:
            attribute = ConnectionDrainingAttribute()
            attribute.enabled = connection_draining["enabled"] == "true"
            attribute.timeout = connection_draining["timeout"]
            self.elb_backend.set_connection_draining_attribute(
                load_balancer_name, attribute)

        connection_settings = self._get_dict_param(
            "LoadBalancerAttributes.ConnectionSettings.")
        if connection_settings:
            attribute = ConnectionSettingAttribute()
            attribute.idle_timeout = connection_settings["idle_timeout"]
            self.elb_backend.set_connection_settings_attribute(
                load_balancer_name, attribute)

        template = self.response_template(MODIFY_ATTRIBUTES_TEMPLATE)
        return template.render(attributes=load_balancer.attributes)
예제 #4
0
def test_connection_draining_attribute():
    conn = boto.connect_elb()
    ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
    lb = conn.create_load_balancer('my-lb', [], ports)

    connection_draining = ConnectionDrainingAttribute()
    connection_draining.enabled = True
    connection_draining.timeout = 60

    conn.modify_lb_attribute("my-lb", "ConnectionDraining", connection_draining)
    attributes = lb.get_attributes(force=True)
    attributes.connection_draining.enabled.should.be.true
    attributes.connection_draining.timeout.should.equal(60)

    connection_draining.timeout = 30
    conn.modify_lb_attribute("my-lb", "ConnectionDraining", connection_draining)
    attributes = lb.get_attributes(force=True)
    attributes.connection_draining.timeout.should.equal(30)

    connection_draining.enabled = False
    conn.modify_lb_attribute("my-lb", "ConnectionDraining", connection_draining)
    attributes = lb.get_attributes(force=True)
    attributes.connection_draining.enabled.should.be.false
예제 #5
0
def set_attributes(name,
                   attributes,
                   region=None,
                   key=None,
                   keyid=None,
                   profile=None):
    """
    Set attributes on an ELB.

    name (string)
        Name of the ELB instance to set attributes for

    attributes
        A dict of attributes to set.

        Valid attributes are:

        access_log (dict)
            enabled (bool)
                Enable storage of access logs.
            s3_bucket_name (string)
                The name of the S3 bucket to place logs.
            s3_bucket_prefix (string)
                Prefix for the log file name.
            emit_interval (int)
                Interval for storing logs in S3 in minutes. Valid values are
                5 and 60.

        connection_draining (dict)
            enabled (bool)
                Enable connection draining.
            timeout (int)
                Maximum allowed time in seconds for sending existing
                connections to an instance that is deregistering or unhealthy.
                Default is 300.

        cross_zone_load_balancing (dict)
            enabled (bool)
                Enable cross-zone load balancing.

    CLI example to set attributes on an ELB:

    .. code-block:: bash

        salt myminion boto_elb.set_attributes myelb '{"access_log": {"enabled": "true", "s3_bucket_name": "mybucket", "s3_bucket_prefix": "mylogs/", "emit_interval": "5"}}' region=us-east-1
    """
    conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)

    al = attributes.get("access_log", {})
    czlb = attributes.get("cross_zone_load_balancing", {})
    cd = attributes.get("connection_draining", {})
    cs = attributes.get("connecting_settings", {})
    if not al and not czlb and not cd and not cs:
        log.error("No supported attributes for ELB.")
        return False
    if al:
        _al = AccessLogAttribute()
        _al.enabled = al.get("enabled", False)
        if not _al.enabled:
            msg = "Access log attribute configured, but enabled config missing"
            log.error(msg)
            return False
        _al.s3_bucket_name = al.get("s3_bucket_name", None)
        _al.s3_bucket_prefix = al.get("s3_bucket_prefix", None)
        _al.emit_interval = al.get("emit_interval", None)
        added_attr = conn.modify_lb_attribute(name, "accessLog", _al)
        if added_attr:
            log.info("Added access_log attribute to %s elb.", name)
        else:
            log.error("Failed to add access_log attribute to %s elb.", name)
            return False
    if czlb:
        _czlb = CrossZoneLoadBalancingAttribute()
        _czlb.enabled = czlb["enabled"]
        added_attr = conn.modify_lb_attribute(name, "crossZoneLoadBalancing",
                                              _czlb.enabled)
        if added_attr:
            log.info("Added cross_zone_load_balancing attribute to %s elb.",
                     name)
        else:
            log.error("Failed to add cross_zone_load_balancing attribute.")
            return False
    if cd:
        _cd = ConnectionDrainingAttribute()
        _cd.enabled = cd["enabled"]
        _cd.timeout = cd.get("timeout", 300)
        added_attr = conn.modify_lb_attribute(name, "connectionDraining", _cd)
        if added_attr:
            log.info("Added connection_draining attribute to %s elb.", name)
        else:
            log.error("Failed to add connection_draining attribute.")
            return False
    if cs:
        _cs = ConnectionSettingAttribute()
        _cs.idle_timeout = cs.get("idle_timeout", 60)
        added_attr = conn.modify_lb_attribute(name, "connectingSettings", _cs)
        if added_attr:
            log.info("Added connecting_settings attribute to %s elb.", name)
        else:
            log.error("Failed to add connecting_settings attribute.")
            return False
    return True
예제 #6
0
def set_attributes(name,
                   attributes,
                   region=None,
                   key=None,
                   keyid=None,
                   profile=None):
    '''
    Set attributes on an ELB.

    CLI example to set attributes on an ELB:

    .. code-block:: bash

        salt myminion boto_elb.set_attributes myelb '{"access_log": {"enabled": "true", "s3_bucket_name": "mybucket", "s3_bucket_prefix": "mylogs/", "emit_interval": "5"}}' region=us-east-1
    '''
    conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)

    al = attributes.get('access_log', {})
    czlb = attributes.get('cross_zone_load_balancing', {})
    cd = attributes.get('connection_draining', {})
    cs = attributes.get('connecting_settings', {})
    if not al and not czlb and not cd and not cs:
        log.error('No supported attributes for ELB.')
        return False
    if al:
        _al = AccessLogAttribute()
        _al.enabled = al.get('enabled', False)
        if not _al.enabled:
            msg = 'Access log attribute configured, but enabled config missing'
            log.error(msg)
            return False
        _al.s3_bucket_name = al.get('s3_bucket_name', None)
        _al.s3_bucket_prefix = al.get('s3_bucket_prefix', None)
        _al.emit_interval = al.get('emit_interval', None)
        added_attr = conn.modify_lb_attribute(name, 'accessLog', _al)
        if added_attr:
            log.info('Added access_log attribute to {0} elb.'.format(name))
        else:
            msg = 'Failed to add access_log attribute to {0} elb.'
            log.error(msg.format(name))
            return False
    if czlb:
        _czlb = CrossZoneLoadBalancingAttribute()
        _czlb.enabled = czlb['enabled']
        added_attr = conn.modify_lb_attribute(name, 'crossZoneLoadBalancing',
                                              _czlb.enabled)
        if added_attr:
            msg = 'Added cross_zone_load_balancing attribute to {0} elb.'
            log.info(msg.format(name))
        else:
            log.error('Failed to add cross_zone_load_balancing attribute.')
            return False
    if cd:
        _cd = ConnectionDrainingAttribute()
        _cd.enabled = cd['enabled']
        _cd.timeout = cd.get('timeout', 300)
        added_attr = conn.modify_lb_attribute(name, 'connectionDraining', _cd)
        if added_attr:
            msg = 'Added connection_draining attribute to {0} elb.'
            log.info(msg.format(name))
        else:
            log.error('Failed to add connection_draining attribute.')
            return False
    if cs:
        _cs = ConnectionSettingAttribute()
        _cs.idle_timeout = cs.get('idle_timeout', 60)
        added_attr = conn.modify_lb_attribute(name, 'connectingSettings', _cs)
        if added_attr:
            msg = 'Added connecting_settings attribute to {0} elb.'
            log.info(msg.format(name))
        else:
            log.error('Failed to add connecting_settings attribute.')
            return False
    return True
예제 #7
0
파일: boto_elb.py 프로젝트: iquaba/salt
def set_attributes(name, attributes, region=None, key=None, keyid=None,
                   profile=None):
    '''
    Set attributes on an ELB.

    CLI example to set attributes on an ELB:

    .. code-block:: bash

        salt myminion boto_elb.set_attributes myelb '{"access_log": {"enabled": "true", "s3_bucket_name": "mybucket", "s3_bucket_prefix": "mylogs/", "emit_interval": "5"}}' region=us-east-1
    '''
    conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)

    al = attributes.get('access_log', {})
    czlb = attributes.get('cross_zone_load_balancing', {})
    cd = attributes.get('connection_draining', {})
    cs = attributes.get('connecting_settings', {})
    if not al and not czlb and not cd and not cs:
        log.error('No supported attributes for ELB.')
        return False
    if al:
        _al = AccessLogAttribute()
        _al.enabled = al.get('enabled', False)
        if not _al.enabled:
            msg = 'Access log attribute configured, but enabled config missing'
            log.error(msg)
            return False
        _al.s3_bucket_name = al.get('s3_bucket_name', None)
        _al.s3_bucket_prefix = al.get('s3_bucket_prefix', None)
        _al.emit_interval = al.get('emit_interval', None)
        added_attr = conn.modify_lb_attribute(name, 'accessLog', _al)
        if added_attr:
            log.info('Added access_log attribute to {0} elb.'.format(name))
        else:
            msg = 'Failed to add access_log attribute to {0} elb.'
            log.error(msg.format(name))
            return False
    if czlb:
        _czlb = CrossZoneLoadBalancingAttribute()
        _czlb.enabled = czlb['enabled']
        added_attr = conn.modify_lb_attribute(name, 'crossZoneLoadBalancing',
                                              _czlb.enabled)
        if added_attr:
            msg = 'Added cross_zone_load_balancing attribute to {0} elb.'
            log.info(msg.format(name))
        else:
            log.error('Failed to add cross_zone_load_balancing attribute.')
            return False
    if cd:
        _cd = ConnectionDrainingAttribute()
        _cd.enabled = cd['enabled']
        _cd.timeout = cd.get('timeout', 300)
        added_attr = conn.modify_lb_attribute(name, 'connectionDraining', _cd)
        if added_attr:
            msg = 'Added connection_draining attribute to {0} elb.'
            log.info(msg.format(name))
        else:
            log.error('Failed to add connection_draining attribute.')
            return False
    if cs:
        _cs = ConnectionSettingAttribute()
        _cs.idle_timeout = cs.get('idle_timeout', 60)
        added_attr = conn.modify_lb_attribute(name, 'connectingSettings', _cs)
        if added_attr:
            msg = 'Added connecting_settings attribute to {0} elb.'
            log.info(msg.format(name))
        else:
            log.error('Failed to add connecting_settings attribute.')
            return False
    return True
예제 #8
0
파일: boto_elb.py 프로젝트: bryson/salt
def set_attributes(name, attributes, region=None, key=None, keyid=None, profile=None):
    """
    Set attributes on an ELB.

    name (string)
        Name of the ELB instance to set attributes for

    attributes
        A dict of attributes to set.

        Valid attributes are:

        access_log (dict)
            enabled (bool)
                Enable storage of access logs.
            s3_bucket_name (string)
                The name of the S3 bucket to place logs.
            s3_bucket_prefix (string)
                Prefix for the log file name.
            emit_interval (int)
                Interval for storing logs in S3 in minutes. Valid values are
                5 and 60.

        connection_draining (dict)
            enabled (bool)
                Enable connection draining.
            timeout (int)
                Maximum allowed time in seconds for sending existing
                connections to an instance that is deregistering or unhealthy.
                Default is 300.

        cross_zone_load_balancing (dict)
            enabled (bool)
                Enable cross-zone load balancing.

    CLI example to set attributes on an ELB:

    .. code-block:: bash

        salt myminion boto_elb.set_attributes myelb '{"access_log": {"enabled": "true", "s3_bucket_name": "mybucket", "s3_bucket_prefix": "mylogs/", "emit_interval": "5"}}' region=us-east-1
    """
    conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)

    al = attributes.get("access_log", {})
    czlb = attributes.get("cross_zone_load_balancing", {})
    cd = attributes.get("connection_draining", {})
    cs = attributes.get("connecting_settings", {})
    if not al and not czlb and not cd and not cs:
        log.error("No supported attributes for ELB.")
        return False
    if al:
        _al = AccessLogAttribute()
        _al.enabled = al.get("enabled", False)
        if not _al.enabled:
            msg = "Access log attribute configured, but enabled config missing"
            log.error(msg)
            return False
        _al.s3_bucket_name = al.get("s3_bucket_name", None)
        _al.s3_bucket_prefix = al.get("s3_bucket_prefix", None)
        _al.emit_interval = al.get("emit_interval", None)
        added_attr = conn.modify_lb_attribute(name, "accessLog", _al)
        if added_attr:
            log.info("Added access_log attribute to {0} elb.".format(name))
        else:
            msg = "Failed to add access_log attribute to {0} elb."
            log.error(msg.format(name))
            return False
    if czlb:
        _czlb = CrossZoneLoadBalancingAttribute()
        _czlb.enabled = czlb["enabled"]
        added_attr = conn.modify_lb_attribute(name, "crossZoneLoadBalancing", _czlb.enabled)
        if added_attr:
            msg = "Added cross_zone_load_balancing attribute to {0} elb."
            log.info(msg.format(name))
        else:
            log.error("Failed to add cross_zone_load_balancing attribute.")
            return False
    if cd:
        _cd = ConnectionDrainingAttribute()
        _cd.enabled = cd["enabled"]
        _cd.timeout = cd.get("timeout", 300)
        added_attr = conn.modify_lb_attribute(name, "connectionDraining", _cd)
        if added_attr:
            msg = "Added connection_draining attribute to {0} elb."
            log.info(msg.format(name))
        else:
            log.error("Failed to add connection_draining attribute.")
            return False
    if cs:
        _cs = ConnectionSettingAttribute()
        _cs.idle_timeout = cs.get("idle_timeout", 60)
        added_attr = conn.modify_lb_attribute(name, "connectingSettings", _cs)
        if added_attr:
            msg = "Added connecting_settings attribute to {0} elb."
            log.info(msg.format(name))
        else:
            log.error("Failed to add connecting_settings attribute.")
            return False
    return True
예제 #9
0
파일: api.py 프로젝트: gimlids/riker
def deploy_latest_app_ami(app_name, env_name):

    global aws
    aws = AWS.from_config(config)

    aws.connect()

    lb_group_ids=[aws.get_security_group_id('riker-load-balancer')]
    inst_group_ids=[aws.get_security_group_id('riker-instance')]

    app = App(env_name, app_name)

    health_check_target = app.config.get('health_check', 'TCP:80')

    name = re.sub('[^A-Za-z0-9\-]', '-', app.name)

    app_image = LatestAppImage(app).get()

    print '-----> Connecting to ELB'
    elb_conn = boto.connect_elb()

    log('info', 'Load balancer', show_header=True)
    load_balancer_name = name
    try:
        elb_result = elb_conn.get_all_load_balancers(load_balancer_names=[load_balancer_name])
        lb = elb_result[0]
        log('info', 'Found {}'.format(load_balancer_name))
    except boto.exception.BotoServerError:
        log('info', 'Not found, creating load balancer')
        listeners = [(80, 80, 'HTTP', 'HTTP')]
        lb = elb_conn.create_load_balancer(name=load_balancer_name,
                                           zones=None,
                                           complex_listeners=listeners,
                                           security_groups=lb_group_ids,
                                           subnets=[aws.subnet_id])
    hc = HealthCheck(target=health_check_target)
    lb.configure_health_check(hc)
    cda = ConnectionDrainingAttribute()
    cda.enabled = True
    cda.timeout = 300
    elb_conn.modify_lb_attribute(load_balancer_name=load_balancer_name,
                                  attribute='connectionDraining',
                                  value=cda)

    print '-----> Connecting to AutoScale'
    as_conn = boto.connect_autoscale()

    log('info', 'Launch configuration', show_header=True)
    launch_config_name = "{}-{}".format(name, app_image.tags['deploy-id'])
    lc_result = as_conn.get_all_launch_configurations(names=[launch_config_name])
    if len(lc_result) == 0:
        log('info', 'Not found, creating LaunchConfiguration')
        lc = LaunchConfiguration(name=launch_config_name,
                                 image_id=app_image.id,
                                 key_name=aws.key_pair_name,
                                 security_groups=inst_group_ids,
                                 instance_type=aws.instance_type)
        as_conn.create_launch_configuration(lc)
    else:
        log('info', 'Found {}'.format(launch_config_name))
        lc = lc_result[0]

    existing_group = None
    deploy_id = int(app_image.tags['deploy-id'] or 0)
    log('info', 'Getting previous auto-scaling group', show_header=True)
    for did in xrange(deploy_id-1, 0, -1):
        existing_group_name = "{}-{}".format(name, did)
        log('info', '{} ?'.format(existing_group_name))
        ag_result = as_conn.get_all_groups(names=[existing_group_name])
        if len(ag_result) > 0:
            existing_group = ag_result[0]
            log('info', 'Found {}'.format(existing_group.name))
            break
        else:
            log('info', 'No')

    if existing_group is not None:
        existing_healthy_instances = [inst for inst in existing_group.instances if inst.lifecycle_state == 'InService' and inst.health_status == 'Healthy']
        existing_healthy_instance_count = len(existing_healthy_instances)
        desired_capacity = existing_group.desired_capacity
        min_size = existing_group.min_size
        max_size = existing_group.max_size
        if existing_healthy_instance_count == 0 and desired_capacity == 0:
            print '-----> WARNING: existing auto-scaling group {} has no healthy instances and a desired capacity of 0. New auto-scaling group will launch 1 instance.'.format(existing_group)
            desired_capacity = 1
            min_size = 1
            max_size = max_size if max_size > 0 else 1
    else:
        existing_healthy_instance_count = 0
        desired_capacity = 1
        min_size = 1
        max_size = 1

    log('info', '{} existing instance(s) found'.format(existing_healthy_instance_count), show_header=True)

    log('info', 'Existing auto-scale properties: desired_capacity={}, min_size={}, max_size={}'.format(desired_capacity, min_size, max_size))

    log('info', 'Auto-scaling group', show_header=True)
    group_name = "{}-{}".format(name, app_image.tags['deploy-id'])
    ag_result = as_conn.get_all_groups(names=[group_name])
    if len(ag_result) == 0:
        log('info', 'Not found, creating autoscale group')
        ag = AutoScalingGroup(name=group_name,
                              load_balancers=[load_balancer_name], launch_config=lc,
                              desired_capacity=desired_capacity, min_size=min_size, max_size=max_size,
                              health_check_type='ELB', health_check_period='300',
                              vpc_zone_identifier=aws.subnet_id)
        as_conn.create_auto_scaling_group(ag)
    else:
        log('info', 'Found {}'.format(group_name))
        ag = ag_result[0]
        ag.desired_capacity = desired_capacity
        ag.max_size = max_size
        ag.min_size = min_size
        ag.launch_config_name = launch_config_name
        ag.update()

    log('info', 'Waiting for new instances to become healthy', show_header=True)
    all_healthy = False
    for i in xrange(60):
        if i > 0:
            print '       ---'
            time.sleep(10)
        elb_result = elb_conn.get_all_load_balancers(load_balancer_names=[load_balancer_name])
        lb = elb_result[0]
        lb_insts = lb.get_instance_health()
        print '       Load-balancer instances: {}'.format(lb_insts)
        # NOTE: re-get auto-scaling group to get updated instance info.
        ag = as_conn.get_all_groups(names=[group_name])[0]
        ag_insts = [inst for inst in ag.instances]
        log('info', 'Auto-scaling group Instances: {}'.format(ag_insts))
        if len(ag_insts) < desired_capacity:
            not_yet_launched_count = desired_capacity - len(ag_insts)
            log('info', '{} new instance(s) not yet launched'.format(not_yet_launched_count))
            continue
        ag_inst_ids = set(inst.instance_id for inst in ag_insts)
        lb_inst_ids = set(inst.instance_id for inst in lb_insts)
        asg_insts_not_in_lb = ag_inst_ids.difference(lb_inst_ids)
        if len(asg_insts_not_in_lb) > 0:
            log('info', '{} new instance(s) not yet in load balancer'.format(len(asg_insts_not_in_lb)))
            continue
        new_lb_insts = [inst for inst in lb_insts if inst.instance_id in ag_inst_ids]
        healthy_new_lb_insts = [inst for inst in new_lb_insts if inst.state == 'InService']
        all_healthy = len(healthy_new_lb_insts) == len(ag_insts)
        log('info', '{} new instance(s) are healthy'.format(len(healthy_new_lb_insts)))
        diff = existing_healthy_instance_count - len(healthy_new_lb_insts)
        if existing_group is not None and diff >= 0:
            change = False
            if existing_group.desired_capacity != diff:
                existing_group.desired_capacity = diff
                change = True
            if existing_group.max_size != diff:
                existing_group.max_size = diff
                change = True
            if diff < existing_group.min_size:
                existing_group.min_size = diff
                change = True
            if change:
                existing_group.update()
                log('info', 'Change previous auto-scale group {} properties: desired_capacity={}, min_size={}, max_size={}'.format(existing_group, existing_group.desired_capacity, existing_group.min_size, existing_group.max_size))
        if all_healthy:
            log('info', 'All new instances healthy!', show_header=True)
            healthy_lb_inst_ids = [inst.instance_id for inst in lb_insts if inst.state == 'InService']
            previous_healthy_inst_ids = [inst.instance_id for inst in existing_healthy_instances] if existing_group else []
            not_yet_out_of_service = set(previous_healthy_inst_ids).intersection(healthy_lb_inst_ids)
            if len(not_yet_out_of_service) > 0:
                log('info', 'Waiting to remove previous instances ({}) from load balancer'.format(not_yet_out_of_service))
            else:
                log('info', 'All previous instances ({}) have been removed from load balancer'.format(previous_healthy_inst_ids), show_header=True)
        if all_healthy and len(not_yet_out_of_service) == 0:
            break
    else:
        raise Exception("Timeout")

    elb_result = elb_conn.get_all_load_balancers(load_balancer_names=[load_balancer_name])
    lb = elb_result[0]
    lb_insts = [inst for inst in lb.get_instance_health() if inst.state == 'InService']
    print '-----> Deployed {} instance(s) of {} to {}'.format(lb_insts, app.name, lb.dns_name)

    print '-----> DONE!'
예제 #10
0
파일: api.py 프로젝트: ddnn55/riker
def deploy_latest_app_ami(app_name, env_name):

    global aws
    aws = AWS.from_config(config)

    aws.connect()

    lb_group_ids = [aws.get_security_group_id('riker-load-balancer')]
    inst_group_ids = [aws.get_security_group_id('riker-instance')]

    app = App(env_name, app_name)

    health_check_target = app.config.get('health_check', 'TCP:80')

    name = re.sub('[^A-Za-z0-9\-]', '-', app.name)

    app_image = LatestAppImage(app).get()

    print '-----> Connecting to ELB'
    elb_conn = boto.connect_elb()

    log('info', 'Load balancer', show_header=True)
    load_balancer_name = name
    try:
        elb_result = elb_conn.get_all_load_balancers(
            load_balancer_names=[load_balancer_name])
        lb = elb_result[0]
        log('info', 'Found {}'.format(load_balancer_name))
    except boto.exception.BotoServerError:
        log('info', 'Not found, creating load balancer')
        listeners = [(80, 80, 'HTTP', 'HTTP')]
        lb = elb_conn.create_load_balancer(name=load_balancer_name,
                                           zones=None,
                                           complex_listeners=listeners,
                                           security_groups=lb_group_ids,
                                           subnets=[aws.subnet_id])
    hc = HealthCheck(target=health_check_target)
    lb.configure_health_check(hc)
    cda = ConnectionDrainingAttribute()
    cda.enabled = True
    cda.timeout = 300
    elb_conn.modify_lb_attribute(load_balancer_name=load_balancer_name,
                                 attribute='connectionDraining',
                                 value=cda)

    print '-----> Connecting to AutoScale'
    as_conn = boto.connect_autoscale()

    log('info', 'Launch configuration', show_header=True)
    launch_config_name = "{}-{}".format(name, app_image.tags['deploy-id'])
    lc_result = as_conn.get_all_launch_configurations(
        names=[launch_config_name])
    if len(lc_result) == 0:
        log('info', 'Not found, creating LaunchConfiguration')
        lc = LaunchConfiguration(name=launch_config_name,
                                 image_id=app_image.id,
                                 key_name=aws.key_pair_name,
                                 security_groups=inst_group_ids,
                                 instance_type=aws.instance_type)
        as_conn.create_launch_configuration(lc)
    else:
        log('info', 'Found {}'.format(launch_config_name))
        lc = lc_result[0]

    existing_group = None
    deploy_id = int(app_image.tags['deploy-id'] or 0)
    log('info', 'Getting previous auto-scaling group', show_header=True)
    for did in xrange(deploy_id - 1, 0, -1):
        existing_group_name = "{}-{}".format(name, did)
        log('info', '{} ?'.format(existing_group_name))
        ag_result = as_conn.get_all_groups(names=[existing_group_name])
        if len(ag_result) > 0:
            existing_group = ag_result[0]
            log('info', 'Found {}'.format(existing_group.name))
            break
        else:
            log('info', 'No')

    if existing_group is not None:
        existing_healthy_instances = [
            inst for inst in existing_group.instances
            if inst.lifecycle_state == 'InService'
            and inst.health_status == 'Healthy'
        ]
        existing_healthy_instance_count = len(existing_healthy_instances)
        desired_capacity = existing_group.desired_capacity
        min_size = existing_group.min_size
        max_size = existing_group.max_size
        if existing_healthy_instance_count == 0 and desired_capacity == 0:
            print '-----> WARNING: existing auto-scaling group {} has no healthy instances and a desired capacity of 0. New auto-scaling group will launch 1 instance.'.format(
                existing_group)
            desired_capacity = 1
            min_size = 1
            max_size = max_size if max_size > 0 else 1
    else:
        existing_healthy_instance_count = 0
        desired_capacity = 1
        min_size = 1
        max_size = 1

    log('info',
        '{} existing instance(s) found'.format(
            existing_healthy_instance_count),
        show_header=True)

    log(
        'info',
        'Existing auto-scale properties: desired_capacity={}, min_size={}, max_size={}'
        .format(desired_capacity, min_size, max_size))

    log('info', 'Auto-scaling group', show_header=True)
    group_name = "{}-{}".format(name, app_image.tags['deploy-id'])
    ag_result = as_conn.get_all_groups(names=[group_name])
    if len(ag_result) == 0:
        log('info', 'Not found, creating autoscale group')
        ag = AutoScalingGroup(name=group_name,
                              load_balancers=[load_balancer_name],
                              launch_config=lc,
                              desired_capacity=desired_capacity,
                              min_size=min_size,
                              max_size=max_size,
                              health_check_type='ELB',
                              health_check_period='300',
                              vpc_zone_identifier=aws.subnet_id)
        as_conn.create_auto_scaling_group(ag)
    else:
        log('info', 'Found {}'.format(group_name))
        ag = ag_result[0]
        ag.desired_capacity = desired_capacity
        ag.max_size = max_size
        ag.min_size = min_size
        ag.launch_config_name = launch_config_name
        ag.update()

    log('info',
        'Waiting for new instances to become healthy',
        show_header=True)
    all_healthy = False
    for i in xrange(60):
        if i > 0:
            print '       ---'
            time.sleep(10)
        elb_result = elb_conn.get_all_load_balancers(
            load_balancer_names=[load_balancer_name])
        lb = elb_result[0]
        lb_insts = lb.get_instance_health()
        print '       Load-balancer instances: {}'.format(lb_insts)
        # NOTE: re-get auto-scaling group to get updated instance info.
        ag = as_conn.get_all_groups(names=[group_name])[0]
        ag_insts = [inst for inst in ag.instances]
        log('info', 'Auto-scaling group Instances: {}'.format(ag_insts))
        if len(ag_insts) < desired_capacity:
            not_yet_launched_count = desired_capacity - len(ag_insts)
            log(
                'info', '{} new instance(s) not yet launched'.format(
                    not_yet_launched_count))
            continue
        ag_inst_ids = set(inst.instance_id for inst in ag_insts)
        lb_inst_ids = set(inst.instance_id for inst in lb_insts)
        asg_insts_not_in_lb = ag_inst_ids.difference(lb_inst_ids)
        if len(asg_insts_not_in_lb) > 0:
            log(
                'info', '{} new instance(s) not yet in load balancer'.format(
                    len(asg_insts_not_in_lb)))
            continue
        new_lb_insts = [
            inst for inst in lb_insts if inst.instance_id in ag_inst_ids
        ]
        healthy_new_lb_insts = [
            inst for inst in new_lb_insts if inst.state == 'InService'
        ]
        all_healthy = len(healthy_new_lb_insts) == len(ag_insts)
        log('info',
            '{} new instance(s) are healthy'.format(len(healthy_new_lb_insts)))
        diff = existing_healthy_instance_count - len(healthy_new_lb_insts)
        if existing_group is not None and diff >= 0:
            change = False
            if existing_group.desired_capacity != diff:
                existing_group.desired_capacity = diff
                change = True
            if existing_group.max_size != diff:
                existing_group.max_size = diff
                change = True
            if diff < existing_group.min_size:
                existing_group.min_size = diff
                change = True
            if change:
                existing_group.update()
                log(
                    'info',
                    'Change previous auto-scale group {} properties: desired_capacity={}, min_size={}, max_size={}'
                    .format(existing_group, existing_group.desired_capacity,
                            existing_group.min_size, existing_group.max_size))
        if all_healthy:
            log('info', 'All new instances healthy!', show_header=True)
            healthy_lb_inst_ids = [
                inst.instance_id for inst in lb_insts
                if inst.state == 'InService'
            ]
            previous_healthy_inst_ids = [
                inst.instance_id for inst in existing_healthy_instances
            ] if existing_group else []
            not_yet_out_of_service = set(
                previous_healthy_inst_ids).intersection(healthy_lb_inst_ids)
            if len(not_yet_out_of_service) > 0:
                log(
                    'info',
                    'Waiting to remove previous instances ({}) from load balancer'
                    .format(not_yet_out_of_service))
            else:
                log('info',
                    'All previous instances ({}) have been removed from load balancer'
                    .format(previous_healthy_inst_ids),
                    show_header=True)
        if all_healthy and len(not_yet_out_of_service) == 0:
            break
    else:
        raise Exception("Timeout")

    elb_result = elb_conn.get_all_load_balancers(
        load_balancer_names=[load_balancer_name])
    lb = elb_result[0]
    lb_insts = [
        inst for inst in lb.get_instance_health() if inst.state == 'InService'
    ]
    print '-----> Deployed {} instance(s) of {} to {}'.format(
        lb_insts, app.name, lb.dns_name)

    print '-----> DONE!'