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
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.
14 # This script reconfigure UCSM vnics for varios OPNFV deployers
15 # Usage: reconfigUcsNet.py [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
35 from collections import defaultdict
40 def getpassword(prompt):
41 if platform.system() == "Linux":
42 return getpass.unix_getpass(prompt=prompt)
43 elif platform.system() == "Windows" or platform.system() == "Microsoft":
44 return getpass.win_getpass(prompt=prompt)
46 return getpass.getpass(prompt=prompt)
49 def get_servers(handle=None):
51 Return list of servers
53 orgObj = handle.GetManagedObject(None, OrgOrg.ClassId(), {OrgOrg.DN : "org-root"})[0]
54 servers = handle.GetManagedObject(orgObj, LsServer.ClassId())
55 for server in servers:
56 if server.Type == 'instance' and POD_PREFIX in server.Dn:
60 def set_boot_policy(handle=None, server=None, policy=None):
62 Modify Boot policy of server
64 obj = handle.GetManagedObject(None, LsServer.ClassId(), {
65 LsServer.DN: server.Dn})
66 handle.SetManagedObject(obj, LsServer.ClassId(), {
67 LsServer.BOOT_POLICY_NAME: policy} )
68 print " Configured boot policy: {}".format(policy)
71 def ack_pending(handle=None, server=None):
73 Acknowledge pending state of server
75 handle.AddManagedObject(server, LsmaintAck.ClassId(), {
76 LsmaintAck.DN: server.Dn + "/ack",
78 LsmaintAck.ADMIN_STATE:"trigger-immediate",
79 LsmaintAck.SCHEDULER:"",
80 LsmaintAck.POLICY_OWNER:"local"}, True)
81 print " Pending-reboot -> Acknowledged."
84 def get_vnics(handle=None, server=None):
86 Return list of vnics for given server
88 vnics = handle.ConfigResolveChildren(VnicEther.ClassId(), server.Dn, None, YesOrNo.TRUE)
89 return vnics.OutConfigs.GetChild()
92 def get_network_config(handle=None):
94 Print current network config
96 print "\nCURRENT NETWORK CONFIG:"
97 print " d - default, t - tagged"
98 for server in get_servers(handle):
99 print ' {}'.format(server.Name)
100 print ' Boot policy: {}'.format(server.OperBootPolicyName)
101 for vnic in get_vnics(handle, server):
102 print ' {}'.format(vnic.Name)
103 print ' {}'.format(vnic.Addr)
104 vnicIfs = handle.ConfigResolveChildren(VnicEtherIf.ClassId(), vnic.Dn, None, YesOrNo.TRUE)
105 for vnicIf in vnicIfs.OutConfigs.GetChild():
106 if vnicIf.DefaultNet == 'yes':
107 print ' Vlan: {}d'.format(vnicIf.Vnet)
109 print ' Vlan: {}t'.format(vnicIf.Vnet)
112 def add_interface(handle=None, lsServerDn=None, vnicEther=None, templName=None, order=None, macAddr=None):
114 Add interface to server specified by server.DN name
116 print " Adding interface: {}, template: {}, server.Dn: {}".format(vnicEther, templName, lsServerDn)
117 obj = handle.GetManagedObject(None, LsServer.ClassId(), {LsServer.DN:lsServerDn})
118 vnicEtherDn = lsServerDn + "/ether-" + vnicEther
120 VnicEther.STATS_POLICY_NAME: "default",
121 VnicEther.NAME: vnicEther,
122 VnicEther.DN: vnicEtherDn,
123 VnicEther.SWITCH_ID: "A-B",
124 VnicEther.ORDER: order,
125 "adminHostPort": "ANY",
126 VnicEther.ADMIN_VCON: "any",
127 VnicEther.ADDR: macAddr,
128 VnicEther.NW_TEMPL_NAME: templName,
129 VnicEther.MTU: "1500"}
130 handle.AddManagedObject(obj, VnicEther.ClassId(), params, True)
133 def remove_interface(handle=None, vnicEtherDn=None):
135 Remove interface specified by Distinguished Name (vnicEtherDn)
137 print " Removing interface: {}".format(vnicEtherDn)
138 obj = handle.GetManagedObject(None, VnicEther.ClassId(), {VnicEther.DN:vnicEtherDn})
139 handle.RemoveManagedObject(obj)
142 def read_yaml_file(yamlFile):
144 Read vnic config from yaml file
146 # TODO: add check if vnic templates specified in file exist on UCS
147 with open(yamlFile, 'r') as stream:
148 return yaml.load(stream)
151 def set_network(handle=None, yamlFile=None):
153 Configure VLANs on POD according specified network
155 # add interfaces and bind them with vNIC templates
156 print "\nRECONFIGURING VNICs..."
157 pod_data = read_yaml_file(yamlFile)
158 network = pod_data['network']
160 for index, server in enumerate(get_servers(handle)):
161 # Assign template to interface
162 for iface, data in network.iteritems():
163 add_interface(handle, server.Dn, iface, data['template'], data['order'], data['mac-list'][index])
165 # Remove other interfaces which have not assigned required vnic template
166 vnics = get_vnics(handle, server)
168 if not any(data['template'] in vnic.OperNwTemplName for iface, data in network.iteritems()):
169 remove_interface(handle, vnic.Dn)
170 print " {} removed, template: {}".format(vnic.Name, vnic.OperNwTemplName)
172 # Set boot policy template
173 if not INSTALLER in server.Dn:
174 set_boot_policy(handle, server, pod_data['boot-policy'])
177 if __name__ == "__main__":
178 # Latest urllib2 validate certs by default
179 # The process wide "revert to the old behaviour" hook is to monkeypatch the ssl module
180 # https://bugs.python.org/issue22417
182 if hasattr(ssl, '_create_unverified_context'):
183 ssl._create_default_https_context = ssl._create_unverified_context
186 parser = optparse.OptionParser()
187 parser.add_option('-i', '--ip',dest="ip",
188 help="[Mandatory] UCSM IP Address")
189 parser.add_option('-u', '--username',dest="userName",
190 help="[Mandatory] Account Username for UCSM Login")
191 parser.add_option('-p', '--password',dest="password",
192 help="[Mandatory] Account Password for UCSM Login")
193 parser.add_option('-f', '--file',dest="yamlFile",
194 help="[Optional] Yaml file contains network config you want to set on UCS POD1")
195 (options, args) = parser.parse_args()
199 parser.error("Provide UCSM IP Address")
200 if not options.userName:
202 parser.error("Provide UCSM UserName")
203 if not options.password:
204 options.password=getpassword("UCSM Password:")
206 handle.Login(options.ip, options.userName, options.password)
208 # Change vnic template if specified in cli option
209 if (options.yamlFile != None):
210 set_network(handle, options.yamlFile)
213 print "\nWait until Overall Status of all nodes is OK..."
214 timeout = time.time() + 60*10 #10 minutes timeout
217 for server in get_servers(handle):
218 if server.OperState == "pending-reboot":
219 ack_pending(handle,server)
220 list_of_states.append(server.OperState)
221 print " {}, {} seconds remains.".format(list_of_states, round(timeout-time.time()))
222 if all(state == "ok" for state in list_of_states):
224 if time.time() > timeout:
225 raise Exception("Timeout reached while waiting for OK status.")
228 # Show current vnic MACs and VLANs
229 get_network_config(handle)
233 except Exception, err:
235 print "Exception:", str(err)
236 import traceback, sys
238 traceback.print_exc(file=sys.stdout)