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)
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 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)
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 __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 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]
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)
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)
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)
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
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)
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
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 = {}
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
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
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