Exemple #1
0
def dhcp_query_ip(server, username, password, mac):
    '''
    Get IP address according to the MAC address, from target
    server, wich credential username:password
    :param server: server name
    :param username: server username
    :param password: server password
    :param mac: MAC address of the target node
    :return: IP address of the target node
    '''
    conn = CSSH(ip=server, username=username, password=password)
    if not conn.connect():
        raise Exception(
            'Fail to connect to server {} to query IP'.format(server))

    rsp = conn.remote_shell(
        'grep -A 2 -B 7 "{}" /var/lib/dhcp/dhcpd.leases | grep "lease" | tail -n 1'
        .format(mac))
    if rsp['exitcode'] != 0:
        conn.disconnect()
        raise Exception(
            'Fail to get response from server {} to query IP\n{}'.format(
                server, json.dumps(rsp, indent=4)))
    if not rsp['stdout']:
        conn.disconnect()
        raise Exception(
            'Find no DHCP lease information for MAC: {}'.format(mac))

    p_ip = r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
    p = re.search(p_ip, rsp['stdout'])
    if p:
        if is_valid_ip(p.group(1)):
            conn.disconnect()
            return p.group(1)
Exemple #2
0
    def __init__(self, dict_node):
        """
        dict_node example:
        {
            "name": "vnode_a_20160126114700",
            "power": [
                {"vPDU": "vpdu_1", "outlet": "1.1"}
            ],
            "admin":{
                "ip": "192.168.134.114",
                "username": "******",
                "password": "******"
            },
            "bmc": {
                "ip": "172.31.128.2",
                "username": "******",
                "password": "******"
            }
        }
        """

        CDevice.__init__(self, 'vNode')

        self.dict_config = dict_node

        # vBMC
        obj_bmc = CBMC(self.dict_config.get('bmc', {}))
        self.bmc = obj_bmc

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        if 'admin' not in self.dict_config:
            raise Exception('No "admin" network defined for node {}'.format(
                self.name))
        self.ip = self.dict_config['admin'].get('ip', '')
        self.username = self.dict_config['admin'].get('username', '')
        self.password = self.dict_config['admin'].get('password', '')

        if self.dict_config.get('guest_os'):
            self.guest_ip = self.dict_config['guest_os'].get('ip', '')
            self.guest_user = self.dict_config['guest_os'].get('username', '')
            self.guest_password = self.dict_config['guest_os'].get(
                'password', '')

        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip,
                                     username='',
                                     password='',
                                     port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip,
                        username=self.username,
                        password=self.password,
                        port=22)
        self.b_sol = False
Exemple #3
0
def dhcp_query_ip(server, username, password, mac):
    '''
    Get IP address according to the MAC address, from target
    server, wich credential username:password
    :param server: server name
    :param username: server username
    :param password: server password
    :param mac: MAC address of the target node
    :return: IP address of the target node
    '''
    conn = CSSH(ip=server,
                username=username,
                password=password)
    if not conn.connect():
        raise Exception('Fail to connect to server {} to query IP'.format(server))

    rsp = conn.remote_shell('grep -A 2 -B 7 "{}" /var/lib/dhcp/dhcpd.leases | grep "lease" | tail -n 1'.format(mac))
    if rsp['exitcode'] != 0:
        conn.disconnect()
        raise Exception('Fail to get response from server {} to query IP\n{}'.
                        format(server, json.dumps(rsp, indent=4)))
    if not rsp['stdout']:
        conn.disconnect()
        raise Exception('Find no DHCP lease information for MAC: {}'.format(mac))

    p_ip = r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
    p = re.search(p_ip, rsp['stdout'])
    if p:
        if is_valid_ip(p.group(1)):
            conn.disconnect()
            return p.group(1)
Exemple #4
0
    def __init__(self, dict_pdu):

        CDevice.__init__(self, 'vPDU')

        self.dict_config = dict_pdu

        self.ip = self.dict_config.get('ip', '')
        self.name = self.dict_config.get('name', '')
        self.community = self.dict_config.get('community', '')

        # Build outlet mapping
        self.outlet = {}
        for str_outlet, str_password in self.dict_config.get('outlet',
                                                             {}).items():
            self.outlet[str_outlet] = {'node': None, 'password': str_password}

        self.snmp = CSNMP(self.ip, self.community)
        self.ssh_vpdu = CSSH(ip=self.ip, username='', password='', port=20022)
Exemple #5
0
    def __init__(self, dict_node):
        """
        dict_node example:
        {
            "name": "vnode_a_20160126114700",
            "power": [
                {"vPDU": "vpdu_1", "outlet": "1.1"}
            ],
            "admin":{
                "ip": "192.168.134.114",
                "username": "******",
                "password": "******"
            },
            "bmc": {
                "ip": "172.31.128.2",
                "username": "******",
                "password": "******"
            }
        }
        """

        CDevice.__init__(self, 'vNode')

        self.dict_config = dict_node

        # vBMC
        obj_bmc = CBMC(self.dict_config.get('bmc', {}))
        self.bmc = obj_bmc

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        if 'admin' not in self.dict_config:
            raise Exception('No "admin" network defined for node {}'.format(self.name))
        self.ip = self.dict_config['admin'].get('ip', '')
        self.username = self.dict_config['admin'].get('username', '')
        self.password = self.dict_config['admin'].get('password', '')

        if self.dict_config.get('guest_os'):
            self.guest_ip = self.dict_config['guest_os'].get('ip', '')
            self.guest_user = self.dict_config['guest_os'].get('username', '')
            self.guest_password = self.dict_config['guest_os'].get('password', '')

        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip, username='', password='', port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip, username=self.username, password=self.password, port=22)
        self.b_sol = False
Exemple #6
0
def arp_query_ip(server, username, password, mac):
    '''
    Get IP address according to the MAC address, from target
    server, wich credential username:password
    :param server: server name
    :param username: server username
    :param password: server password
    :param mac: MAC address of the target node
    :return: IP address of the target node
    '''
    conn = CSSH(ip=server,
                username=username,
                password=password)
    if not conn.connect():
        raise Exception('Fail to connect to server {} to query IP'.format(server))

    rsp = conn.remote_shell('arp -an | grep {}'.format(mac))
    if rsp['exitcode'] != 0:
        conn.disconnect()
        raise Exception('Fail to get response from server {} to query IP\n{}'.
                        format(server, json.dumps(rsp, indent=4)))

    p_ip = r'\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)'
    list_info = rsp['stdout'].split('\n')
    list_ip = []
    for each_info in list_info:
        p = re.search(p_ip, each_info)
        if p:
            if is_valid_ip(p.group(1)):
                list_ip.append(p.group(1))
    if len(list_ip) != 1:
        conn.disconnect()
        raise Exception('MAC conflict for IP: {}'.format(list_ip))
    else:
        conn.disconnect()
        return list_ip[0]
Exemple #7
0
def arp_query_ip(server, username, password, mac):
    '''
    Get IP address according to the MAC address, from target
    server, wich credential username:password
    :param server: server name
    :param username: server username
    :param password: server password
    :param mac: MAC address of the target node
    :return: IP address of the target node
    '''
    conn = CSSH(ip=server,
                username=username,
                password=password)
    if not conn.connect():
        raise Exception('Fail to connect to server {} to query IP'.format(server))

    rsp = conn.remote_shell('arp -an | grep {}'.format(mac))
    if rsp['exitcode'] != 0:
        conn.disconnect()
        raise Exception('Fail to get response from server {} to query IP\n{}'.
                        format(server, json.dumps(rsp, indent=4)))

    p_ip = r'\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)'
    list_info = rsp['stdout'].split('\n')
    list_ip = []
    for each_info in list_info:
        p = re.search(p_ip, each_info)
        if p:
            if is_valid_ip(p.group(1)):
                list_ip.append(p.group(1))
    if len(list_ip) != 1:
        conn.disconnect()
        raise Exception('MAC conflict for IP: {}'.format(list_ip))
    else:
        conn.disconnect()
        return list_ip[0]
