Source0:       opnfv-apex-common.tar.gz
 
 BuildArch:     noarch
-BuildRequires: python-docutils
+BuildRequires: python-docutils python34-devel
 Requires:      openstack-tripleo opnfv-apex-sdn opnfv-apex-undercloud openvswitch qemu-kvm bridge-utils libguestfs-tools
-Requires:      initscripts net-tools iputils iproute iptables
+Requires:      initscripts net-tools iputils iproute iptables python34
 
 %description
 Scripts for OPNFV deployment using RDO Manager
 mkdir -p %{buildroot}%{_var}/opt/opnfv/lib/
 install lib/common-functions.sh %{buildroot}%{_var}/opt/opnfv/lib/
 install lib/utility-functions.sh %{buildroot}%{_var}/opt/opnfv/lib/
+mkdir -p %{buildroot}%{python3_sitelib}/apex/
+install lib/python/apex/__init__.py %{buildroot}%{python3_sitelib}/apex/
+install lib/python/apex/ip_utils.py %{buildroot}%{python3_sitelib}/apex/
 mkdir -p %{buildroot}%{_var}/opt/opnfv/lib/installer/onos/
 install lib/installer/onos/onos_gw_mac_update.sh %{buildroot}%{_var}/opt/opnfv/lib/installer/onos/
 
 %attr(755,root,root) %{_bindir}/opnfv-util
 %{_var}/opt/opnfv/lib/common-functions.sh
 %{_var}/opt/opnfv/lib/utility-functions.sh
