6996539 Convert AI to use ipadm instead of ifconfig
authornirmal27<Nirmal.Agarwal@oracle.com>
Mon, 23 Apr 2012 21:42:14 -0600
changeset 1648 34cd5dab176b
parent 1647 026affedb710
child 1649 7dc7a57d562a
6996539 Convert AI to use ipadm instead of ifconfig
usr/src/cmd/auto-install/ai_get_manifest.py
usr/src/cmd/installadm/installadm-common.sh
--- a/usr/src/cmd/auto-install/ai_get_manifest.py	Mon Apr 23 13:28:43 2012 -0700
+++ b/usr/src/cmd/auto-install/ai_get_manifest.py	Mon Apr 23 21:42:14 2012 -0600
@@ -37,6 +37,7 @@
 from subprocess import Popen, PIPE
 import re
 import sys
+from struct import pack
 import tempfile
 import time
 import traceback
@@ -52,6 +53,10 @@
 
 AI_MANIFEST_ATTACHMENT_NAME = 'manifest.xml'  # named as MIME attachment
 
+# Network commands
+IPADM = "/usr/sbin/ipadm"
+DLADM = "/usr/sbin/dladm"
+
 
 class AILog:
     """
@@ -368,44 +373,31 @@
         #
         # Obtain network interface name, which will be queried in next
         # step in order to obtain required network parameters
-        #
-        # Search for the first interface, which is UP - omit loopback
-        # interfaces. Then use ifconfig for query the information about
-        # that interface and store the result.
-        #
-        cmd = "/usr/sbin/ifconfig -au | /usr/bin/grep '[0-9]:' " \
-            "| /usr/bin/grep -v 'LOOPBACK'"
-        AICriteriaNetworkInterface.network_iface, ret = ai_exec_cmd(cmd)
+        # 
+        # get name, class and active property of all network interfaces
+        # Select the 1st interface whose class is 'ip' and is active.
+        cmd = IPADM + " show-if -o ifname,class,active -p"
+
+        output, ret = ai_exec_cmd(cmd)
 
-        if ret != 0:
-            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
-                          "Could not obtain name of valid network interface")
-            AICriteriaNetworkInterface.network_iface = None
-        else:
-            AICriteriaNetworkInterface.network_iface = \
-                AICriteriaNetworkInterface.network_iface.split(':')[0]
+        if not ret:
+            for ifprop in output.splitlines():
+                # check for presence of all values
+                if ifprop.count(":") != 2:
+                    continue
+                ifname, ifclass, ifstate = ifprop.split(":")
+                if ifclass == 'ip' and ifstate == 'yes':
+                    AICriteriaNetworkInterface.network_iface = ifname
+                    break
 
+        if AICriteriaNetworkInterface.network_iface:
             AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
                           "Network interface obtained: %s",
                           AICriteriaNetworkInterface.network_iface)
-
-            #
-            # Collect all available information about network interface
-            #
-            cmd = "/usr/sbin/ifconfig %s" % \
-                AICriteriaNetworkInterface.network_iface
-
-            AICriteriaNetworkInterface.ifconfig_iface_info, ret = \
-                ai_exec_cmd(cmd)
-
-            if ret != 0 or \
-               AICriteriaNetworkInterface.ifconfig_iface_info == "":
-                AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
-                              "Could not obtain information about "
-                              "network interface %s",
-                              AICriteriaNetworkInterface.network_iface)
-
-                AICriteriaNetworkInterface.ifconfig_iface_info = None
+        else:
+            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
+                          "Could not obtain name of valid network interface "
+                          "name")
 
 
 class AICriteriaMAC(AICriteriaNetworkInterface):
@@ -426,49 +418,27 @@
 
         AICriteriaMAC.client_mac_initialized = True
 
-        if AICriteriaNetworkInterface.ifconfig_iface_info is None:
-            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
-                          "Could not obtain MAC address")
-        else:
-            AICriteriaMAC.client_mac = AICriteriaNetworkInterface. \
-                ifconfig_iface_info.split("ether", 1)
+        if AICriteriaNetworkInterface.network_iface:
 
-            if len(AICriteriaMAC.client_mac) < 2:
-                AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
-                              "Could not obtain client MAC address")
-                AICriteriaMAC.client_mac = None
-            else:
-                AICriteriaMAC.client_mac = AICriteriaMAC.\
-                    client_mac[1].strip().split()[0].strip()
+            # use dladm to get the mac information
+            cmd = (DLADM + " show-linkprop -p mac-address -co value " +
+                    AICriteriaNetworkInterface.network_iface)
+
+            output, ret = ai_exec_cmd(cmd)
 
-                #
-                # remove ':' and pad with '0's
-                #
-                # This step makes sure that the criteria are
-                # passed to the server in the format which
-                # server can understand. This is just an interim
-                # solution.
-                #
-                # For longer term, all criteria should be
-                # passed to the server in native format letting
-                # the server side control the process of
-                # conversion.
-                #
+            if not ret:
+                parts = output.strip("\n").split(":")
+                # set mac address if it is formatted properly
+                if len(parts) == 6:
+                    AICriteriaMAC.client_mac = ''.join([val.zfill(2)
+                                                       for val in parts])
+                    AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
+                                  "Client MAC address: %s",
+                                  AICriteriaMAC.client_mac)
 
-                client_mac_parts = \
-                    AICriteriaMAC.client_mac.split(":")
-
-                AICriteriaMAC.client_mac = "%s%s%s%s%s%s" % \
-                    (client_mac_parts[0].zfill(2),
-                     client_mac_parts[1].zfill(2),
-                     client_mac_parts[2].zfill(2),
-                     client_mac_parts[3].zfill(2),
-                     client_mac_parts[4].zfill(2),
-                     client_mac_parts[5].zfill(2))
-
-                AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
-                              "Client MAC address: %s",
-                              AICriteriaMAC.client_mac)
+        if not AICriteriaMAC.client_mac:
+            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
+                          "Could not obtain client MAC address")
 
         AICriteria.__init__(self, AICriteriaMAC.client_mac)
 
@@ -479,6 +449,7 @@
     """
 
     client_ip = None