Exemple #8
0
    def __init__(self, dict_pdu):

        CDevice.__init__(self, 'vPDU')

        self.dict_config = dict_pdu

        self.ip = self.dict_config.get('ip', '')
        self.name = self.dict_config.get('name', '')
        self.community = self.dict_config.get('community', '')

        # Build outlet mapping
        self.outlet = {}
        for str_outlet, str_password in self.dict_config.get('outlet', {}).items():
            self.outlet[str_outlet] = {
                'node': None,
                'password': str_password
            }

        self.snmp = CSNMP(self.ip, self.community)
        self.ssh_vpdu = CSSH(ip=self.ip, username='', password='', port=20022)
Exemple #9
0
class CNode(CDevice):
    def __init__(self, dict_node):
        """
        dict_node example:
        {
            "name": "vnode_a_20160126114700",
            "power": [
                {"vPDU": "vpdu_1", "outlet": "1.1"}
            ],
            "admin":{
                "ip": "192.168.134.114",
                "username": "******",
                "password": "******"
            },
            "bmc": {
                "ip": "172.31.128.2",
                "username": "******",
                "password": "******"
            }
        }
        """

        CDevice.__init__(self, 'vNode')

        self.dict_config = dict_node

        # vBMC
        obj_bmc = CBMC(self.dict_config.get('bmc', {}))
        self.bmc = obj_bmc

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        if 'admin' not in self.dict_config:
            raise Exception('No "admin" network defined for node {}'.format(
                self.name))
        self.ip = self.dict_config['admin'].get('ip', '')
        self.username = self.dict_config['admin'].get('username', '')
        self.password = self.dict_config['admin'].get('password', '')

        if self.dict_config.get('guest_os'):
            self.guest_ip = self.dict_config['guest_os'].get('ip', '')
            self.guest_user = self.dict_config['guest_os'].get('username', '')
            self.guest_password = self.dict_config['guest_os'].get(
                'password', '')

        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip,
                                     username='',
                                     password='',
                                     port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip,
                        username=self.username,
                        password=self.password,
                        port=22)
        self.b_sol = False

    def get_config(self):
        return self.dict_config

    def get_name(self):
        return self.name

    def set_bmc(self, obj_bmc):
        self.bmc = obj_bmc

    def get_bmc(self):
        return self.bmc

    def get_ip(self):
        return self.ip

    def set_ip(self, str_ip):
        self.ip = str_ip

    def get_username(self):
        return self.username

    def set_username(self, str_username):
        self.username = str_username

    def get_password(self):
        return self.password

    def set_password(self, str_password):
        self.password = str_password

    def get_port_ipmi_console(self):
        return self.port_ipmi_console

    def power_on(self):
        if not self.power:
            raise Exception(
                'Can\'t operate node\'s power, please bind to any PDU first.')
        for power_unit in self.power:
            if not power_unit[0].match_outlet_password(power_unit[1]):
                return False
            if not power_unit[0].power_on(power_unit[1]):
                return False
        return True

    def power_off(self):
        if not self.power:
            raise Exception(
                'Can\'t operate node\'s power, please bind to any PDU first.')
        for power_unit in self.power:
            if not power_unit[0].match_outlet_password(power_unit[1]):
                return False
            if not power_unit[0].power_off(power_unit[1]):
                return False
        return True

    def _has_power_control(self):
        if self.power:
            return True
        else:
            return False

    @with_connect('ssh')
    def sol_activate(self, log_dir=''):
        '''
        SSH to this BMC, then activate SOL
        Leverage SSH to capture output flow
        '''

        if self.b_sol:
            self.log('WARNING',
                     'BMC {} SOL has been activated'.format(self.ip))
            return

        # Connect
        self.ssh.send_command(
            'ipmitool -I lanplus -H {} -U {} -P {} sol activate{}'.format(
                self.bmc.get_ip(), self.bmc.get_username(),
                self.bmc.get_password(), chr(13)))

        # Wait 2s to flush heading string
        time.sleep(2)

        self.b_sol = True

    @with_connect('ssh')
    def sol_is_alive(self):

        if not self.b_sol:
            self.log('WARNING', 'BMC {} SOL is not activated'.format(self.ip))
            return False

        retry = 30
        for i in range(retry):
            self.ssh.start_cache()
            time.sleep(3)
            str_cache = self.ssh.get_cache()
            if str_cache:
                self.log('INFO', 'SOL is alive')
                return True
        self.log('WARNING',
                 'BMC {} SOL is not alive, no output in 90s'.format('self.ip'))
        return False

    @with_connect('ssh')
    def sol_deactivate(self):
        '''
        Deactivate SOL, then disconnect SSH on this BMC port 22
        '''

        if not self.b_sol:
            self.log('WARNING', 'BMC {} SOL is not activated'.format(self.ip))
            return

        # Disconnect
        self.ssh.send_command('~.')

        self.b_sol = False

    @with_connect('ssh')
    def send_file(self, src, dst):
        '''
        Put file from src to dst, return canonicalized path of destination
        '''
        self.log(
            "INFO",
            "Send file {} to {} on node {}...".format(src, dst,
                                                      self.get_name()))
        with self.ssh.h_ssh.open_sftp() as sftp:
            sftp.put(src, dst)
            return str(sftp.normalize(dst))

    @with_connect('ssh')
    def get_instance_name(self):
        '''
        Get run time node names from admin network.
        You may get multiple instances in the same environment, but this function
        has not handled this condition yet.
        It now focus on one infrasim instances in one admin network.
        :return:
        '''
        self.log(
            "INFO",
            "Get runtime instance name from node {}...".format(self.get_ip()))
        p_name = re.compile(r'] (.*)-node is running')

        rsp = self.ssh.send_command_wait_string(
            str_command='echo {} | sudo -S infrasim node status {}'.format(
                self.password, chr(13)),
            wait='~$')
        rsp = strip_color_code(rsp)

        list_name = list(set(p_name.findall(rsp)))
        active_num = len(list_name)
        if active_num == 1:
            return list_name[0]
        elif active_num == 0:
            raise Exception("Infrasim node is not running on {}".format(
                self.ip))
        else:
            raise Exception(
                "Multiple infrasim instances {} are detected on {}. "
                "This is not supported yet.".format(list_name, self.ip))

    def retry_get_instance_name(self):
        '''
        Retry to get nodes name in case there is a node reboot before trying to get instance name
        :return: 
        '''
        retry = 20
        interval = 2
        str_node_name = ""
        for i in range(retry):
            try:
                str_node_name = self.get_instance_name()
                break
            except Exception as e:
                time.sleep(interval)
        return str_node_name

    @with_connect('ssh')
    def update_instance_config(self, str_instance_name, payload, *key):
        '''
        Update configuration file, assign payload to target key.
        :param str_instance_name:
        :param dict_payload:
        :return:
        '''
        self.log(
            "INFO", "Update config for instance {} on node {}...".format(
                str_instance_name, self.get_ip()))
        str_key = []
        for element in key:
            str_key.append(str(element))
        self.log(
            "INFO", "{}: \n{}".format(" > ".join(str_key),
                                      json.dumps(payload, indent=4)))
        remote_path = os.path.join(".infrasim", str_instance_name, "etc",
                                   "infrasim.yml")
        with self.ssh.h_ssh.open_sftp() as sftp:
            conf = None
            with sftp.open(remote_path, 'r') as remote_file:
                conf = yaml.load(remote_file)
                update_option(conf, payload, *key)
            if str(payload) != str(get_option(conf, *key)):
                self.log("WARNING", "Failed to update config option. After updating, option chain actually is: \n{}\n"\
                         "Payload is: \n {}\n".format(get_option(conf, *key), payload))
            with sftp.open('tmp.yml', 'w') as remote_file:
                yaml.dump(conf, remote_file, default_flow_style=False)
            with sftp.open('tmp.yml', 'r') as remote_file:
                conf = yaml.load(remote_file)
                if payload != get_option(conf, *key):
                    self.log("WARNING", "Failed to dump config file after updating config. After updating,"\
                             "option chain actually is: \n{}\n Payload is: \n{}\n".format(get_option(conf, *key), payload))

        self.ssh.send_command_wait_string(
            str_command="echo {} | sudo -S mv tmp.yml {}".format(
                self.password, remote_path) + chr(13),
            wait="~$")

    @with_connect('ssh')
    def get_instance_config(self, str_instance_name):
        '''
        Get configuration
        :param str_instance_name:
        :param dict_payload:
        :return:
        '''
        self.log(
            "INFO", "Get config for instance {} on node {}...".format(
                str_instance_name, self.get_ip()))
        remote_path = os.path.join(".infrasim", str_instance_name, "etc",
                                   "infrasim.yml")
        with self.ssh.h_ssh.open_sftp() as sftp:
            with sftp.open(remote_path, 'r') as remote_file:
                return yaml.load(remote_file)
