Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify that EIP was actually associated. #25

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions aws_ec2_assign_elastic_ip/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import logging.config
import sys
import time

if sys.platform in ['win32', 'cygwin']:
import ntpath as ospath
Expand Down Expand Up @@ -68,6 +69,9 @@ def main():
logger.info('Would assign IP {0}'.format(address.public_ip))
else:
_assign_address(instance_id, address)
if args.verify:
if not _verify_associated(instance_id, address):
sys.exit(1)


def _assign_address(instance_id, address):
Expand Down Expand Up @@ -102,6 +106,60 @@ def _assign_address(instance_id, address):
logger.info('Successfully associated Elastic IP {0} with {1}'.format(
address.public_ip, instance_id))

def _verify_associated(instance_id, address, retries=10, retry_interval=0.1):
"""
Check that address is actually associated with instance_id by querying
the EC2 API.

:type instance_id: str
:param instance_id: Instance ID
:type address: boto.ec2.address
:param address: Elastic IP address
:type retries: int
:param retries: Number of times to retry failures
:type retry_interval: float
:param retry_interval: Sleep interval between retries
:returns: bool -- True if EIP is actually associated
"""

logger.debug('Verifying that {0} is associated with {1}'.format(
instance_id, address.public_ip))

actual = connection.get_all_addresses(addresses=[address.public_ip])[0]

if actual.instance_id == instance_id:
logger.info(
'Verified that {0} is really associated with {1} ({2}/{3})'.format(
actual.public_ip, instance_id, actual.network_interface_id,
actual.association_id))
return True

if actual.instance_id:
logger.error(('Somehow {0!r} is associated with {1!r},' +
' not expected instance {2!r}').format(address.public_ip,
actual.instance_id,
instance_id))
return False

if actual.association_id:
logger.warning(
'Elastic IP {0} is already associated with {1!r}'.format(
actual.public_ip, actual.network_interface_id))
else:
logger.info('Elastic IP {0} is not yet associated'.format(
address.public_ip))

if retries > 0:
logger.info('Retrying verification...')
time.sleep(retry_interval)
return _verify_associated(instance_id=instance_id, address=address,
retries=retries - 1,
retry_interval=retry_interval)

logger.error(
'Ran out of retries verifying association of {0!r} to {1!r}'.format(
address.public_ip, instance_id))
return False

def _get_unassociated_address():
""" Return the first unassociated EIP we can find
Expand Down
4 changes: 4 additions & 0 deletions aws_ec2_assign_elastic_ip/command_line_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
help=(
'Turn on dry run mode. No address will be assigned,\n'
'we will only print which we whould take'))
PARSER.add_argument(
'--skip-verify',
help='Skip verification that the EIP was successfully associated',
action='store_false', dest='verify')
PARSER.add_argument(
'--valid-ips',
help=(
Expand Down