Merge "Script for reconfiguring UCS network"
[releng.git] / utils / lab-reconfiguration / reconfigUcsNet.py
1 #!/usr/bin/python
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #  http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 # This script reconfigure UCSM vnics for varios OPNFV deployers
15 # Usage: reconfigUcsNet.py [options]
16 #
17 # Options:
18 # -h, --help            show this help message and exit
19 # -i IP, --ip=IP        [Mandatory] UCSM IP Address
20 # -u USERNAME, --username=USERNAME
21 #                       [Mandatory] Account Username for UCSM Login
22 # -p PASSWORD, --password=PASSWORD
23 #                       [Mandatory] Account Password for UCSM Login
24 # -f FILE, --file=FILE
25 #                       [Optional] Yaml file with network config you want to set for POD
26 #                       If not present only current network config will be printed
27 #
28
29 import getpass
30 import optparse
31 import platform
32 import yaml
33 from UcsSdk import *
34 from collections import defaultdict
35
36
37 def getpassword(prompt):
38     if platform.system() == "Linux":
39         return getpass.unix_getpass(prompt=prompt)
40     elif platform.system() == "Windows" or platform.system() == "Microsoft":
41         return getpass.win_getpass(prompt=prompt)
42     else:
43         return getpass.getpass(prompt=prompt)
44
45
46 def get_servers(handle=None):
47     """
48     Return list of servers
49     """
50     orgObj = handle.GetManagedObject(None, OrgOrg.ClassId(), {OrgOrg.DN : "org-root"})[0]
51     servers = handle.GetManagedObject(orgObj, LsServer.ClassId())
52     for server in servers:
53         if server.Type == 'instance' and "POD-2" in server.Dn:
54             yield server
55
56 def get_vnics(handle=None, server=None):
57     """
58     Return list of vnics for given server
59     """
60     vnics = handle.ConfigResolveChildren(VnicEther.ClassId(), server.Dn, None, YesOrNo.TRUE)
61     return vnics.OutConfigs.GetChild()
62
63
64 def get_network_config(handle=None):
65     """
66     Print current network config
67     """
68     print "\nCURRENT NETWORK CONFIG:"
69     for server in get_servers(handle):
70         print ' {}'.format(server.Name)
71         for vnic in get_vnics(handle, server):
72             print '  {}'.format(vnic.Name)
73             print '   {}'.format(vnic.Addr)
74             vnicIfs = handle.ConfigResolveChildren(VnicEtherIf.ClassId(), vnic.Dn, None, YesOrNo.TRUE)
75             for vnicIf in vnicIfs.OutConfigs.GetChild():
76                 print '    Vlan: {}'.format(vnicIf.Vnet)
77
78
79 def add_interface(handle=None, lsServerDn=None, vnicEther=None, templName=None, order=None):
80     """
81     Add interface to server specified by server.DN name
82     """
83     print " Adding interface: {}, template: {}, server.Dn: {}".format(vnicEther, templName, lsServerDn)
84     obj = handle.GetManagedObject(None, LsServer.ClassId(), {LsServer.DN:lsServerDn})
85     vnicEtherDn = lsServerDn + "/ether-" + vnicEther
86     params = {
87         VnicEther.STATS_POLICY_NAME: "default",
88         VnicEther.NAME: vnicEther,
89         VnicEther.DN: vnicEtherDn,
90         VnicEther.SWITCH_ID: "A-B",
91         VnicEther.ORDER: order,
92         "adminHostPort": "ANY",
93         VnicEther.ADMIN_VCON: "any",
94         VnicEther.NW_TEMPL_NAME: templName,
95         VnicEther.MTU: "1500"}
96     handle.AddManagedObject(obj, VnicEther.ClassId(), params, True)
97
98
99 def remove_interface(handle=None, vnicEtherDn=None):
100     """
101     Remove interface specified by Distinguished Name (vnicEtherDn)
102     """
103     print " Removing interface: {}".format(vnicEtherDn)
104     obj = handle.GetManagedObject(None, VnicEther.ClassId(), {VnicEther.DN:vnicEtherDn})
105     handle.RemoveManagedObject(obj)
106
107
108 def read_yaml_file(yamlFile):
109     """
110     Read vnic config from yaml file
111     """
112     # TODO: add check if vnic templates specified in file exist on UCS
113     with open(yamlFile, 'r') as stream:
114         return yaml.load(stream)
115
116
117 def set_network(handle=None, yamlFile=None):
118     """
119     Configure VLANs on POD according specified network
120     """
121     # add interfaces and bind them with vNIC templates
122     # TODO: make sure MAC address for admin is still same
123     print "\nRECONFIGURING VNICs..."
124     network = read_yaml_file(yamlFile)
125     for server in get_servers(handle):
126         for iface, data in network.iteritems():
127             add_interface(handle, server.Dn, iface, data['template'], data['order'])
128         # Remove other interfaces which have not assigned required vnic template
129         vnics = get_vnics(handle, server)
130         for vnic in vnics:
131             if not any(data['template'] in vnic.OperNwTemplName for iface, data in network.iteritems()):
132                 remove_interface(handle, vnic.Dn)
133                 print "  {} removed, template: {}".format(vnic.Name, vnic.OperNwTemplName)
134
135
136 if __name__ == "__main__":
137     # Latest urllib2 validate certs by default
138     # The process wide "revert to the old behaviour" hook is to monkeypatch the ssl module
139     # https://bugs.python.org/issue22417
140     import ssl
141     if hasattr(ssl, '_create_unverified_context'):
142         ssl._create_default_https_context = ssl._create_unverified_context
143     try:
144         handle = UcsHandle()
145         parser = optparse.OptionParser()
146         parser.add_option('-i', '--ip',dest="ip",
147                         help="[Mandatory] UCSM IP Address")
148         parser.add_option('-u', '--username',dest="userName",
149                         help="[Mandatory] Account Username for UCSM Login")
150         parser.add_option('-p', '--password',dest="password",
151                         help="[Mandatory] Account Password for UCSM Login")
152         parser.add_option('-f', '--file',dest="yamlFile",
153                         help="[Optional] Yaml file contains network config you want to set on UCS POD1")
154         (options, args) = parser.parse_args()
155
156         if not options.ip:
157             parser.print_help()
158             parser.error("Provide UCSM IP Address")
159         if not options.userName:
160             parser.print_help()
161             parser.error("Provide UCSM UserName")
162         if not options.password:
163             options.password=getpassword("UCSM Password:")
164
165         handle.Login(options.ip, options.userName, options.password)
166
167         if (options.yamlFile != None):
168             print options.yamlFile
169             set_network(handle, options.yamlFile)
170         get_network_config(handle)
171
172         handle.Logout()
173
174     except Exception, err:
175         handle.Logout()
176         print "Exception:", str(err)
177         import traceback, sys
178         print '-'*60
179         traceback.print_exc(file=sys.stdout)
180         print '-'*60