+    client_ip_prefix = None
     client_ip_string = None
     client_ip_initialized = False
 
@@ -491,23 +462,31 @@
             return
 
         AICriteriaIP.client_ip_initialized = True
-        if AICriteriaNetworkInterface.ifconfig_iface_info == None:
-            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
-                          "Could not obtain IP address")
-        else:
-            AICriteriaIP.client_ip = AICriteriaNetworkInterface. \
-                ifconfig_iface_info.split("inet", 1)[1].strip().\
-                split()[0].strip()
+
+        if AICriteriaNetworkInterface.network_iface:
+            cmd = (IPADM + " show-addr -o ADDR -p " +
+                   AICriteriaNetworkInterface.network_iface)
+
+            output, ret = ai_exec_cmd(cmd)
+
+            if not ret:
+                if '/' in output:
+                    AICriteriaIP.client_ip, AICriteriaIP.client_ip_prefix = \
+                        output.strip("\n").split("/")
 
-            # remove '.'
-            ip_split = AICriteriaIP.client_ip.split('.')
-            AICriteriaIP.client_ip_string = "%03d%03d%03d%03d" % \
-                (int(ip_split[0]), int(ip_split[1]),
-                 int(ip_split[2]), int(ip_split[3]))
+                    ip_split = AICriteriaIP.client_ip.split(".")
+                    AICriteriaIP.client_ip_string = ''.join([val.zfill(3)
+                                                    for val in ip_split])
+                    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Client IP address: "
+                                  "%s", AICriteriaIP.client_ip_string)
+                    AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Network prefix: %s",
+                                  AICriteriaIP.client_ip_prefix)
 
-            AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
-                          "Client IP address: %s",
-                          AICriteriaIP.client_ip_string)
+        if not AICriteriaIP.client_ip_string:
+            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
+                          "Could not obtain network address")
+            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
+                          "Could not obtain network prefix")
 
         AICriteria.__init__(self, AICriteriaIP.client_ip_string)
 
@@ -531,47 +510,21 @@
 
         AICriteriaNetwork.client_net_initialized = True
 
-        if AICriteriaNetworkInterface.ifconfig_iface_info == None or \
-            AICriteriaIP.client_ip == None:
-            AIGM_LOG.post(AILog.AI_DBGLVL_ERR,
-                          "Could not obtain network address")
-        else:
-            # extract network mask
-            client_netmask = \
-                long(AICriteriaNetworkInterface.ifconfig_iface_info.
-                    split("netmask", 1)[1].strip().split()[0].strip(), 16)
+        if AICriteriaIP.client_ip_string and \
+           AICriteriaIP.client_ip_prefix:
 