Exemple #10
0
class CNode(CDevice):
    def __init__(self, dict_node):
        """
        dict_node example:
        {
            "name": "vnode_a_20160126114700",
            "power": [
                {"vPDU": "vpdu_1", "outlet": "1.1"}
            ],
            "admin":{
                "ip": "192.168.134.114",
                "username": "******",
                "password": "******"
            },
            "bmc": {
                "ip": "172.31.128.2",
                "username": "******",
                "password": "******"
            }
        }
        """

        CDevice.__init__(self, 'vNode')

        self.dict_config = dict_node

        # vBMC
        obj_bmc = CBMC(self.dict_config.get('bmc', {}))
        self.bmc = obj_bmc

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        if 'admin' not in self.dict_config:
            raise Exception('No "admin" network defined for node {}'.format(self.name))
        self.ip = self.dict_config['admin'].get('ip', '')
        self.username = self.dict_config['admin'].get('username', '')
        self.password = self.dict_config['admin'].get('password', '')
        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip, username='', password='', port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip, username=self.username, password=self.password, port=22)
        self.b_sol = False

    def get_config(self):
        return self.dict_config

    def get_name(self):
        return self.name

    def set_bmc(self, obj_bmc):
        self.bmc = obj_bmc

    def get_bmc(self):
        return self.bmc

    def get_ip(self):
        return self.ip

    def set_ip(self, str_ip):
        self.ip = str_ip

    def get_username(self):
        return self.username

    def set_username(self, str_username):
        self.username = str_username

    def get_password(self):
        return self.password

    def set_password(self, str_password):
        self.password = str_password

    def get_port_ipmi_console(self):
        return self.port_ipmi_console

    def power_on(self):
        if not self.power:
            raise Exception('Can\'t operate node\'s power, please bind to any PDU first.')
        for power_unit in self.power:
            if not power_unit[0].match_outlet_password(power_unit[1]):
                return False
            if not power_unit[0].power_on(power_unit[1]):
                return False
        return True

    def power_off(self):
        if not self.power:
            raise Exception('Can\'t operate node\'s power, please bind to any PDU first.')
        for power_unit in self.power:
            if not power_unit[0].match_outlet_password(power_unit[1]):
                return False
            if not power_unit[0].power_off(power_unit[1]):
                return False
        return True

    def _has_power_control(self):
        if self.power:
            return True
        else:
            return False

    @with_connect('ssh')
    def sol_activate(self, log_dir=''):
        '''
        SSH to this BMC, then activate SOL
        Leverage SSH to capture output flow
        '''

        if self.b_sol:
            self.log('WARNING', 'BMC {} SOL has been activated'.format(self.ip))
            return

        # Connect
        self.ssh.send_command('ipmitool -I lanplus -H {} -U {} -P {} sol activate{}'.
                              format(self.bmc.get_ip(),
                                     self.bmc.get_username(),
                                     self.bmc.get_password(),
                                     chr(13)))

        # Wait 2s to flush heading string
        time.sleep(2)

        self.b_sol = True

    @with_connect('ssh')
    def sol_is_alive(self):

        if not self.b_sol:
            self.log('WARNING', 'BMC {} SOL is not activated'.format(self.ip))
            return False

        retry = 30
        for i in range(retry):
            self.ssh.start_cache()
            time.sleep(3)
            str_cache = self.ssh.get_cache()
            if str_cache:
                self.log('INFO', 'SOL is alive')
                return True
        self.log('WARNING', 'BMC {} SOL is not alive, no output in 90s'.format('self.ip'))
        return False

    @with_connect('ssh')
    def sol_deactivate(self):
        '''
        Deactivate SOL, then disconnect SSH on this BMC port 22
        '''

        if not self.b_sol:
            self.log('WARNING', 'BMC {} SOL is not activated'.format(self.ip))
            return

        # Disconnect
        self.ssh.send_command('~.')

        self.b_sol = False

    @with_connect('ssh')
    def send_file(self, src, dst):
        '''
        Put file from src to dst, return canonicalized path of destination
        '''
        self.log("INFO", "Send file {} to {} on node {}...".format(src, dst, self.get_name()))
        with self.ssh.h_ssh.open_sftp() as sftp:
            sftp.put(src, dst)
            return str(sftp.normalize(dst))

    @with_connect('ssh')
    def get_instance_name(self):
        '''
        Get run time node names from admin network.
        You may get multiple instances in the same environment, but this function
        has not handled this condition yet.
        It now focus on one infrasim instances in one admin network.
        :return:
        '''
        self.log("INFO", "Get runtime instance name from node {}...".format(self.get_ip()))
        p_name = re.compile(r"] (.*)-node is running")

        rsp = self.ssh.send_command_wait_string(str_command='echo {} | sudo -S infrasim node status {}'.
                                                format(self.password, chr(13)),
                                                wait='~$')

        list_name = list(set(p_name.findall(rsp)))
        active_num = len(list_name)
        if active_num == 1:
            return list_name[0]
        elif active_num == 0:
            raise Exception("Infrasim node is not running on {}".format(self.ip))
        else:
            raise Exception("Multiple infrasim instances {} are detected on {}. "
                            "This is not supported yet.".
                            format(list_name, self.ip))

    @with_connect('ssh')
    def update_instance_config(self, str_instance_name, payload, *key):
        '''
        Update configuration file, assign payload to target key.
        :param str_instance_name:
        :param dict_payload:
        :return:
        '''
        self.log("INFO", "Update config for instance {} on node {}...".format(str_instance_name, self.get_ip()))
        str_key = []
        for element in key:
            str_key.append(str(element))
        self.log("INFO", "{}: \n{}".format(" > ".join(str_key), json.dumps(payload, indent=4)))
        remote_path = os.path.join(".infrasim", str_instance_name, "etc", "infrasim.yml")
        with self.ssh.h_ssh.open_sftp() as sftp:
            conf = None
            with sftp.open(remote_path, 'r') as remote_file:
                conf = yaml.load(remote_file)
                update_option(conf, payload, *key)
            with sftp.open('tmp.yml', 'w') as remote_file:
                yaml.dump(conf, remote_file, default_flow_style=False)

        self.ssh.send_command_wait_string(str_command="echo {} | sudo -S mv tmp.yml {}".
                                          format(self.password, remote_path)+chr(13),
                                          wait="~$")

    @with_connect('ssh')
    def get_instance_config(self, str_instance_name):
        '''
        Get configuration
        :param str_instance_name:
        :param dict_payload:
        :return:
        '''
        self.log("INFO", "Get config for instance {} on node {}...".format(str_instance_name, self.get_ip()))
        remote_path = os.path.join(".infrasim", str_instance_name, "etc", "infrasim.yml")
        with self.ssh.h_ssh.open_sftp() as sftp:
            with sftp.open(remote_path, 'r') as remote_file:
                return yaml.load(remote_file)
