def main()

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)