-            # Translate IP address in string format to long
-            ip_part = AICriteriaIP.client_ip.split('.')
-            ip_long = long(ip_part[0]) << 24 | long(ip_part[1]) << \
-                16 | long(ip_part[2]) << 8 | long(ip_part[3])
-
-            client_network_long = ip_long & client_netmask
-
-            AIGM_LOG.post(AILog.AI_DBGLVL_INFO,
-                          "Mask: %08lX, IP: %08lX, Network: %08lX",
-                          client_netmask, ip_long, client_network_long)
+            # calculate netmask from ip prefix
+            bits = 0xffffffff ^ (1 << 32 -
+                                 int(AICriteriaIP.client_ip_prefix)) - 1
+            dotted_netmask = socket.inet_ntoa(pack('>I', bits))
 
-            AICriteriaNetwork.client_net_string = \
-                "%03ld%03ld%03ld%03ld" % \
-                (client_network_long >> 24,
-                 client_network_long >> 16 & 0xff,
-                 client_network_long >> 8 & 0xff,
-                 client_network_long & 0xff)
+            ip_parts = AICriteriaIP.client_ip.split(".")
+            netmask_parts = dotted_netmask.split(".")
+            AICriteriaNetwork.client_net = ".".join([str(int(i) & int(n))
+                for i, n in zip(ip_parts, netmask_parts)])
 
-            maskbits = 0
-            for shift in range(32):
-                if ((client_netmask >> shift) & 1):
-                    maskbits = 32 - shift
-                    break
-
-            AICriteriaNetwork.client_net = \
-                "%ld.%ld.%ld.%ld/%d" % \
-                (client_network_long >> 24,
-                 client_network_long >> 16 & 0xff,
-                 client_network_long >> 8 & 0xff,
-                 client_network_long & 0xff,
-                 maskbits)
+            AICriteriaNetwork.client_net_string = "".join([val.zfill(3)
+                for val in AICriteriaNetwork.client_net.split(".")])
 
             AIGM_LOG.post(AILog.AI_DBGLVL_INFO, "Client net: %s",
                           AICriteriaNetwork.client_net_string)
--- a/usr/src/cmd/installadm/installadm-common.sh	Mon Apr 23 13:28:43 2012 -0700
+++ b/usr/src/cmd/installadm/installadm-common.sh	Mon Apr 23 21:42:14 2012 -0600
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 #
 # Description:
 #       It contains common functions used by installadm subcommands
@@ -42,7 +42,7 @@
 GREP=/bin/grep
 HEAD=/bin/head
 HOSTNAME=/bin/hostname
-IFCONFIG=/usr/sbin/ifconfig
+IPADM=/usr/sbin/ipadm
 LN=/bin/ln
 MKDIR=/bin/mkdir
 MOUNT=/usr/sbin/mount
@@ -191,7 +191,7 @@
 
 	# Find the IP address(es) for the interface route(1) provided. Use
 	# ipadm(1) to look up interface addresses;
-	server_ip=$(/usr/sbin/ipadm show-addr -p -o ADDR ${interface}/ | \
+	server_ip=$($IPADM show-addr -p -o ADDR ${interface}/ | \
 		    $EGREP -v -- "$IPADM_GREP_STRING")
 
 	# see if interface has multiple VLANs
@@ -224,34 +224,6 @@
 }
 
 #
-# get_ip_netmask
-#
-# Purpose : Get the netmask set for the given IP address on the current host.
-#           Assumes IP address is currently set on an interface.
-#
-# Arguments :
-#	$1 - IP address
-#
-# Returns netmask in hexidecimal notation (e.g. ffffff00)
-#
-get_ip_netmask()
-{
-	ipaddr=$1
-
-	if [[ -z "$ipaddr" ]]; then
-		return
-	fi
-
-	$IFCONFIG -a | $GREP broadcast | $AWK '{print $2, $4}' | \
-		while read t_ipaddr t_netmask ; do
-			if [ "$t_ipaddr" = "$ipaddr" ]; then
-				print "$t_netmask"
-				break
-			fi
-		done
-}
-
-#
 # get_grub_title
 #
 # Purpose: Get the line used in the title line of the grub menu.
