Script for reconfiguring UCS network 44/1044/3
authorPeter Bandzi <pbandzi@cisco.com>
Tue, 21 Jul 2015 14:31:40 +0000 (16:31 +0200)
committerPeter Bandzi <pbandzi@cisco.com>
Wed, 22 Jul 2015 08:00:04 +0000 (10:00 +0200)
Script will reconfigure POD-2 network for foreman or fuel
Networ is specified in yaml file.
Template must be created on UCS.

JIRA: OCTO-109

Change-Id: I375a387c7607eb5dea126812569d8e19fda0c5c0
Signed-off-by: Peter Bandzi <pbandzi@cisco.com>
utils/lab-reconfiguration/create_venv.sh [new file with mode: 0755]
utils/lab-reconfiguration/foreman.yaml [new file with mode: 0644]
utils/lab-reconfiguration/fuel.yaml [new file with mode: 0644]
utils/lab-reconfiguration/reconfigUcsNet.py [new file with mode: 0755]
utils/lab-reconfiguration/requirements.pip [new file with mode: 0644]

diff --git a/utils/lab-reconfiguration/create_venv.sh b/utils/lab-reconfiguration/create_venv.sh
new file mode 100755 (executable)
index 0000000..19d9b49
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash -e
+
+# Script checks that venv exists. If it doesn't it will be created
+# It requires python2.7 and virtualenv packages installed
+
+BASEDIR=`dirname $0`
+
+function venv_install() {
+    if command -v virtualenv-2.7; then
+        virtualenv-2.7 $1
+    elif command -v virtualenv2; then
+        virtualenv2 $1
+    elif command -v virtualenv; then
+        virtualenv $1
+    else
+        echo Cannot find virtualenv command.
+        return 1
+    fi
+}
+
+# exit when something goes wrong during venv install
+set -e
+if [ ! -d "$BASEDIR/venv" ]; then
+    venv_install $BASEDIR/venv
+    echo "Virtualenv created."
+fi
+
+if [ ! -f "$BASEDIR/venv/updated" -o $BASEDIR/requirements.pip -nt $BASEDIR/venv/updated ]; then
+    source $BASEDIR/venv/bin/activate
+    pip install -r $BASEDIR/requirements.pip
+    touch $BASEDIR/venv/updated
+    echo "Requirements installed."
+    deactivate
+fi
+set +e
diff --git a/utils/lab-reconfiguration/foreman.yaml b/utils/lab-reconfiguration/foreman.yaml
new file mode 100644 (file)
index 0000000..ad91ba9
--- /dev/null
@@ -0,0 +1,14 @@
+# Vnic configuration for foreman deploy
+
+eth0:
+    order: 1
+    template: foreman-control
+eth1:
+    order: 2
+    template: foreman-private
+eth2:
+    order: 3
+    template: foreman-public
+eth3:
+    order: 4
+    template: foreman-storage
diff --git a/utils/lab-reconfiguration/fuel.yaml b/utils/lab-reconfiguration/fuel.yaml
new file mode 100644 (file)
index 0000000..3f31939
--- /dev/null
@@ -0,0 +1,8 @@
+# Vnic configuration for fuel deploy
+
+eth0:
+    order: 1
+    template: fuel-public
+eth1:
+    order: 2
+    template: fuel-tagged
diff --git a/utils/lab-reconfiguration/reconfigUcsNet.py b/utils/lab-reconfiguration/reconfigUcsNet.py
new file mode 100755 (executable)
index 0000000..8adace0
--- /dev/null
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script reconfigure UCSM vnics for varios OPNFV deployers
+# Usage: reconfigUcsNet.py [options]
+#
+# Options:
+# -h, --help            show this help message and exit
+# -i IP, --ip=IP        [Mandatory] UCSM IP Address
+# -u USERNAME, --username=USERNAME
+#                       [Mandatory] Account Username for UCSM Login
+# -p PASSWORD, --password=PASSWORD
+#                       [Mandatory] Account Password for UCSM Login
+# -f FILE, --file=FILE
+#                       [Optional] Yaml file with network config you want to set for POD
+#                       If not present only current network config will be printed
+#
+
+import getpass
+import optparse
+import platform
+import yaml
+from UcsSdk import *
+from collections import defaultdict
+
+
+def getpassword(prompt):
+    if platform.system() == "Linux":
+        return getpass.unix_getpass(prompt=prompt)
+    elif platform.system() == "Windows" or platform.system() == "Microsoft":
+        return getpass.win_getpass(prompt=prompt)
+    else:
+        return getpass.getpass(prompt=prompt)
+
+
+def get_servers(handle=None):
+    """
+    Return list of servers
+    """
+    orgObj = handle.GetManagedObject(None, OrgOrg.ClassId(), {OrgOrg.DN : "org-root"})[0]
+    servers = handle.GetManagedObject(orgObj, LsServer.ClassId())
+    for server in servers:
+        if server.Type == 'instance' and "POD-2" in server.Dn:
+            yield server
+
+def get_vnics(handle=None, server=None):
+    """
+    Return list of vnics for given server
+    """
+    vnics = handle.ConfigResolveChildren(VnicEther.ClassId(), server.Dn, None, YesOrNo.TRUE)
+    return vnics.OutConfigs.GetChild()
+
+
+def get_network_config(handle=None):
+    """
+    Print current network config
+    """
+    print "\nCURRENT NETWORK CONFIG:"
+    for server in get_servers(handle):
+        print ' {}'.format(server.Name)
+        for vnic in get_vnics(handle, server):
+            print '  {}'.format(vnic.Name)
+            print '   {}'.format(vnic.Addr)
+            vnicIfs = handle.ConfigResolveChildren(VnicEtherIf.ClassId(), vnic.Dn, None, YesOrNo.TRUE)
+            for vnicIf in vnicIfs.OutConfigs.GetChild():
+                print '    Vlan: {}'.format(vnicIf.Vnet)
+
+
+def add_interface(handle=None, lsServerDn=None, vnicEther=None, templName=None, order=None):
+    """
+    Add interface to server specified by server.DN name
+    """
+    print " Adding interface: {}, template: {}, server.Dn: {}".format(vnicEther, templName, lsServerDn)
+    obj = handle.GetManagedObject(None, LsServer.ClassId(), {LsServer.DN:lsServerDn})
+    vnicEtherDn = lsServerDn + "/ether-" + vnicEther
+    params = {
+        VnicEther.STATS_POLICY_NAME: "default",
+        VnicEther.NAME: vnicEther,
+        VnicEther.DN: vnicEtherDn,
+        VnicEther.SWITCH_ID: "A-B",
+        VnicEther.ORDER: order,
+        "adminHostPort": "ANY",
+        VnicEther.ADMIN_VCON: "any",
+        VnicEther.NW_TEMPL_NAME: templName,
+        VnicEther.MTU: "1500"}
+    handle.AddManagedObject(obj, VnicEther.ClassId(), params, True)
+
+
+def remove_interface(handle=None, vnicEtherDn=None):
+    """
+    Remove interface specified by Distinguished Name (vnicEtherDn)
+    """
+    print " Removing interface: {}".format(vnicEtherDn)
+    obj = handle.GetManagedObject(None, VnicEther.ClassId(), {VnicEther.DN:vnicEtherDn})
+    handle.RemoveManagedObject(obj)
+
+
+def read_yaml_file(yamlFile):
+    """
+    Read vnic config from yaml file
+    """
+    # TODO: add check if vnic templates specified in file exist on UCS
+    with open(yamlFile, 'r') as stream:
+        return yaml.load(stream)
+
+
+def set_network(handle=None, yamlFile=None):
+    """
+    Configure VLANs on POD according specified network
+    """
+    # add interfaces and bind them with vNIC templates
+    # TODO: make sure MAC address for admin is still same
+    print "\nRECONFIGURING VNICs..."
+    network = read_yaml_file(yamlFile)
+    for server in get_servers(handle):
+        for iface, data in network.iteritems():
+            add_interface(handle, server.Dn, iface, data['template'], data['order'])
+        # Remove other interfaces which have not assigned required vnic template
+        vnics = get_vnics(handle, server)
+        for vnic in vnics:
+            if not any(data['template'] in vnic.OperNwTemplName for iface, data in network.iteritems()):
+                remove_interface(handle, vnic.Dn)
+                print "  {} removed, template: {}".format(vnic.Name, vnic.OperNwTemplName)
+
+
+if __name__ == "__main__":
+    # Latest urllib2 validate certs by default
+    # The process wide "revert to the old behaviour" hook is to monkeypatch the ssl module
+    # https://bugs.python.org/issue22417
+    import ssl
+    if hasattr(ssl, '_create_unverified_context'):
+        ssl._create_default_https_context = ssl._create_unverified_context
+    try:
+        handle = UcsHandle()
+        parser = optparse.OptionParser()
+        parser.add_option('-i', '--ip',dest="ip",
+                        help="[Mandatory] UCSM IP Address")
+        parser.add_option('-u', '--username',dest="userName",
+                        help="[Mandatory] Account Username for UCSM Login")
+        parser.add_option('-p', '--password',dest="password",
+                        help="[Mandatory] Account Password for UCSM Login")
+        parser.add_option('-f', '--file',dest="yamlFile",
+                        help="[Optional] Yaml file contains network config you want to set on UCS POD1")
+        (options, args) = parser.parse_args()
+
+        if not options.ip:
+            parser.print_help()
+            parser.error("Provide UCSM IP Address")
+        if not options.userName:
+            parser.print_help()
+            parser.error("Provide UCSM UserName")
+        if not options.password:
+            options.password=getpassword("UCSM Password:")
+
+        handle.Login(options.ip, options.userName, options.password)
+
+        if (options.yamlFile != None):
+            print options.yamlFile
+            set_network(handle, options.yamlFile)
+        get_network_config(handle)
+
+        handle.Logout()
+
+    except Exception, err:
+        handle.Logout()
+        print "Exception:", str(err)
+        import traceback, sys
+        print '-'*60
+        traceback.print_exc(file=sys.stdout)
+        print '-'*60
diff --git a/utils/lab-reconfiguration/requirements.pip b/utils/lab-reconfiguration/requirements.pip
new file mode 100644 (file)
index 0000000..8cd1db0
--- /dev/null
@@ -0,0 +1,2 @@
+UcsSdk==0.8.2.2
+PyYAML