def find_connection_id(client, connection_id=None, connection_name=None):
    params = {}
    if connection_id:
        params['connectionId'] = connection_id
    try:
        response = describe_connections(client, params)
    except (BotoCoreError, ClientError) as e:
        if connection_id:
            msg = "Failed to describe DirectConnect ID {0}".format(
                connection_id)
        else:
            msg = "Failed to describe DirectConnect connections"
        raise DirectConnectError(msg=msg,
                                 last_traceback=traceback.format_exc(),
                                 exception=e)

    match = []
    if len(response.get('connections', [])) == 1 and connection_id:
        if response['connections'][0]['connectionState'] != 'deleted':
            match.append(response['connections'][0]['connectionId'])

    for conn in response.get('connections', []):
        if connection_name == conn[
                'connectionName'] and conn['connectionState'] != 'deleted':
            match.append(conn['connectionId'])

    if len(match) == 1:
        return match[0]
    else:
        raise DirectConnectError(
            msg="Could not find a valid DirectConnect connection")
Beispiel #2
0
def update_lag(client, lag_id, lag_name, min_links, num_connections, wait,
               wait_timeout):
    start = time.time()

    if min_links and min_links > num_connections:
        raise DirectConnectError(
            msg=
            "The number of connections {0} must be greater than the minimum number of links "
            "{1} to update the LAG {2}".format(num_connections, min_links,
                                               lag_id),
            last_traceback=None,
            exception=None)

    while True:
        try:
            _update_lag(client, lag_id, lag_name, min_links)
        except botocore.exceptions.ClientError as e:
            if wait and time.time() - start <= wait_timeout:
                continue
            msg = "Failed to update Direct Connect link aggregation group {0}.".format(
                lag_id)
            if "MinimumLinks cannot be set higher than the number of connections" in e.response[
                    'Error']['Message']:
                msg += "Unable to set the min number of links to {0} while the LAG connections are being requested".format(
                    min_links)
            raise DirectConnectError(msg=msg,
                                     last_traceback=traceback.format_exc(),
                                     exception=e)
        else:
            break
Beispiel #3
0
def create_lag(client, num_connections, location, bandwidth, name,
               connection_id):
    if not name:
        raise DirectConnectError(
            msg=
            "Failed to create a Direct Connect link aggregation group: name required.",
            last_traceback=None,
            exception="")

    parameters = dict(numberOfConnections=num_connections,
                      location=location,
                      connectionsBandwidth=bandwidth,
                      lagName=name)
    if connection_id:
        parameters.update(connectionId=connection_id)
    try:
        lag = client.create_lag(**parameters)
    except botocore.exceptions.ClientError as e:
        raise DirectConnectError(
            msg="Failed to create DirectConnect link aggregation group {0}".
            format(name),
            last_traceback=traceback.format_exc(),
            exception=e)

    return lag['lagId']
Beispiel #4
0
def delete_lag(client, lag_id):
    try:
        client.delete_lag(lagId=lag_id)
    except botocore.exceptions.ClientError as e:
        raise DirectConnectError(msg="Failed to delete Direct Connect link aggregation group {0}.".format(lag_id),
                                 last_traceback=traceback.format_exc(),
                                 exception=e)
Beispiel #5
0
def ensure_present(client, num_connections, lag_id, lag_name, location,
                   bandwidth, connection_id, min_links, wait, wait_timeout):
    exists = lag_exists(client, lag_id, lag_name)
    if not exists and lag_id:
        raise DirectConnectError(
            msg="The Direct Connect link aggregation group {0} does not exist."
            .format(lag_id),
            last_traceback=None,
            exception="")

    # the connection is found; get the latest state and see if it needs to be updated
    if exists:
        lag_id = exists
        latest_state = lag_status(client, lag_id)
        if lag_changed(latest_state, lag_name, min_links):
            update_lag(client, lag_id, lag_name, min_links, num_connections,
                       wait, wait_timeout)
            return True, lag_id
        return False, lag_id

    # no connection found; create a new one
    else:
        lag_id = create_lag(client, num_connections, location, bandwidth,
                            lag_name, connection_id)
        update_lag(client, lag_id, lag_name, min_links, num_connections, wait,
                   wait_timeout)
        return True, lag_id
Beispiel #6
0
def describe_virtual_interfaces(client, lag_id):
    try:
        response = client.describe_virtual_interfaces(connectionId=lag_id)
    except botocore.exceptions.ClientError as e:
        raise DirectConnectError(msg="Failed to describe any virtual interfaces associated with LAG: {0}".format(lag_id),
                                 last_traceback=traceback.format_exc(),
                                 exception=e)
    return response.get('virtualInterfaces', [])
def get_connection_state(client, connection_id):
    try:
        response = describe_connections(client, dict(connectionId=connection_id))
        return response['connections'][0]['connectionState']
    except (BotoCoreError, ClientError, IndexError) as e:
        raise DirectConnectError(msg="Failed to describe DirectConnect connection {0} state".format(connection_id),
                                 last_traceback=traceback.format_exc(),
                                 exception=e)
Beispiel #8
0
def disassociate_vis(client, lag_id, virtual_interfaces):
    for vi in virtual_interfaces:
        delete_virtual_interface(client, vi['virtualInterfaceId'])
        try:
            response = client.delete_virtual_interface(virtualInterfaceId=vi['virtualInterfaceId'])
        except botocore.exceptions.ClientError as e:
            raise DirectConnectError(msg="Could not delete virtual interface {0} to delete link aggregation group {1}.".format(vi, lag_id),
                                     last_traceback=traceback.format_exc(),
                                     exception=e)