Exemple #11
0
class CPDU(CDevice):
    def __init__(self, dict_pdu):

        CDevice.__init__(self, 'vPDU')

        self.dict_config = dict_pdu

        self.ip = self.dict_config.get('ip', '')
        self.name = self.dict_config.get('name', '')
        self.community = self.dict_config.get('community', '')

        # Build outlet mapping
        self.outlet = {}
        for str_outlet, str_password in self.dict_config.get('outlet', {}).items():
            self.outlet[str_outlet] = {
                'node': None,
                'password': str_password
            }

        self.snmp = CSNMP(self.ip, self.community)
        self.ssh_vpdu = CSSH(ip=self.ip, username='', password='', port=20022)

    def get_config(self):
        return self.dict_config

    def get_ip(self):
        return self.ip

    def get_name(self):
        return self.name

    def get_community(self):
        return self.community

    def connect(self, obj_node, str_outlet):
        '''
        Connect a node to certain outlet
        :param obj_node: virtual node instance of idic.stack.Node.CNode
        :param str_outlet: a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        :return: True | False
            True is successfully connect PDU and node
            False is fail to connect PDU and node
        '''
        if str_outlet not in self.outlet:
            raise KeyError('Outlet {} is not defined in PDU {}'.format(str_outlet, self.name))
        if self.outlet[str_outlet]['node']:
            self.log('WARNING', '{} outlet {} is occupied by node {}, fail to connect'.
                     format(self.name, str_outlet, self.outlet[str_outlet]['node'].get_name()))
            return False
        else:
            # Some operation on SSH

            self.outlet[str_outlet]['node'] = obj_node
            if (self, str_outlet) not in obj_node.power:
                obj_node.power.append((self, str_outlet))
            self.log('INFO', 'Connect PDU {} outlet {} to node {} DONE'.
                     format(self.name, str_outlet, obj_node.get_name()))
            return True

    def disconnect(self, str_outlet):
        '''
        Disconnect an outlet
        :param str_outlet: a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        :return: True | False
            True is successfully disconnect PDU and node
            False is fail to disconnect PDU and node
        '''
        if str_outlet not in self.outlet:
            raise KeyError('Outlet {} is not defined in PDU {}'.format(str_outlet, self.name))
        if not self.outlet[str_outlet]['node']:
            self.log('INFO', '{} outlet {} is not connected'.format(self.name, str_outlet))
            return True
        else:
            # Some operation on SSH

            obj_node = self.outlet[str_outlet]['node']
            if (self, str_outlet) in obj_node.power:
                obj_node.power.remove((self, str_outlet))
            self.outlet[str_outlet]['node'] = None
            return True

    def self_check(self):
        list_fail_item = []
        for str_check_item, oid in OID_CHECK_LIST.items():
            err_indicator, err_status, err_index, var_binds = self.snmp.get(oid)
            if err_indicator or err_status or err_index:
                self.log('ERROR', "{} (IP: {}) fail on {} check:\n"
                                  "Error indicator: {}\n"
                                  "Error status: {}\n"
                                  "Error index: {}".
                         format(self.name, self.ip, str_check_item,
                                str(err_indicator), err_status, err_index))
                list_fail_item.append(str_check_item)
            else:
                self.log('INFO', "{} check {} is done".
                         format(self.name, str_check_item))

        if list_fail_item:
            self.log('ERROR', 'Fail items: {}'.format(str(list_fail_item)))
            return False
        else:
            return True

    def get_outlet_password(self, str_outlet):
        if str_outlet not in self.outlet:
            raise KeyError('Outlet {} is not defined in PDU {}'.format(str_outlet, self.name))
        return self.outlet[str_outlet].get('password', '')

    @with_connect('ssh_vpdu')
    def set_outlet_password(self, str_outlet, str_password):
        # Some operation on SSH
        pass

    def match_outlet_password(self, str_outlet, str_password=''):
        '''
        Match a password on a certain outlet before power on/off operation
        :param str_outlet: a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        :param str_password: password in string
        '''
        oid = OID_PDU_OUT_PWD_ROOT + tuple(str_outlet.split('.'))
        if not str_password:
            str_password = self.get_outlet_password(str_outlet)

        err_indicator, err_status, err_index, var_binds = self.snmp.set(oid, 'OctetString', str_password)
        if err_indicator or err_status or err_index:
            self.log('ERROR', "{} (IP: {}) fail to match password \"{}\" on outlet {}:\n"
                              "Error indicator: {}\n"
                              "Error status: {}\n"
                              "Error index: {}".
                     format(self.name, self.ip, str_password, str_outlet,
                            str(err_indicator), err_status, err_index))
            return False
        else:
            self.log('INFO', "{} match password on outlet {}: {} is done".
                     format(self.name, str_outlet, str_password))
            return True

    def power_on(self, str_outlet):
        '''
        Power on a certain outlet
        :param str_outlet:  a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        '''
        oid = OID_PDU_OUT_ON_ROOT + tuple(str_outlet.split('.'))
        err_indicator, err_status, err_index, var_binds = self.snmp.set(oid, 'Integer', INT_PDU_OUT_ON)
        if err_indicator or err_status or err_index:
            self.log('ERROR', "{} (IP: {}) fail to power on outlet {}:\n"
                              "Error indicator: {}\n"
                              "Error status: {}\n"
                              "Error index: {}".
                     format(self.name, self.ip, str_outlet,
                            str(err_indicator), err_status, err_index))
            return False
        else:
            self.log('INFO', "{} power on outlet {} is done".
                     format(self.name, str_outlet))
            return True

    def power_off(self, str_outlet):
        '''
        Power off a certain outlet
        :param str_outlet:  a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        '''
        oid = OID_PDU_OUT_ON_ROOT + tuple(str_outlet.split('.'))
        err_indicator, err_status, err_index, var_binds = self.snmp.set(oid, 'Integer', INT_PDU_OUT_OFF)
        if err_indicator or err_status or err_index:
            self.log('ERROR', "{} (IP: {}) fail to power off outlet {}:\n"
                              "Error indicator: {}\n"
                              "Error status: {}\n"
                              "Error index: {}".
                     format(self.name, self.ip, str_outlet,
                            str(err_indicator), err_status, err_index))
            return False
        else:
            self.log('INFO', "{} power off outlet {} is done".
                     format(self.name, str_outlet))
            return True

    @with_connect('ssh_vpdu')
    def verify_password_set(self):
        '''
        Verify pdu password set. password set, and password list commands are tested.
        :return: return "True" if test pass, else return "False"
        '''
        # password list to check password of pdu 1 before password set
        str_rsp_pwd_list = self.ssh_vpdu.send_command_wait_string(str_command='password list 1'+chr(13),
                                                                  wait='(vPDU)',
                                                                  int_time_out=10,
                                                                  b_with_buff=False)

        # get pattern line
        pattern = r'\|\s*\d+\s*\|\s*\S+\s*\|'
        m_pwd_list = re.search(pattern, str_rsp_pwd_list)

        # If the pdu have at least 1 port set with password,
        # test to set the first port's password, and then set it back to original
        if m_pwd_list:

            # split pattern line, get port and password
            m_pwd_stripped_space = m_pwd_list.group(0).strip("|").replace(" ", "")
            port_pwd = re.split(r'\|\s*', m_pwd_stripped_space)
            port = port_pwd[0]
            pwd = port_pwd[1]

            tmp_pwd = pwd+pwd

            # password list to check password of pdu 1 before password set
            self.ssh_vpdu.send_command_wait_string(str_command='password set 1 ' + port + ' ' + tmp_pwd + chr(13),
                                                   wait='(vPDU)',
                                                   int_time_out=10,
                                                   b_with_buff=False)
            str_rsp_pwd_tmp_list = self.ssh_vpdu.send_command_wait_string(str_command='password list 1'+chr(13),
                                                                          wait='(vPDU)',
                                                                          int_time_out=10,
                                                                          b_with_buff=False)

            pattern = r'\|\s*'+port+'\s*\|\s*'+tmp_pwd+'\s*\|'
            m_tmp_pwd = re.search(pattern, str_rsp_pwd_tmp_list)

            if not m_tmp_pwd:
                self.log('WARNING', 'Command "password set 1 {} {}" fails to change pdu port password. '
                                    'Password list before "password set" is"\n'
                                    '{}\n'
                                    'Password list after "password set" is:\n'
                                    '{}\n'
                                    'PDU is {} {}'.
                         format(port, tmp_pwd, str_rsp_pwd_list, str_rsp_pwd_tmp_list, self.get_ip(), self.get_name()))
                return False
            else:
                # set password of password of the port of pdu 1 back to original.
                self.ssh_vpdu.send_command_wait_string(str_command='password set 1 ' + port + ' ' + pwd + chr(13),
                                                       wait='(vPDU)',
                                                       int_time_out=10,
                                                       b_with_buff=False)
                self.ssh_vpdu.send_command_wait_string(str_command='password list 1'+chr(13),
                                                       wait='(vPDU)',
                                                       int_time_out=10,
                                                       b_with_buff=False)
                return True

        # If the pdu doesn't have port set with password, set password for vpdu 1 port 1.
        else:
            port = '1'
            pwd = 'idic'
            # password list to check password of pdu 1 before password set
            self.ssh_vpdu.send_command_wait_string(str_command='password set 1 ' + port + ' ' + pwd + chr(13),
                                                   wait='(vPDU)',
                                                   int_time_out=10,
                                                   b_with_buff = False)
            str_rsp_pwd_tmp_list = self.ssh_vpdu.send_command_wait_string(str_command='password list 1'+chr(13),
                                                                          wait='(vPDU)',
                                                                          int_time_out=10,
                                                                          b_with_buff=False)

            pattern = r'\|\s*'+port+'\s*\|\s*'+pwd+'\s*\|'
            m_tmp_pwd = re.search(pattern, str_rsp_pwd_tmp_list)

            if not m_tmp_pwd:
                self.log('WARNING', 'Command "password set 1 {} {}" fails to change pdu port password. '
                                    'Password list before "password set" is"\n'
                                    '{}\n'
                                    'Password list after "password set" is:\n'
                                    '{}\n'
                                    'PDU is {} {}'.
                         format(port, pwd, str_rsp_pwd_list, str_rsp_pwd_tmp_list, self.get_ip(), self.get_name()))
                return False
            else:
                return True
