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