Beispiel #9
0
def create_connection(client, location, bandwidth, name, lag_id):
    if not name:
        raise DirectConnectError(msg="Failed to create a Direct Connect connection: name required.")
    params = {
        'location': location,
        'bandwidth': bandwidth,
        'connectionName': name,
    }
    if lag_id:
        params['lagId'] = lag_id

    try:
        connection = AWSRetry.backoff(**retry_params)(client.create_connection)(**params)
    except (BotoCoreError, ClientError) as e:
        raise DirectConnectError(msg="Failed to create DirectConnect connection {0}".format(name),
                                 last_traceback=traceback.format_exc(),
                                 exception=e)
    return connection['connectionId']
Beispiel #10
0
 def run_func(*args, **kwargs):
     try:
         result = AWSRetry.jittered_backoff(
             retries=8,
             delay=5,
             catch_extra_error_codes=['DirectConnectClientException'
                                      ])(f)(*args, **kwargs)
     except (ClientError, BotoCoreError) as e:
         raise DirectConnectError(failure_msg, traceback.format_exc(),
                                  e)
     return result
Beispiel #11
0
def lag_exists(client, lag_id=None, lag_name=None, verify=True):
    """ If verify=True, returns the LAG ID or None
        If verify=False, returns the LAG's data (or an empty dict)
    """
    try:
        if lag_id:
            response = client.describe_lags(lagId=lag_id)
        else:
            response = client.describe_lags()
    except botocore.exceptions.ClientError as e:
        if lag_id and verify:
            return False
        elif lag_id:
            return {}
        else:
            failed_op = "Failed to describe DirectConnect link aggregation groups."
        raise DirectConnectError(msg=failed_op,
                                 last_traceback=traceback.format_exc(),
                                 exception=e)

    match = []  # List of LAG IDs that are exact matches
    lag = []  # List of LAG data that are exact matches

    # look for matching connections
    if len(response.get('lags', [])) == 1 and lag_id:
        if response['lags'][0]['lagState'] != 'deleted':
            match.append(response['lags'][0]['lagId'])
            lag.append(response['lags'][0])
    else:
        for each in response.get('lags', []):
            if each['lagState'] != 'deleted':
                if not lag_id:
                    if lag_name == each['lagName']:
                        match.append(each['lagId'])
                else:
                    match.append(each['lagId'])

    # verifying if the connections exists; if true, return connection identifier, otherwise return False
    if verify and len(match) == 1:
        return match[0]
    elif verify:
        return False

    # not verifying if the connection exists; just return current connection info
    else:
        if len(lag) == 1:
            return lag[0]
        else:
            return {}
Beispiel #12
0
def ensure_absent(client, lag_id, lag_name, force_delete,
                  delete_with_disassociation, wait, wait_timeout):
    lag_id = lag_exists(client, lag_id, lag_name)
    if not lag_id:
        return False

    latest_status = lag_status(client, lag_id)

    # determine the associated connections and virtual interfaces to disassociate
    virtual_interfaces, connections = get_connections_and_virtual_interfaces(
        client, lag_id)

    # If min_links is not 0, there are associated connections, or if there are virtual interfaces, ask for force_delete
    if any((latest_status['minimumLinks'], virtual_interfaces,
            connections)) and not force_delete:
        raise DirectConnectError(
            msg=
            "There are a minimum number of links, hosted connections, or associated virtual interfaces for LAG {0}. "
            "To force deletion of the LAG use delete_force: True (if the LAG has virtual interfaces they will be deleted). "
            "Optionally, to ensure hosted connections are deleted after disassociation use delete_with_disassociation: True "
            "and wait: True (as Virtual Interfaces may take a few moments to delete)"
            .format(lag_id),
            last_traceback=None,
            exception=None)

    # update min_links to be 0 so we can remove the LAG
    update_lag(client, lag_id, None, 0, len(connections), wait, wait_timeout)

    # if virtual_interfaces and not delete_vi_with_disassociation: Raise failure; can't delete while vi attached
    for connection in connections:
        disassociate_connection_and_lag(client, connection['connectionId'],
                                        lag_id)
        if delete_with_disassociation:
            delete_connection(client, connection['connectionId'])

    for vi in virtual_interfaces:
        delete_virtual_interface(client, vi['virtualInterfaceId'])

    start_time = time.time()
    while True:
        try:
            delete_lag(client, lag_id)
        except DirectConnectError as e:
            if ('until its Virtual Interfaces are deleted' in e.exception
                ) and (time.time() - start_time < wait_timeout) and wait:
                continue
        else:
            return True
def connection_exists(client,
                      connection_id=None,
                      connection_name=None,
                      verify=True):
    params = {}
    if connection_id:
        params['connectionId'] = connection_id
    try:
        response = AWSRetry.backoff(**retry_params)(
            client.describe_connections)(**params)
    except (BotoCoreError, ClientError) as e:
        if connection_id:
            msg = "Failed to describe DirectConnect ID {0}".format(
                connection_id)
        else:
            msg = "Failed to describe DirectConnect connections"
        raise DirectConnectError(msg=msg,
                                 last_traceback=traceback.format_exc(),
                                 exception=e)

    match = []
    connection = []

    # look for matching connections

    if len(response.get('connections', [])) == 1 and connection_id:
        if response['connections'][0]['connectionState'] != 'deleted':
            match.append(response['connections'][0]['connectionId'])
            connection.extend(response['connections'])

    for conn in response.get('connections', []):
        if connection_name == conn[
                'connectionName'] and conn['connectionState'] != 'deleted':
            match.append(conn['connectionId'])
            connection.append(conn)

    # verifying if the connections exists; if true, return connection identifier, otherwise return False
    if verify and len(match) == 1:
        return match[0]
    elif verify:
        return False
    # not verifying if the connection exists; just return current connection info
    elif len(connection) == 1:
        return {'connection': connection[0]}
    return {'connection': {}}