That should be all the dhcp settings correct

CsGuestNetwork moved out of configure
dnsmasq config all switched to CsDhcp
This commit is contained in:
Ian Southam 2014-08-20 16:08:42 +02:00 committed by wilderrodrigues
parent b45c71ee31
commit 8f4461567d
4 changed files with 166 additions and 65 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
"""

View File

@ -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)