+%{python3_sitelib}/apex/ip_utils.py
+%{python3_sitelib}/apex/__init__.py
+%{python3_sitelib}/apex/__pycache__/*
 %{_var}/opt/opnfv/lib/installer/onos/onos_gw_mac_update.sh
 %{_sysconfdir}/opnfv-apex/os-nosdn-nofeature-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-odl_l2-nofeature-ha.yaml
 %doc %{_docdir}/opnfv/inventory.yaml.example
 
 %changelog
+* Fri Apr 15 2016 Feng Pan <fpan@redhat.com> - 3.0-2
+- Adds python ip utility lib.
 * Mon Apr 11 2016 Tim Rozet <trozet@redhat.com> - 3.0-1
 - adding opnfv-util
 * Mon Apr 04 2016 Dan Radez <dradez@redhat.com> - 3.0-0
 
     fi
 fi
 
+# Make sure python is installed
+if ! rpm -q python34-devel > /dev/null; then
+    sudo yum install -y epel-release
+    if ! sudo yum install -y python34-devel; then
+        echo "Failed to install python34-devel package..."
+        exit 1
+    fi
+fi
+
 # Execute make against targets
 for t in $MAKE_TARGETS; do
     run_make $t
 
 # Common Functions used by  OPNFV Apex
 # author: Tim Rozet (trozet@redhat.com)
 
+#python ip_gen command
+ip_gen="python3.4 -B -m apex.ip_utils generate_ip_range"
+
 ##converts subnet mask to prefix
 ##params: subnet mask
 function prefix2mask {
 }
 
 ##generates usable IP range in correct format based on CIDR
-##assumes the first 20 IPs are used (by undercloud or otherwise)
+##A block of 20 IP addresses are reserved at beginning of address space.
+##A block of 22 IP addresses are reserved at end of address space, this includes
+##the broadcast IP address.
+##In a /24 IPv4 CIDR, this results in .1-20 as as .234-255 being excluded.
 ##params: cidr
 function generate_usable_ip_range {
-  local first_ip first_block_ip last_block_ip
-  #first_ip=$(ipcalc  -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  first_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  first_ip=$(increment_ip ${first_ip} 1)
-  first_block_ip=$(increment_ip ${first_ip} 20)
-  #last_block_ip=$(ipcalc  -nb $1 | grep HostMax: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  last_block_ip=$(ipcalc -nmpb $1 | grep BROADCAST= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  last_block_ip=$(subtract_ip ${last_block_ip} 1)
-  if [[ -z "$first_block_ip" || -z "$last_block_ip" ]]; then
+  if [ -z "$1" ]; then
     return 1
-  else
-    last_block_ip=$(subtract_ip ${last_block_ip} 21)
-    echo "${first_block_ip},${last_block_ip}"
   fi
+  echo $($ip_gen $1 21 -23)
 }
 
+
 ##find the undercloud IP address
 ##finds first usable IP on subnet
 ##params: interface
 ##generates undercloud IP address based on CIDR
 ##params: cidr
 function generate_provisioner_ip {
-  local provisioner_ip
-  #provisioner_ip=$(ipcalc  -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  provisioner_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  if [ -z "$provisioner_ip" ]; then
+  if [ -z "$1" ]; then
     return 1
   fi
-  provisioner_ip=$(increment_ip ${provisioner_ip} 1)
-  echo "$provisioner_ip"
+  echo $($ip_gen $1 1 1)
 }
 
+
 ##finds the dhcp range available via interface
 ##uses first 8 IPs, after 2nd IP
 ##params: interface
 ##uses first 8 IPs, after 1st IP
 ##params: cidr
 function generate_dhcp_range {
-  local dhcp_range_start dhcp_range_end first_ip
-  #first_ip=$(ipcalc  -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  first_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  if [ -z "$first_ip" ]; then
+  if [ -z "$1" ]; then
     return 1
   fi
-  first_ip=$(increment_ip ${first_ip} 1)
-  dhcp_range_start=$(increment_ip ${first_ip} 1)
-  dhcp_range_end=$(increment_ip ${dhcp_range_start} 8)
-  echo "${dhcp_range_start},${dhcp_range_end}"
+  echo $($ip_gen $1 2 10)
 }
 
 ##finds the introspection range available via interface
 ##uses 8 IPs, after the first 10 IPs
 ##params: cidr
 function generate_introspection_range {
-  local inspect_range_start inspect_range_end first_ip
-  #first_ip=$(ipcalc  -nb $1 | grep HostMin: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  first_ip=$(ipcalc -nmpb $1 | grep NETWORK= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  if [ -z "$first_ip" ]; then
+  if [ -z "$1" ]; then
     return 1
   fi
-  first_ip=$(increment_ip ${first_ip} 1)
-  inspect_range_start=$(increment_ip ${first_ip} 10)
-  inspect_range_end=$(increment_ip ${inspect_range_start} 8)
-  echo "${inspect_range_start},${inspect_range_end}"
+  echo $($ip_gen $1 11 19)
 }
 
 ##finds the floating ip range available via interface
 }
 
 ##generate the floating range available via CIDR
-##uses last 20 IPs of subnet, minus last IP
+##uses last 20 IPs of subnet, minus last 2 IPs.
+##In a /24 IPv4 CIDR, this would result in floating ip range of .234-253
 ##params: cidr
 function generate_floating_ip_range {
-  local float_range_start float_range_end last_ip
-  #last_ip=$(ipcalc  -nb $1 | grep HostMax: | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  last_ip=$(ipcalc -nmpb $1 | grep BROADCAST= | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+")
-  if [ -z "$last_ip" ]; then
+  if [ -z "$1" ]; then
     return 1
   fi
-  last_ip=$(subtract_ip ${last_ip} 2)
-  float_range_start=$(subtract_ip ${last_ip} 19)
-  float_range_end=${last_ip}
-  echo "${float_range_start},${float_range_end}"
+  echo $($ip_gen $1 -22 -3)
 }
 
 ##attach interface to OVS and set the network config correctly
 
--- /dev/null
+##############################################################################
+# Copyright (c) 2016 Feng Pan (fpan@redhat.com) and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
 
--- /dev/null
+
+##############################################################################
+# Copyright (c) 2016 Feng Pan (fpan@redhat.com) and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+
+import ipaddress
+
+
+def generate_ip_range(args):
+    """
+    Generate IP range in string format for given CIDR.
+    This function works for both IPv4 and IPv6.
+
+    args is expected to contain the following members:
+    CIDR: any valid CIDR representation.
+    start_position: starting index, default to first address in subnet (1)
+    end_position:  ending index, default to last address in subnet (-1)
+
+    Returns IP range in string format. A single IP is returned if start and end IPs are identical.
+    """
+    cidr = ipaddress.ip_network(args.CIDR)
+    (start_index, end_index) = (args.start_position, args.end_position)
+    if cidr[start_index] == cidr[end_index]:
+        return str(cidr[start_index])
+    else:
+        return ','.join(sorted([str(cidr[start_index]), str(cidr[end_index])]))
+
+
+def main():
+    import argparse
+    import sys
+
+    parser = argparse.ArgumentParser()
+    subparsers = parser.add_subparsers()
+
+    parser_gen_ip_range = subparsers.add_parser('generate_ip_range', help='Generate IP Range given CIDR')
+    parser_gen_ip_range.add_argument('CIDR', help='Network in CIDR notation')
+    parser_gen_ip_range.add_argument('start_position', type=int, help='Starting index')
+    parser_gen_ip_range.add_argument('end_position', type=int, help='Ending index')
+    parser_gen_ip_range.set_defaults(func=generate_ip_range)
+
+    args = parser.parse_args(sys.argv[1:])
+    print(args.func(args))
+
+
+if __name__ == '__main__':
+    main()
+