def exec_command(self, cmd): output = self._access.exec_command(cmd) logger.info('CMD: {}'.format(cmd)) logger.info('CMD OUTPUT: {}'.format(output)) return output
def config_dhcp(self, *args, **kwargs): """ method to configure dhcp server param : kwargs : dict server : dhcp server ip address, range : dhcp range ip address for client, gateway: gateway for client, subnet : subnet for client, Returns: :bool - True on success or False on failure: example: config_dhcp(server='2.2.2.10', range='2.2.2.2-2.2.2.6', gateway='2.2.2.1', subnet='2.2.2.0') """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) if 'range' not in kwargs: raise ValueError( 'The "range" is a mandatory parameter, should be split with "-"' ) range = kwargs.get('range') try: range = range.split('-') except: raise ValueError('The range value should be split with "-"!') range_start = range[0] range_end = range[1] if 'subnet' not in kwargs: raise ValueError('The "subnet" is a mandatory parameter!') subnet = kwargs.get('subnet') if 'server' not in kwargs: raise ValueError('The "server" is a mandatory parameter!') server = kwargs.get('server') interface = "eth1" netmask = '255.255.255.0' gateway_info = '' if 'interface' in kwargs: interface = kwargs.get('interface') if 'subnet' in kwargs: subnet = kwargs.get('subnet') if 'netmask' in kwargs: netmask = kwargs.get('netmaks') if 'gateway' in kwargs: gateway = kwargs.get('gateway') gateway_info = \ """ option routers {}; option subnet-mask {}; """.format(gateway, netmask) conf_info = \ """ ddns-update-style interim; ignore client-updates; subnet %s netmask %s { range dynamic-bootp %s %s; default-lease-time 300; max-lease-time 300; %s } """ % (subnet, netmask, range_start, range_end, gateway_info) service = "isc-dhcp-server" service_path = '/etc/default' service_file = '{}/{}'.format(service_path, service) self._access.shell("sed -i -e 's/INTERFACES=.*/INTERFACES=\"{}\"/g' {}".format(\ interface, service_file)) self.config_ip("{}/{}".format(server, netmask), interface) conf_path = '/etc/dhcp' conf_filename = "dhcpd.conf" conf_file = '{}/{}'.format(conf_path, conf_filename) self._access.shell("mv {} {}.bak".format(conf_file, conf_file)) self._access.shell("touch {}".format(conf_file)) for contents in va_parse_as_lines(conf_info): if len(contents) != 0: output = self._access.shell("echo '{}' >> {}".format( contents, conf_file)) try: self.service_stop(service) self.service_start(service) except ValueError as e: pass try: output = int(self._access.shell("netstat -uap |grep dhcpd -c")[0]) except: output = 0 if not output: logger.error('Failed to setup DHCP server') return (False) logger.info('Succeed to setup DHCP server') return True
def check_tcpdump(self, file, expr, *args, **kwargs): """ method to check traffic packets via tcpdump param : expr : expression to match traffic packet : file : packets file : kwargs : dict example : check_tcpdump(file, expr, **kwargs) kwargs = { 'exact' : 3, expect to receive packets number 'fuzzy' : 3-5, expect to receive packets number } return: True on success or False on failure """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) cmd = "tcpdump -nev -r {}".format(file) shell = self._access.shell packets_info = shell(cmd) shell("sudo rm -f {}".format(file)) if 'packets_info' not in dir(): logger.error('Failed to query traffic packets') return False got_packet_count = 0 logger.info('Packets info: {}'.format(packets_info)) for info in packets_info[0].split('\n'): info = info.strip() if re.search(expr, info) is not None: got_packet_count += 1 logger.info('Received packets number: {}'.format(got_packet_count)) if got_packet_count == 0: logger.info('Expression: {}'.format(expr)) if 'exact' in kwargs: packet_count = int(kwargs.get('exact')) if packet_count != got_packet_count: logger.error('Expected value: {}, actual value: {}'.format( packet_count, got_packet_count)) return False elif 'fuzzy' in kwargs: packet_count = kwargs.get('fuzzy') if '-' not in packet_count: logger.error('Invalid "fuzzy" parameter, expected value \ like this: 2-5') return False packet_count_min = int(packet_count.split('-')[0]) packet_count_max = int(packet_count.split('-')[1]) if packet_count_min > packet_count_max: logger.error('Invalid parameter: {}, the second parameter \ should be lager than first'.format(packet_count)) return False if packet_count_min > got_packet_count or \ packet_count_max < got_packet_count: logger.error('Expected value: {}-{}, actual value: {}'.format( packet_count_min, packet_count_max, got_packet_count)) return False else: if got_packet_count == 0: logger.error('Expected to receive at least one traffic packet') return False logger.info('Succeed to check traffic packets') return True
def start(self, *args, **kwargs): """ method used to start the Ftp traffic process in the background on the client. It does a clean up of file if existing locally. It launches the lftp client tool in the background, and gets the corresponding pid. If it cannot retrieve the pid it means the transfer is already complete or the process launch failed. kwargs: :file_size (str): size of the file to be put or get in terms of MB :mode (str): transfer mode, active or passive :rate (int): transfer rate (kb) :operation (str): put (upload) or get (download) :timeout (int): lftp timeout """ self._cmd = 'lftp' self._type = 'ftp' self._mode = 'passive' self._rate = 1024 * 128 self._timeout = 90 self._file_size = 100 self._operation = 'get' self._stats = None self._outfile = None if 'mode' in kwargs: self._mode = kwargs.get('mode') if 'rate' in kwargs: self._rate = kwargs.get('rate') self._rate = int(self._rate) * 1024 if 'operation' in kwargs: self._operation = kwargs.get('operation') if 'file_size' in kwargs: self._file_size = kwargs.get('file_size') if 'timeout' in kwargs: self._timeout = kwargs.get('timeout') self.ctr_port = kwargs.get('port',21) try: self._setup_server_infra() self._build_ftp_cmd() except ValueError as e: raise e client = self._conf_client self._transfer_cleanup_util(True) pid, outfile = client.exec_background(self._cmd, redirect=True, search_expr=self._cmd.split(' ')[0]) logger.info('Ftp pid: {}'.format(pid)) logger.info('Outfile: {}'.format(outfile)) self._outfile = outfile if not pid or outfile is None: raise ValueError('Ftp traffic not started') times = 1 sleeptime = 0.2 self._stats = self.get_stats() while (self._stats == 'failed' or self._stats is None) and times <= 5: logger.debug('Sleeping {} seconds to start traffic'.format(sleeptime)) time.sleep(sleeptime) self._stats = self.get_stats() times += 1 if self._stats == 'failed' or self._stats is None: raise ValueError('Ftp traffic not started') logger.info('Ftp traffic started')
def config_dns(self, *args, **kwargs): """ method to configure dns server param : kwargs : dict domain : domain name, record : a record of dns like "pc IN A 6.6.6.6" Returns: :bool - True on success or False on failure: example: config_dns(domain='varmour.net', record=['pc IN A 6.6.6.6']) """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) domain = 'varmour.net' record = 'pc IN A 6.6.6.6;' if 'domain' in kwargs: domain = kwargs.get('domain') if 'record' in kwargs: record = kwargs.get('record') if not isinstance(record, list): record = [record] soa_info = \ """ $TTL 86400 $ORIGIN {}. @ IN SOA pc.{}. master.pc.{}. ( 2008031101 ;Serial 86400 ;refresh 7200 ;retry 86400 ;expire 120 ;ttl ) """.format(domain, domain, domain) record_info = \ """ @ IN NS pc.{}. @ IN MX 5 pc test IN A 1.1.1.1; """.format(domain) for info in record: record_info = "{}\n{}".format(record_info, info) conf_info = \ """ zone "." { type hint; file "/etc/bind/db.root"; }; zone "localhost" { type master; file "/etc/bind/db.local"; }; zone "127.in-addr.arpa" { type master; file "/etc/bind/db.127"; }; zone "0.in-addr.arpa" { type master; file "/etc/bind/db.0"; }; zone "255.in-addr.arpa" { type master; file "/etc/bind/db.255"; }; zone "%s" IN { type master; file "/etc/bind/%s"; }; """ % (domain, domain) resolv_info = \ """ nameserver 127.0.0.1 """ service = "bind9" conf_path = '/etc/bind' conf_filename = "named.conf.default-zones" conf_file = '{}/{}'.format(conf_path, conf_filename) zone_info = soa_info + record_info zone_filename = domain zone_file = '{}/{}'.format(conf_path, zone_filename) resolv_file = '/etc/resolv.conf' for contents, f in zip([zone_info, conf_info, resolv_info], [zone_file, conf_file, resolv_file]): self._access.shell("mv {} {}.bak".format(f, f)) self._access.shell("touch {}".format(f)) for cont in va_parse_as_lines(contents): if len(cont) != 0: output = self._access.shell("echo '{}' >> {}".format( cont, f)) try: self.service_stop(service) self.service_start(service) except ValueError as e: logger.error(e) return False name, ip = self.send_dns_query(name='test.{}'.format(domain)) if ip != "1.1.1.1": logger.error('Failed to setup DNS server!') return False logger.info('Succeed to setup DNS server') return True
def setup(self, **kwargs): """ Implementation of setup test bed Kwargs: None Return: True : Succeed to setup test bed False : Failed to setup testbed Examples: vatpobj = VaTopo(test_param_file, topo_file) vatpobj.setup() """ setup_tb = self.control_data.get('setup_tb') cleanup_dut_cfg = self.control_data.get('cleanup_dut_cfg') upgrade_device = self.control_data.get('upgrade_device') logger.info("*********************************") logger.info("* ") logger.info("* Start to setup topology ") logger.info("* ") logger.info("*********************************") if (setup_tb.upper() == 'Y'): #Config links if not self.config_links(): logger.error('Failed to configure links') return False #Config interface if not self.va_config_interfaces(): logger.error('Failed to configure ip address of interfaces') return False #Config interface if not self.va_config_routes(): logger.error('Failed to configure routes') return False else: logger.info('Noe need to setup testbed') if (cleanup_dut_cfg.upper() == 'Y'): # Reset director if not self.va_reset_director(): return False else: logger.info('Not need to cleanup director') #upgrade device if need. if (upgrade_device.upper() == 'Y' and self.image is not None): if not self.va_update_firmware_for_directors(self.image): return False else: logger.info('Not need to upgrade device') #reconnect all cp/ep/epi logger.debug("*********************************") logger.debug("* ") logger.debug("* Finished to setup topology ") logger.debug("* ") logger.debug("*********************************") return True
def cleanup(self, **kwargs): """ Implementation of cleanup test bed Kwargs: None Return: True : Succeed to cleanup test bed False : Failed to cleanup testbed Examples: vatpobj = VaTopo(test_param_file, topo_file) vatpobj.cleanup() """ cleanup_tb = self.control_data.get('cleanup_tb') restore_dut_cfg = self.control_data.get('restore_dut_cfg') logger.info("*********************************") logger.info("* ") logger.info("* Start to clean topology ") logger.info("* ") logger.info("*********************************") if (cleanup_tb.upper() == 'Y'): #Remove interface if not self.va_unset_interfaces(): logger.error('Failed to remove ip address of interfaces') return False #Remove route if not self.va_unset_routes(): logger.error('Failed to remove routes') return False #Remove link if not self.revert_links(): logger.error('Failed to revert links') return False else: logger.info('Not need to cleanup testbed') if (restore_dut_cfg.upper() == 'Y'): # Reset director if not self.va_reset_director(): return False else: logger.info('Not need to restore director') logger.info("*********************************") logger.info("* ") logger.info("* Finished to clean topology ") logger.info("* ") logger.info("*********************************") return True
def recover_vcenter_workloads(self, filename=None): """ this method is apply to recover workloads. i.e putting workloads to its original state.this method is used for disaster recovery. Args: :original (list): original backup list where, user wants to revert back. """ if not filename: return original = '' try: fd = open(filename, 'r') for lines in fd.readline(): original += lines fd.close() except IOError: logger.error("Can not Open file {}. Please see filename and\ path".format(filename)) original_state = ast.literal_eval(original) current_state = self.take_backup_vcenter() for current_obj in current_state: vm = current_obj['name'] current_host = current_obj['host'] current_network = current_obj['network'] for original_obj in original_state: if original_obj['name'] == vm: if original_obj['host'] == current_host: logger.info("Host of VM:{} is the same as " "original. Not changed.".format(vm)) else: logger.info("Host is not the same for VM:{}" "original host was {}, changed " "host is {}.".format( vm, original_obj['host'], current_host)) logger.info( "Going to change host for VM:{}...".format(vm)) self.vmotion(vm, original_obj['host']) if current_network == original_obj["network"]: logger.info("Network of VM:{} is the same as original." " Not changed.".format(vm)) else: logger.info("Network is not the same for VM:{}" " original network was {}, " "changed network is " "{}".format(vm, original_obj["network"], current_network)) logger.info("Network is going to change....") logger.info("Removing va-tag..") self.remove_tag_from_vm(vm) for nets in original_obj["network"]: for interface, portgroup in nets.items(): self.change_vm_vnic(vm, interface, portgroup)
def config_links(self): """ set link according to topo file Kwargs: None Return: True : Succeed to set link according to topo file. False : Failed to set link according to topo file. Examples: vatpobj = VaTopo(test_param_file, topo_file) vatpobj.config_links() """ link_info = self.link_info reserved_vlan = self.va_get_reserved_vlan() reserved_vlans = [] for vlan_range in reserved_vlan: vlan_start = int(vlan_range.split('-')[0]) vlan_end = int(vlan_range.split('-')[1]) vlans = range(vlan_start, vlan_end) reserved_vlans += vlans logger.info("Start to config link") index = 0 for link_key in link_info.keys(): num = 1 for pc_key in link_info[link_key]: if num == 1: src_port_sw = link_info[link_key][pc_key]['interface'][ 'vswitch'] src_portgroup = link_info[link_key][pc_key]['interface'][ 'port_group'] src_int = link_info[link_key][pc_key]['interface'][ 'phy_name'] src_dev = pc_key if num == 2: dst_port_sw = link_info[link_key][pc_key]['interface'][ 'vswitch'] dst_portgroup = link_info[link_key][pc_key]['interface'][ 'port_group'] dst_int = link_info[link_key][pc_key]['interface'][ 'phy_name'] dst_dev = pc_key if 'vlan' in link_info[link_key][pc_key] and \ link_info[link_key][pc_key]['vlan'] is not None: vlan_val = link_info[link_key][pc_key]['vlan'] else: vlan_val = reserved_vlans[index] hv_uqid = link_info[link_key][pc_key]['hyp_visor']['uniq_id'] num += 1 index += 1 if (len(link_info[link_key]) == 2) and (src_port_sw != dst_port_sw): logger.error('The link is not in the same switch') return False else: if len(link_info[link_key]) == 2: logger.info('Connection:{} Access vlan ({}),from {}:{}, to {}:{}, switch : {}'\ .format(link_key,vlan_val,src_dev,src_int,dst_dev,dst_int,src_port_sw)) else: logger.info('Connection:{} Access vlan ({}),{}:{}, switch : {}' \ .format(link_key, vlan_val, src_dev, src_int, src_port_sw)) vswobj = self.swobjs[hv_uqid][src_port_sw] if not vswobj.update_vlan(src_portgroup, vlan_val): return False #update portgroup for destination pc/device if need if len(link_info[link_key]) == 2: if not vswobj.update_vlan(dst_portgroup, vlan_val): return False vswobj.show_sw() logger.info("Completed to config link") return True
def va_send_and_verify_tftp(*args, **kwargs): """ API to send traffic and verify session related to FTP param : kwargs : dict example : va_send_and_verify_tftp(**kwargs) kwargs = { 'traffic_data' : { 'client' : pc1, 'server' : pc2, 'dest_intf' : 'eth1', more parameters refer to Icmp, }, 'session_data' : { 'policy' : 'test_pol', more parameters refer to va_verify_session, } 'dev_obj' : dir_1, return: :bool - True on success or False on failure: """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) if 'traffic_data' not in kwargs or \ 'session_data' not in kwargs: raise ValueError('traffic_data and session_data are \ mandatory parameters!\n') traffic_data = kwargs.get('traffic_data') session_data = kwargs.get('session_data') if 'dev_obj' not in kwargs: raise ValueError('dev_obj is mandatory parameter!\n') dev_obj = kwargs.get('dev_obj') dev_obj.va_clear_session() tftp_obj = Tftp(**traffic_data) try: tftp_obj.start(**traffic_data) except ValueError as e: logger.error(e) logger.debug('Start to clean traffic since got exception') tftp_obj.stop() return False session = dev_obj.va_get_session() times = 1 session_data['proto'] = 'tftp' data_session_before = dev_obj.va_get_data_session(**session_data) time.sleep(1) data_session_after = dev_obj.va_get_data_session(**session_data) is_increment = dev_obj.va_check_session_packets_increment( data_session_before, data_session_after) while times <= 6 and not is_increment: logger.info( 'Retry {} times to check if session packet increment'.format( times)) time.sleep(1) data_session_after = dev_obj.va_get_data_session(**session_data) is_increment = dev_obj.va_check_session_packets_increment( data_session_before, data_session_after) times += 1 tftp_obj.stop() if not is_increment: return False session_data['session'] = session if not dev_obj.va_verify_session(**session_data): return False del session_data['session'] return True
def start(self): """ method used to start the telnet traffic process in the background on the client. It does a clean up of file if existing locally. It launches the telnet client tool in the background, and gets the corresponding pid. If it cannot retrieve the pid it means the transfer is already complete or the process launch failed. """ cmd = self._telnet_cmd if not cmd: logger.info('Command is not passed ') pass # TODO: raise exception or warning logger.info('Server' + str(self._server)) servershell = LinuxShell(host=self._server, user=self._server_uid, pswd=self._server_pw) output, status = servershell.exec_command(' ls') print('server output : {} , Status : ', output, status) logger.info('Adding telnet details and restart xientd') xinetd_cmd = 'sudo apt-get install xinetd' telnet_server_details = '''service telnet { flags = REUSE socket_type = stream wait = no user = root server = /usr/sbin/in.telnetd log_on_failure += USERID disable = no }''' print(telnet_server_details) telnet_file_create_cmd = 'sudo echo \"' + telnet_server_details + \ '\" > /etc/xinetd.d/telnet' logger.info('check if the telnet service is already running') telnet_service_cmd = 'cat /etc/xinetd.d/telnet' output, status = servershell.exec_command(telnet_service_cmd) print('server output : {} , Status : ', output, status) if 'service telnet' in str(output): logger.info('telnet file already exists') else: print('telnet server details ', telnet_file_cmd) output, status = servershell.exec_command(telnet_file_create_cmd) print('server output : {} , Status : ', output, status) logger.info('restarting xinetd') xinetd_cmd = ' sudo chmod -R 777 /etc/xinetd.d/telnet; \ sudo chown -R 777 /etc/xinetd.d/telnet ' output, status = servershell.exec_command(xinetd_cmd) print('server output : {} , Status : ', output, status) xinetd_cmd = ' sudo /etc/init.d/xinetd restart ' output, status = servershell.exec_command(xinetd_cmd) print('server output : {} , Status : ', output, status) print('CLIENT execution starts here...............', self._client) clientshell = LinuxShell(host=self._client, user=self._client_uid, pswd=self._client_pw) print(cmd) output, status = clientshell.exec_command(cmd) logger.info('Telnet Command execution Output :\n' + str(output)) time.sleep(2) output = '' output, status = clientshell.exec_command('ps -ef | grep telnet') logger.info('......check the process is running or not in below \ output :....\n' + str(output)) #if 'sleep' + self._telnet_destination in str(output): if 'sleep' in str(output): logger.info('TELNET session started sucessfully \ output : \n' + str(output)) return True, output else: logger.error(".....TELNET session NOT started sucessfully") logger.error('this system might not have telnetd.\ Pleae install using the command : \ sudo apt-get install xinetd telnetd') return False, None
def va_send_and_verify_icmp(*args, **kwargs): """ API to send traffic, capture packet and verify session related to ICMP param : kwargs : dict example : va_send_and_verify_icmp(**kwargs) kwargs = { 'traffic_data' : { 'client' : pc1, 'server' : pc2, 'src_intf' : 'eth1', 'dest_intf' : 'eth1', 'size' : 64, 'count' : 5, more parameters refer to Icmp, }, 'tcpdump_data' : { 'expr' : expression to match packets, 'host' : 15.15.15.2, 'intf' : 'eth4', more parameters refer to start_tcpdump and check_tcpdump, }, 'session_data' : { 'policy' : 'test_pol', more parameters refer to va_verify_session, } 'dev_obj' : dir_1, return: :bool - True on success or False on failure: """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) if 'traffic_data' not in kwargs or \ 'session_data' not in kwargs: raise ValueError('traffic_data and session_data are \ mandatory parameters!\n') traffic_data = kwargs.get('traffic_data') session_data = kwargs.get('session_data') if 'dev_obj' not in kwargs: raise ValueError('dev_obj is mandatory parameter!\n') dev_obj = kwargs.get('dev_obj') if 'client' not in traffic_data or \ 'server' not in traffic_data or \ 'src_intf' not in traffic_data or \ 'dest_intf' not in traffic_data: raise ValueError('client, server, src_intf and dest_intf are \ mandatory parameters!\n') client = traffic_data.get('client') server = traffic_data.get('server') src_intf = traffic_data.get('src_intf') dest_intf = traffic_data.get('dest_intf') client_ip = client.get_ip(src_intf) server_ip = server.get_ip(dest_intf) tcpdump_data = None if 'tcpdump_data' in kwargs: tcpdump_data = kwargs.get('tcpdump_data') if 'intf' not in tcpdump_data: raise ValueError('intf is mandatory parameter!\n') intf = tcpdump_data.get('intf') if 'expr' in tcpdump_data: expr = tcpdump_data.get('expr') else: expr = '{}\s+>\s+{}:\s+ICMP echo request'.format( client_ip, server_ip) icmp_obj = Icmp(**traffic_data) if tcpdump_data is not None: packets_file, pid, process_file = server.start_tcpdump(intf=intf) if packets_file is None: return False dev_obj.va_clear_session() try: icmp_obj.start(**traffic_data) except ValueError as e: logger.error(e) logger.debug('Start to clean traffic since got exception') icmp_obj.stop() return False session = dev_obj.va_get_session() icmp_obj.stop() if tcpdump_data is not None: time.sleep(2) if not server.stop_tcpdump(pid, process_file): return False if not server.check_tcpdump(packets_file, expr, **tcpdump_data): return False session_data['proto'] = 'icmp' session_data['session'] = session if not dev_obj.va_verify_session(**session_data): return False del session_data['session'] return True
def va_clean_ha(*args, **kwargs): """ API to clean HA environment. param : kwargs : dict example : va_clean_ha(**kwargs) kwargs = { 'master' : {dir1 : {'local_address' : '8.8.8.1/24', 'remote_address' : '8.8.8.2', 'priority' : 8, 'preempt' : enable, 'sw_obj' : vswitch object, } }, 'pb' : {dir2 : {'local_address' : '8.8.8.2/24', 'remote_address' : '8.8.8.1' 'priority' : 10, 'preempt' : enable, 'sw_obj' : vswitch object, } }, 'origin_vlan' : dict, included vlan_port, vlan_id and vswitch of HA, used to split vlan of fabric of pb into different from master, 'timeout' : 60, } return: :bool - True on success or False on failure: """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) clean_status = True if 'master' not in kwargs or \ 'pb' not in kwargs: raise ValueError("master and pb are mandatory parameter!\n") master, master_kwargs = kwargs.get('master').popitem() pb, pb_kwargs = kwargs.get('pb').popitem() for kwgs in [master_kwargs, pb_kwargs]: if 'local_address' not in kwgs or \ 'remote_address' not in kwgs or\ 'sw_obj' not in kwgs: raise ValueError("'local_address', 'remote_address', \ 'sw_obj' are mandatory parameters!\n") if 'origin_vlan' not in kwargs: raise ValueError("origin_vlan is mandatory parameter!\n") origin_vlan = kwargs.pop('origin_vlan') if 'timeout' in kwargs: timeout = kwargs.get('timeout') else: timeout = 60 * 2 pb_uniq_id = pb._resource.get_uniq_id() pb_sw_obj = pb_kwargs.get('sw_obj') vlan_data = origin_vlan.get(pb_uniq_id) vlan_data['sw_obj'] = pb_sw_obj if not master.va_check_ha_is_master() and \ pb.va_check_ha_is_master(): if not pb.va_do_ha_failover(): return False for dev_obj in [master, pb]: times = 1 sleeptime = 10 is_ready = dev_obj.va_check_ha_ready() while not is_ready and times <= 30: logger.info('Sleeping {} seconds to wait'.format(sleeptime)) time.sleep(sleeptime) is_ready = dev_obj.va_check_ha_ready() times += 1 if not is_ready: return False if not va_update_ha_vlan(**vlan_data): return False if pb.va_show_ha().get('HA Mode') == 'ON': if not pb.va_remove_ha(*args, **pb_kwargs): clean_status = False if not pb.va_delete_db(): clean_status = False pb.va_reboot(reconnect_delay=timeout) if master.va_show_ha().get('HA Mode') == 'ON': if not master.va_remove_ha(*args, **master_kwargs): clean_status = False logger.info('Successfully cleaned HA environment') return clean_status
def va_setup_ha(*args, **kwargs): """ API to setup HA environment. param : kwargs : dict example : va_setup_ha(**kwargs) kwargs = { 'master' : {dir1 : {'local_address' : '8.8.8.1/24', 'remote_address' : '8.8.8.2', 'priority' : 8, 'preempt' : enable, 'sw_obj' : vswitch object, 'vlan' : 3, used to update vlan of fabric into the same with pb } }, 'pb' : {dir2 : {'local_address' : '8.8.8.2/24', 'remote_address' : '8.8.8.1' 'priority' : 10, 'preempt' : enable, 'sw_obj' : vswitch object, 'vlan' : 3, used to update vlan of fabric into the same with master } }, 'origin_vlan' : dict, included vlan_port, vlan_id and vswitch of HA, used to split vlan of fabric of pb into different from master 'timeout' : 60, } return: :bool - True on success or False on failure: """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) if 'master' not in kwargs or \ 'pb' not in kwargs: raise ValueError("master and pb are mandatory parameter!\n") master, master_kwargs = kwargs.get('master').popitem() pb, pb_kwargs = kwargs.get('pb').popitem() for kwgs in [master_kwargs, pb_kwargs]: if 'local_address' not in kwgs or \ 'remote_address' not in kwgs or\ 'vlan' not in kwgs or\ 'sw_obj' not in kwgs: raise ValueError("'local_address', 'remote_address', \ 'vlan' and 'sw_obj' are mandatory parameters!\n") if 'origin_vlan' not in kwargs: raise ValueError("origin_vlan is mandatory parameter!\n") origin_vlan = kwargs.pop('origin_vlan') if 'timeout' in kwargs: timeout = kwargs.get('timeout') else: timeout = 60 * 2 master_uniq_id = master._resource.get_uniq_id() pb_uniq_id = pb._resource.get_uniq_id() master_sw_obj = master_kwargs.get('sw_obj') pb_sw_obj = pb_kwargs.get('sw_obj') vlan_data = origin_vlan.get(pb_uniq_id) vlan_data['sw_obj'] = pb_sw_obj if not va_update_ha_vlan(**vlan_data): return False times = 1 sleeptime = 10 status = master.va_check_chassis_status() while not status and times <= 6: logger.info('Sleeping {} seconds to wait'.format(sleeptime)) time.sleep(sleeptime) status = master.va_check_chassis_status() times += 1 if not status: return False if not master.va_config_ha(*args, **master_kwargs): return False times = 1 sleeptime = 2 ha_info = master.va_show_ha() ha_mode = ha_info.get('HA Mode') while ha_mode != 'ON' and times <= 6: logger.info('Sleeping {} seconds to wait'.format(sleeptime)) time.sleep(sleeptime) ha_info = master.va_show_ha() ha_mode = ha_info.get('HA Mode') times += 1 if ha_mode != 'ON': return False if not pb.va_delete_db(): return False pb.va_reboot(reconnect_delay=timeout) if not pb.va_config_ha(*args, **pb_kwargs): return False pb.va_reboot(reconnect_delay=timeout) for uniq_id in [master_uniq_id, pb_uniq_id]: vlan_data = dict() if uniq_id == master_uniq_id: vlan_data = master_kwargs elif uniq_id == pb_uniq_id: vlan_data = pb_kwargs vlan_data['port_group'] = origin_vlan[uniq_id]['port_group'] if not va_update_ha_vlan(**vlan_data): return False for dev_obj in [master, pb]: times = 1 sleeptime = 10 logger.debug('Waiting HA to normal') try: ha_info = dev_obj.va_show_ha() ha_mode = ha_info.get('HA Mode') except: pass while ha_mode != 'ON' and times <= 6: logger.info('Sleeping {} seconds to wait'.format(sleeptime)) time.sleep(sleeptime) try: ha_info = dev_obj.va_show_ha() ha_mode = ha_info.get('HA Mode') except: pass times += 1 times = 1 sleeptime = 10 is_ready = dev_obj.va_check_ha_ready() while not is_ready and times <= 30: logger.info('Sleeping {} seconds to wait'.format(sleeptime)) time.sleep(sleeptime) is_ready = dev_obj.va_check_ha_ready() times += 1 if not is_ready: logger.error('Unsuccessfully configured HA environment') return False logger.info('Successfully configured HA environment') return True
def tcpreplay(self, *args, **kwargs): """ method used to tcpreplay param : kwargs : dict : src_net : source subnet, : src_intf : source interface, : dest_obj : destination object, : dest_intf : destination interface, : path : file path of traffic packet file, : infile : traffic packet file, : pps|mbps : Replay packets at a given packets/sec|Mbps, fast as possible by default returns: :tuple - True and output on success or False and error message on failure: example : tcpreplay(**kwargs) kwargs = { 'infile' : 'google.pcap', 'src_net' : '15.15.15.0/24', 'dest_obj' : pc2, 'mbps' : 3, } """ logger.info("\nIn subroutine: " + sys._getframe().f_code.co_name) if 'dest_obj' not in kwargs: raise ValueError('"dest_obj" is a mandatory parameter!') dest_obj = kwargs.get('dest_obj') if 'src_net' not in kwargs: raise ValueError('"src_net" is a mandatory parameter!') src_net = kwargs.get('src_net') if 'infile' not in kwargs: raise ValueError('"infile" is a mandatory parameter!') infile = kwargs.get('infile') outfile = "tcprewrite_outfile" if outfile in kwargs: outfile = kwargs.get('outfile') path = '/tmp' if 'path' in kwargs: path = kwargs.get('path') if '/' not in infile: infile = "{}/{}".format(path, infile) if '/' not in outfile: outfile = "{}/{}".format(path, outfile) cachefile = '{}/cachefile'.format(path) src_intf = 'eth1' dest_intf = 'eth1' if 'src_intf' in kwargs: src_intf = kwargs.get('src_intf') if 'dest_intf' in kwargs: dest_intf = kwargs.get('dest_intf') src_mac = self.get_mac(src_intf) dest_mac = dest_obj.get_mac(dest_intf) enet_smac = "{},{}".format(dest_mac, src_mac) enet_dmac = "{},{}".format(src_mac, dest_mac) if 'pps' in kwargs: opt_rate = "--pps={}".format(kwargs.get('pps')) elif 'mbps' in kwargs: opt_rate = "--mbps={}".format(kwargs.get('mbps')) else: opt_rate = "--topspeed" cmd_prep = "tcpprep" cmd_rewrite = "tcprewrite" cmd_replay = "tcpreplay" cmd_prep = "{} --cidr={} --pcap={} --cachefile={}".format(cmd_prep, src_net, \ infile, cachefile) cmd_rewrite = "{} --enet-smac={} --enet-dmac={} --fixcsum --cachefile={} \ --infile={} --outfile={}".format(cmd_rewrite, enet_smac, enet_dmac, cachefile, \ infile, outfile) cmd_replay = "{} --cachefile={} --intf1={} --intf2={} {} {}".format(cmd_replay, \ cachefile, src_intf, dest_intf, opt_rate, outfile) pattern = re.compile(r'command not found|No such file or directory') for cmd in [cmd_prep, cmd_rewrite, cmd_replay]: output = self._access.shell(cmd) if pattern.search(output[0]) is not None: return(False, output[0]) for f in [infile, outfile, cachefile]: self._access.shell("rm -f {}".format(f)) logger.debug('Tcpreplay info: \n{}'.format(output[0])) pattern = re.compile(r'Actual: \d+ packets \(\d+ bytes\) sent') if pattern.search(output[0]) is None: logger.error('Failed to tcpreplay, expected expression: {}'.format(pattern)) return(False, output[0]) logger.info('Succeed to tcpreplay') return(True, output[0])
def start(self, *args, **kwargs): """ method used to start the Icmp traffic process in the background on the client. It does a clean up of file if existing locally. It launches the ping client tool in the background, and gets the corresponding pid. If it cannot retrieve the pid it means the transfer is already complete or the process launch failed. kwargs: :src_intf (str): source interface name :count (int): number of ICMP pings :size (int): size of the ping packet :timeout (int): ping timeout """ self._cmd = 'ping' self._type = 'ping' self._count = 5 self._size = 56 self._timeout = int(self._count) + 3 self._interval = 1.0 self._src_intf = None self._stats = None self._outfile = None if 'src_intf' in kwargs: self._src_intf = kwargs.get('src_intf') if 'count' in kwargs: self._count = kwargs.get('count') if 'size' in kwargs: self._size = kwargs.get('size') if 'timeout' in kwargs: self._timeout = kwargs.get('timeout') if 'interval' in kwargs: self._interval = kwargs.get('interval') try: self._build_ping_cmd() except ValueError as e: raise e client = self._conf_client pid, outfile = client.exec_background( self._cmd, redirect=True, search_expr=self._cmd.split(' ')[0]) logger.info('Icmp pid: {}'.format(pid)) logger.info('Outfile: {}'.format(outfile)) self._outfile = outfile if not pid or outfile is None: raise ValueError('Icmp traffic not started!') times = 1 sleeptime = 0.1 self._stats = self.get_stats() while (self._stats == 'failed' or self._stats is None) and times <= 5: logger.debug( 'Sleeping {} seconds to start traffic'.format(sleeptime)) time.sleep(sleeptime) self._stats = self.get_stats() times += 1 if self._stats == 'failed' or self._stats is None: raise ValueError('Icmp traffic not started!') logger.info('Icmp traffic started')