aboutsummaryrefslogtreecommitdiffstats
path: root/resources/tools/testbed-setup/cimc/cimclib.py
diff options
context:
space:
mode:
authorPeter Mikus <pmikus@cisco.com>2019-02-23 16:27:07 +0000
committerPeter Mikus <pmikus@cisco.com>2019-05-22 09:30:11 +0000
commit04ea580e111ddf5be6101be1fbfe9fde56f1a214 (patch)
tree09247ed50f1da5e09b79dcf41a05b38afeaa4ee2 /resources/tools/testbed-setup/cimc/cimclib.py
parentc6cd03e08d9429168b0e183b8dcbce991112f279 (diff)
Ansible: Add CIMC/IPMI/COBBLER
- added tasks and handlers for CIMC, IPMI, COBBLER - allows provisioning of servers via COBBLER Change-Id: I64080069260dabb8a6e3b648aeff12f109d3f7c2 Signed-off-by: Peter Mikus <pmikus@cisco.com>
Diffstat (limited to 'resources/tools/testbed-setup/cimc/cimclib.py')
-rw-r--r--resources/tools/testbed-setup/cimc/cimclib.py414
1 files changed, 0 insertions, 414 deletions
diff --git a/resources/tools/testbed-setup/cimc/cimclib.py b/resources/tools/testbed-setup/cimc/cimclib.py
deleted file mode 100644
index f91832e0c9..0000000000
--- a/resources/tools/testbed-setup/cimc/cimclib.py
+++ /dev/null
@@ -1,414 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 Cisco and/or its affiliates.
-# 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.
-
-import requests
-import xml.etree.ElementTree as et
-import re
-
-from requests.packages.urllib3.exceptions import InsecureRequestWarning
-requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
-
-BASEDN = "sys/rack-unit-1"
-
-###
-### Helper function - iterate through a list in pairs
-###
-def chunks(lst, chunksize):
- """Yield successive n-sized chunks from l."""
- for i in range(0, len(lst), chunksize):
- yield lst[i:i+chunksize]
-
-###
-### Helper function: Perform an XML request to CIMC
-###
-def xml_req(ip, xml, debug=False):
- if debug:
- print "DEBUG: XML-REQUEST:"
- et.dump(xml)
- headers = {'Content-Type': 'text/xml'}
- req = requests.post('https://' + ip + '/nuova', headers=headers,
- verify=False, data=et.tostring(xml))
- resp = et.fromstring(req.content)
- if debug:
- print "DEBUG: XML-RESPONSE:"
- et.dump(resp)
-
- if resp.tag == 'error':
- if debug:
- print "XML response contains error:"
- et.dump(error)
- raise RuntimeError('XML response contains error')
- return resp
-
-###
-### Authenticate (Log-In) to CIMC and obtain a cookie
-###
-def login(ip, username, password):
- reqxml = et.Element('aaaLogin',
- attrib={'inName':username, 'inPassword':password})
- respxml = xml_req(ip, reqxml)
- try:
- cookie = respxml.attrib['outCookie']
- except:
- print "Cannot find cookie in CIMC server response."
- print "CIMC server output:"
- et.dump(respxml)
- raise
-
- return cookie
-
-###
-### Log out from CIMC.
-###
-### Note: There is a maximum session limit in CIMC and sessions to take a long
-### time (10 minutes) to time out. Therefore, calling this function during
-### testing is essential, otherwise one will quickly exhaust all available
-### sessions.
-###
-def logout(ip, cookie):
- reqxml = et.Element('aaaLogout', attrib={'cookie': cookie,
- 'inCookie': cookie})
- xml_req(ip, reqxml)
-
-###
-### Power off the host
-###
-def powerOff(ip, cookie, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': BASEDN})
- inconfig = et.SubElement(reqxml, 'inConfig')
- et.SubElement(inconfig, 'computeRackUnit',
- attrib={'adminPower': 'down', 'dn': BASEDN})
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-###
-### Power on the host
-###
-def powerOn(ip, cookie, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': BASEDN})
- inconfig = et.SubElement(reqxml, 'inConfig')
- et.SubElement(inconfig, 'computeRackUnit',
- attrib={'adminPower': 'up', 'dn': BASEDN})
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-###
-### Restore BIOS to default settings
-###
-def restoreBiosDefaultSettings(ip, cookie, debug=False):
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'biosPlatformDefaults'})
- respxml = xml_req(ip, reqxml, debug)
-
- configs = respxml.find('outConfigs')
- defaults = configs.find('biosPlatformDefaults')
-
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'dn': "{}/bios/bios-settings".format(BASEDN)})
- inconfig = et.SubElement(reqxml, 'inConfig')
- biosset = et.SubElement(inconfig, 'biosSettings')
- biosset.extend(defaults)
-
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-###
-### Apply specified BIOS settings.
-###
-### These must be a list of strings in XML format. Not currently very
-### user friendly. Format can either be obtained from CIMC
-### documention, or by setting them manually and then fetching
-### BIOS settings via CIMC XML API.
-###
-def setBiosSettings(ip, cookie, settings, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'dn': "{}/bios/bios-settings".format(BASEDN)})
- inconfig = et.SubElement(reqxml, 'inConfig')
- biosset = et.SubElement(inconfig, 'biosSettings')
- print "Applying settings:"
- print settings
- for s in settings:
- x = et.fromstring(s)
- et.dump(x)
- biosset.append(et.fromstring(s))
-
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-###
-### Delete any existing virtual drives
-###
-### WARNING: THIS WILL ERASE ALL DATA ON ALL DISKS, WITHOUT ANY CONFIRMATION
-### QUESTION.
-###
-### The server must be POWERED ON for this to succeed.
-###
-def deleteAllVirtualDrives(ip, cookie, debug=False):
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'storageController'})
- respxml = xml_req(ip, reqxml, debug)
-
- configs = respxml.find('outConfigs')
- for sc in configs.iter('storageController'):
- if debug:
- print "DEBUG: SC DN {} ID {}".format(sc.attrib['dn'],
- sc.attrib['id'])
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'dn': sc.attrib['dn']})
- inconfig = et.SubElement(reqxml, 'inConfig')
- et.SubElement(inconfig, 'storageController',
- attrib={'adminAction': 'delete-all-vds-reset-pds',
- 'dn': sc.attrib['dn']})
- xml_req(ip, reqxml, debug)
-
-###
-### Create a single RAID-10 across all drives.
-###
-### The server must be POWERED ON for this to succeed.
-###
-def createRaid10_all(ip, cookie, debug=False):
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'storageController'})
- respxml = xml_req(ip, reqxml, debug)
-
- configs = respxml.find('outConfigs')
- for sc in configs.iter('storageController'):
- if debug:
- print "DEBUG: SC DN {} ID {}".format(sc.attrib['dn'],
- sc.attrib['id'])
- #
- # Find disk size and number of disks
- #
- disks = []
- total_size = 0
- for pd in sc.iter('storageLocalDisk'):
- if debug:
- print "DEBUG: PD {} size {}".format(pd.attrib['id'],
- pd.attrib['coercedSize'])
- disks.append(pd.attrib['id'])
- total_size += int(pd.attrib['coercedSize'].split(' ')[0])
-
- #
- # Create a RAID10 array of all available disks, as in:
- # [1,2][3,4][5,6][7,8][9,10][11,12][13,14][15,16][17,18]
- #
- raid_size = total_size/2
- raid_span = ''
- for p in list(chunks(disks, 2)):
- raid_span += "[{},{}]".format(p[0], p[1])
-
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'dn': sc.attrib['dn']})
- inconfig = et.SubElement(reqxml, 'inConfig')
- et.SubElement(inconfig,
- 'storageVirtualDriveCreatorUsingUnusedPhysicalDrive',
- attrib={'virtualDriveName': 'raid10-all',
- 'size': str(raid_size)+' MB',
- 'raidLevel': '10', 'driveGroup': raid_span,
- 'adminState': 'trigger'})
-
- xml_req(ip, reqxml, debug)
-
-###
-### Create a single RAID across from empty drives as provided.
-###
-### The server must be POWERED ON for this to succeed.
-###
-def createRaid(ip, cookie, name, raidlevel, size, drives, debug=False):
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'storageController'})
- respxml = xml_req(ip, reqxml, debug)
-
- configs = respxml.find('outConfigs')
- for sc in configs.iter('storageController'):
- if debug:
- print "DEBUG: SC DN {} ID {}".format(sc.attrib['dn'],
- sc.attrib['id'])
-
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'dn': sc.attrib['dn']})
- inconfig = et.SubElement(reqxml, 'inConfig')
- et.SubElement(inconfig,
- 'storageVirtualDriveCreatorUsingUnusedPhysicalDrive',
- attrib={'virtualDriveName': name,
- 'size': str(size)+' MB',
- 'raidLevel': raidlevel,
- 'driveGroup': drives,
- 'adminState': 'trigger'})
-
- xml_req(ip, reqxml, debug)
-
-###
-### Enable Serial-Over-LAN (SOL) console and redirect BIOS output to
-### serial console
-###
-def enableConsoleRedir(ip, cookie, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': "{}/bios/bios-settings".format(BASEDN)})
- inconfig = et.SubElement(reqxml, 'inConfig')
- bs = et.SubElement(inconfig, 'biosSettings',
- attrib={'dn': "{}/bios/bios-settings".format(BASEDN)})
- et.SubElement(bs,
- 'biosVfConsoleRedirection',
- attrib={'vpConsoleRedirection': 'com-0',
- 'vpBaudRate': '115200'})
- respxml = xml_req(ip, reqxml, debug)
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': BASEDN+'/sol-if'})
- inconfig = et.SubElement(reqxml, 'inConfig')
- et.SubElement(inconfig, 'solIf',
- attrib={'dn': BASEDN+'/sol-if', 'adminState': 'enable',
- 'speed': '115200', 'comport': 'com0'})
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-###
-### Boot into UEFI bootloader (we may use this to "park" the host in
-### powered-on state)
-###
-def bootIntoUefi(ip, cookie, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': BASEDN+'/boot-policy'})
- inconfig = et.SubElement(reqxml, 'inConfig')
- bootDef = et.SubElement(inconfig, 'lsbootDef',
- attrib={'dn': BASEDN+'/boot-policy',
- 'rebootOnUpdate': 'yes'})
- et.SubElement(bootDef, 'lsbootEfi',
- attrib={'rn': 'efi-read-only', 'order': '1',
- 'type': 'efi'})
-
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-###
-### Boot via PXE. Reboot immediately.
-###
-def bootPXE(ip, cookie, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': BASEDN+'/boot-policy'})
- inconfig = et.SubElement(reqxml, 'inConfig')
- bootDef = et.SubElement(inconfig, 'lsbootDef',
- attrib={'dn': BASEDN+'/boot-policy',
- 'rebootOnUpdate': 'yes'})
- et.SubElement(bootDef, 'lsbootLan',
- attrib={'rn': 'lan-read-only', 'order': '1',
- 'type': 'lan', 'prot': 'pxe'})
-
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-
-###
-### Boot via Local HDD first, then via PXE. Do not reboot immediately.
-###
-def bootHDDPXE(ip, cookie, debug=False):
- reqxml = et.Element('configConfMo',
- attrib={'cookie': cookie, 'inHierarchical': 'false',
- 'dn': BASEDN+'/boot-policy'})
- inconfig = et.SubElement(reqxml, 'inConfig')
- bootDef = et.SubElement(inconfig, 'lsbootDef',
- attrib={'dn': BASEDN+'/boot-policy',
- 'rebootOnUpdate': 'no'})
- storage = et.SubElement(bootDef, 'lsbootStorage',
- attrib={'rn': 'storage-read-write',
- 'access': 'read-write',
- 'order': '1', 'type': 'storage'})
- et.SubElement(storage, 'lsbootLocalStorage',
- attrib={'rn': 'local-storage'})
- et.SubElement(bootDef, 'lsbootLan',
- attrib={'rn': 'lan-read-only', 'order': '2',
- 'type': 'lan', 'prot': 'pxe'})
-
- respxml = xml_req(ip, reqxml, debug)
- return respxml
-
-###
-### Return LOM port 1 MAC address
-###
-def getLOMMacAddress(ip, cookie, debug=False):
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'networkAdapterUnit'})
- respxml = xml_req(ip, reqxml, debug)
- reqxml = et.Element('configResolveDn',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'dn': BASEDN+'/network-adapter-L/eth-1'})
- respxml = xml_req(ip, reqxml, debug)
-
- oc = respxml.find('outConfig')
- netw = oc.find('networkAdapterEthIf')
- if debug:
- print "DEBUG: MAC address is {}".format(netw.get('mac'))
- return netw.get('mac')
-
-###
-### Return all port MAC addresses
-###
-def getMacAddresses(ip, cookie, debug=False):
- maclist = {}
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'networkAdapterUnit'})
- respxml = xml_req(ip, reqxml, debug)
- oc = respxml.find('outConfigs')
- for adapter in oc.iter('networkAdapterUnit'):
- if debug:
- print "DEBUG: ADAPTER SLOT {} MODEL {}".format(adapter.attrib['slot'],
- adapter.attrib['model'])
- slot = adapter.attrib['slot']
- maclist[slot] = {}
- for port in adapter.iter('networkAdapterEthIf'):
- if debug:
- print "DEBUG: SLOT {} PORT {} MAC {}".format(slot,
- port.attrib['id'],
- port.attrib['mac'])
- maclist[slot][port.attrib['id']] = port.attrib['mac'].lower()
-
- reqxml = et.Element('configResolveClass',
- attrib={'cookie': cookie, 'inHierarchical': 'true',
- 'classId': 'adaptorUnit'})
- respxml = xml_req(ip, reqxml, debug)
- oc = respxml.find('outConfigs')
- for adapter in oc.iter('adaptorUnit'):
- if debug:
- print "DEBUG: VIC ADAPTER SLOT {} MODEL {}".format(adapter.attrib['pciSlot'],
- adapter.attrib['model'])
- slot = adapter.attrib['pciSlot']
- maclist[slot] = {}
- for port in adapter.iter('adaptorHostEthIf'):
- portnum = int(re.sub('eth([0-9]+)', '\\1', port.attrib['name']))+1
- if debug:
- print "DEBUG: VIC SLOT {} PORT {} MAC {}".format(slot,
- portnum,
- port.attrib['mac'])
- maclist[slot][portnum] = port.attrib['mac'].lower()
-
- return maclist