Exemple #12
0
    def __init__(self, dict_chassis):
        """
        dict_chassis example:
        {
            "name": "chassis",
            "ip": "192.168.132.144",
            "username": "******",
            "password": "******",
            "chassis_node_a": [{
                "admin": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******",
                    "port": "18022"
                },
                "guest_os": {
                    "ip": "10.62.83.132",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******"
                }
            }],
            "chassis_node_b": [{
                "admin": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******",
                    "port": "28022"
                },
                "guest_os": {
                    "ip": "10.62.83.136",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******"
                }
            }]
        }
        """

        CDevice.__init__(self, 'vChassis')

        self.dict_config = dict_chassis

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        self.node_a_name = '{}_a'.format(self.name)
        self.node_b_name = '{}_b'.format(self.name)

        self.ip = self.dict_config.get('ip', '')
        self.dict_node_a = self.dict_config.get(self.node_a_name)
        self.dict_node_b = self.dict_config.get(self.node_b_name)

        self.username = self.dict_config.get('username', '')
        self.password = self.dict_config.get('password', '')
        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip,
                                     username='',
                                     password='',
                                     port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip,
                        username=self.username,
                        password=self.password,
                        port=22)
Exemple #13
0
    def __init__(self, dict_chassis):
        """
        dict_chassis example:
        {
            "name": "chassis",
            "ip": "192.168.132.144",
            "username": "******",
            "password": "******",
            "chassis_node_a": [{
                "admin": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******",
                    "port": "18022"
                },
                "guest_os": {
                    "ip": "10.62.83.132",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******"
                }
            }],
            "chassis_node_b": [{
                "admin": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******",
                    "port": "28022"
                },
                "guest_os": {
                    "ip": "10.62.83.136",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******"
                }
            }]
        }
        """

        CDevice.__init__(self, 'vChassis')

        self.dict_config = dict_chassis

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        self.node_a_name = '{}_a'.format(self.name)
        self.node_b_name = '{}_b'.format(self.name)

        self.ip = self.dict_config.get('ip', '')
        self.dict_node_a = self.dict_config.get(self.node_a_name)
        self.dict_node_b = self.dict_config.get(self.node_b_name)

        self.username = self.dict_config.get('username', '')
        self.password = self.dict_config.get('password', '')
        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip, username='', password='', port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip, username=self.username, password=self.password, port=22)
Exemple #14
0
class CChassis(CDevice):
    def __init__(self, dict_chassis):
        """
        dict_chassis example:
        {
            "name": "chassis",
            "ip": "192.168.132.144",
            "username": "******",
            "password": "******",
            "chassis_node_a": [{
                "admin": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******",
                    "port": "18022"
                },
                "guest_os": {
                    "ip": "10.62.83.132",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******"
                }
            }],
            "chassis_node_b": [{
                "admin": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******",
                    "port": "28022"
                },
                "guest_os": {
                    "ip": "10.62.83.136",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******"
                }
            }]
        }
        """

        CDevice.__init__(self, 'vChassis')

        self.dict_config = dict_chassis

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        self.node_a_name = '{}_a'.format(self.name)
        self.node_b_name = '{}_b'.format(self.name)

        self.ip = self.dict_config.get('ip', '')
        self.dict_node_a = self.dict_config.get(self.node_a_name)
        self.dict_node_b = self.dict_config.get(self.node_b_name)

        self.username = self.dict_config.get('username', '')
        self.password = self.dict_config.get('password', '')
        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip, username='', password='', port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip, username=self.username, password=self.password, port=22)

    def get_config(self):
        return self.dict_config

    def get_name(self):
        return self.name

    def get_ip(self):
        return self.ip

    def set_ip(self, str_ip):
        self.ip = str_ip

    def get_guest_ip(self, node):
        self.guest_ip = node.dict_config['guest_os'].get('ip', '')
        return self.guest_ip

    def get_guest_user(self, node):
        self.guest_user = node.dict_config['guest_os'].get('username', '')
        return self.guest_user

    def get_guest_password(self, node):
        self.guest_password = node.dict_config['guest_os'].get('password', '')
        return self.guest_password

    def get_username(self):
        return self.username

    def set_username(self, str_username):
        self.username = str_username

    def get_password(self):
        return self.password

    def get_node_list(self):
        node_list = []
        for item in self.dict_config:
            p_node = re.search(r'{}_(.*)'.format(self.name), item)
            if p_node:
                obj_node = CNode(self.dict_config.get(item))
                node_list.append(obj_node)
        return node_list

    def set_password(self, str_password):
        self.password = str_password

    @with_connect('ssh')
    def chassis_start(self):
        '''
        To start a chassis, which will include infrasim chassis, node_a and node_b
        :return:
        '''
        self.log("INFO", "Start infrasim chassis {}...".format(self.name))
        str_command = "sudo infrasim chassis start {}".format(self.name)
        self.ssh.remote_shell(str_command)

    @with_connect('ssh')
    def get_instance_name(self):
        '''
        Get run time chassis, node_a and node_b name from chassis host vm.
        :return: chassis_ins_name, node_ins_a, node_ins_b
        '''
        self.log("INFO", "Get chassis runtime instance name from {}...".format(self.get_ip()))
        command = 'ps ax |grep infrasim-chassis |grep -v grep'
        rsp_dict = self.ssh.remote_shell(command)
        rsp = rsp_dict.get('stdout')
        chassis_ins_name = strip_color_code((rsp.split('\n'))[0].split()[6])

        self.log("INFO", "Get node_a runtime instance name ...")
        str_command = "sudo infrasim node status {}".format(self.node_a_name)
        rsp = self.ssh.remote_shell(str_command)
        p_name = re.search(r'(.*)-node is running', rsp.get('stdout'))
        node_ins_a = ''
        if p_name:
            node_ins_a = self.node_a_name
        else:
            self.log("WARNING", "Node {} is not running".format(self.node_a_name))

        self.log("INFO", "Get node_b runtime instance name ...")
        str_command = 'sudo infrasim node status {}'.format(self.node_b_name)
        rsp = self.ssh.remote_shell(str_command)
        p_name = re.search(r'(.*)-node is running', rsp.get('stdout'))
        node_ins_b = ''
        if p_name:
            node_ins_b = self.node_b_name
        else:
            self.log("WARNING", "Node {} is not running".format(self.node_b_name))

        return chassis_ins_name, node_ins_a, node_ins_b

    @with_connect('ssh')
    def guest_access(self, node):
        '''
        Access to node_a and node_b guest OS: ping the ip address in guest os
        :return: True or False
        '''
        guest_ip = self.get_guest_ip(node)
        str_command = 'ping {} -c 3 '.format(guest_ip)
        rsp = self.ssh.remote_shell(str_command)
        ping = re.search(r'0% packet loss', rsp.get('stdout'))

        if ping:
            return True
        else:
            self.log("WARNING", "Guest OS can not access; Check your chassis!!")
            return False

    @with_connect('ssh')
    def ipmi_lan_print(self, node):
        '''
        run ipmitool lan print on a/b node
        :return:
        '''
        cmd = 'ipmitool -I lanplus -H {} -U {} -P {} lan print'.format(node.bmc.get_ip(),
                                                                       node.bmc.get_username(),
                                                                       node.bmc.get_password())
        rsp = self.ssh.remote_shell(cmd)
        return rsp.get("stdout")

    @with_connect('ssh')
    def ipmi_fru_print(self, node):
        '''
        run ipmitool command to get fru info on a/b node
        :return:
        '''
        cmd = 'ipmitool -I lanplus -H {} -U {} -P {} fru print'.format(node.bmc.get_ip(),
                                                                       node.bmc.get_username(),
                                                                       node.bmc.get_password())
        rsp = self.ssh.remote_shell(cmd)
        return rsp.get('stdout')

    @with_connect('ssh')
    def send_command_to_guest(self, node, cmd_str):
        '''
        Send command to guest os
        :return: {
            'stdout': str_stdout,
            'stderr': str_stderr,
            'exitcode': int_exitcode
        }
        '''
        cmd = r"sudo sshpass -p {} ssh -o StrictHostKeyChecking=no -tt {}@{} '{}' ".format(node.guest_password,
                                                                                           node.guest_user,
                                                                                           node.guest_ip,
                                                                                           cmd_str)
        rst_dict = self.ssh.remote_shell(cmd)
        return rst_dict
