in code/assign-ip-new-ip6-parallel.py [0:0]
def main():
instance_id = None
currIPList = []
cmd = "ip a |grep -v eth0|grep 'scope global' |cut -d ' ' -f 6"
region= None
instanceData = {}
initcontainer=False
if len(sys.argv) >0 :
if sys.argv[1] == "initContainers":
initcontainer=True
if initcontainer == False:
tprint("Running as Sidecar container")
while (1) :
retCode=0
try:
# at the very first iteration, get the instance ID of the underlying worker & create a temp oto3 client to get instance data attached ENIs and corresponding subnet IP CIDRblocks
if not instance_id :
data = get_instance_id()
instance_id = data[0]
region = data[1]
tprint ("Got InstanceId: " + instance_id + " region: " + region)
ec2_client = boto3.client('ec2', region_name=region)
get_instanceDetails(ec2_client,instance_id,instanceData)
ec2ClientArr = {}
#Tn this coode, we are planning to do parallel processing and same client cant be used parallely for multiple parallel requests, so we are creating a Map/dictionary of ec2 clients for each ENI/subnet CIDR attached to the worker
# These clients are stored as values against the dictionary where subnet cidr is the key
for cidr in instanceData:
k = boto3.client('ec2', region_name=region)
ec2ClientArr[cidr] = k
#Run the shell command on the pod which will get the list of multus secondary interfaces Ips (non eth0)
ips = shell_run_cmd(cmd,retCode)
newIPList = ips.splitlines()
if retCode == 0 :
ipmap = defaultdict(list)
ip6map = defaultdict(list)
noChange=True
#if there are IPs allocated on the pod, and these IPs are not new i.e. not same as received in the previous interation then
# Find the subnet cidr from the pod IP address using the IPNetwork helper class and store the ips against the subnet ipcidr (ipv4 and ipv6 separately)
if len(newIPList) > 0 :
for ipaddress in newIPList:
if ipaddress not in currIPList:
ip = IPNetwork(ipaddress)
cidr = str(ip.cidr)
if netaddr.valid_ipv4(str(ip.ip)):
ipmap[cidr].append(str(ip.ip))
else :
ip6map[cidr].append(str(ip.ip))
noChange=False
# if there are changes in the ips (new vs old) then reassign the ipv4 IP addresses asynchronously to save time (parallel execution)
if noChange == False :
if len(ipmap) > 0:
procipv4 = []
for key in ipmap:
p = Process(target=assign_ip_to_nic, args=(ipmap[key],instanceData[key],ec2ClientArr[key]))
p.start()
procipv4.append(p)
# wait for the parallel requests to complete execution and return
for p in procipv4:
p.join(2)
tprint ("Finished all IPV4")
# if there are changes in the ips (new vs old) then release the ipv6 IP addresses from old ENIs asynchronously to save time (parallel execution)
if len(ip6map) > 0:
procipv6 = []
for key in ip6map:
p = Process(target=release_ipv6, args=(ip6map[key],key,ec2ClientArr[key]))
p.start()
procipv6.append(p)
for p in procipv6:
p.join(2)
# if there are changes in the ips (new vs old) then relassignease the ipv6 IP addressess to the worker ENIs asynchronously to save time (parallel execution)
for key in ip6map:
p = Process(target=assign_ip6_to_nic, args=(ip6map[key],instanceData[key],ec2ClientArr[key]))
p.start()
procipv6.append(p)
for p in procipv6:
p.join(2)
tprint ("Finished all IPv6")
# Once all the ipv4 and ipv6 assignments are completed, then copy the newIp list as current List
currIPList = copy.deepcopy(newIPList)
if initcontainer == True :
tprint ("Started as initcontainer. Exiting after successful execution")
exit(0)
else:
tprint ("No IPs present in system for cmd: "+ cmd )
else:
tprint ("Error received: " + retCode + " for command: "+ cmd )
# If these are any exceptions in ip assignment to the NICs then catch it using catch all exception and keep trying & logging untill the problem is resolved
except (Exception) as e:
tprint ("Exception :" + str(e))
tprint ("continuing the handling")
time.sleep(0.5)