基於boto的幾個Elastic IP的用法

原始的boto關於ElasticIP的api使用起來比較不友好,例如實例與EIP關聯的時候,需要給出VPC裏的EIP的allocation_id,而allocation_id要從eip的屬性裏找出來,disassociate eip的時候,需要提供association_id,這個id比較難找。而常規的思路是,不管是關聯和解關聯,只需要提供實例ID和EIP就行,因此我封裝了幾個函數來使EIP的使用變的稍微友好點。
(ElasticIP和PublicIP的區別,詳見我的這篇文章http://imbusy.me/elastic_ip-and-public_ip.html

1,將eip的allocation函數封裝,返回IP和allocationIP的字典,供後面關聯函數使用

import boto.ec2
region = 'ap-southeast-1'

def eip_allocation(domain='vpc'):
    conn = boto.ec2.connect_to_region(region)
    allocation = conn.allocate_address(domain='vpc', dry_run=False)
    return {'public_ip':allocation.public_ip,
            'allocation_id':allocation.allocation_id}

返回字典例如
{'public_ip':'54.169.xx.xx', 'allocation_id':'eipalloc-b2e3xxxx'}

2,原始的associate函數需要給出實例ID和EIP的allocation_id,那假如不是分配IP後立即使用,而是把已經存在的EIP與實例關聯,這樣就得通過EIP來解析出allocation_id,於是重新包裝下,使其只需要實例ID和EIP即可,而eip_allocation函數正好二者都返回,隨便選用。

def eip_association(instance_id,public_ip):
    '''Notice: need InstanceID and PublicIP to make association'''
    conn = boto.ec2.connect_to_region(region)
    ##make sure input ip is valid EIP
    try:
        address = conn.get_all_addresses(addresses=[public_ip])
    except boto.exception.EC2ResponseError:
        print "Error: IP not found or not EIP"
    else:
        allocation_id = address[0].allocation_id
    ## to call boto associate_address func
    conn.associate_address(
        instance_id=instance_id,
        public_ip=None,
        allocation_id=allocation_id,
        network_interface_id=None,
        private_ip_address=None,
        allow_reassociation=False,
        dry_run=False)

3,disassociate原始的函數也是需要association_id的,而正常思路是只需要提供EIP就可以將其與實例解除關聯,於是重新包裝了函數,只需要給出EIP就能解除關聯

def eip_disassociation(public_ip):
    conn = boto.ec2.connect_to_region(region)
    '''Notice: use public_ip to get network_interface_id
    and use network_interface_id to get association_id'''
    ##make sure input ip is valid EIP
    try:
        address = conn.get_all_addresses(addresses=[public_ip])
    except boto.exception.EC2ResponseError:
        print "Error: IP not found or not EIP"
    else:
        association_id = address[0].association_id
        #network_interface_id = address[0].network_interface_id    
    conn.disassociate_address(
        public_ip=None,
        association_id=association_id,
        dry_run=False)

4,釋放EIP,重新包裝了下,使其不需要allocation_id,只需要給出EIP就能釋放,並且會判斷EIP是否被使用,只有沒被使用的EIP才能被釋放,當然,每個函數還有個判斷輸入的EIP是否爲真實的EIP。

def eip_release(public_ip):
    conn = boto.ec2.connect_to_region(region)
    ##make sure input ip is valid EIP
    try:
        address = conn.get_all_addresses(addresses=[public_ip])
    except boto.exception.EC2ResponseError:
        print "Error: IP not found or not EIP"
    else:
        association_id = address[0].association_id
        allocation_id = address[0].allocation_id
    ## only release EIP that not associated to any instance
    if association_id == None:
        conn.release_address(
            public_ip=None,
            allocation_id=allocation_id)
    else:
        print "IP %s is in use, cannot be released" % public_ip

5,重新構造了個函數,用戶給實例快速更換EIP,適用於爬蟲服務器,因爲他的IP經常被封掉。另外提一句,如果實例創建之初自動分配過Public IP的話,關聯EIP之後,PublicIP也會變成與ElasticIP一樣(被覆蓋),等解除EIP關聯之後,PublicIP纔會顯露,但此時會重新分配,因此PublicIP會變。

def eip_change(instance_id):
    conn = boto.ec2.connect_to_region(region)
    reservations = conn.get_all_reservations([instance_id])
    instances = reservations[0].instances
    inst = instances[0]
    old_public_ip = inst.ip_address
    ##make sure the public ip is valid EIP
    try:
        address = conn.get_all_addresses(addresses=[old_public_ip])
    except boto.exception.EC2ResponseError:
        print "Error: Old public IP not found or not EIP"
    else:
        eip_disassociation(old_public_ip)
        eip_release(old_public_ip)
    ## add new IP 
    allocation = eip_allocation()
    public_ip = allocation['public_ip']
    eip_association(instance_id,public_ip)

6,下面是主函數裏的調用示例

def main():
    #usage demos
    #eip_disassociation('54.xx.xx.xx')
    #eip_association('i-xxxxxxxx','54.xx.xx.xx')
    #eip_release('54.xx.xx.xx')
    #eip_change('i-xxxxxxxx')

if __name__ == '__main__':
    main()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章