Exemple #15
0
    def __init__(self, dict_hwimo):
        '''
        Init Monorail instance
        :param dict_hwimo: a dict includes HWIMO information, e.g.
        {
            "ip": "192.168.128.1"
            "platform": "RackHD",
            "monorail_rest_rev": "1.1",
            "monorail_rest_protocol": "http",
            "monorail_rest_port": 8080,
            "username": "",
            "password": ""
        }
        '''

        CDevice.__init__(self, 'Monorail', None, None)

        try:
            self.str_device_type = 'monorail'
            self.str_sub_type = 'Root'
            # Monorail IP
            self.ip = dict_hwimo['ip']
            self.username = dict_hwimo['username']
            self.password = dict_hwimo['password']
            self.rest_username = dict_hwimo['rest_username']
            self.rest_password = dict_hwimo['rest_password']

            # Monorail REST info
            self.str_mon_rev = dict_hwimo['rest_rev']
            self.str_mon_protocol = dict_hwimo['rest_protocol']
            self.str_mon_port = dict_hwimo['rest_port']
            self.uri = '{0}://{1}:{2}/api/{3}'.format(self.str_mon_protocol,
                                                      self.ip,
                                                      self.str_mon_port,
                                                      self.str_mon_rev)
        except Exception:
            self.log('ERROR', 'Fail to build {}\n{}'\
                     .format(self.str_sub_type, traceback.format_exc()))

        self.obj_rest_agent = APIClient()
        self.set_rest_agent(self.obj_rest_agent)
        self.set_rackhd_rest_auth()
        self.obj_ssh_agent = CSSH(self.ip, self.username, self.password)

        self.b_valid = True

        # Pre-defined next level object
        self.catalogs = None
        self.config = None
        self.files = None
        self.obj_lookups = None
        self.nodes = None
        self.obms = None
        self.pollers = None
        self.profiles = None
        self.schemas = None
        self.skus = None
        self.tasks = None
        self.templates = None
        self.versions = None
        self.workflowtasks = None
        self.workflows = None
        self.workflow_library = None
        self.mon_data = {}
