7082285 /usr/sbin/installadm-convert dumps traceback with IndexError code
authorHarold N Shaw- Oracle <Harold.Shaw@oracle.COM>
Fri, 02 Sep 2011 14:41:51 -0600
changeset 1452 b7fef0a4f803
parent 1451 9b3261795610
child 1453 dc760d706d10
7082285 /usr/sbin/installadm-convert dumps traceback with IndexError code
usr/src/cmd/installadm/installadm-convert.py
--- a/usr/src/cmd/installadm/installadm-convert.py	Fri Sep 02 12:45:02 2011 -0700
+++ b/usr/src/cmd/installadm/installadm-convert.py	Fri Sep 02 14:41:51 2011 -0600
@@ -130,49 +130,90 @@
         return socket.inet_ntoa(struct.pack('L', ipaddr))
 
     @staticmethod
+    def next_in_range(cur_ipaddr, last_ipaddr):
+        """
+        Return true if the ipaddr is the next in the range of IP addresses
+        whose last IP address is currently defined by last_ipaddr
+
+        This function treats addresses in the network as Class C.  The
+        first 3 octets are treated as the network bits and the last octet is
+        treated as the host bits.  That is not true but it does simplify the
+        processing. It is legal to have a range of addresses such as
+        192.168.12.240-192.168.13.32.  This is treated as 2 ranges
+        (192.168.12.240-192.168.12.254) and (192.168.13.0-192.168.13.32).
+        """
+        # Set up a regular expression to pull the last tuple from an IP
+        regexp = re.compile("^(\d{1,3}\.\d{1,3}\.\d{1,3})\.(\d{1,3})$")
+
+        # Break the IP address into two string values 
+        m = regexp.match(cur_ipaddr)
+        if m is None:
+            raise SUNDHCPData.DHCPError("generate_ip_ranges: bad IP "
+                                        "format [%s]" % cur_ipaddr)
+
+        cur_network_octet = m.group(1)
+        cur_host_octet = m.group(2)
+
+        # Break the IP address into two string values; 
+        m = regexp.match(last_ipaddr)
+        if m is None:
+            raise SUNDHCPData.DHCPError("generate_ip_ranges: bad IP "
+                           "format [%s]" % last_ipaddr)
+
+        last_network_octet = m.group(1)
+        last_host_octet = m.group(2)
+
+        if cur_network_octet != last_network_octet or \
+            int(cur_host_octet) != int(last_host_octet) + 1:
+
+            return False
+
+        return True
+
+    @staticmethod
     def generate_ip_ranges(clients):
         """
         Generate the set of ip ranges from the list of clients
+        passed into this method.  The list of clients will be those
+        returned by the call to 'pntadm -P <network>'. The set of networks
+        is generated by calling 'pntadm -L'.  This method is called once for
+        each network.
+        The output will be a list of dictionaries of the form:
+            [{'nextserver':<IP addr>, 'loaddr':<IP addr>, 'hiaddr':<IP addr>}]
+
+        The output of this method is used to generate the ISC DHCP range
+        values in the subnet stanzas.
         """
         ranges = list()
-        in_range = False
-        last_ip_tuple = -2
-
-        # Set up a regular expression to pull the last tuple from an IP
-        regexp = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.(\d{1,3})$")
+        last_addr = None
+        start_addr = None
 
         # Get a sorted list of the ip addresses by unpacking, sorting, and
         # then returning it to its original form
         sorted_clients = map(SUNDHCPData._pack_addr,
             sorted([SUNDHCPData._unpack_addr(client) for \
             client in clients['Client IP']]))
-        last_addr = ''
-        start_addr = ''
-        for client_addr in sorted_clients:
-            # Create a list of dictionaries each containing the range and the
-            # server IP for that range
-            m = regexp.match(client_addr)
-            if m is None:
-                raise SUNDHCPData.SUNDHCPError("generate_ip_ranges: bad IP "
-                                               "format [%s]" % client_addr)
 
-            client_ip_tuple = m.group(1)
-            # Is this tuple part of the current range
-            if int(client_ip_tuple) != int(last_ip_tuple) + 1:
-                if in_range:
-                    ranges.append({'nextserver': clients['Server IP'][0],
-                                  'loaddr': start_addr, 'hiaddr': last_addr})
-                    in_range = False
+        # Create a list of dictionaries each containing a range of
+        # consecutive IP addresses in the DHCP network table and the
+        # server IP for that range
+        for client_addr in sorted_clients:
+            # if first time throught the loop - init the range start
+            if start_addr is None:
                 start_addr = client_addr
-            else:
-                in_range = True
+            elif not SUNDHCPData.next_in_range(client_addr, last_addr):
+                # if not then create range list entry and reset the start
+                # value for the range
+                ranges.append({'nextserver': clients['Server IP'][0],
+                              'loaddr': start_addr, 'hiaddr': last_addr})
+                start_addr = client_addr
 
+            # This is now the last IP address in the range
             last_addr = client_addr
-            last_ip_tuple = client_ip_tuple
 
-        if in_range:
-            ranges.append({'nextserver': clients['Server IP'][0],
-                          'loaddr': start_addr, 'hiaddr': last_addr})
+        # Create 'range' list entry with any remaining addresses
+        ranges.append({'nextserver': clients['Server IP'][0],
+                      'loaddr': start_addr, 'hiaddr': last_addr})
 
         return ranges
 
@@ -1739,7 +1780,7 @@
             for subnet_range in macros[mname]['ip_ranges']:
                 try:
                     config_file.write(dhcp.CFGFILE_SUBNET_RANGE_STRING %
-                                  subnet_range + "\n")
+                                      subnet_range)
                 except KeyError:
                     if not cfg_error_found:
                         print DHCP_ERR