Add acknowledgment of reboot if needed
[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 import time
34 from UcsSdk import *
35 from collections import defaultdict
36
37
38 def getpassword(prompt):
39     if platform.system() == "Linux":
40         return getpass.unix_getpass(prompt=prompt)
41     elif platform.system() == "Windows" or platform.system() == "Microsoft":
42         return getpass.win_getpass(prompt=prompt)
43     else:
44         return getpass.getpass(prompt=prompt)
45
46
47 def get_servers(handle=None):
48     """
49     Return list of servers
50     """
51     orgObj = handle.GetManagedObject(None, OrgOrg.ClassId(), {OrgOrg.DN : "org-root"})[0]
52     servers = handle.GetManagedObject(orgObj, LsServer.ClassId())
53     for server in servers:
54         if server.Type == 'instance' and "POD-2" in server.Dn:
55             yield server
56
57
58 def ack_pending(handle=None, server=None):
59     """
60     Acknowledge pending state of server
61     """
62     handle.AddManagedObject(server, LsmaintAck.ClassId(), {LsmaintAck.DN: server.Dn + "/ack", LsmaintAck.DESCR:"", LsmaintAck.ADMIN_STATE:"trigger-immediate", LsmaintAck.SCHEDULER:"", LsmaintAck.POLICY_OWNER:"local"}, True)
63
64
65 def get_vnics(handle=None, server=None):
66     """
67     Return list of vnics for given server
68     """
69     vnics = handle.ConfigResolveChildren(VnicEther.ClassId(), server.Dn, None, YesOrNo.TRUE)
70     return vnics.OutConfigs.GetChild()
71
72
73 def get_network_config(handle=None):
74     """
75     Print current network config
76     """
77     print "\nCURRENT NETWORK CONFIG:"
78     print " d - default, t - tagged"
79     for server in get_servers(handle):
80         print ' {}'.format(server.Name)
81         for vnic in get_vnics(handle, server):
82             print '  {}'.format(vnic.Name)
83             print '   {}'.format(vnic.Addr)
84             vnicIfs = handle.ConfigResolveChildren(VnicEtherIf.ClassId(), vnic.Dn, None, YesOrNo.TRUE)
85             for vnicIf in vnicIfs.OutConfigs.GetChild():
86                 if vnicIf.DefaultNet == 'yes':
87                     print '    Vlan: {}d'.format(vnicIf.Vnet)
88                 else:
89                     print '    Vlan: {}t'.format(vnicIf.Vnet)
90
91
92 def add_interface(handle=None, lsServerDn=None, vnicEther=None, templName=None, order=None, macAddr=None):
93     """
94     Add interface to server specified by server.DN name
95     """
96     print " Adding interface: {}, template: {}, server.Dn: {}".format(vnicEther, templName, lsServerDn)
97     obj = handle.GetManagedObject(None, LsServer.ClassId(), {LsServer.DN:lsServerDn})
98     vnicEtherDn = lsServerDn + "/ether-" + vnicEther
99     params = {
100         VnicEther.STATS_POLICY_NAME: "default",
101         VnicEther.NAME: vnicEther,
102         VnicEther.DN: vnicEtherDn,
103         VnicEther.SWITCH_ID: "A-B",
104         VnicEther.ORDER: order,
105         "adminHostPort": "ANY",
106         VnicEther.ADMIN_VCON: "any",
107         VnicEther.ADDR: macAddr,
108         VnicEther.NW_TEMPL_NAME: templName,
109         VnicEther.MTU: "1500"}
110     handle.AddManagedObject(obj, VnicEther.ClassId(), params, True)
111
112
113 def remove_interface(handle=None, vnicEtherDn=None):
114     """
115     Remove interface specified by Distinguished Name (vnicEtherDn)
116     """
117     print " Removing interface: {}".format(vnicEtherDn)
118     obj = handle.GetManagedObject(None, VnicEther.ClassId(), {VnicEther.DN:vnicEtherDn})
119     handle.RemoveManagedObject(obj)
120
121
122 def read_yaml_file(yamlFile):
123     """
124     Read vnic config from yaml file
125     """
126     # TODO: add check if vnic templates specified in file exist on UCS
127     with open(yamlFile, 'r') as stream:
128         return yaml.load(stream)
129
130
131 def set_network(handle=None, yamlFile=None):
132     """
133     Configure VLANs on POD according specified network
134     """
135     # add interfaces and bind them with vNIC templates
136     print "\nRECONFIGURING VNICs..."
137     network = read_yaml_file(yamlFile)
138     for index, server in enumerate(get_servers(handle)):
139         for iface, data in network.iteritems():
140             add_interface(handle, server.Dn, iface, data['template'], data['order'], data['mac-list'][index])
141         # Remove other interfaces which have not assigned required vnic template
142         vnics = get_vnics(handle, server)
143         for vnic in vnics:
144             if not any(data['template'] in vnic.OperNwTemplName for iface, data in network.iteritems()):
145                 remove_interface(handle, vnic.Dn)
146                 print "  {} removed, template: {}".format(vnic.Name, vnic.OperNwTemplName)
147
148
149 if __name__ == "__main__":
150     # Latest urllib2 validate certs by default
151     # The process wide "revert to the old behaviour" hook is to monkeypatch the ssl module
152     # https://bugs.python.org/issue22417
153     import ssl
154     if hasattr(ssl, '_create_unverified_context'):
155         ssl._create_default_https_context = ssl._create_unverified_context
156     try:
157         handle = UcsHandle()
158         parser = optparse.OptionParser()
159         parser.add_option('-i', '--ip',dest="ip",
160                         help="[Mandatory] UCSM IP Address")
161         parser.add_option('-u', '--username',dest="userName",
162                         help="[Mandatory] Account Username for UCSM Login")
163         parser.add_option('-p', '--password',dest="password",
164                         help="[Mandatory] Account Password for UCSM Login")
165         parser.add_option('-f', '--file',dest="yamlFile",
166                         help="[Optional] Yaml file contains network config you want to set on UCS POD1")
167         (options, args) = parser.parse_args()
168
169         if not options.ip:
170             parser.print_help()
171             parser.error("Provide UCSM IP Address")
172         if not options.userName:
173             parser.print_help()
174             parser.error("Provide UCSM UserName")
175         if not options.password:
176             options.password=getpassword("UCSM Password:")
177
178         handle.Login(options.ip, options.userName, options.password)
179
180         # Change vnic template if specified in cli option
181         if (options.yamlFile != None):
182             set_network(handle, options.yamlFile)
183
184         time.sleep(3)
185
186         print "\nCheck if acknowledge is needed..."
187         for server in get_servers(handle):
188             print " {}: {}".format(server.Dn, server.OperState)
189             if server.OperState == "pending-reboot":
190                 ack_pending(handle,server)
191                 print " Acknowledged."
192
193         print "\nWait until Overall Status of all nodes is OK..."
194         timeout = time.time() + 60*5   #5 minutes timeout
195         while True:
196             list_of_states = []
197             for server in get_servers(handle):
198                 list_of_states.append(server.OperState)
199             print " {}".format(list_of_states)
200             if all(state == "ok" for state in list_of_states) or time.time() > timeout:
201                 break
202             time.sleep(2)
203
204         # Show current vnic MACs and VLANs
205         get_network_config(handle)
206
207         handle.Logout()
208
209     except Exception, err:
210         handle.Logout()
211         print "Exception:", str(err)
212         import traceback, sys
213         print '-'*60
214         traceback.print_exc(file=sys.stdout)
215         print '-'*60