Пример #1
1
def test_imc_context_manager_no_timeout():
    try:
        import ConfigParser
    except:
        import configparser as ConfigParser

    from imcsdk.imchandle import ImcHandle
    from ..connection import info

    host = 'imc'
    config = ConfigParser.RawConfigParser()
    config.read(info.CONNECTION_CFG_FILEPATH)
    hostname = config.get(host, "hostname")
    username = config.get(host, "username")
    password = config.get(host, "password")

    handle = ImcHandle(hostname, username, password)
    with handle:
        server_dn = get_server_dn(handle)
        mo = handle.query_dn(server_dn, timeout=600)
        usr_lbl = "test-lbl2"
        mo.usr_lbl = usr_lbl
        handle.set_mo(mo, timeout=600)
        mo = handle.query_dn(server_dn)

    assert_equal(mo.usr_lbl, usr_lbl)
Пример #2
0
def test_imc_context_manager_no_timeout():
    try:
        import ConfigParser
    except:
        import configparser as ConfigParser

    from imcsdk.imchandle import ImcHandle
    from ..connection import info

    host = 'imc'
    config = ConfigParser.RawConfigParser()
    config.read(info.CONNECTION_CFG_FILEPATH)
    hostname = config.get(host, "hostname")
    username = config.get(host, "username")
    password = config.get(host, "password")

    handle = ImcHandle(hostname, username, password)
    with handle:
        server_dn = get_server_dn(handle)
        mo = handle.query_dn(server_dn, timeout=600)
        usr_lbl = "test-lbl2"
        mo.usr_lbl = usr_lbl
        handle.set_mo(mo, timeout=600)
        mo = handle.query_dn(server_dn)

    assert_equal(mo.usr_lbl, usr_lbl)
Пример #3
0
def reboot(cimc_ip, cimc_user, cimc_password):
    handle = ImcHandle(cimc_ip, cimc_user, cimc_password)
    handle.login(auto_refresh=False)
    mo = handle.config_resolve_dn("sys/rack-unit-1")
    mo.admin_power = ComputeRackUnit.ADMIN_POWER_BMC_RESET_IMMEDIATE
    try:
        handle.set_mo(mo)
        # handle.set_imc_managedobject(
        #     mo, class_id="ComputeRackUnit",
        #     params={
        #         ComputeRackUnit.ADMIN_POWER:
        #             ComputeRackUnit.CONST_ADMIN_POWER_BMC_RESET_IMMEDIATE,
        #         ComputeRackUnit.DN: "sys/rack-unit-1"})
    except Exception as e:
        print(e)
Пример #4
0
def update_snmp():
    """ Update IMC SNMP and Trap Destination """
    handle = ImcHandle(IMC_HOST, IMC_USER, IMC_PASS)
    handle.login()

    imc_snmp = handle.query_dn('sys/svc-ext/snmp-svc')
    imc_snmp.admin_state = 'enabled'
    imc_snmp.community = 'public'
    handle.set_mo(imc_snmp)

    imc_snmp_trap_dest = handle.query_dn('sys/svc-ext/snmp-svc/snmp-trap-1')
    imc_snmp_trap_dest.admin_state = 'enabled'
    imc_snmp_trap_dest.hostname = '10.10.10.10'
    imc_snmp_trap_dest.version = 'v2c'
    handle.set_mo(imc_snmp_trap_dest)

    handle.logout()
Пример #5
0
        handle.login()

        from imcsdk.mometa.storage.StorageVirtualDriveCreatorUsingUnusedPhysicalDrive import StorageVirtualDriveCreatorUsingUnusedPhysicalDrive

        for raid_params in settings_file['raid_config']:
            print "Create virtual drive %s with RAID level %s" % (
                raid_params['drive_name'], raid_params['raid_level'])
            mo = StorageVirtualDriveCreatorUsingUnusedPhysicalDrive(
                parent_mo_or_dn=raid_params['dn'],
                virtual_drive_name=raid_params['drive_name'],
                raid_level=raid_params['raid_level'],
                size=raid_params['size'],
                drive_group=raid_params['drive_group'],
                write_policy="Write Through",
                admin_state="trigger")
            handle.set_mo(mo)

            if raid_params['boot_drive'] == 'yes':
                print "Set virtual drive %s as boot drive" % raid_params[
                    'drive_name']
                from imcsdk.mometa.storage.StorageVirtualDrive import StorageVirtualDrive
                mo = StorageVirtualDrive(parent_mo_or_dn=raid_params['dn'],
                                         id="0",
                                         admin_action="set-boot-drive")
                handle.set_mo(mo)
        handle.logout()
        pause = raw_input('')

        # Redfish API operations
        # ----------------------
        # check CIMC fw version and update if not at desired version
from imcsdk.imchandle import ImcHandle

# Create a connection handle
handle = ImcHandle("192.168.1.23", "admin", "password")

# Create a connection handle
handle.login()

# Query for the NTP Server
imc_ntp_server_mo = handle.query_dn("sys/svc-ext/ntp-svc")

print "NTP config inicial: "
print imc_ntp_server_mo

# Set NTP Server parameters
imc_ntp_server_mo.ntp_enable = "yes"
imc_ntp_server_mo.ntp_server1 = "5.5.5.5"

# Commit the changes to the IMC
handle.set_mo(imc_ntp_server_mo)
print "NTP config applied"

