2 Description: IPv6 Support and Management to Slices
3 ipv6 nodemanager plugin
5 Author: Guilherme Sperb Machado <gsm@machados.org>
16 from sliver_libvirt import Sliver_Libvirt
17 from xml.dom.minidom import parseString
21 radvdConfFile = '/etc/radvd.conf'
24 logger.log("ipv6: plugin starting up...")
26 def buildLibvirtDefaultNetConfig(dom):
28 # create the <network> element
29 networkElem = dom.createElement("network")
30 # create <name> element
31 nameElem = dom.createElement("name")
32 textName = dom.createTextNode("default")
33 nameElem.appendChild(textName)
34 # create <uuid> element
35 uuidElem = dom.createElement("uuid")
36 textUUID = dom.createTextNode(str(uuid.uuid1()))
37 uuidElem.appendChild(textUUID)
38 # create <forward> element
39 forwardElem = dom.createElement("forward")
40 forwardElem.setAttribute("mode", "nat")
41 # create <nat> element
42 natElem = dom.createElement("nat")
43 # create <port> element
44 portElem = dom.createElement("port")
45 portElem.setAttribute("end", "65535")
46 portElem.setAttribute("start", "1024")
47 # create the ipv4 <ip> element
48 ipElem0 = dom.createElement("ip")
49 ipElem0.setAttribute("address", "192.168.122.1")
50 ipElem0.setAttribute("netmask", "255.255.255.0")
51 # create the <dhcp> element
52 dhcpElem = dom.createElement("dhcp")
53 # create the <range> element
54 rangeElem = dom.createElement("range")
55 rangeElem.setAttribute("end", "192.168.122.254")
56 rangeElem.setAttribute("start", "192.168.122.2")
57 # create the <bridge> element
58 bridgeElem = dom.createElement("bridge")
59 bridgeElem.setAttribute("delay", "0")
60 bridgeElem.setAttribute("name", "virbr0")
61 bridgeElem.setAttribute("stp", "on")
63 # build the whole thing
64 natElem.appendChild(portElem)
65 forwardElem.appendChild(natElem)
67 dhcpElem.appendChild(rangeElem)
68 ipElem0.appendChild(dhcpElem)
69 networkElem.appendChild(nameElem)
70 networkElem.appendChild(uuidElem)
71 networkElem.appendChild(forwardElem)
72 networkElem.appendChild(bridgeElem)
73 networkElem.appendChild(ipElem0)
76 def checkForIPv6(defaultNetworkConfig):
77 netnodes = defaultNetworkConfig.getElementsByTagName('network')
79 for netnode in netnodes:
80 ips = netnode.getElementsByTagName('ip')
82 if ip.getAttribute('family')=='ipv6':
83 logger.log("ipv6: the configuration already have an IPv6 address/prefix set for the slivers! %s/%s" % (ip.getAttribute('address'), ip.getAttribute('prefix')) )
89 def addIPv6(defaultNetworkConfig, ipv6addr, prefix):
91 netnodes = defaultNetworkConfig.getElementsByTagName('network')
92 for netnode in netnodes:
93 # create the ipv6 <ip> element 1
94 ipElem1 = defaultNetworkConfig.createElement("ip")
95 ipElem1.setAttribute("family", "ipv6")
96 ipElem1.setAttribute("address", ipv6addr)
97 ipElem1.setAttribute("prefix", prefix)
98 # create the ipv6 <ip> element 2
99 # it's ugly, I know, but we need a link-local address on the interface!
100 ipElem2 = defaultNetworkConfig.createElement("ip")
101 ipElem2.setAttribute("family", "ipv6")
102 ipElem2.setAttribute("address", "fe80:1234::1")
103 ipElem2.setAttribute("prefix", "64")
104 # adding to the 'defaultNetworkConfig'
105 netnode.appendChild(ipElem1)
106 netnode.appendChild(ipElem2)
107 return defaultNetworkConfig
109 def changeIPv6(dom, ipv6addr, prefix):
110 ips = dom.getElementsByTagName('ip')
112 if ip.getAttribute("family")=='ipv6' and not(re.match(r'fe80(.*)', ip.getAttribute("address"), re.I)):
113 ip.setAttribute("address", ipv6addr)
114 ip.setAttribute("prefix", prefix)
119 networks = dom.getElementsByTagName('network')
120 for network in networks:
121 ips = network.getElementsByTagName('ip')
123 if ip.getAttribute("family")=='ipv6':
124 network.removeChild(ip)
128 def checkIfIPv6IsDifferent(dom, ipv6addr, prefix):
129 netnodes = dom.getElementsByTagName('network')
130 for netnode in netnodes:
131 ips = netnode.getElementsByTagName('ip')
133 if ip.getAttribute('family')=='ipv6' and not( re.match(r'fe80(.*)', ip.getAttribute("address"), re.I) ) and (ip.getAttribute('address')!=ipv6addr or ip.getAttribute('prefix')!=prefix):
134 logger.log("ipv6: the IPv6 address or prefix are different. Change detected!")
140 def setAutostart(network):
142 network.setAutostart(1)
144 logger.log("ipv6: network could not set to autostart")
147 def setUp(networkLibvirt, connLibvirt, networkElem, ipv6addr, prefix):
148 newXml = networkElem.toxml()
149 #logger.log(networkElem.toxml())
152 # logger.log(repr(method))
153 networkLibvirt.undefine()
154 networkLibvirt.destroy()
155 connLibvirt.networkCreateXML(newXml)
156 networkDefault = connLibvirt.networkDefineXML(newXml)
157 setAutostart(networkDefault)
158 commandForwarding = ['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1']
159 logger.log_call(commandForwarding, timeout=15*60)
164 MinRtrAdvInterval 30;
165 MaxRtrAdvInterval 100;
174 """ % (ipv6addr+"/"+prefix)
175 f=open(radvdConfFile,'w')
180 logger.log("ipv6: set up process finalized. Enabled IPv6 address to the slivers!")
182 def cleanUp(networkLibvirt, connLibvirt, networkElem):
183 dom = removeIPv6(networkElem)
185 networkLibvirt.undefine()
186 networkLibvirt.destroy()
187 # TODO: set autostart for the network
188 connLibvirt.networkCreateXML(newXml)
189 networkDefault = connLibvirt.networkDefineXML(newXml)
190 setAutostart(networkDefault)
192 logger.log("ipv6: cleanup process finalized. The IPv6 support on the slivers was removed.")
195 commandKillRadvd = ['killall', 'radvd']
196 logger.log_call(commandKillRadvd, timeout=15*60)
199 commandRadvd = ['radvd']
200 logger.log_call(commandRadvd, timeout=15*60)
202 def GetSlivers(data, config, plc):
205 #for sliver in data['slivers']:
206 #ipv6addr,prefixlen = tools.get_sliver_ipv6(sliver['name'])
207 #tools.add_ipv6addr_hosts_line(sliver['name'], data['hostname'], ipv6addr)
208 #result = tools.search_ipv6addr_hosts(sliver['name'], ipv6addr)
209 #logger.log("tools: result=%s" % (str(result)) )
210 #tools.remove_all_ipv6addr_hosts(sliver['name'], data['hostname'])
216 interfaces = data['interfaces']
217 logger.log(repr(interfaces))
218 for interface in interfaces:
219 logger.log('ipv6: get interface 1: %r'%(interface))
220 if 'interface_tag_ids' in interface:
221 interface_tag_ids = "interface_tag_ids"
222 interface_tag_id = "interface_tag_id"
223 settings = plc.GetInterfaceTags({interface_tag_id:interface[interface_tag_ids]})
224 isSliversIPv6PrefixSet = False
225 for setting in settings:
226 #logger.log(repr(setting))
227 # TODO: create a static variable to describe the "sliversipv6prefix" tag
228 if setting['tagname']=='sliversipv6prefix':
229 ipv6addrprefix = setting['value'].split('/', 1)
230 ipv6addr = ipv6addrprefix[0]
231 prefix = ipv6addrprefix[1]
232 logger.log("ipv6: %s" % (ipv6addr) )
233 validIPv6 = tools.isValidIPv6(ipv6addr)
235 logger.log("ipv6: the 'sliversipv6prefix' tag presented a non-valid IPv6 address!")
237 # connecting to the libvirtd
238 connLibvirt = Sliver_Libvirt.getConnection(type)
239 list = connLibvirt.listAllNetworks()
240 for networkLibvirt in list:
241 xmldesc = networkLibvirt.XMLDesc()
242 dom = parseString(xmldesc)
243 hasIPv6 = checkForIPv6(dom)
245 # let's first check if the IPv6 is different or is it the same...
246 isDifferent = checkIfIPv6IsDifferent(dom, ipv6addr, prefix)
248 logger.log("ipv6: the tag 'sliversipv6prefix' was modified! Updating the configuration with the new one...")
249 networkElem = changeIPv6(dom, ipv6addr, prefix)
250 setUp(networkLibvirt, connLibvirt, networkElem, ipv6addr, prefix)
251 logger.log("ipv6: trying to reboot the slivers...")
252 tools.reboot_sliver('blah')
254 logger.log("ipv6: starting to redefine the virtual network...")
255 #networkElem = buildLibvirtDefaultNetConfig(dom,ipv6addr,prefix)
256 networkElem = addIPv6(dom, ipv6addr, prefix)
257 setUp(networkLibvirt, connLibvirt, networkElem, ipv6addr, prefix)
258 logger.log("ipv6: trying to reboot the slivers...")
259 tools.reboot_sliver('blah')
260 isSliversIPv6PrefixSet = True
261 if not(isSliversIPv6PrefixSet):
262 # connecting to the libvirtd
263 connLibvirt = Sliver_Libvirt.getConnection(type)
264 list = connLibvirt.listAllNetworks()
265 for networkLibvirt in list:
266 xmldesc = networkLibvirt.XMLDesc()
267 dom = parseString(xmldesc)
268 if checkForIPv6(dom):
269 cleanUp(networkLibvirt, connLibvirt, dom)
270 logger.log("ipv6: trying to reboot the slivers...")
271 tools.reboot_sliver('blah')
273 logger.log("ipv6: all done!")