@@ -552,7 +524,7 @@
 
 	# get all addresses and
 	# remove <IPv6 | 127.0.0.1 | unconfigured DHCP interfaces>
-	interfaces=$(/usr/sbin/ipadm show-addr -p -o ADDR,STATE | \
+	interfaces=$($IPADM show-addr -p -o ADDR,STATE | \
 	    $EGREP -v "${IPADM_GREP_STRING}|^127.0.0.1" | \
 	    $EGREP -e ':ok$|:tentative$' | \
 	    $SED 's/:ok$//;s/:tentative$//')
@@ -888,128 +860,3 @@
 	print "${s_addr[0]}.${s_addr[1]}.${s_addr[2]}.${s_addr[3]}"
 	return
 }
-
-
-#
-# find_network_attr
-#
-# Purpose : Given an IP address, figure out which network on this
-#	    server it belongs to, or its netmask, depending on $2.
-#	    Workhorse function for find_network(), find_network_nmask() and
-#	    find_network_baseIP()
-#
-# Parameters :
-#	$1 - IP address
-#	$2 - what gets returned: one of "network", "netmask" or "netIPaddr"
-#		- "network" specifies that this function returns the network
-#			corresponding to the IP address (IP addr & netmask)
-#		- "netmask" specifies that this function returns the netmask
-#			of the network corresponding to the IP address
-#		- "netIPaddr" specifies that this function returns the base IP
-#			address of the network corresponding to the IP address
-# Returns :
-#	Network for IP address passed in.
-#
-find_network_attr()
-{
-	typeset ipaddr=$1
-	typeset attr=$2
-
-	if [[ -z "$ipaddr" ]] ; then
-		return
-	fi
-
-	# Iterate through the interfaces to figure what the possible
-	# networks are (in case this is a multi-homed server).
-	# For each network, use its netmask with the given IP address 
-	# to see if resulting network matches.
-	$IFCONFIG -a | $GREP broadcast | $AWK '{print $2, $4}' | \
-		while read t_ipaddr t_netmask ; do
-
-			# convert hex netmask into bits for CIDR notation
-			typeset bits
-			# 32 bits minus however many are masked out for hosts
-			((bits=32-log2(2**32-16#$t_netmask)))
-
-			# get network of this interface
-			if_network=$(calculate_net_addr ${t_ipaddr}/$bits)
-			if [[ -z $if_network ]]; then
-				continue
-			fi
-
-			# get network for passed in ipaddr based
-			# on this interfaces's netmask
-			ip_network=$(calculate_net_addr ${ipaddr}/$bits)
-			if [[ -z $ip_network ]]; then
-				continue
-			fi
-
-			# if networks match, this is the network that
-			# the passed in ipaddr belongs to.
-			if [ "$if_network" = "$ip_network" ] ; then
-				case $attr in
-					"network" )
-						print "$if_network"
-						;;
-					"netmask" )
-						print "$t_netmask"
-						;;
-					"netIPaddr" )
-						print "$t_ipaddr"
-						;;
-				esac
-				break
-			fi
-		done
-}
-
-#
-# find_network
-#
-# Purpose : Given an IP address, figure out which network on this
-#	    server it belongs to.
-#
-# Parameters :
-#	$1 - IP address
-#
-# Returns :
-#	Network for IP address passed in.
-#
-find_network()
-{
-	print $(find_network_attr $1 "network")
-}
-
-#
-# find_network_nmask()
-#
-# Purpose : Given an IP address, figure out which network on this server it
-#	belongs to, and return that network's netmask.
-#
-# Parameters :
-#	$1 - IP address
-#
-# Returns :
-#	Netmask for IP address passed in.
-#
-find_network_nmask()
-{
-	print $(find_network_attr $1 "netmask")
-}
-
-#
-# find_network_baseIP()
-#
-# Purpose : Given an IP address, figure out which network on this server it
-#	belongs to, and return that network's base IP address.
-#
-# Parameters :
-#	$1 - IP address
-#
-# Returns :
-#	Netmask for IP address passed in.
-#
-find_network_baseIP()
-{
-	print $(find_network_attr $1 "netIPaddr")
-}