samba-tool/dns: remove use of dns_record_match from add and delete
[amitay/samba.git] / python / samba / netcmd / dns.py
index 775be9e5608e06cd6e8432014ab48cb118d0c620..fe5a2930dd90eb48c21926140e841c909299b56c 100644 (file)
 #
 
 import samba.getopt as options
+from samba import WERRORError
 from struct import pack
 from socket import inet_ntoa
+from socket import inet_ntop
+from socket import AF_INET
+from socket import AF_INET6
 import shlex
 
 from samba.netcmd import (
@@ -34,7 +38,11 @@ def dns_connect(server, lp, creds):
     if server.lower() == 'localhost':
         server = '127.0.0.1'
     binding_str = "ncacn_ip_tcp:%s[sign]" % server
-    dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
+    try:
+        dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
+    except RuntimeError, e:
+        raise CommandError('Connecting to DNS RPC server %s failed with %s' % (server, e))
+
     return dns_conn
 
 
@@ -126,7 +134,7 @@ def ip4_array_string(array):
     if not array:
         return ret
     for i in xrange(array.AddrCount):
-        addr = '%s' % inet_ntoa(pack('i', array.AddrArray[i]))
+        addr = inet_ntop(AF_INET, pack('I', array.AddrArray[i]))
         ret.append(addr)
     return ret
 
@@ -137,11 +145,11 @@ def dns_addr_array_string(array):
         return ret
     for i in xrange(array.AddrCount):
         if array.AddrArray[i].MaxSa[0] == 0x02:
-            addr = '%d.%d.%d.%d (%d)' % \
-                tuple(array.AddrArray[i].MaxSa[4:8] + [array.AddrArray[i].MaxSa[3]])
+            x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[4:8]
+            addr = inet_ntop(AF_INET, x)
         elif array.AddrArray[i].MaxSa[0] == 0x17:
-            addr = '%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x (%d)' % \
-                tuple(array.AddrArray[i].MaxSa[4:20] + [array.AddrArray[i].MaxSa[3]])
+            x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[8:24]
+            addr = inet_ntop(AF_INET6, x)
         else:
             addr = 'UNKNOWN'
         ret.append(addr)
@@ -615,13 +623,16 @@ def dns_record_match(dns_conn, server, zone, name, record_type, data):
         buflen, res = dns_conn.DnssrvEnumRecords2(
             dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name, None,
             record_type, select_flags, None, None)
-    except RuntimeError, e:
-        return None
+    except WERRORError as e:
+        if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+            # Either the zone doesn't exist, or there were no records.
+            # We can't differentiate the two.
+            return None
+        raise e
 
     if not res or res.count == 0:
         return None
 
-    rec_match = None
     for rec in res.rec[0].records:
         if rec.wType != record_type:
             continue
@@ -671,10 +682,9 @@ def dns_record_match(dns_conn, server, zone, name, record_type, data):
                             (rec.data.str[i].str == urec.data.str[i].str)
 
         if found:
-            rec_match = rec
-            break
+            return rec
 
-    return rec_match
+    return None
 
 
 class cmd_serverinfo(Command):
@@ -885,9 +895,15 @@ class cmd_zonecreate(Command):
         name_and_param.pszNodeName = 'AllowUpdate'
         name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
 
-        res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
-                                        0, 'ResetDwordProperty', typeid,
-                                        name_and_param)
+        try:
+            res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
+                                            0, 'ResetDwordProperty', typeid,
+                                            name_and_param)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_ZONE_ALREADY_EXISTS':
+                self.outf.write('Zone already exists.')
+            raise e
+
         self.outf.write('Zone %s created successfully\n' % zone)
 
 
@@ -912,11 +928,17 @@ class cmd_zonedelete(Command):
         dns_conn = dns_connect(server, self.lp, self.creds)
 
         zone = zone.lower()
-        res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                        0, server, zone, 0, 'DeleteZoneFromDs',
-                                        dnsserver.DNSSRV_TYPEID_NULL,
-                                        None)
-        self.outf.write('Zone %s delete successfully\n' % zone)
+        try:
+            res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                            0, server, zone, 0, 'DeleteZoneFromDs',
+                                            dnsserver.DNSSRV_TYPEID_NULL,
+                                            None)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist and so could not be deleted.')
+            raise e
+
+        self.outf.write('Zone %s deleted successfully\n' % zone)
 
 
 class cmd_query(Command):
@@ -986,9 +1008,15 @@ class cmd_query(Command):
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
 
-        buflen, res = dns_conn.DnssrvEnumRecords2(
+        try:
+            buflen, res = dns_conn.DnssrvEnumRecords2(
                 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name,
                 None, record_type, select_flags, None, None)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Record or zone does not exist.')
+            raise e
+
         print_dnsrecords(self.outf, res)
 
 
@@ -1058,16 +1086,17 @@ class cmd_add_record(Command):
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
 
-        rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
-                data)
-        if rec_match is not None:
-            raise CommandError('Record already exists')
-
         add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
         add_rec_buf.rec = rec
 
-        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                     0, server, zone, name, add_rec_buf, None)
+        try:
+            dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                         0, server, zone, name, add_rec_buf, None)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist; record could not be added.\n')
+            raise e
+
         self.outf.write('Record added successfully\n')
 
 
@@ -1112,7 +1141,7 @@ class cmd_update_record(Command):
         rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
                 olddata)
         if not rec_match:
-            raise CommandError('Record does not exist')
+            raise CommandError('Record or zone does not exist.')
 
         # Copy properties from existing record to new record
         rec.dwFlags = rec_match.dwFlags
@@ -1126,13 +1155,19 @@ class cmd_update_record(Command):
         del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
         del_rec_buf.rec = rec_match
 
-        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                        0,
-                                        server,
-                                        zone,
-                                        name,
-                                        add_rec_buf,
-                                        del_rec_buf)
+        try:
+            dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                         0,
+                                         server,
+                                         zone,
+                                         name,
+                                         add_rec_buf,
+                                         del_rec_buf)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist; record could not be updated.\n')
+            raise e
+
         self.outf.write('Record updated successfully\n')
 
 
@@ -1166,25 +1201,28 @@ class cmd_delete_record(Command):
             raise CommandError('Deleting record of type %s is not supported' % rtype)
 
         record_type = dns_type_flag(rtype)
+        rec = data_to_dns_record(record_type, data)
 
         self.lp = sambaopts.get_loadparm()
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
 
-        rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
-        if not rec_match:
-            raise CommandError('Record does not exist')
-
         del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
-        del_rec_buf.rec = rec_match
+        del_rec_buf.rec = rec
+
+        try:
+            dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+                                         0,
+                                         server,
+                                         zone,
+                                         name,
+                                         None,
+                                         del_rec_buf)
+        except WERRORError as e:
+            if e.args[1] == 'WERR_DNS_ERROR_NAME_DOES_NOT_EXIST':
+                self.outf.write('Zone does not exist; record could not be deleted.\n')
+            raise e
 
-        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
-                                        0,
-                                        server,
-                                        zone,
-                                        name,
-                                        None,
-                                        del_rec_buf)
         self.outf.write('Record deleted successfully\n')