# Verify changes applied
imc_ntp_server_mo = handle.query_dn("sys/svc-ext/ntp-svc")
print "NTP new config: "
print imc_ntp_server_mo

# Logout from the server
handle.logout()
Пример #7
0
class CimcServer(LabServer):
    RAID_0, RAID_1, RAID_10 = '0', '1', '10'

    def __init__(self, pod, dic):
        super(CimcServer, self).__init__(pod=pod, dic=dic)
        self._handle = None
        self._dump_xml = False
        self._logout_on_each_command = False

    def logger(self, message):
        self.log('CIMC ' + message)

    @property
    def handle(self):
        from imcsdk.imchandle import ImcHandle
        from urllib2 import URLError

        if self._handle is None:
            self._handle = ImcHandle(self.oob_ip, self.oob_username, self.oob_password)
            try:
                self._handle.login()
            except URLError as ex:
                raise RuntimeError('{}: {} {}'.format(self, ex, self.oob_ip))
        return self._handle

    def cimc_get_raid_battery_status(self):
        return self._handle.query_classid(class_id='storageRaidBattery')

    def _cimc_bios_lom(self, status):
        self.logger('{} all LOM'.format(status))
        actual = self._handle.query_classid(class_id='BiosVfLOMPortOptionROM')
        if actual.Status != status:
            params = {'Dn': 'sys/rack-unit-1/bios/bios-settings/LOMPort-OptionROM', 'VpLOMPortsAllState': status, 'vpLOMPort0State': status, 'vpLOMPort1State': status}
            self._handle.set_mo('set_imc_managedobject', in_mo=None, class_id='BiosVfLOMPortOptionROM', params=params)
            self.cimc_power_cycle()

    def cimc_enable_loms_in_bios(self):
        self._cimc_bios_lom(status='Enable')

    def cimc_disable_loms_in_bios(self):
        self._cimc_bios_lom(status='Disable')

    def cimc_list_all_nics(self):
        self.log('{} getting CIMC NICs'.format(self.oob_ip))
        r1 = self.handle.query_classid(class_id='networkAdapterEthIf')  # physical Intel NICs (or others in PCI-E slots)
        r2 = self.handle.query_classid(class_id='adaptorExtEthIf')  # physical Cisco VIC in MLOM

        return {x.dn: x.mac for x in r1 + r2}

    def cimc_list_all_nics_and_vnics(self):
        r1 = self.handle.query_classid(class_id='networkAdapterEthIf')  # physical Intel NICs (or others in PCI-E slots)
        r2 = self.handle.query_classid(class_id='adaptorExtEthIf')  # physical Cisco VIC in MLOM
        r3 = self.handle.query_classid(class_id='adaptorHostEthIf')  # virtual Cisco vNIC in MLOM

        return {x.dn: x.mac for x in r1 + r2 + r3}

    def cimc_list_pci_nic(self):
        r = self.handle.query_classid('networkAdapterUnit')
        return [{'Dn': x.Dn, 'Model': x.Model} for x in r]

    def cimc_list_vnics(self):
        ans1 = self.handle.query_classid('adaptorHostEthIf')
        ans2 = self.handle.query_classid('adaptorEthGenProfile')
        vnics = {x.Name: {'mac': x.Mac, 'uplink': x.UplinkPort, 'pci-slot': x.UsnicCount, 'dn': x.Dn, 'mtu': x.Mtu, 'name': x.Name, 'pxe-boot': x.PxeBoot} for x in ans1}
        vlans_dict = {x.Dn.replace('/general', ''): {'vlan': x.Vlan, 'vlan_mode': x.VlanMode} for x in ans2}
        for vnic in vnics.values():
            vlans = vlans_dict[vnic.get('dn')]
            vnic.update(vlans)
        return vnics

    def cimc_enable_sol(self):
        self.logger('enabling SOL')
        params = {'dn': 'sys/rack-unit-1/sol-if', 'adminState': 'enable', 'speed': '115200'}
        self.cimc_set_mo_by_class_id(class_id='solIf', params=params)

    def create_storage(self, raid=RAID_1, disks_needed=2, clean_vds=False):
        """

        :param clean_vds: Clean all virtual drives before creating any
        :param raid: Please select from '0','1','10','5','6'
        :param disks_needed: Number of disks needed
        :return:
        """
        if raid not in [self.RAID_0, self.RAID_1, self.RAID_10]:
            raise ValueError('RAID request is not correct. Use one of the {0}. Got: {1}'.format(','.join([self.RAID_0, self.RAID_1, self.RAID_10]), raid))
        
        virtual_drives_list = self.handle.query_classid(class_id='storageVirtualDrive')
        if virtual_drives_list:
            if clean_vds:
                self.logger('Cleaning Virtual Drives to create new one.')
                for vd in virtual_drives_list:
                    self.handle.remove_mo(vd)
            else:
                self.logger('Virtual Drive already exists.')
                return
        disks = self.handle.query_classid('storageLocalDisk')
        # get 2 or more disks to form RAID
        disks_by_size = {}
        map(lambda x: disks_by_size.setdefault(x.get_attr('CoercedSize'), []).append(x), disks)
        available_disks = filter(lambda x: len(disks_by_size[x]) > disks_needed, disks_by_size.keys())
        if len(available_disks) == 0:
            raise Exception('Not enough disks to build RAID {0}. Minimum required are {1}.'.format(raid, disks_needed))
        size = available_disks[0]
        drive_group = ','.join(map(lambda x: x.Id, disks_by_size[size])[:disks_needed])

        params = {'raidLevel': raid, 'size': size, 'virtualDriveName': "RAID", 'dn': "sys/rack-unit-1/board/storage-SAS-SLOT-HBA/virtual-drive-create",
                  'driveGroup': '[{0}]'.format(drive_group), 'adminState': 'trigger', 'writePolicy': 'Write Through'}
        self.logger('Creating Virtual Drive RAID {0}. Using storage {0}'.format(raid, drive_group))
        self.cimc_set_mo_by_class_id(class_id="storageVirtualDriveCreatorUsingUnusedPhysicalDrive", params=params)

    def cimc_delete_all_vnics(self):
        self.logger('deleting all vNICs')
        vnic_names = self.cimc_list_vnics().keys()
        for vnic_name in vnic_names:
            self.cimc_delete_vnic(vnic_name=vnic_name)

    def cimc_delete_vnic(self, vnic_name):
        dn = 'sys/rack-unit-1/adaptor-MLOM/host-eth-{}'.format(vnic_name)
        if 'eth0' in vnic_name or 'eth1' in vnic_name:  # no way to delete eth0 or eth1, so reset them to default
            self.logger(message='Resetting vNIC ' + vnic_name)
            ethX = self.handle.query_dn(dn)
            ethX.mac = 'AUTO'
            ethX.mtu = 1500
            ethX.pxe_boot = False
            ethX.uplink_port = vnic_name[-1]
            self.handle.set_mo(ethX)

            profile = self.handle.query_dn('sys/rack-unit-1/adaptor-{}/host-eth-{}/general'.format(pci_slot_id, name))
            profile.vlan = None
            profile.order = 'ANY'
            self.handle.set_mo(profile)
        else:
            self.logger(message='Deleting vNIC ' + dn)
            vnic = self.handle.query_dn(dn=dn)
            self.handle.remove_mo(vnic)

    def cimc_set_ssh_timeout(self, timeout=3600):
        self.cmd('set_imc_managedobject', in_mo=None, class_id='commHttps', params={'Dn': 'sys/svc-ext/https-svc', 'sessionTimeout': str(timeout)})

    def cimc_change_boot_order(self, pxe_order=1, hdd_order=2):
        self.logger('updating boot order: PXE as #{0}, HDD as #{1}'.format(pxe_order, hdd_order))
        boot_configs = [{'params': {'Dn': 'sys/rack-unit-1/boot-policy/lan-read-only', 'Order': pxe_order, 'Access': 'read-only'}, 'class_id': 'LsbootLan'},
                        {'params': {'Dn': 'sys/rack-unit-1/boot-policy/storage-read-write', 'Order': hdd_order, 'Access': 'read-write'}, 'class_id': 'LsbootStorage'}]
        for boot_config in boot_configs:
            boot_device = self.cmd('get_imc_managedobject', in_mo=None, class_id=None, params={'Dn': boot_config['params']['Dn']})
            if boot_device:
                self.cmd('set_imc_managedobject', in_mo=boot_device, class_id=None, params=boot_config['params'])
            else:
                self.cmd('add_imc_managedobject', in_mo=None, class_id=boot_config['class_id'], params=boot_config['params'])

    def cimc_create_vnic(self, pci_slot_id, uplink_port, order, name, mac, vlan, is_pxe_enabled):
        from imcsdk.mometa.adaptor.AdaptorHostEthIf import AdaptorHostEthIf

        self.logger(message='creating vNIC {} on PCI id {} uplink {} mac={} vlan={} pxe: {}'.format(name, pci_slot_id, uplink_port, mac, vlan, is_pxe_enabled))
        if name in ['eth0', 'eth1']:  # eth0 and eth1 are default, only possible to modify there parameters, no way to rename ot delete
            ethX = self.handle.query_dn('sys/rack-unit-1/adaptor-{}/host-eth-{}'.format(pci_slot_id, name))
            ethX.mac = mac
            ethX.mtu = 1500
            ethX.pxe_boot = is_pxe_enabled
            self.handle.set_mo(ethX)
        else:
            vnic = AdaptorHostEthIf(parent_mo_or_dn='sys/rack-unit-1/adaptor-' + pci_slot_id,
                                    name=name, mac=mac,
                                    mtu=1500, pxe_boot=is_pxe_enabled, uplink_port=uplink_port)
            self.handle.add_mo(vnic)
        profile = self.handle.query_dn('sys/rack-unit-1/adaptor-{}/host-eth-{}/general'.format(pci_slot_id, name))
        profile.vlan = vlan
        profile.order = order
        self.handle.set_mo(profile)

    def cimc_get_power_status(self):
        return self.handle.query_classid('computeRackUnit')[0].get_attr('OperPower')

    def _cimc_power(self, requested_state):
        import time

        self.logger('power {0}'.format(requested_state))
        rack = self.handle.query_dn('sys/rack-unit-1')
        rack.admin_power = requested_state
        self.handle.set_mo(rack)
        time.sleep(120)  # wait for the server to come up

    def cimc_power_down(self):
        current_power_state = self.cimc_get_power_status()
        if current_power_state == 'on':
            self._cimc_power('down')
        else:
            self.log(' is already OFF')

    def cimc_power_up(self):
        current_power_state = self.cimc_get_power_status()
        if current_power_state == 'off':
            self._cimc_power('up')
        else:
            self.log(' is already ON')

    def cimc_reset(self):
        pass
        # from ImcSdk.ImcMos import ComputeRackUnit

        # mo = handle.config_resolve_dn("sys/rack-unit-1")

        # mo.admin_power = ComputeRackUnit.CONST_ADMIN_POWER_BMC_RESET_IMMEDIATE
        # set_imc_managedobject(mo, class_id="ComputeRackUnit", params={ComputeRackUnit.ADMIN_POWER:
        #                                                 ComputeRackUnit.CONST_ADMIN_POWER_BMC_RESET_IMMEDIATE,
        #                                             ComputeRackUnit.DN: "sys/rack-unit-1"})

    def cimc_power_cycle(self):
        current_power_state = self.cimc_get_power_status()
        self._cimc_power('up' if current_power_state == 'off' else 'cycle-immediate')

    def cimc_recreate_vnics(self):
        actual_vnics = self.cimc_list_all_nics_and_vnics()
        actual_loms = [x for x in self.cimc_list_pci_nic_ports() if 'L' in x['Dn']]

        for nic_order, nic in enumerate(self.lom_nics_dic.values()):  # NIC order starts from 0
            names = nic.get_names()
            macs = nic.get_macs()
            port_ids = nic.get_port_ids()
            for name, mac, port_id in zip(names, macs, port_ids):
                if port_id in ['LOM-1', 'LOM-2']:
                    actual_mac = actual_loms[port_id]['mac']
                    if mac.upper() != actual_mac.upper():
                        raise ValueError('{}: "{}" actual mac is "{}" while requested "{}". Edit lab config!'.format(self.id, port_id, actual_mac, mac))
                else:
                    if 'eth' not in self.get_nics() and nic.is_ssh():  # if no NIC called eth and it's nic on ssh network, use default eth0, eth1
                        if name in actual_vnics:
                            self.cimc_delete_vnic(vnic_name=name)
                        name = 'eth' + name[-1]
                    if name in actual_vnics:
                        if mac == actual_vnics[name]['mac'] and str(nic.get_vlan_id()) == str(actual_vnics[name]['vlan']):  # this nic is already in CIMC
                            self.logger(message='vNIC {} is already configured'.format(name))
                            if name in actual_vnics:
                                actual_vnics.pop(name)
                            continue
                        else:
                            self.logger('deleting {} since mac or vlan is not correct: {}'.format(name, actual_vnics[name]))
                            self.cimc_delete_vnic(vnic_name=name)
                    pci_slot_id, uplink_port = port_id.split('/')
                    self.cimc_create_vnic(pci_slot_id=pci_slot_id, uplink_port=uplink_port, order='ANY', name=name, mac=mac, vlan=nic.get_vlan_id(), is_pxe_enabled=nic.is_pxe())
                    if name in actual_vnics:
                        actual_vnics.pop(name)
        for vnic_name in actual_vnics.keys():  # delete all actual which are not requested
            self.cimc_delete_vnic(vnic_name)

    def cimc_configure(self, is_debug=False):
        self._dump_xml = is_debug
        lab_type = self.pod.get_type()
        self.logger('configuring for {}'.format(lab_type))
        self.cimc_set_hostname()
        self.cimc_power_up()
        if self.pod.get_type() == self.pod.MERCURY:
            self.cimc_disable_loms_in_bios()
        else:
            is_any_nic_on_lom = any(map(lambda x: x.is_on_lom(), self.get_nics().values()))
            if is_any_nic_on_lom:
                self.cimc_enable_loms_in_bios()
            self.cimc_recreate_vnics()
            self.cimc_change_boot_order(pxe_order=1, hdd_order=2)
        # if lab_type == self.lab().LAB_MERCURY:
        #    self.create_storage('1', 2, True)

    def cimc_get_adaptors(self):
        r = self.handle.query_classid('AdaptorUnit')
        return r

    def cimc_set_mlom_adaptor(self, pci_slot, n_vnics):
        self.logger(message='allowing MLOM-{} to use up to {} vNICs'.format(pci_slot, n_vnics))
        # self.cimc_set_mo_by_class_id(class_id='adaptorUnit', params={'dn': 'sys/rack-unit-1/adaptor-{0}'.format(pci_slot), 'description': str(self)})
        self.cimc_set_mo_by_class_id(class_id='adaptorGenProfile', params={'dn': 'sys/rack-unit-1/adaptor-{0}/general'.format(pci_slot), 'fipMode': 'enabled', 'vntagMode': 'enabled', 'numOfVMFexIfs': n_vnics})

    def cimc_get_mgmt_nic(self):
        return self.handle.query_classid('mgmtIf')[0]

    def cimc_set_hostname(self):
        current = self.cimc_get_mgmt_nic()
        new_cimc_hostname = '{}-ru{}-{}'.format(self.pod, self.hardware, self.id)
        if new_cimc_hostname != current.hostname:
            self.logger(message='setting hostname to {}'.format(new_cimc_hostname))
            current.hostname = new_cimc_hostname
            self.handle.set_mo(current)
        else:
            self.logger(message='hostname is already {}'.format(new_cimc_hostname))

    @staticmethod
    def cimc_deduce_wiring_by_lldp(pod):
        import yaml
        from lab.wire import Wire

        cimc_info_file_path = pod.get_artifact_file_path('cimc-{}.yaml'.format(pod))
        try:
            with open(cimc_info_file_path) as f:
                cimc_info_dic = yaml.load(f.read())
        except IOError:
            cimc_info_dic = {}
            for cimc in sorted(pod.cimc_servers_dic.values()):
                cimc_info_dic[cimc.oob_ip] = cimc.cimc_list_all_nics()  # returns dic of {port_id: mac}
            with open(cimc_info_file_path, mode='w') as f:
                yaml.dump(cimc_info_dic, f)

        wires_cfg = []
        for node in sorted(pod.cimc_servers_dic.values()):
            for port1, mac in cimc_info_dic[node.oob_ip].items():
                neis = [x.find_neighbour_with_mac(mac=mac, cimc_port_id=port1) for x in pod.switches]
                neis = filter(lambda n: n is not None, neis)
                if neis:
                    assert len(neis) == 1, 'More then 1 switch is found connected to {} {}'.format(node, port1)
                    nei = neis[0]
                    wires_cfg.append({'node1': node.id, 'port1': port1, 'mac': mac, 'node2': nei.n9.id, 'port2': nei.port.port_id, 'pc-id': nei.port.pc_id})
                else:
                    wires_cfg.append({'node1': node.id, 'port1': port1, 'mac': mac, 'node2': None,      'port2': None,             'pc-id': None})

        pod.wires.extend(Wire.add_wires(pod=pod, wires_cfg=wires_cfg))