Exemple #16
0
class CPDU(CDevice):
    def __init__(self, dict_pdu):

        CDevice.__init__(self, 'vPDU')

        self.dict_config = dict_pdu

        self.ip = self.dict_config.get('ip', '')
        self.name = self.dict_config.get('name', '')
        self.community = self.dict_config.get('community', '')

        # Build outlet mapping
        self.outlet = {}
        for str_outlet, str_password in self.dict_config.get('outlet',
                                                             {}).items():
            self.outlet[str_outlet] = {'node': None, 'password': str_password}

        self.snmp = CSNMP(self.ip, self.community)
        self.ssh_vpdu = CSSH(ip=self.ip, username='', password='', port=20022)

    def get_config(self):
        return self.dict_config

    def get_ip(self):
        return self.ip

    def get_name(self):
        return self.name

    def get_community(self):
        return self.community

    def connect(self, obj_node, str_outlet):
        '''
        Connect a node to certain outlet
        :param obj_node: virtual node instance of idic.stack.Node.CNode
        :param str_outlet: a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        :return: True | False
            True is successfully connect PDU and node
            False is fail to connect PDU and node
        '''
        if str_outlet not in self.outlet:
            raise KeyError('Outlet {} is not defined in PDU {}'.format(
                str_outlet, self.name))
        if self.outlet[str_outlet]['node']:
            self.log(
                'WARNING',
                '{} outlet {} is occupied by node {}, fail to connect'.format(
                    self.name, str_outlet,
                    self.outlet[str_outlet]['node'].get_name()))
            return False
        else:
            # Some operation on SSH

            self.outlet[str_outlet]['node'] = obj_node
            if (self, str_outlet) not in obj_node.power:
                obj_node.power.append((self, str_outlet))
            self.log(
                'INFO', 'Connect PDU {} outlet {} to node {} DONE'.format(
                    self.name, str_outlet, obj_node.get_name()))
            return True

    def disconnect(self, str_outlet):
        '''
        Disconnect an outlet
        :param str_outlet: a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        :return: True | False
            True is successfully disconnect PDU and node
            False is fail to disconnect PDU and node
        '''
        if str_outlet not in self.outlet:
            raise KeyError('Outlet {} is not defined in PDU {}'.format(
                str_outlet, self.name))
        if not self.outlet[str_outlet]['node']:
            self.log(
                'INFO',
                '{} outlet {} is not connected'.format(self.name, str_outlet))
            return True
        else:
            # Some operation on SSH

            obj_node = self.outlet[str_outlet]['node']
            if (self, str_outlet) in obj_node.power:
                obj_node.power.remove((self, str_outlet))
            self.outlet[str_outlet]['node'] = None
            return True

    def self_check(self):
        list_fail_item = []
        for str_check_item, oid in OID_CHECK_LIST.items():
            err_indicator, err_status, err_index, var_binds = self.snmp.get(
                oid)
            if err_indicator or err_status or err_index:
                self.log(
                    'ERROR', "{} (IP: {}) fail on {} check:\n"
                    "Error indicator: {}\n"
                    "Error status: {}\n"
                    "Error index: {}".format(self.name,
                                             self.ip, str_check_item,
                                             str(err_indicator), err_status,
                                             err_index))
                list_fail_item.append(str_check_item)
            else:
                self.log(
                    'INFO',
                    "{} check {} is done".format(self.name, str_check_item))

        if list_fail_item:
            self.log('ERROR', 'Fail items: {}'.format(str(list_fail_item)))
            return False
        else:
            return True

    def get_outlet_password(self, str_outlet):
        if str_outlet not in self.outlet:
            raise KeyError('Outlet {} is not defined in PDU {}'.format(
                str_outlet, self.name))
        return self.outlet[str_outlet].get('password', '')

    @with_connect('ssh_vpdu')
    def set_outlet_password(self, str_outlet, str_password):
        # Some operation on SSH
        pass

    def match_outlet_password(self, str_outlet, str_password=''):
        '''
        Match a password on a certain outlet before power on/off operation
        :param str_outlet: a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        :param str_password: password in string
        '''
        oid = OID_PDU_OUT_PWD_ROOT + tuple(str_outlet.split('.'))
        if not str_password:
            str_password = self.get_outlet_password(str_outlet)

        err_indicator, err_status, err_index, var_binds = self.snmp.set(
            oid, 'OctetString', str_password)
        if err_indicator or err_status or err_index:
            self.log(
                'ERROR',
                "{} (IP: {}) fail to match password \"{}\" on outlet {}:\n"
                "Error indicator: {}\n"
                "Error status: {}\n"
                "Error index: {}".format(self.name, self.ip,
                                         str_password, str_outlet,
                                         str(err_indicator), err_status,
                                         err_index))
            return False
        else:
            self.log(
                'INFO', "{} match password on outlet {}: {} is done".format(
                    self.name, str_outlet, str_password))
            return True

    def power_on(self, str_outlet):
        '''
        Power on a certain outlet
        :param str_outlet:  a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        '''
        oid = OID_PDU_OUT_ON_ROOT + tuple(str_outlet.split('.'))
        err_indicator, err_status, err_index, var_binds = self.snmp.set(
            oid, 'Integer', INT_PDU_OUT_ON)
        if err_indicator or err_status or err_index:
            self.log(
                'ERROR', "{} (IP: {}) fail to power on outlet {}:\n"
                "Error indicator: {}\n"
                "Error status: {}\n"
                "Error index: {}".format(self.name, self.ip, str_outlet,
                                         str(err_indicator), err_status,
                                         err_index))
            return False
        else:
            self.log(
                'INFO',
                "{} power on outlet {} is done".format(self.name, str_outlet))
            return True

    def power_off(self, str_outlet):
        '''
        Power off a certain outlet
        :param str_outlet:  a string of "<pdu#>.<port#>", e.g. "1.1", "3.2"
        '''
        oid = OID_PDU_OUT_ON_ROOT + tuple(str_outlet.split('.'))
        err_indicator, err_status, err_index, var_binds = self.snmp.set(
            oid, 'Integer', INT_PDU_OUT_OFF)
        if err_indicator or err_status or err_index:
            self.log(
                'ERROR', "{} (IP: {}) fail to power off outlet {}:\n"
                "Error indicator: {}\n"
                "Error status: {}\n"
                "Error index: {}".format(self.name, self.ip, str_outlet,
                                         str(err_indicator), err_status,
                                         err_index))
            return False
        else:
            self.log(
                'INFO',
                "{} power off outlet {} is done".format(self.name, str_outlet))
            return True

    @with_connect('ssh_vpdu')
    def verify_password_set(self):
        '''
        Verify pdu password set. password set, and password list commands are tested.
        :return: return "True" if test pass, else return "False"
        '''
        # password list to check password of pdu 1 before password set
        str_rsp_pwd_list = self.ssh_vpdu.send_command_wait_string(
            str_command='password list 1' + chr(13),
            wait='(vPDU)',
            int_time_out=10,
            b_with_buff=False)

        # get pattern line
        pattern = r'\|\s*\d+\s*\|\s*\S+\s*\|'
        m_pwd_list = re.search(pattern, str_rsp_pwd_list)

        # If the pdu have at least 1 port set with password,
        # test to set the first port's password, and then set it back to original
        if m_pwd_list:

            # split pattern line, get port and password
            m_pwd_stripped_space = m_pwd_list.group(0).strip("|").replace(
                " ", "")
            port_pwd = re.split(r'\|\s*', m_pwd_stripped_space)
            port = port_pwd[0]
            pwd = port_pwd[1]

            tmp_pwd = pwd + pwd

            # password list to check password of pdu 1 before password set
            self.ssh_vpdu.send_command_wait_string(
                str_command='password set 1 ' + port + ' ' + tmp_pwd + chr(13),
                wait='(vPDU)',
                int_time_out=10,
                b_with_buff=False)
            str_rsp_pwd_tmp_list = self.ssh_vpdu.send_command_wait_string(
                str_command='password list 1' + chr(13),
                wait='(vPDU)',
                int_time_out=10,
                b_with_buff=False)

            pattern = r'\|\s*' + port + '\s*\|\s*' + tmp_pwd + '\s*\|'
            m_tmp_pwd = re.search(pattern, str_rsp_pwd_tmp_list)

            if not m_tmp_pwd:
                self.log(
                    'WARNING',
                    'Command "password set 1 {} {}" fails to change pdu port password. '
                    'Password list before "password set" is"\n'
                    '{}\n'
                    'Password list after "password set" is:\n'
                    '{}\n'
                    'PDU is {} {}'.format(port, tmp_pwd, str_rsp_pwd_list,
                                          str_rsp_pwd_tmp_list, self.get_ip(),
                                          self.get_name()))
                return False
            else:
                # set password of password of the port of pdu 1 back to original.
                self.ssh_vpdu.send_command_wait_string(
                    str_command='password set 1 ' + port + ' ' + pwd + chr(13),
                    wait='(vPDU)',
                    int_time_out=10,
                    b_with_buff=False)
                self.ssh_vpdu.send_command_wait_string(
                    str_command='password list 1' + chr(13),
                    wait='(vPDU)',
                    int_time_out=10,
                    b_with_buff=False)
                return True

        # If the pdu doesn't have port set with password, set password for vpdu 1 port 1.
        else:
            port = '1'
            pwd = 'idic'
            # password list to check password of pdu 1 before password set
            self.ssh_vpdu.send_command_wait_string(
                str_command='password set 1 ' + port + ' ' + pwd + chr(13),
                wait='(vPDU)',
                int_time_out=10,
                b_with_buff=False)
            str_rsp_pwd_tmp_list = self.ssh_vpdu.send_command_wait_string(
                str_command='password list 1' + chr(13),
                wait='(vPDU)',
                int_time_out=10,
                b_with_buff=False)

            pattern = r'\|\s*' + port + '\s*\|\s*' + pwd + '\s*\|'
            m_tmp_pwd = re.search(pattern, str_rsp_pwd_tmp_list)

            if not m_tmp_pwd:
                self.log(
                    'WARNING',
                    'Command "password set 1 {} {}" fails to change pdu port password. '
                    'Password list before "password set" is"\n'
                    '{}\n'
                    'Password list after "password set" is:\n'
                    '{}\n'
                    'PDU is {} {}'.format(port, pwd, str_rsp_pwd_list,
                                          str_rsp_pwd_tmp_list, self.get_ip(),
                                          self.get_name()))
                return False
            else:
                return True
Exemple #17
0
    def get_host_ssh(self, obj_node, username, password, **kwargs):
        '''
        Build a SSH connection to host in virtual node
        '''
        if 'qemu_ip' in kwargs:
            self.log('INFO', 'Build host SSH to {}@{}'.format(username, kwargs['qemu_ip']))
            conn = CSSH(ip=kwargs['qemu_ip'], username=username, password=password, port=kwargs.get('port', 22))
            conn.connect()
            return conn

        # To get host's IP address:
        #     - Get MAC
        #     - Get IP via DHCP lease on DHCP server
        #     - Check if IP is available
        #     - SSH to host
        if 'dhcp_server' in kwargs and 'dhcp_user' in kwargs and 'dhcp_pass' in kwargs:
            self.log('INFO', 'Query host IP from DHCP server {} ...'.format(kwargs['dhcp_server']))

            # Get IP
            rsp_qemu = obj_node.get_bmc().ssh.remote_shell('ps aux | grep qemu')
            if rsp_qemu['exitcode'] != 0:
                raise Exception('Fail to get node {} qemu MAC address'.format(obj_node.get_name()))
            qemu_mac = rsp_qemu['stdout'].split('mac=')[1].split(' ')[0].lower()
            self.log('INFO', 'Node {} host MAC address is: {}'.format(obj_node.get_name(), qemu_mac))

            self.log('INFO', 'Wait node {} host IP address in up to 300s ...'.format(obj_node.get_name()))
            time_start = time.time()
            qemu_ip = ''
            while time.time() - time_start < 300:
                try:
                    qemu_ip = dhcp_query_ip(server=kwargs['dhcp_server'],
                                            username=kwargs['dhcp_user'],
                                            password=kwargs['dhcp_pass'],
                                            mac=qemu_mac)
                    if qemu_ip == obj_node.get_bmc().get_ip():
                        self.log('WARNING', 'IP lease for mac {} is {} to node {}\'s BMC, '
                                            'waiting for host IP lease, retry after 30s ...'.
                                 format(qemu_mac, qemu_ip, obj_node.get_name()))
                        time.sleep(30)
                        continue
                    rsp = os.system('ping -c 1 {}'.format(qemu_ip))
                    if rsp != 0:
                        self.log('WARNING', 'Find an IP {} lease for mac {} on node {}, '
                                            'but this IP address is not available, retry after 30s ...'.
                                 format(qemu_ip, qemu_mac, obj_node.get_name()))
                        time.sleep(30)
                        continue
                    else:
                        self.log('INFO', 'Node {} host get IP {}'.format(obj_node.get_name(), qemu_ip))
                        break
                except Exception, e:
                    self.log('WARNING', 'Fail to get node {}\'s host IP: {}'.format(obj_node.get_name(), e))
                    time.sleep(30)

            if not qemu_ip:
                raise Exception('Fail to get node {}\'s host IP in 300s, '
                                'check if vSwith\'s promiscuous mode is "Accept"'.
                                format(obj_node.get_name()))

            conn = CSSH(ip=qemu_ip,
                        username=kwargs.get('host_username', 'june'),
                        password=kwargs.get('host_password', '111111'),
                        port=kwargs.get('port', 22))
            conn.connect()
            return conn
