s4:samba_dnsupdate Add a 'file based' mode to samba_dnsupdate
authorAndrew Bartlett <abartlet@samba.org>
Tue, 9 Mar 2010 12:34:10 +0000 (23:34 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 11 Mar 2010 00:27:48 +0000 (11:27 +1100)
For the testsuite to use DNS like names, we need to write these names
to a file.

Also, to have this run in 'make test' the usual rules about 'no 127.*'
IP addresses in DNS must be skipped, so glue.interface_ips takes two
arguments now

source4/scripting/bin/samba_dnsupdate
source4/scripting/python/pyglue.c
source4/scripting/python/samba/provision.py

index 2e9c469adff8733ea49cfeebc40f0e68836f8ebc..4fdd10de0ac692d83e704e42c4714522c36d549a 100755 (executable)
@@ -20,6 +20,7 @@
 
 import getopt
 import os
+import fcntl
 import sys
 import tempfile
 
@@ -49,6 +50,8 @@ sambaopts = options.SambaOptions(parser)
 parser.add_option_group(sambaopts)
 parser.add_option_group(options.VersionOptions(parser))
 parser.add_option("--verbose", action="store_true")
+parser.add_option("--all-interfaces", action="store_true")
+parser.add_option("--use-file", type="string", help="Use a file, rather than real DNS calls")
 
 creds = None
 ccachename = None
@@ -63,7 +66,12 @@ lp = sambaopts.get_loadparm()
 
 domain = lp.get("realm")
 host = lp.get("netbios name")
-IPs = glue.interface_ips(lp)
+if opts.all_interfaces:
+    all_interfaces = True
+else:
+    all_interfaces = False
+
+IPs = glue.interface_ips(lp, all_interfaces)
 nsupdate_cmd = lp.get('nsupdate command')
 
 if len(IPs) == 0:
@@ -94,38 +102,37 @@ def get_credentials(lp):
 #############################################
 # an object to hold a parsed DNS line
 class dnsobj(object):
-    def __init__(self):
-        self.type = None
-        self.name = None
+    def __init__(self, string_form):
+        list = string_form.split()
         self.dest = None
         self.port = None
         self.ip = None
         self.existing_port = None
         self.existing_weight = None
+        self.type = list[0]
+        self.name = list[1]
+        if self.type == 'SRV':
+            self.dest = list[2]
+            self.port = list[3]
+        elif self.type == 'A':
+            self.ip   = list[2] # usually $IP, which gets replaced
+        elif self.type == 'CNAME':
+            self.dest = list[2]
+        else:
+            print "Received unexpected DNS reply of type %s" % self.type
+            raise
+
     def __str__(self):
-        if d.type == "A":     return "%s:%s:%s" % (self.type, self.name, self.ip)
-        if d.type == "SRV":   return "%s:%s:%s:%s" % (self.type, self.name, self.dest, self.port)
-        if d.type == "CNAME": return "%s:%s:%s" % (self.type, self.name, self.dest)
+        if d.type == "A":     return "%s %s %s" % (self.type, self.name, self.ip)
+        if d.type == "SRV":   return "%s %s %s %s" % (self.type, self.name, self.dest, self.port)
+        if d.type == "CNAME": return "%s %s %s" % (self.type, self.name, self.dest)
 
 
 ################################################
 # parse a DNS line from
 def parse_dns_line(line, sub_vars):
-    d = dnsobj()
     subline = samba.substitute_var(line, sub_vars)
-    list = subline.split()
-    d.type = list[0]
-    d.name = list[1]
-    if d.type == 'SRV':
-        d.dest = list[2]
-        d.port = list[3]
-    elif d.type == 'A':
-        d.ip   = list[2] # usually $IP, which gets replaced
-    elif d.type == 'CNAME':
-        d.dest = list[2]
-    else:
-        print "Received unexpected DNS reply of type %s" % d.type
-        raise
+    d = dnsobj(subline)
     return d
 
 ############################################
@@ -142,6 +149,24 @@ def check_dns_name(d):
     normalised_name = d.name.rstrip('.') + '.'
     if opts.verbose:
         print "Looking for DNS entry %s as %s" % (d, normalised_name)
+    if opts.use_file is not None:
+        try:
+            dns_file = open(opts.use_file, "r")
+        except IOError:
+            return False
+        
+        line = dns_file.readline()
+        while line:
+            line = line.rstrip().lstrip()
+            if line[0] == "#":
+                line = dns_file.readline()
+                continue
+            if line.lower() == str(d).lower():
+                return True
+            line = dns_file.readline()
+        return False
+
     try:
         ans = resolver.query(normalised_name, d.type)
     except resolver.NXDOMAIN:
@@ -167,6 +192,7 @@ def check_dns_name(d):
                     d.existing_weight = str(rdata.weight)
     if opts.verbose:
         print "Failed to find DNS entry %s" % d
+
     return False
 
 
@@ -195,6 +221,14 @@ def call_nsupdate(d):
 
     if opts.verbose:
         print "Calling nsupdate for %s" % d
+
+    if opts.use_file is not None:
+        wfile = open(opts.use_file, 'a')
+        fcntl.lockf(wfile, fcntl.LOCK_EX)
+        wfile.write(str(d)+"\n")
+        fcntl.lockf(wfile, fcntl.LOCK_UN)
+        return
+
     (tmp_fd, tmpfile) = tempfile.mkstemp()
     f = os.fdopen(tmp_fd, 'w')
     if d.type == "A":
index 6fe789ae73bcf55e542015fb825cf03d232d6bb1..89cf18e16ab40bf781f51e3032787f083be8739b 100644 (file)
@@ -614,8 +614,9 @@ static PyObject *py_interface_ips(PyObject *self, PyObject *args)
        struct loadparm_context *lp_ctx;
        struct interface *ifaces;
        int i, ifcount;
+       int all_interfaces;
 
-       if (!PyArg_ParseTuple(args, "O", &py_lp_ctx))
+       if (!PyArg_ParseTuple(args, "Oi", &py_lp_ctx, &all_interfaces))
                return NULL;
 
        lp_ctx = lp_from_py_object(py_lp_ctx);
@@ -633,7 +634,7 @@ static PyObject *py_interface_ips(PyObject *self, PyObject *args)
        /* first count how many are not loopback addresses */
        for (ifcount = i = 0; i<count; i++) {
                const char *ip = iface_n_ip(ifaces, i);
-               if (!iface_same_net(ip, "127.0.0.1", "255.0.0.0")) {
+               if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
                        ifcount++;
                }
        }
@@ -641,7 +642,7 @@ static PyObject *py_interface_ips(PyObject *self, PyObject *args)
        pylist = PyList_New(ifcount);
        for (ifcount = i = 0; i<count; i++) {
                const char *ip = iface_n_ip(ifaces, i);
-               if (!iface_same_net(ip, "127.0.0.1", "255.0.0.0")) {
+               if (!(!all_interfaces && iface_same_net(ip, "127.0.0.1", "255.0.0.0"))) {
                        PyList_SetItem(pylist, ifcount, PyString_FromString(ip));
                        ifcount++;
                }
index cb90141730b19ac9d0bd87e91e10f35dc2e8cdc8..bac234cfac6fbf743c0892e4717707bad80645ad 100644 (file)
@@ -1182,7 +1182,7 @@ def provision(setup_dir, message, session_info,
     paths.bind_gid = bind_gid
 
     if hostip is None:
-        hostips = glue.interface_ips(lp)
+        hostips = glue.interface_ips(lp, False)
         if len(hostips) == 0:
             message("No external IPv4 address has been found: I use the loopback.")
             hostip = '127.0.0.1'