Пример #8
0
# Query for SNMP settings
imc_snmp_mo = handle.query_dn("sys/svc-ext/snmp-svc")

print "SNMP config inicial: "
print imc_snmp_mo

# Set SNMP parameters
imc_snmp_mo.admin_state = "enabled"
imc_snmp_mo.com2_sec = "full"
imc_snmp_mo.community = "private"
imc_snmp_mo.trap_community = "private"
imc_snmp_mo.sys_contact = "Mr XPTO"
imc_snmp_mo.sys_location = "Datacenter Y"

# Commit the changes to the IMC
handle.set_mo(imc_snmp_mo)

# Verify changes applied
imc_snmp_mo = handle.query_dn("sys/svc-ext/snmp-svc")

print "SNMP new config: "
print imc_snmp_mo

# Query for SNMP Trap1 settings
imc_snmp_trap1_mo = handle.query_dn("sys/svc-ext/snmp-svc/snmp-trap-1")

print "SNMP Trap-1config inicial: "
print imc_snmp_trap1_mo

# Set SNMP Trap-1 parameters
imc_snmp_trap1_mo.admin_state = "enabled"
Пример #9
0
class CimcServer(LabServer):
    RAID_0, RAID_1, RAID_10 = '0', '1', '10'

    def __init__(self, pod, dic):
        super(CimcServer, self).__init__(pod=pod, dic=dic)
        self._handle = None
        self._dump_xml = False
        self._logout_on_each_command = False

    def logger(self, message):
        self.log('CIMC ' + message)

    @property
    def handle(self):
        from imcsdk.imchandle import ImcHandle
        from urllib2 import URLError

        if self._handle is None:
            self._handle = ImcHandle(self.oob_ip, self.oob_username,
                                     self.oob_password)
            try:
                self._handle.login()
            except URLError as ex:
                raise RuntimeError('{}: {} {}'.format(self, ex, self.oob_ip))
        return self._handle

    def cimc_get_raid_battery_status(self):
        return self._handle.query_classid(class_id='storageRaidBattery')

    def _cimc_bios_lom(self, status):
        self.logger('{} all LOM'.format(status))
        actual = self._handle.query_classid(class_id='BiosVfLOMPortOptionROM')
        if actual.Status != status:
            params = {
                'Dn': 'sys/rack-unit-1/bios/bios-settings/LOMPort-OptionROM',
                'VpLOMPortsAllState': status,
                'vpLOMPort0State': status,
                'vpLOMPort1State': status
            }
            self._handle.set_mo('set_imc_managedobject',
                                in_mo=None,
                                class_id='BiosVfLOMPortOptionROM',
                                params=params)
            self.cimc_power_cycle()

    def cimc_enable_loms_in_bios(self):
        self._cimc_bios_lom(status='Enable')

    def cimc_disable_loms_in_bios(self):
        self._cimc_bios_lom(status='Disable')

    def cimc_list_all_nics(self):
        self.log('{} getting CIMC NICs'.format(self.oob_ip))
        r1 = self.handle.query_classid(
            class_id='networkAdapterEthIf'
        )  # physical Intel NICs (or others in PCI-E slots)
        r2 = self.handle.query_classid(
            class_id='adaptorExtEthIf')  # physical Cisco VIC in MLOM

        return {x.dn: x.mac for x in r1 + r2}

    def cimc_list_all_nics_and_vnics(self):
        r1 = self.handle.query_classid(
            class_id='networkAdapterEthIf'
        )  # physical Intel NICs (or others in PCI-E slots)
        r2 = self.handle.query_classid(
            class_id='adaptorExtEthIf')  # physical Cisco VIC in MLOM
        r3 = self.handle.query_classid(
            class_id='adaptorHostEthIf')  # virtual Cisco vNIC in MLOM

        return {x.dn: x.mac for x in r1 + r2 + r3}

    def cimc_list_pci_nic(self):
        r = self.handle.query_classid('networkAdapterUnit')
        return [{'Dn': x.Dn, 'Model': x.Model} for x in r]

    def cimc_list_vnics(self):
        ans1 = self.handle.query_classid('adaptorHostEthIf')
        ans2 = self.handle.query_classid('adaptorEthGenProfile')
        vnics = {
            x.Name: {
                'mac': x.Mac,
                'uplink': x.UplinkPort,
                'pci-slot': x.UsnicCount,
                'dn': x.Dn,
                'mtu': x.Mtu,
                'name': x.Name,
                'pxe-boot': x.PxeBoot
            }
            for x in ans1
        }
        vlans_dict = {
            x.Dn.replace('/general', ''): {
                'vlan': x.Vlan,
                'vlan_mode': x.VlanMode
            }
            for x in ans2
        }
        for vnic in vnics.values():
            vlans = vlans_dict[vnic.get('dn')]
            vnic.update(vlans)
        return vnics

    def cimc_enable_sol(self):
        self.logger('enabling SOL')
        params = {
            'dn': 'sys/rack-unit-1/sol-if',
            'adminState': 'enable',
            'speed': '115200'
        }
        self.cimc_set_mo_by_class_id(class_id='solIf', params=params)

    def create_storage(self, raid=RAID_1, disks_needed=2, clean_vds=False):
        """

        :param clean_vds: Clean all virtual drives before creating any
        :param raid: Please select from '0','1','10','5','6'
        :param disks_needed: Number of disks needed
        :return:
        """
        if raid not in [self.RAID_0, self.RAID_1, self.RAID_10]:
            raise ValueError(
                'RAID request is not correct. Use one of the {0}. Got: {1}'.
                format(','.join([self.RAID_0, self.RAID_1, self.RAID_10]),
                       raid))

        virtual_drives_list = self.handle.query_classid(
            class_id='storageVirtualDrive')
        if virtual_drives_list:
            if clean_vds:
                self.logger('Cleaning Virtual Drives to create new one.')
                for vd in virtual_drives_list:
                    self.handle.remove_mo(vd)
            else:
                self.logger('Virtual Drive already exists.')
                return
        disks = self.handle.query_classid('storageLocalDisk')
        # get 2 or more disks to form RAID
        disks_by_size = {}
        map(
            lambda x: disks_by_size.setdefault(x.get_attr('CoercedSize'), []).
            append(x), disks)
        available_disks = filter(
            lambda x: len(disks_by_size[x]) > disks_needed,
            disks_by_size.keys())
        if len(available_disks) == 0:
            raise Exception(
                'Not enough disks to build RAID {0}. Minimum required are {1}.'
                .format(raid, disks_needed))
        size = available_disks[0]
        drive_group = ','.join(
            map(lambda x: x.Id, disks_by_size[size])[:disks_needed])

        params = {
            'raidLevel': raid,
            'size': size,
            'virtualDriveName': "RAID",
            'dn':
            "sys/rack-unit-1/board/storage-SAS-SLOT-HBA/virtual-drive-create",
            'driveGroup': '[{0}]'.format(drive_group),
            'adminState': 'trigger',
            'writePolicy': 'Write Through'
        }
        self.logger(
            'Creating Virtual Drive RAID {0}. Using storage {0}'.format(
                raid, drive_group))
        self.cimc_set_mo_by_class_id(
            class_id="storageVirtualDriveCreatorUsingUnusedPhysicalDrive",
            params=params)

    def cimc_delete_all_vnics(self):
        self.logger('deleting all vNICs')
        vnic_names = self.cimc_list_vnics().keys()
        for vnic_name in vnic_names:
            self.cimc_delete_vnic(vnic_name=vnic_name)

    def cimc_delete_vnic(self, vnic_name):
        dn = 'sys/rack-unit-1/adaptor-MLOM/host-eth-{}'.format(vnic_name)
        if 'eth0' in vnic_name or 'eth1' in vnic_name:  # no way to delete eth0 or eth1, so reset them to default
            self.logger(message='Resetting vNIC ' + vnic_name)
            ethX = self.handle.query_dn(dn)
            ethX.mac = 'AUTO'
            ethX.mtu = 1500
            ethX.pxe_boot = False
            ethX.uplink_port = vnic_name[-1]
            self.handle.set_mo(ethX)

            profile = self.handle.query_dn(
                'sys/rack-unit-1/adaptor-{}/host-eth-{}/general'.format(
                    pci_slot_id, name))
            profile.vlan = None
            profile.order = 'ANY'
            self.handle.set_mo(profile)
        else:
            self.logger(message='Deleting vNIC ' + dn)
            vnic = self.handle.query_dn(dn=dn)
            self.handle.remove_mo(vnic)

    def cimc_set_ssh_timeout(self, timeout=3600):
        self.cmd('set_imc_managedobject',
                 in_mo=None,
                 class_id='commHttps',
                 params={
                     'Dn': 'sys/svc-ext/https-svc',
                     'sessionTimeout': str(timeout)
                 })

    def cimc_change_boot_order(self, pxe_order=1, hdd_order=2):
        self.logger('updating boot order: PXE as #{0}, HDD as #{1}'.format(
            pxe_order, hdd_order))
        boot_configs = [{
            'params': {
                'Dn': 'sys/rack-unit-1/boot-policy/lan-read-only',
                'Order': pxe_order,
                'Access': 'read-only'
            },
            'class_id': 'LsbootLan'
        }, {
            'params': {
                'Dn': 'sys/rack-unit-1/boot-policy/storage-read-write',
                'Order': hdd_order,
                'Access': 'read-write'
            },
            'class_id': 'LsbootStorage'
        }]
        for boot_config in boot_configs:
            boot_device = self.cmd('get_imc_managedobject',
                                   in_mo=None,
                                   class_id=None,
                                   params={'Dn': boot_config['params']['Dn']})
            if boot_device:
                self.cmd('set_imc_managedobject',
                         in_mo=boot_device,
                         class_id=None,
                         params=boot_config['params'])
            else:
                self.cmd('add_imc_managedobject',
                         in_mo=None,
                         class_id=boot_config['class_id'],
                         params=boot_config['params'])

    def cimc_create_vnic(self, pci_slot_id, uplink_port, order, name, mac,
                         vlan, is_pxe_enabled):
        from imcsdk.mometa.adaptor.AdaptorHostEthIf import AdaptorHostEthIf

        self.logger(
            message=
            'creating vNIC {} on PCI id {} uplink {} mac={} vlan={} pxe: {}'.
            format(name, pci_slot_id, uplink_port, mac, vlan, is_pxe_enabled))
        if name in [
                'eth0', 'eth1'
        ]:  # eth0 and eth1 are default, only possible to modify there parameters, no way to rename ot delete
            ethX = self.handle.query_dn(
                'sys/rack-unit-1/adaptor-{}/host-eth-{}'.format(
                    pci_slot_id, name))
            ethX.mac = mac
            ethX.mtu = 1500
            ethX.pxe_boot = is_pxe_enabled
            self.handle.set_mo(ethX)
        else:
            vnic = AdaptorHostEthIf(
                parent_mo_or_dn='sys/rack-unit-1/adaptor-' + pci_slot_id,
                name=name,
                mac=mac,
                mtu=1500,
                pxe_boot=is_pxe_enabled,
                uplink_port=uplink_port)
            self.handle.add_mo(vnic)
        profile = self.handle.query_dn(
            'sys/rack-unit-1/adaptor-{}/host-eth-{}/general'.format(
                pci_slot_id, name))
        profile.vlan = vlan
        profile.order = order
        self.handle.set_mo(profile)

    def cimc_get_power_status(self):
        return self.handle.query_classid('computeRackUnit')[0].get_attr(
            'OperPower')

    def _cimc_power(self, requested_state):
        import time

        self.logger('power {0}'.format(requested_state))
        rack = self.handle.query_dn('sys/rack-unit-1')
        rack.admin_power = requested_state
        self.handle.set_mo(rack)
        time.sleep(120)  # wait for the server to come up

    def cimc_power_down(self):
        current_power_state = self.cimc_get_power_status()
        if current_power_state == 'on':
            self._cimc_power('down')
        else:
            self.log(' is already OFF')

    def cimc_power_up(self):
        current_power_state = self.cimc_get_power_status()
        if current_power_state == 'off':
            self._cimc_power('up')
        else:
            self.log(' is already ON')

    def cimc_reset(self):
        pass
        # from ImcSdk.ImcMos import ComputeRackUnit

        # mo = handle.config_resolve_dn("sys/rack-unit-1")

        # mo.admin_power = ComputeRackUnit.CONST_ADMIN_POWER_BMC_RESET_IMMEDIATE
        # set_imc_managedobject(mo, class_id="ComputeRackUnit", params={ComputeRackUnit.ADMIN_POWER:
        #                                                 ComputeRackUnit.CONST_ADMIN_POWER_BMC_RESET_IMMEDIATE,
        #                                             ComputeRackUnit.DN: "sys/rack-unit-1"})

    def cimc_power_cycle(self):
        current_power_state = self.cimc_get_power_status()
        self._cimc_power('up' if current_power_state ==
                         'off' else 'cycle-immediate')

    def cimc_recreate_vnics(self):
        actual_vnics = self.cimc_list_all_nics_and_vnics()
        actual_loms = [
            x for x in self.cimc_list_pci_nic_ports() if 'L' in x['Dn']
        ]

        for nic_order, nic in enumerate(
                self.lom_nics_dic.values()):  # NIC order starts from 0
            names = nic.get_names()
            macs = nic.get_macs()
            port_ids = nic.get_port_ids()
            for name, mac, port_id in zip(names, macs, port_ids):
                if port_id in ['LOM-1', 'LOM-2']:
                    actual_mac = actual_loms[port_id]['mac']
                    if mac.upper() != actual_mac.upper():
                        raise ValueError(
                            '{}: "{}" actual mac is "{}" while requested "{}". Edit lab config!'
                            .format(self.id, port_id, actual_mac, mac))
                else:
                    if 'eth' not in self.get_nics() and nic.is_ssh(
                    ):  # if no NIC called eth and it's nic on ssh network, use default eth0, eth1
                        if name in actual_vnics:
                            self.cimc_delete_vnic(vnic_name=name)
                        name = 'eth' + name[-1]
                    if name in actual_vnics:
                        if mac == actual_vnics[name]['mac'] and str(
                                nic.get_vlan_id()) == str(
                                    actual_vnics[name]
                                    ['vlan']):  # this nic is already in CIMC
                            self.logger(
                                message='vNIC {} is already configured'.format(
                                    name))
                            if name in actual_vnics:
                                actual_vnics.pop(name)
                            continue
                        else:
                            self.logger(
                                'deleting {} since mac or vlan is not correct: {}'
                                .format(name, actual_vnics[name]))
                            self.cimc_delete_vnic(vnic_name=name)
                    pci_slot_id, uplink_port = port_id.split('/')
                    self.cimc_create_vnic(pci_slot_id=pci_slot_id,
                                          uplink_port=uplink_port,
                                          order='ANY',
                                          name=name,
                                          mac=mac,
                                          vlan=nic.get_vlan_id(),
                                          is_pxe_enabled=nic.is_pxe())
                    if name in actual_vnics:
                        actual_vnics.pop(name)
        for vnic_name in actual_vnics.keys(
        ):  # delete all actual which are not requested
            self.cimc_delete_vnic(vnic_name)

    def cimc_configure(self, is_debug=False):
        self._dump_xml = is_debug
        lab_type = self.pod.get_type()
        self.logger('configuring for {}'.format(lab_type))
        self.cimc_set_hostname()
        self.cimc_power_up()
        if self.pod.get_type() == self.pod.MERCURY:
            self.cimc_disable_loms_in_bios()
        else:
            is_any_nic_on_lom = any(
                map(lambda x: x.is_on_lom(),
                    self.get_nics().values()))
            if is_any_nic_on_lom:
                self.cimc_enable_loms_in_bios()
            self.cimc_recreate_vnics()
            self.cimc_change_boot_order(pxe_order=1, hdd_order=2)
        # if lab_type == self.lab().LAB_MERCURY:
        #    self.create_storage('1', 2, True)

    def cimc_get_adaptors(self):
        r = self.handle.query_classid('AdaptorUnit')
        return r

    def cimc_set_mlom_adaptor(self, pci_slot, n_vnics):
        self.logger(message='allowing MLOM-{} to use up to {} vNICs'.format(
            pci_slot, n_vnics))
        # self.cimc_set_mo_by_class_id(class_id='adaptorUnit', params={'dn': 'sys/rack-unit-1/adaptor-{0}'.format(pci_slot), 'description': str(self)})
        self.cimc_set_mo_by_class_id(
            class_id='adaptorGenProfile',
            params={
                'dn': 'sys/rack-unit-1/adaptor-{0}/general'.format(pci_slot),
                'fipMode': 'enabled',
                'vntagMode': 'enabled',
                'numOfVMFexIfs': n_vnics
            })

    def cimc_get_mgmt_nic(self):
        return self.handle.query_classid('mgmtIf')[0]

    def cimc_set_hostname(self):
        current = self.cimc_get_mgmt_nic()
        new_cimc_hostname = '{}-ru{}-{}'.format(self.pod, self.hardware,
                                                self.id)
        if new_cimc_hostname != current.hostname:
            self.logger(
                message='setting hostname to {}'.format(new_cimc_hostname))
            current.hostname = new_cimc_hostname
            self.handle.set_mo(current)
        else:
            self.logger(
                message='hostname is already {}'.format(new_cimc_hostname))

    @staticmethod
    def cimc_deduce_wiring_by_lldp(pod):
        import yaml
        from lab.wire import Wire

        cimc_info_file_path = pod.get_artifact_file_path(
            'cimc-{}.yaml'.format(pod))
        try:
            with open(cimc_info_file_path) as f:
                cimc_info_dic = yaml.load(f.read())
        except IOError:
            cimc_info_dic = {}
            for cimc in sorted(pod.cimc_servers_dic.values()):
                cimc_info_dic[cimc.oob_ip] = cimc.cimc_list_all_nics(
                )  # returns dic of {port_id: mac}
            with open(cimc_info_file_path, mode='w') as f:
                yaml.dump(cimc_info_dic, f)

        wires_cfg = []
        for node in sorted(pod.cimc_servers_dic.values()):
            for port1, mac in cimc_info_dic[node.oob_ip].items():
                neis = [
                    x.find_neighbour_with_mac(mac=mac, cimc_port_id=port1)
                    for x in pod.switches
                ]
                neis = filter(lambda n: n is not None, neis)
                if neis:
                    assert len(
                        neis
                    ) == 1, 'More then 1 switch is found connected to {} {}'.format(
                        node, port1)
                    nei = neis[0]
                    wires_cfg.append({
                        'node1': node.id,
                        'port1': port1,
                        'mac': mac,
                        'node2': nei.n9.id,
                        'port2': nei.port.port_id,
                        'pc-id': nei.port.pc_id
                    })
                else:
                    wires_cfg.append({
                        'node1': node.id,
                        'port1': port1,
                        'mac': mac,
                        'node2': None,
                        'port2': None,
                        'pc-id': None
                    })

        pod.wires.extend(Wire.add_wires(pod=pod, wires_cfg=wires_cfg))