Exemple #18
0
class CChassis(CDevice):
    def __init__(self, dict_chassis):
        """
        dict_chassis example:
        {
            "name": "chassis",
            "ip": "192.168.132.144",
            "username": "******",
            "password": "******",
            "chassis_node_a": [{
                "admin": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******",
                    "port": "18022"
                },
                "guest_os": {
                    "ip": "10.62.83.132",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.141",
                    "username": "******",
                    "password": "******"
                }
            }],
            "chassis_node_b": [{
                "admin": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******",
                    "port": "28022"
                },
                "guest_os": {
                    "ip": "10.62.83.136",
                    "username": "******",
                    "password": "******",
                    "port": "22"
                },
                "bmc": {
                    "ip": "10.62.83.145",
                    "username": "******",
                    "password": "******"
                }
            }]
        }
        """

        CDevice.__init__(self, 'vChassis')

        self.dict_config = dict_chassis

        # Power, a tuple of PDU information:
        # (obj_pdu, str_outlet)
        self.power = []

        self.name = self.dict_config.get('name', '')
        self.node_a_name = '{}_a'.format(self.name)
        self.node_b_name = '{}_b'.format(self.name)

        self.ip = self.dict_config.get('ip', '')
        self.dict_node_a = self.dict_config.get(self.node_a_name)
        self.dict_node_b = self.dict_config.get(self.node_b_name)

        self.username = self.dict_config.get('username', '')
        self.password = self.dict_config.get('password', '')
        self.port_ipmi_console = self.dict_config.get('ipmi-console', 9300)
        self.ssh_ipmi_console = CSSH(self.ip,
                                     username='',
                                     password='',
                                     port=self.port_ipmi_console)
        self.ssh = CSSH(self.ip,
                        username=self.username,
                        password=self.password,
                        port=22)

    def get_config(self):
        return self.dict_config

    def get_name(self):
        return self.name

    def get_ip(self):
        return self.ip

    def set_ip(self, str_ip):
        self.ip = str_ip

    def get_guest_ip(self, node):
        self.guest_ip = node.dict_config['guest_os'].get('ip', '')
        return self.guest_ip

    def get_guest_user(self, node):
        self.guest_user = node.dict_config['guest_os'].get('username', '')
        return self.guest_user

    def get_guest_password(self, node):
        self.guest_password = node.dict_config['guest_os'].get('password', '')
        return self.guest_password

    def get_username(self):
        return self.username

    def set_username(self, str_username):
        self.username = str_username

    def get_password(self):
        return self.password

    def get_node_list(self):
        node_list = []
        for item in self.dict_config:
            p_node = re.search(r'{}_(.*)'.format(self.name), item)
            if p_node:
                obj_node = CNode(self.dict_config.get(item))
                node_list.append(obj_node)
        return node_list

    def set_password(self, str_password):
        self.password = str_password

    @with_connect('ssh')
    def chassis_start(self):
        '''
        To start a chassis, which will include infrasim chassis, node_a and node_b
        :return:
        '''
        self.log("INFO", "Start infrasim chassis {}...".format(self.name))
        str_command = "sudo infrasim chassis start {}".format(self.name)
        self.ssh.remote_shell(str_command)

    @with_connect('ssh')
    def get_instance_name(self):
        '''
        Get run time chassis, node_a and node_b name from chassis host vm.
        :return: chassis_ins_name, node_ins_a, node_ins_b
        '''
        self.log(
            "INFO", "Get chassis runtime instance name from {}...".format(
                self.get_ip()))
        command = 'ps ax |grep infrasim-chassis |grep -v grep'
        rsp_dict = self.ssh.remote_shell(command)
        rsp = rsp_dict.get('stdout')
        chassis_ins_name = strip_color_code((rsp.split('\n'))[0].split()[6])

        self.log("INFO", "Get node_a runtime instance name ...")
        str_command = "sudo infrasim node status {}".format(self.node_a_name)
        rsp = self.ssh.remote_shell(str_command)
        p_name = re.search(r'(.*)-node is running', rsp.get('stdout'))
        node_ins_a = ''
        if p_name:
            node_ins_a = self.node_a_name
        else:
            self.log("WARNING",
                     "Node {} is not running".format(self.node_a_name))

        self.log("INFO", "Get node_b runtime instance name ...")
        str_command = 'sudo infrasim node status {}'.format(self.node_b_name)
        rsp = self.ssh.remote_shell(str_command)
        p_name = re.search(r'(.*)-node is running', rsp.get('stdout'))
        node_ins_b = ''
        if p_name:
            node_ins_b = self.node_b_name
        else:
            self.log("WARNING",
                     "Node {} is not running".format(self.node_b_name))

        return chassis_ins_name, node_ins_a, node_ins_b

    @with_connect('ssh')
    def guest_access(self, node):
        '''
        Access to node_a and node_b guest OS: ping the ip address in guest os
        :return: True or False
        '''
        guest_ip = self.get_guest_ip(node)
        str_command = 'ping {} -c 3 '.format(guest_ip)
        rsp = self.ssh.remote_shell(str_command)
        ping = re.search(r'0% packet loss', rsp.get('stdout'))

        if ping:
            return True
        else:
            self.log("WARNING",
                     "Guest OS can not access; Check your chassis!!")
            return False

    @with_connect('ssh')
    def ipmi_lan_print(self, node):
        '''
        run ipmitool lan print on a/b node
        :return:
        '''
        cmd = 'ipmitool -I lanplus -H {} -U {} -P {} lan print'.format(
            node.bmc.get_ip(), node.bmc.get_username(),
            node.bmc.get_password())
        rsp = self.ssh.remote_shell(cmd)
        return rsp.get("stdout")

    @with_connect('ssh')
    def ipmi_fru_print(self, node):
        '''
        run ipmitool command to get fru info on a/b node
        :return:
        '''
        cmd = 'ipmitool -I lanplus -H {} -U {} -P {} fru print'.format(
            node.bmc.get_ip(), node.bmc.get_username(),
            node.bmc.get_password())
        rsp = self.ssh.remote_shell(cmd)
        return rsp.get('stdout')

    @with_connect('ssh')
    def send_command_to_guest(self, node, cmd_str):
        '''
        Send command to guest os
        :return: {
            'stdout': str_stdout,
            'stderr': str_stderr,
            'exitcode': int_exitcode
        }
        '''
        cmd = r"sudo sshpass -p {} ssh -o StrictHostKeyChecking=no -tt {}@{} '{}' ".format(
            node.guest_password, node.guest_user, node.guest_ip, cmd_str)
        rst_dict = self.ssh.remote_shell(cmd)
        return rst_dict