#! /usr/bin/env python # set interfaces in hv_kvp_daemon style import fileinput import sys import errno import os import shutil import tempfile import subprocess if_filename="/etc/network/interfaces" '''Get quiet''' sys.stdout = open(os.devnull, 'w') sys.stderr = open(os.devnull, 'w') try: if_file=open(if_filename,"r+") except IOError as e: exit(e.errno) else: if_file.close() def kvp_dict(file): return dict(line.strip().split("=") for line in file) #setting the hwaddress to something azure is not expecting is fatal networking if len(sys.argv) != 2 : exit(errno.EINVAL) kvp=dict(line.strip().split("=") for line in fileinput.input()) if not "HWADDR" in kvp : exit(errno.EPROTO) if not "DEVICE" in kvp : exit(1) output=[] basename=kvp["DEVICE"] if "DHCP" in kvp and kvp["DHCP"]=="yes" : output += ["auto " + basename] output += ["iface " + basename + " inet dhcp"] output += [""] else: ''' Matchup the interface specific lines ''' '''DNS entries will go with the first interface and there can be a max of three''' autolist=[] dns=[] if "DNS1" in kvp : dns+=[kvp["DNS1"]] if "DNS2" in kvp : dns+=[kvp["DNS2"]] if "DNS3" in kvp : dns+=[kvp["DNS3"]] ''' No real max for the number of interface + aliases ... only required is the address (but mate everything up that comes in. ''' '''ipv4 first''' v4names=[name for name in kvp.keys() if name.startswith("IPADDR")] v4names.sort() v6names=[name for name in kvp.keys() if name.startswith("IPV6ADDR")] v6names.sort() '''IPV6 requires a netmask''' '''If an ipv6 exists, you'll want to turn off /proc/sys/net/ipv6/conf/all/autoconf with up echo 0 > /proc/sys/net/ipv6/conf/all/autoconf''' '''Counter needs to increment as soon as any interface is set.''' if_count=0 for v4 in v4names: ifname=basename suffix="" if if_count : ifname+=":" + str(if_count) suffix="_"+str(if_count) if not ifname in autolist: autolist += [ifname] output += [ "iface " + ifname + " inet static"] output += [ "\t" + "address " + kvp[v4]] if "NETMASK"+suffix in kvp.keys(): output += ["\tnetmask " + kvp["NETMASK"+suffix]] if "GATEWAY"+suffix in kvp.keys(): output += ["\tgateway " + kvp["GATEWAY"+suffix]] if not if_count : output += ["\tdns-nameservers " + ' '.join(dns)] output += [""] if_count+=1 if6_count=0 if6_used=0 for v6 in v6names: ifname=basename suffix="" if if6_used : ifname+=":" + str(if6_used) if if6_count : suffix="_" + str(if6_count) if not ifname in autolist: autolist += [ifname] if "IPV6NETMASK"+suffix in kvp.keys(): output += [ "iface " + ifname + " inet6 static"] output += [ "\taddress " + kvp[v6]] output += [ "\tnetmask " + kvp["IPV6NETMASK"+suffix]] if "IPV6_DEFAULTGW"+suffix in kvp.keys(): output += [ "\tgateway " + kvp["IPV6_DEFAULTGW"+suffix] ] if not if_count : output += ["\tdns-nameservers " + ' '.join(dns)] output += [""] if_count += 1 if6_used += 1 if6_count += 1 output = ["auto "+" ".join(autolist)] + output print "===================================" print output print "===================================" ''' Time to clean out the existing interface file''' # Markers. start_mark = "# The following stanza(s) added by hv_set_ifconfig" end_mark = "#End of hv_set_ifconfig stanzas" f=open(if_filename,"r") flines=f.readlines() f.close() newfile=[] pitchstanza=0 inastanza=0 stanza=[] prev_line=None for line in flines: if line.startswith("auto"): if inastanza: if not pitchstanza: newfile.extend(stanza) stanza=[] inastanza=0 newline="" autoline=line.strip().split(" ") for word in autoline: if (not word == basename) and (not word.startswith(basename+":")): newline+=word + " " newline = newline.strip() if not newline == "auto": newfile += [newline.strip()] elif line.startswith(("iface","mapping","source")): '''Read a stanza''' '''A Stanza can also start with allow- ie allow-hotplug''' if inastanza: if not pitchstanza: newfile.extend(stanza) stanza=[] inastanza=1 pitchstanza=0 autoline=line.strip().split(" ") for word in autoline: if (word == basename) or (word.startswith(basename+":")): pitchstanza=1 if not pitchstanza: stanza+=[line.strip()] elif line.strip() in (start_mark, end_mark): if inastanza: if not pitchstanza: newfile.extend(stanza) stanza=[] inastanza = 0 pitchstanza = 0 # Deduplicate markers. if line != prev_line: newfile += [line.strip()] else: if inastanza: if not pitchstanza: stanza+=[line.strip()] else: if not pitchstanza: newfile += [line.strip()] prev_line=line def emit(line): print(line) os.write(fd, line + "\n") # Insert the new output at the end and inside the existing markers if found. emitted = False fd, path = tempfile.mkstemp() for line in newfile: if line == end_mark: emit("\n".join(output)) emitted = True emit(line) if not emitted: emit(start_mark) emit("\n".join(output)) emit(end_mark) os.close(fd) shutil.copy(path,if_filename) os.chmod(if_filename,0644) #print "TMPFILE is at: " + path #print "Copied file is at: " + if_filename try: retcode = subprocess.call("ifdown "+basename , shell=True) if retcode < 0: print >>sys.stderr, "Child was terminated by signal", -retcode else: print >>sys.stderr, "Child returned", retcode except OSError as e: print >>sys.stderr, "Execution failed:", e try: retcode = subprocess.call("ifup "+basename , shell=True) if retcode < 0: print >>sys.stderr, "Child was terminated by signal", -retcode else: print >>sys.stderr, "Child returned", retcode except OSError as e: print >>sys.stderr, "Execution failed:", e