]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - debian/cloud-tools/hv_set_ifconfig
UBUNTU: [Debian] hv: hv_set_ifconfig -- switch to approved indentation
[mirror_ubuntu-zesty-kernel.git] / debian / cloud-tools / hv_set_ifconfig
1 #!/usr/bin/python3
2 #
3 # hv_set_ifconfig <config> -- take the hv_kvp_daemon generated configuration
4 # file and apply it to the Ubuntu configuration.
5 #
6
7 # CONFIG example:
8 # HWADDR=11:22:33:44:55:66
9 # DEVICE=foo1
10 # DHCP=yes
11
12 # CONFIG example:
13 # HWADDR=11:22:33:44:55:66
14 # DEVICE=foo1
15 # IPADDR=192.168.99.10
16 # GATEWAY=192.168.99.1
17 # DNS1=192.168.88.250
18 # IPADDR2=192.168.99.11
19 # IPV6ADDR=2001:DB8:99::10
20 # IPV6NETMASK=64
21 # IPV6_DEFAULTGW=2001:DB8:99::10
22
23 # set interfaces in hv_kvp_daemon style
24 import fileinput
25 import sys
26 import errno
27 import os
28 import shutil
29 import tempfile
30 import subprocess
31
32 if_filename="/etc/network/interfaces"
33
34 # Drop our output (XXX?)
35 sys.stdout = open(os.devnull, 'w')
36 sys.stderr = open(os.devnull, 'w')
37
38 # Confirm we can open the network configuration.
39 try:
40 if_file=open(if_filename,"r+")
41 except IOError as e:
42 exit(e.errno)
43 else:
44 if_file.close()
45
46 # Usage: hv_set_ifconfig <config>
47 if len(sys.argv) != 2 :
48 exit(errno.EINVAL)
49
50 #
51 # Here is the format of the ip configuration file:
52 #
53 # HWADDR=macaddr
54 # DEVICE=interface name
55 # BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
56 # or "none" if no boot-time protocol should be used)
57 #
58 kvp=dict(line.strip().split("=") for line in fileinput.input())
59
60 # Setting the hwaddress to something azure is not expecting is fatal
61 # to networking.
62 if not "HWADDR" in kvp :
63 exit(errno.EPROTO)
64
65 # Confirm we have a device specified.
66 if not "DEVICE" in kvp :
67 exit(1)
68
69 output=[]
70 basename=kvp["DEVICE"]
71
72 if "DHCP" in kvp and kvp["DHCP"]=="yes" :
73 output += ["auto " + basename]
74 output += ["iface " + basename + " inet dhcp"]
75 output += [""]
76 else:
77 # Matchup the interface specific lines
78
79 # DNS entries will go with the first interface
80 # and there can be a max of three
81 autolist=[]
82 dns=[]
83 if "DNS1" in kvp :
84 dns+=[kvp["DNS1"]]
85 if "DNS2" in kvp :
86 dns+=[kvp["DNS2"]]
87 if "DNS3" in kvp :
88 dns+=[kvp["DNS3"]]
89
90
91 # No real max for the number of interface + aliases ...
92 # only required is the address (but mate everything up that comes in.
93
94 # IPv4
95 v4names=[name for name in kvp.keys() if name.startswith("IPADDR")]
96 v4names.sort()
97
98 if_count=0
99 for v4 in v4names:
100 ifname=basename
101 suffix=""
102 if if_count :
103 ifname+=":" + str(if_count)
104 suffix="_"+str(if_count)
105 if not ifname in autolist:
106 autolist += [ifname]
107 output += [ "iface " + ifname + " inet static"]
108 output += [ "\t" + "address " + kvp[v4]]
109 if "NETMASK"+suffix in kvp.keys():
110 output += ["\tnetmask " + kvp["NETMASK"+suffix]]
111 if "GATEWAY"+suffix in kvp.keys():
112 output += ["\tgateway " + kvp["GATEWAY"+suffix]]
113 if not if_count :
114 output += ["\tdns-nameservers " + ' '.join(dns)]
115 output += [""]
116 if_count+=1
117
118
119 # IPv6 requires a netmask
120 # If an ipv6 exists, you'll want to turn off /proc/sys/net/ipv6/conf/all/autoconf with
121 # echo 0 > /proc/sys/net/ipv6/conf/all/autoconf
122 v6names=[name for name in kvp.keys() if name.startswith("IPV6ADDR")]
123 v6names.sort()
124
125 if6_count=0
126 if6_used=0
127 for v6 in v6names:
128 ifname=basename
129 suffix=""
130 if if6_used :
131 ifname+=":" + str(if6_used)
132 if if6_count :
133 suffix="_" + str(if6_count)
134 if not ifname in autolist:
135 autolist += [ifname]
136 if "IPV6NETMASK"+suffix in kvp.keys():
137 output += [ "iface " + ifname + " inet6 static"]
138 output += [ "\taddress " + kvp[v6]]
139 output += [ "\tnetmask " + kvp["IPV6NETMASK"+suffix]]
140 if "IPV6_DEFAULTGW"+suffix in kvp.keys():
141 output += [ "\tgateway " + kvp["IPV6_DEFAULTGW"+suffix] ]
142 if not if_count :
143 output += ["\tdns-nameservers " + ' '.join(dns)]
144 output += [""]
145 if_count += 1
146 if6_used += 1
147 if6_count += 1
148
149 # Mark this new interface for automatic up.
150 output = ["auto "+" ".join(autolist)] + output
151
152 print("===================================")
153 print(output)
154 print("===================================")
155
156
157 ''' Time to clean out the existing interface file'''
158
159 # Markers.
160 start_mark = "# The following stanza(s) added by hv_set_ifconfig"
161 end_mark = "#End of hv_set_ifconfig stanzas"
162
163 f=open(if_filename,"r")
164 flines=f.readlines()
165 f.close()
166 newfile=[]
167 pitchstanza=0
168 inastanza=0
169 stanza=[]
170 prev_line=None
171 for line in flines:
172 if line.startswith("auto"):
173 if inastanza:
174 if not pitchstanza:
175 newfile.extend(stanza)
176 stanza=[]
177 inastanza=0
178 newline=""
179 autoline=line.strip().split(" ")
180 for word in autoline:
181 if (not word == basename) and (not word.startswith(basename+":")):
182 newline+=word + " "
183 newline = newline.strip()
184 if not newline == "auto":
185 newfile += [newline.strip()]
186 elif line.startswith(("iface","mapping","source")):
187 '''Read a stanza'''
188 '''A Stanza can also start with allow- ie allow-hotplug'''
189 if inastanza:
190 if not pitchstanza:
191 newfile.extend(stanza)
192 stanza=[]
193 inastanza=1
194 pitchstanza=0
195 autoline=line.strip().split(" ")
196 for word in autoline:
197 if (word == basename) or (word.startswith(basename+":")):
198 pitchstanza=1
199 if not pitchstanza:
200 stanza+=[line.strip()]
201 elif line.strip() in (start_mark, end_mark):
202 if inastanza:
203 if not pitchstanza:
204 newfile.extend(stanza)
205 stanza=[]
206 inastanza = 0
207 pitchstanza = 0
208 # Deduplicate markers.
209 if line != prev_line:
210 newfile += [line.strip()]
211 else:
212 if inastanza:
213 if not pitchstanza:
214 stanza+=[line.strip()]
215 else:
216 if not pitchstanza:
217 newfile += [line.strip()]
218 prev_line=line
219
220
221
222 def emit(line):
223 print(line)
224 output = line + "\n"
225 os.write(fd, output.encode('utf-8'))
226
227 # Insert the new output at the end and inside the existing markers if found.
228 emitted = False
229 fd, path = tempfile.mkstemp()
230 for line in newfile:
231 if line == end_mark:
232 emit("\n".join(output))
233 emitted = True
234 emit(line)
235 if not emitted:
236 emit(start_mark)
237 emit("\n".join(output))
238 emit(end_mark)
239 os.close(fd)
240
241 shutil.copy(path,if_filename)
242 os.chmod(if_filename,0o644)
243
244 #print("TMPFILE is at: " + path)
245 #print("Copied file is at: " + if_filename)
246
247 try:
248 retcode = subprocess.call("ifdown "+basename , shell=True)
249 if retcode < 0:
250 print("Child was terminated by signal", -retcode, file=sys.stderr)
251 else:
252 print("Child returned", retcode, file=sys.stderr)
253 except OSError as e:
254 print("Execution failed:", e, file=sys.stderr)
255
256 try:
257 retcode = subprocess.call("ifup "+basename , shell=True)
258 if retcode < 0:
259 print("Child was terminated by signal", -retcode, file=sys.stderr)
260 else:
261 print("Child returned", retcode, file=sys.stderr)
262 except OSError as e:
263 print("Execution failed:", e, file=sys.stderr)