mirror of https://github.com/apache/cloudstack.git
That should be all the dhcp settings correct
CsGuestNetwork moved out of configure dnsmasq config all switched to CsDhcp
This commit is contained in:
parent
b45c71ee31
commit
8f4461567d
|
|
@ -15,24 +15,17 @@
|
|||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import CsHelper
|
||||
from pprint import pprint
|
||||
import logging
|
||||
from netaddr import *
|
||||
from CsGuestNetwork import CsGuestNetwork
|
||||
|
||||
NO_PRELOAD = False
|
||||
LEASES = "/var/lib/misc/dnsmasq.leases"
|
||||
DHCP_HOSTS = "/etc/dhcphosts.txt"
|
||||
DHCP_OPTS = "/etc/dhcpopts.txt"
|
||||
DNSMASQ_CONF = "/etc/dnsmasq.conf"
|
||||
CLOUD_CONF = "/etc/dnsmasq.d/cloud.conf"
|
||||
|
||||
"""
|
||||
"172.16.1.102": {
|
||||
"default_entry": true,
|
||||
"default_gateway": "172.16.1.1",
|
||||
"host_name": "VM-58976c22-0832-451e-9ab2-039e9f27e415",
|
||||
"ipv4_adress": "172.16.1.102",
|
||||
"ipv6_duid": "00:03:00:01:02:00:26:c3:00:02",
|
||||
"mac_address": "02:00:26:c3:00:02",
|
||||
"type": "dhcpentry"
|
||||
},
|
||||
"""
|
||||
class CsDhcp(object):
|
||||
""" Manage dhcp entries """
|
||||
|
||||
|
|
@ -42,15 +35,19 @@ class CsDhcp(object):
|
|||
if item == "id":
|
||||
continue
|
||||
dnsmasq.add(dbag[item])
|
||||
dnsmasq.collect_leases()
|
||||
dnsmasq.to_str()
|
||||
dnsmasqb4 = CsDnsMasq(NO_PRELOAD)
|
||||
dnsmasqb4.parse_hosts()
|
||||
dnsmasqb4.parse_dnsmasq()
|
||||
if not dnsmasq.compare_hosts(dnsmasqb4):
|
||||
dnsmasq.write_hosts()
|
||||
else:
|
||||
logging.debug("Hosts file is up to date")
|
||||
|
||||
diff = dnsmasq.compare_dnsmasq(dnsmasqb4)
|
||||
if len(diff) > 0:
|
||||
self.updated = True
|
||||
dnsmasq.delete_leases(diff)
|
||||
dnsmasq.write_dnsmasq()
|
||||
dnsmasq.configure_server()
|
||||
|
||||
class CsDnsMasq(object):
|
||||
|
||||
|
|
@ -58,6 +55,9 @@ class CsDnsMasq(object):
|
|||
self.list = []
|
||||
self.hosts = []
|
||||
self.leases = []
|
||||
self.updated = False
|
||||
self.devinfo = CsHelper.get_device_info()
|
||||
self.devs = []
|
||||
if preload:
|
||||
self.add_host("127.0.0.1", "localhost")
|
||||
self.add_host("::1", "localhost ip6-localhost ip6-loopback")
|
||||
|
|
@ -65,18 +65,55 @@ class CsDnsMasq(object):
|
|||
self.add_host("ff02::2", "ip6-allrouters")
|
||||
self.add_host("127.0.0.1", CsHelper.get_hostname())
|
||||
|
||||
def collect_leases(self):
|
||||
# Format is
|
||||
# 0 02:00:56:aa:00:03 10.1.1.18 pup *
|
||||
def delete_leases(self, clist):
|
||||
try:
|
||||
for line in open(LEASES):
|
||||
bits = line.strip().split(' ')
|
||||
to = { "device" : bits[0],
|
||||
"mac" : bits[1],
|
||||
"ip" : bits[2],
|
||||
"host" : bits[3]
|
||||
"host" : bits[3],
|
||||
"del" : False
|
||||
}
|
||||
for l in clist:
|
||||
lbits = l.split(',')
|
||||
if lbits[0] == to['mac'] or \
|
||||
lbits[1] == to['ip']:
|
||||
to['del'] == True
|
||||
break
|
||||
self.leases.append(to)
|
||||
for o in self.leases:
|
||||
if o['del']:
|
||||
cmd = "dhcp_release %s %s %s" % (o.device, o.ip, o.mac)
|
||||
logging.info(cmd)
|
||||
CsHelper.execute(cmd)
|
||||
# Finally add the new lease
|
||||
except IOError:
|
||||
return
|
||||
|
||||
def configure_server(self):
|
||||
self.updated = self.updated or CsHelper.addifmissing(CLOUD_CONF, "dhcp-hostsfile=/etc/dhcphosts.txt")
|
||||
self.updated = self.updated or CsHelper.addifmissing(DNSMASQ_CONF, "dhcp-optsfile=%s:" % DHCP_OPTS)
|
||||
for i in self.devinfo:
|
||||
if not i['dnsmasq']:
|
||||
continue
|
||||
device = i['dev']
|
||||
ip = i['ip'].split('/')[0]
|
||||
line = "dhcp-range=interface:%s,set:interface-%s,%s,static" \
|
||||
% (device, device, ip)
|
||||
self.updated = self.updated or CsHelper.addifmissing(CLOUD_CONF, line)
|
||||
# Next add the domain
|
||||
# if this is a guest network get it there otherwise use the value in resolv.conf
|
||||
gn = CsGuestNetwork(device)
|
||||
line = "dhcp-option=tag:interface-%s,15,%s" % (device,gn.get_domain())
|
||||
self.updated = self.updated or CsHelper.addifmissing(CLOUD_CONF, line)
|
||||
if self.updated:
|
||||
CsHelper.hup_dnsmasq("dnsmasq", "dnsmasq")
|
||||
|
||||
def parse_dnsmasq(self):
|
||||
try:
|
||||
for line in open(DHCP_HOSTS):
|
||||
self.list.append(line.strip())
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
|
|
@ -93,23 +130,35 @@ class CsDnsMasq(object):
|
|||
def compare_hosts(self, obj):
|
||||
return set(self.hosts) == set(obj.hosts)
|
||||
|
||||
def compare_dnsmasq(self, obj):
|
||||
return list(set(self.list).symmetric_difference(set(obj.list)))
|
||||
|
||||
def write_hosts(self):
|
||||
logging.debug("Updating hosts file with new entry")
|
||||
logging.debug("Updating hosts file")
|
||||
handle = open("/etc/hosts", 'w+')
|
||||
for line in self.hosts:
|
||||
handle.write("%s\n" % line)
|
||||
handle.close()
|
||||
|
||||
def write_dnsmasq(self):
|
||||
logging.debug("Updating %s", DHCP_HOSTS)
|
||||
handle = open(DHCP_HOSTS, 'w+')
|
||||
for line in self.list:
|
||||
handle.write("%s\n" % line)
|
||||
b = line.split(',')
|
||||
handle.close()
|
||||
|
||||
def add(self,entry):
|
||||
self.add_host(entry['ipv4_adress'], entry['host_name'])
|
||||
self.add_dnsmasq(entry['ipv4_adress'], entry['host_name'], entry['mac_address'])
|
||||
|
||||
i = IPAddress(entry['ipv4_adress'])
|
||||
# Calculate the device
|
||||
for v in self.devinfo:
|
||||
if i > v['network'].network and i < v['network'].broadcast:
|
||||
v['dnsmasq'] = True
|
||||
|
||||
def add_dnsmasq(self, ip, host, mac):
|
||||
self.list.append("%s,%s,%s,infinite" % (mac, ip, host))
|
||||
|
||||
def add_host(self, ip, host):
|
||||
self.hosts.append("%s\t%s" % (ip, host))
|
||||
|
||||
def to_str(self):
|
||||
pprint(self.hosts)
|
||||
pprint(self.list)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from merge import dataBag
|
||||
import CsHelper
|
||||
|
||||
class CsGuestNetwork:
|
||||
def __init__(self, device):
|
||||
self.data = {}
|
||||
self.guest = True
|
||||
db = dataBag()
|
||||
db.setKey("guestnetwork")
|
||||
db.load()
|
||||
dbag = db.getDataBag()
|
||||
if device in dbag.keys() and len(dbag[device]) != 0:
|
||||
self.data = dbag[device][0]
|
||||
else:
|
||||
self.guest = False
|
||||
|
||||
def is_guestnetwork(self):
|
||||
return self.guest
|
||||
|
||||
def get_domain(self):
|
||||
domain = "cloudnine.internal"
|
||||
if not self.guest:
|
||||
return CsHelper.get_domain()
|
||||
|
||||
if 'domain_name' in self.data:
|
||||
return self.data['domain_name']
|
||||
|
||||
return domain
|
||||
|
|
@ -7,6 +7,8 @@ import logging
|
|||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
from netaddr import *
|
||||
from pprint import pprint
|
||||
|
||||
def updatefile(filename, val, mode):
|
||||
""" add val to file """
|
||||
|
|
@ -18,6 +20,36 @@ def updatefile(filename, val, mode):
|
|||
handle.write(val)
|
||||
handle.close()
|
||||
|
||||
def get_device_info():
|
||||
""" Returns all devices on system with their ipv4 ip netmask """
|
||||
list = []
|
||||
for i in execute("ip addr show"):
|
||||
vals = i.strip().lstrip().rstrip().split()
|
||||
if vals[0] == "inet":
|
||||
to = {}
|
||||
to['ip'] = vals[1]
|
||||
to['dev'] = vals[-1]
|
||||
to['network'] = IPNetwork(to['ip'])
|
||||
to['dnsmasq'] = False
|
||||
list.append(to)
|
||||
return list
|
||||
|
||||
def get_domain():
|
||||
for line in open("/etc/resolv.conf"):
|
||||
vals = line.lstrip().split()
|
||||
if vals[0] == "domain":
|
||||
return vals[1]
|
||||
return "cloudnine.internal"
|
||||
|
||||
def get_ip(device):
|
||||
""" Return first ip on an interface """
|
||||
cmd = "ip addr show dev %s" % device
|
||||
for i in execute(cmd):
|
||||
vals = i.lstrip().split()
|
||||
if (vals[0] == 'inet'):
|
||||
return vals[1]
|
||||
return ""
|
||||
|
||||
def definedinfile(filename, val):
|
||||
""" Check if val is defined in the file """
|
||||
for line in open(filename):
|
||||
|
|
@ -31,6 +63,8 @@ def addifmissing(filename, val):
|
|||
if not definedinfile(filename, val):
|
||||
updatefile(filename, val + "\n", "a")
|
||||
logging.debug("Added %s to file %s" % (val, filename))
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_hostname():
|
||||
for line in open("/etc/hostname"):
|
||||
|
|
@ -46,6 +80,18 @@ def service(name, op):
|
|||
execute("service %s %s" % (name, op))
|
||||
logging.info("Service %s %s" % (name, op))
|
||||
|
||||
def hup_dnsmasq(name, user):
|
||||
pid = ""
|
||||
for i in execute("ps -ef | grep %s" % name):
|
||||
vals = i.lstrip().split()
|
||||
if (vals[0] == user):
|
||||
pid = vals[1]
|
||||
if pid:
|
||||
logging.info("Sent hup to %s", name)
|
||||
execute("kill -HUP %s" % pid)
|
||||
else:
|
||||
service("dnsmasq", "start")
|
||||
|
||||
def copy_if_needed(src, dest):
|
||||
""" Copy a file if the destination does not already exist
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -206,11 +206,7 @@ class CsApp:
|
|||
def __init__(self, ip):
|
||||
self.dev = ip.getDevice()
|
||||
self.ip = ip.get_ip_address()
|
||||
self.domain = "domain.local"
|
||||
self.type = ip.get_type()
|
||||
if self.type == "guest":
|
||||
gn = CsGuestNetwork(self.dev)
|
||||
self.domain = gn.get_domain()
|
||||
global fw
|
||||
|
||||
class CsPasswdSvc(CsApp):
|
||||
|
|
@ -274,39 +270,6 @@ class CsDnsmasq(CsApp):
|
|||
"-A INPUT -i %s -d %s/32 -p tcp -m tcp --dport 53 -j ACCEPT" % ( self.dev, self.ip )
|
||||
])
|
||||
|
||||
def configure_server(self, method = "add"):
|
||||
file = CsFile("/etc/dnsmasq.d/cloud.conf")
|
||||
file.search("dhcp-range=interface:%s" % self.dev, \
|
||||
"dhcp-range=interface:%s,set:interface-%s,%s,static" % (self.dev, self.dev, self.ip))
|
||||
file.search("dhcp-option=tag:interface-%s," % self.dev, \
|
||||
"dhcp-option=tag:interface-%s,15,%s" % (self.dev, self.domain))
|
||||
file.commit()
|
||||
|
||||
if file.is_changed():
|
||||
CsHelper.service("dnsmasq", "restart")
|
||||
|
||||
|
||||
class CsGuestNetwork:
|
||||
def __init__(self, device):
|
||||
self.data = {}
|
||||
db = dataBag()
|
||||
db.setKey("guestnetwork")
|
||||
db.load()
|
||||
dbag = db.getDataBag()
|
||||
for dev in dbag:
|
||||
if dev == "id":
|
||||
continue
|
||||
if len(dbag[dev]) == 0:
|
||||
continue
|
||||
if dev == device:
|
||||
self.data = dbag[dev][0]
|
||||
|
||||
def get_domain(self):
|
||||
if 'domain_name' in self.data:
|
||||
return self.data['domain_name']
|
||||
else:
|
||||
return "cloudnine.internal"
|
||||
|
||||
class CsDevice:
|
||||
""" Configure Network Devices """
|
||||
def __init__(self, dev):
|
||||
|
|
@ -441,7 +404,6 @@ class CsIP:
|
|||
])
|
||||
dns = CsDnsmasq(self)
|
||||
dns.add_firewall_rules()
|
||||
dns.configure_server()
|
||||
app = CsApache(self)
|
||||
app.setup()
|
||||
pwdsvc = CsPasswdSvc(self).setup()
|
||||
|
|
@ -795,8 +757,8 @@ def main(argv):
|
|||
nf = CsNetfilters()
|
||||
nf.compare(fw)
|
||||
|
||||
acls = CsDataBag("dhcpentry")
|
||||
dhcp = CsDhcp(acls.get_bag(), cl)
|
||||
dh = CsDataBag("dhcpentry")
|
||||
dhcp = CsDhcp(dh.get_bag(), cl)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
|
|
|
|||
Loading…
Reference in New Issue