def test_meshing(self): """ Test: 1. Router is in normal-mode 2. Mesh-connections exist 3. All known Routers that are in normal-mode are connected with the tested Router """ logging.debug("%sTest: Correctness of the Mesh-Connections", LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.normal logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) bat_originators = self.remote_system.bat_originators self.assertTrue(len(bat_originators) > 0, "No connected Mesh-Nodes exist") logging.debug("%s[" + u"\u2714" + "] Connected Mesh-Nodes exist", LoggerSetup.get_log_deep(2)) my_bat__originators = self.remote_system.bat_originators my_bat__originators_macs = [originator.mac for originator in my_bat__originators] for router in self.all_routers: if router.id == self.remote_system.id or router.mode == Mode.configuration: continue known_router_mac = router.network_interfaces["mesh0"].mac cnt = my_bat__originators_macs.count(known_router_mac) self.assertTrue(cnt >= 1, "Not connected with known Router(" + str(router.id) + ")") logging.debug("%s[" + u"\u2713" + "] Connected with known Router(" + str(router.id) + ")", LoggerSetup.get_log_deep(2))
def _wca_setup_wizard(self, config): """ Starts the WebConfigurationAssist and sets the values provided by the wizard-mode (in the WebConfiguration). :param config: {node_name, mesh_vpn, limit_bandwidth, show_location, latitude, longitude, altitude, contact,...} """ try: # remote_sytem has to be a router object wca = WebConfigurationAssist(config, self.router) wca.setup_wizard() wca.exit() except Exception as e: logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) raise e # The Router should reboot logging.info("%sWait until Router rebooted (90sec) ...", LoggerSetup.get_log_deep(2)) time.sleep(90) try: Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() except Exception: self._exception_handling()
def _wait_for_job_done(cls, job: RemoteSystemJob, remote_sys: RemoteSystem, done_event: DoneEvent) -> None: """ Wait 5 minutes until the job is done. Handles the result from the job with the job.prepare(data) method. Triggers the next job/test. :param job: job to execute :param remote_sys: the RemoteSystem """ async_result = cls._task_pool.apply_async(func=cls._execute_job, args=(job, remote_sys)) result = async_result.get( 300) # wait 5 minutes or raise an TimeoutError logging.debug("%sJob done " + str(job), LoggerSetup.get_log_deep(1)) logging.debug("%sAt Router(" + str(remote_sys.id) + ")", LoggerSetup.get_log_deep(2)) try: exception = None # task.exception() # TODO #105 if exception is not None: logging.error("%sTask raised an exception: " + str(exception), LoggerSetup.get_log_deep(1)) else: job.post_process(result, cls) finally: cls.set_running_task(remote_sys, None) # start next test in the queue done_event.set() cls.__start_task(remote_sys, None)
def send_data(self, local_file: str, remote_file: str): """ Sends Data via sftp to the RemoteSystem :param local_file: Path to the local file :param remote_file: Path on the Router, where the file should be saved """ try: # TODO: If sftp is installed on the Router ''' sftp = self.ssh.open_sftp() sftp.put(local_file, remote_file) sftp.close() ''' command = 'sshpass -p' + str(self.remote_system.usr_password) + ' scp ' + local_file + ' ' + \ str(self.remote_system.usr_name) + '@' + str(self.remote_system.ip) + ':' + remote_file os.system(command) # TODO: Paramiko_scp have to installed ''' scp = SCPClient(self.ssh.get_transport()) scp.put(local_file, remote_file) ''' logging.debug( "%s[+] Sent data '" + local_file + "' to RemoteSystem '" + str(self.remote_system.usr_name) + "@" + str(self.remote_system.ip) + ":" + remote_file + "'", LoggerSetup.get_log_deep(2)) except Exception as e: logging.error( "%s[-] Couldn't send '" + local_file + "' to RemoteSystem '" + str(self.remote_system.usr_name) + "@" + str(self.remote_system.ip) + ":" + remote_file + "'", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2))
def _wait_for_job_done(cls, job: RemoteSystemJob, remote_sys: RemoteSystem, done_event: DoneEvent) -> None: """ Wait 2 minutes until the job is done. Handles the result from the job with the job.prepare(data) method. Triggers the next job/test. :param job: job to execute :param remote_sys: the RemoteSystem :param done_event: event which will be triggered when the task is finished """ async_result = cls._task_pool.apply_async(func=cls._execute_job, args=(job, remote_sys, cls._routers)) try: result = async_result.get(120) # wait 2 minutes or raise an TimeoutError logging.debug("%sJob done " + str(job), LoggerSetup.get_log_deep(1)) logging.debug("%sAt Router(" + str(remote_sys.id) + ")", LoggerSetup.get_log_deep(2)) job.post_process(result, cls) except Exception as e: logging.error("%sTask raised an exception: " + str(e), LoggerSetup.get_log_deep(1)) cls._task_errors.append((remote_sys.id, sys.exc_info())) finally: cls.set_running_task(remote_sys, None) # start next test in the queue done_event.set() cls.__start_task(remote_sys, None)
def remote_system_wget(self, file: str, remote_path: str, web_server_ip: str): """ The RemoteSystem downloads the file from the PI and stores it at remote_file. Therefore this function starts a webserver in a new thread. :param file: Like '/root/TestFramework/firmware/.../<firmware>.bin' :param remote_path: Like '/tmp/' :param web_server_ip: IP-address of the PI """ webserver = WebServer() try: logging.debug( "%sForce the Router to download Data from the own WebServer ...", LoggerSetup.get_log_deep(2)) webserver.start() # Proves first if file already exists self.send_command('test -f /' + remote_path + '/' + file.split('/')[-1] + ' || wget http://' + web_server_ip + ':' + str(WebServer.PORT_WEBSERVER) + file.replace(WebServer.BASE_DIR, '') + ' -P ' + remote_path) except Exception as e: logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) finally: webserver.join()
def set_new_ip(self, dhcp: bool, iface_name: str, new_ip: str = None, new_ip_mask: int = None): """ Sets the IP either given by 'new_ip'-parameter or via dhclient. :param dhcp: should a dhclient be used? :param iface_name: :param new_ip: :param new_ip_mask: :return: the new IP with the format ip/mask """ iface_ip = None if dhcp: try: self._wait_for_ip_assignment(iface_name) iface_ip = self._get_ip(iface_name) logging.debug( "%s[+] New IP " + iface_ip + " for " + iface_name + " by dhcp", LoggerSetup.get_log_deep(2)) except TimeoutError: logging.debug( "%s[-] Couldn't get a new IP for " + iface_name + " by dhcp", LoggerSetup.get_log_deep(2)) else: iface_ip = new_ip + "/" + str(new_ip_mask) logging.debug("%s[+] New IP " + iface_ip + " for " + iface_name, LoggerSetup.get_log_deep(2)) return iface_ip
def create_interface(self): """ Creates a 'veth'-interface. """ logging.debug("%sCreate Veth Interface ...", LoggerSetup.get_log_deep(2)) try: self.ipdb.create(kind='veth', ifname=self.veth_iface_name1, peer=self.veth_iface_name2).commit() self.ipdb.interfaces[self.veth_iface_name1].up().commit() # veth0 if self.veth_iface_ip1: iface = self.ipdb.interfaces[self.veth_iface_name1] iface.add_ip(self.veth_iface_ip1, self.veth_iface_ip_mask1).commit() # veth1 if self.veth_iface_ip2: iface = self.ipdb.interfaces[self.veth_iface_name2] iface.add_ip(self.veth_iface_ip2, self.veth_iface_ip_mask2).commit() logging.debug( "%s[+] " + self.veth_iface_name1 + " <=> " + self.veth_iface_name2 + " created", LoggerSetup.get_log_deep(3)) except Exception as e: logging.debug( "%s[-] " + self.veth_iface_name1 + self.veth_iface_name2 + " couldn't be created", LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3))
def run(self): """ Copies the firmware image onto the Router, proves if the firmware is in the right file(/tmp/<firmware_name>.bin) and does a Sysupgrade. :return: """ network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning("[-] Couldn't sysupgrade the Router(" + str(self.router.id) + ")") logging.warning(str(e)) return network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/', self.web_server_ip) # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' if not self.debug: logging.debug("sysupgrade ...") try: network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) except TimeoutError: logging.info("%s[+] Router was set into normal mode", LoggerSetup.get_log_deep(2)) self.router.mode = Mode.configuration if Dhclient.update_ip(self.router.vlan_iface_name) == 1: self.router.mode = Mode.unknown logging.error("%s[-] Something went wrong. Use command 'online -r " + str(self.router.id) + "'", LoggerSetup.get_log_deep(2)) except Exception as e: self.router.mode = Mode.unknown logging.error("[-] Something went wrong. Use command 'online -r " + str(self.router.id) + "'") logging.error(str(e)) network_ctrl.exit()
def delete_interface(self, close_ipdb: bool = False): """ Removes the virtual interface. :param close_ipdb: If also the IPDB should be closed """ logging.debug("%sDelete VLAN Interface ...", LoggerSetup.get_log_deep(2)) try: self.ipdb.interfaces[self.vlan_iface_name].remove().commit() if close_ipdb: self.ipdb.release() logging.debug( "%s[+] Interface(" + self.vlan_iface_name + ") successfully deleted", LoggerSetup.get_log_deep(3) ) except KeyError: logging.debug( "%s[+] Interface(" + self.vlan_iface_name + ") is already deleted", LoggerSetup.get_log_deep(3) ) return except Exception as e: logging.error( "%s[-] Interface(" + self.vlan_iface_name + ") couldn't be deleted. Try 'ip link delete <vlan_name>'", LoggerSetup.get_log_deep(3), ) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3))
def create_interface(self): """ Creates a virtual interface on an existing interface (like eth0). """ logging.debug("%sCreate VLAN Interface ...", LoggerSetup.get_log_deep(2)) try: # Get the real link interface link_iface = self.ipdb.interfaces[self.link_iface_name] # Create a Vlan iface = self.ipdb.create(kind="vlan", ifname=self.vlan_iface_name, link=link_iface, vlan_id=self.vlan_iface_id).commit() # Try to assign an IP via dhclient # IP 169.254.235.157/16 is returned when static is expected if (not self._wait_for_ip_assignment()) or (self.ipdb_get_ip("169.254.235.157") == ""): # Otherwise add a static IP iface.add_ip(self._get_matching_ip(str(self.remote_system.ip)), self.remote_system.ip_mask).commit() iface.mtu = 1400 logging.debug("%s[+] " + self.vlan_iface_name + " created with: Link=" + self.link_iface_name + ", VLAN_ID=" + str(self.vlan_iface_id) + ", IP=" + self.ipdb_get_ip("169.254.235.157"), LoggerSetup.get_log_deep(3)) except Exception as e: logging.error("%s[-] " + self.vlan_iface_name + " couldn't be created", LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3))
def test_availability(self): """ Test: 1. Router is in configuration-mode 2. All necessary network-interfaces exist """ necessary_network_interfaces = ["br-setup", "eth1", "lo"] logging.debug( "%sTest: Following Network-Interfaces have to exist in config-mode: " + str(necessary_network_interfaces), LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.configuration logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) existing_network_interfaces = self.remote_system.network_interfaces.values( ) existing_network_interfaces = [ interface.name for interface in existing_network_interfaces ] common_network_interfaces = list( set(necessary_network_interfaces) & set(existing_network_interfaces)) self.assertTrue( len(common_network_interfaces) >= len(necessary_network_interfaces), "Some Network-Interfaces are missing") logging.debug( "%s[" + u"\u2714" + "] All specified Network-Interfaces exist", LoggerSetup.get_log_deep(2))
def send_command(self, command: str, timeout: int = 90) -> List: """ Sends the given command via SSH to the RemoteSystem. :param command: Like 'ping 8.8.8.8' :param timeout: Timeout in seconds :return: The output of the command inside a list. Each output-line is a list-element :exception TimeoutError: If the timeout-limit is reached :exception Exception: If sending the command fails """ try: stdin, stdout, stderr = self.ssh.exec_command(command, timeout=timeout) output = stdout.readlines() logging.debug( "%s[+] Sent the command (" + command + ") to the RemoteSystem", LoggerSetup.get_log_deep(3)) return output except (PipeTimeout, socket.timeout): logging.warning("%s[!] Timeout: No response from RemoteSystem", LoggerSetup.get_log_deep(3)) raise TimeoutError except Exception as e: logging.error("%s[-] Couldn't send the command (" + command + ")", LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) raise e
def run(self): """ Runs new thread and gets the information from the Router via ssh """ logging.info( "%sUpdate the Infos of the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) try: self.network_ctrl.connect_with_remote_system() # Model self.router.model = self._get_router_model() # MAC self.router.mac = self._get_router_mac() # SSID self.router.ssid = self._get_router_ssid() # NetworkInterfaces self.router.interfaces = self._get_router_network_interfaces() # CPUProcesses self.router.cpu_processes = self._get_router_cpu_process() # RAM self.router.ram = self._get_router_mem_ram() # Sockets self.router.sockets = self._get_router_sockets() logging.debug("%s[+] Infos updated", LoggerSetup.get_log_deep(2)) except Exception as e: logging.warning("%s[-] Couldn't update all Infos", LoggerSetup.get_log_deep(2)) logging.error(str(e)) for tb in traceback.format_tb(sys.exc_info()[2]): logging.error("%s" + tb, LoggerSetup.get_log_deep(3)) finally: self.network_ctrl.exit()
def _execute_test(cls, test: FirmwareTestClass, router: Router, routers: List[Router]) -> TestResult: if not isinstance(router, Router): raise ValueError("Chosen Router is not a real Router...") # proofed: this method runs in other process as the server setproctitle(str(router.id) + " - " + str(test)) logging.debug("%sExecute test " + str(test) + " on Router(" + str(router.id) + ")", LoggerSetup.get_log_deep(2)) test_suite = defaultTestLoader.loadTestsFromTestCase(test) # prepare all test cases for test_case in test_suite: logging.debug("%sTestCase " + str(test_case), LoggerSetup.get_log_deep(4)) test_case.prepare(router, routers) result = TestResult() cls.__setns(router) try: result = test_suite.run(result) except Exception as e: logging.error("%sTestCase execution raised an exception", LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3)) test_obj = test() result.addError(test_obj, sys.exc_info()) # add the reason of the exception finally: # I'm sry for this dirty hack, but if you don't do this you get an # "TypeError: cannot serialize '_io.TextIOWrapper' object" because sys.stdout is not serializeable... result._original_stdout = None result._original_stderr = None logging.debug("%sResult from test " + str(result), LoggerSetup.get_log_deep(3)) return result
def run(self): """ Runs new thread and gets the information from the Router via ssh. """ logging.info("%sUpdate the Infos of the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) try: self.network_ctrl.connect_with_remote_system() # Model self.router.model = self._get_router_model() # MAC self.router.mac = self._get_router_mac() # NetworkInterfaces self.router.network_interfaces = self._get_router_network_interfaces() # CPUProcesses self.router.cpu_processes = self._get_router_cpu_process() # RAM self.router.ram = self._get_router_mem_ram() # Sockets self.router.sockets = self._get_router_sockets() # UCI self.router.uci = self._get_router_uci() # Bat Originators self.router.bat_originators = self._get_bat_originator() logging.info("%s[+] Infos updated", LoggerSetup.get_log_deep(2)) except Exception as e: logging.error("%s[-] Couldn't update all Infos", LoggerSetup.get_log_deep(2)) logging.error(str(e)) for tb in traceback.format_tb(sys.exc_info()[2]): logging.error("%s" + tb, LoggerSetup.get_log_deep(3)) finally: self.network_ctrl.exit()
def import_firmwares(self, release_model: str): """ Imports the stored Firmwares, so the firmware_handler can use them. :param release_model: stable, beta, experimental """ path = FIRMWARE_PATH + '/' + release_model + '/' + self.UPDATE_TYPE + '/' logging.debug("%sImport Firmwares from '" + path + "'", LoggerSetup.get_log_deep(2)) count = 0 try: files = os.listdir(path) except Exception: logging.debug("%sNo Firmwares available for import at path '" + path + "'", LoggerSetup.get_log_deep(3)) return for firmware_name in files: try: freifunk_verein = firmware_name.split('-')[1] firmware_version = firmware_name.split('-')[2] file = path + firmware_name url = self.url + '/' + release_model + '/' + self.UPDATE_TYPE + '/' + firmware_name self.firmwares.append(Firmware(firmware_name, firmware_version, freifunk_verein, release_model, file, url)) count += 1 except Exception: logging.warning("%s[-] Couldn't import " + firmware_name, LoggerSetup.get_log_deep(3)) continue logging.debug("%s" + str(count) + " Firmwares imported", LoggerSetup.get_log_deep(3))
def create_interface(self): """ Creates a virtual interface on a existing interface (like eth0) """ logging.debug("%sCreate VLAN Interface ...", LoggerSetup.get_log_deep(2)) try: # Get the real link interface link_iface = self.ipdb.interfaces[self.link_iface_name] # Create a Vlan iface = self.ipdb.create(kind="vlan", ifname=self.vlan_iface_name, link=link_iface, vlan_id=self.vlan_iface_id).commit() # Try to assign an IP via dhclient # IP 169.254.235.157/16 is returned when static is expected if (not self._wait_for_ip_assignment()) or (self.ipdb_get_ip("169.254.235.157") == ""): # Otherwise add a static IP iface.add_ip(self._get_matching_ip(str(self.remote_system.ip)), self.remote_system.ip_mask).commit() iface.mtu = 1400 logging.debug("%s[+] " + self.vlan_iface_name + " created with: Link=" + self.link_iface_name + ", VLAN_ID=" + str(self.vlan_iface_id) + ", IP=" + self.ipdb_get_ip(), LoggerSetup.get_log_deep(3)) except Exception as e: logging.debug("%s[-] " + self.vlan_iface_name + " couldn't be created", LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3))
def test_connection(self): """ Test: 1. Google or FreiFunk is reachable via a Ping """ logging.debug("%sTest: Existence of an Internet-Connection", LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.normal logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) network_ctrl = NetworkCtrl(self.remote_system) network_ctrl.connect_with_remote_system() ping_result1 = network_ctrl.send_command( "ping -c 5 8.8.8.8 | grep received") ping_result2 = network_ctrl.send_command( "ping -c 5 freifunk.net | grep received") self.assertTrue( self._ping_successful(ping_result1[0]) or self._ping_successful(ping_result2[0]), "No Internet-Connection") logging.debug( "%s[" + u"\u2714" + "] At least one Ping was successful => An Internet-Connection exist", LoggerSetup.get_log_deep(2)) network_ctrl.exit()
def delete_interface(self, close_ipdb: bool = False): """ Removes the virtual interface :param close_ipdb: If also the IPDB should be closed. """ logging.debug("%sDelete VLAN Interface ...", LoggerSetup.get_log_deep(2)) try: self.ipdb.interfaces[self.vlan_iface_name].remove().commit() if close_ipdb: self.ipdb.release() logging.debug( "%s[+] Interface(" + self.vlan_iface_name + ") successfully deleted", LoggerSetup.get_log_deep(3)) except KeyError: logging.debug( "%s[+] Interface(" + self.vlan_iface_name + ") is already deleted", LoggerSetup.get_log_deep(3)) return except Exception as e: logging.debug( "%s[-] Interface(" + self.vlan_iface_name + ") couldn't be deleted. Try 'ip link delete <vlan_name>'", LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3))
def __init__(self, ipdb: IPDB, nsp_name: str): """ Creats a namespace for a specific vlan_iface :param nsp_name: :param ipdb: IPDB is a transactional database, containing records, representing network stack objects. Any change in the database is not reflected immidiately in OS, but waits until commit() is called. """ logging.debug("%sCreate Namespace ...", LoggerSetup.get_log_deep(2)) self.ipdb = ipdb if ipdb else IPDB() self.ipdb_netns = None self.nsp_name = nsp_name try: self.ipdb_netns = IPDB(nl=NetNS(nsp_name)) self.ipdb_netns.interfaces['lo'].up().commit() logging.debug( "%s[+] Namespace(" + nsp_name + ") successfully created", LoggerSetup.get_log_deep(3)) # self.encapsulate_interface() except Exception as e: logging.debug("%s[-] Couldn't create Namespace(" + nsp_name + ")", LoggerSetup.get_log_deep(3)) for tb in traceback.format_tb(sys.exc_info()[2]): logging.error("%s" + tb, LoggerSetup.get_log_deep(3)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(3)) self.remove()
def test_meshing(self): """ Test: 1. Router is in normal-mode 2. Mesh-connections exist 3. All known Routers that are in normal-mode are connected with the tested Router """ logging.debug("%sTest: Correctness of the Mesh-Connections", LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.normal logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) bat_originators = self.remote_system.bat_originators self.assertTrue( len(bat_originators) > 0, "No connected Mesh-Nodes exist") logging.debug("%s[" + u"\u2714" + "] Connected Mesh-Nodes exist", LoggerSetup.get_log_deep(2)) my_bat__originators = self.remote_system.bat_originators my_bat__originators_macs = [ originator.mac for originator in my_bat__originators ] for router in self.all_routers: if router.id == self.remote_system.id or router.mode == Mode.configuration: continue known_router_mac = router.network_interfaces["mesh0"].mac cnt = my_bat__originators_macs.count(known_router_mac) self.assertTrue( cnt >= 1, "Not connected with known Router(" + str(router.id) + ")") logging.debug( "%s[" + u"\u2713" + "] Connected with known Router(" + str(router.id) + ")", LoggerSetup.get_log_deep(2))
def run(self): """ Copies the firmware image onto the Router, proves if the firmware is in the right file(/tmp/<firmware_name>.bin) and does a Sysupgrade. """ network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.warning("%s[-] Couldn't sysupgrade the Router(" + str(self.router.id) + ")", LoggerSetup.get_log_deep(2)) logging.warning(str(e)) return network_ctrl.remote_system_wget(self.router.firmware.file, '/tmp/', self.web_server_ip) # sysupgrade -n <firmware_name> // -n verwirft die letzte firmware arg = '-n' if self.n else '' if not self.debug: logging.debug("%sSysupgrade (this will force a TimeoutError)...", LoggerSetup.get_log_deep(2)) try: network_ctrl.send_command('sysupgrade ' + arg + ' ' + '/tmp/' + self.router.firmware.name) except TimeoutError: try: Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception: self._execption_hanling() except Exception: self._execption_hanling() network_ctrl.exit()
def send_data(self, local_file: str, remote_file: str): """ Sends Data via sftp to the RemoteSystem :param local_file: Path to the local file :param remote_file: Path on the Router, where the file should be saved """ try: # TODO: If sftp is installed on the Router ''' sftp = self.ssh.open_sftp() sftp.put(local_file, remote_file) sftp.close() ''' command = 'sshpass -p' + str(self.remote_system.usr_password) + ' scp ' + local_file + ' ' + \ str(self.remote_system.usr_name) + '@' + str(self.remote_system.ip) + ':' + remote_file os.system(command) # TODO: Paramiko_scp have to installed ''' scp = SCPClient(self.ssh.get_transport()) scp.put(local_file, remote_file) ''' logging.debug("%s[+] Sent data '" + local_file + "' to RemoteSystem '" + str(self.remote_system.usr_name) + "@" + str(self.remote_system.ip) + ":" + remote_file + "'", LoggerSetup.get_log_deep(2)) except Exception as e: logging.error("%s[-] Couldn't send '" + local_file + "' to RemoteSystem '" + str(self.remote_system.usr_name) + "@" + str(self.remote_system.ip) + ":" + remote_file + "'", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2))
def test_close(self): """ Tests close :return: Tests results """ LoggerSetup.setup() LoggerSetup.shutdown() self.assertEqual(False, LoggerSetup.is_setup_loaded())
def join(self): logging.info("%sStop WebServer ...", LoggerSetup.get_log_deep(1)) time.sleep(2) try: self.httpd.shutdown() logging.debug("%s[+] WebServer successfully stoped", LoggerSetup.get_log_deep(2)) except Exception as e: logging.debug("%s[-] WebServer couldn't stoped", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(1))
def test_is_loaded(self): """ Tests is loaded :return: Tests results """ LoggerSetup.setup() result = LoggerSetup.is_setup_loaded() LoggerSetup.shutdown() self.assertEqual(True, result)
def run(self): logging.info( "%sStart WebServer on port " + str(WebServer.PORT_WEBSERVER) + " ...", LoggerSetup.get_log_deep(1)) try: self.httpd.serve_forever() except Exception as e: logging.debug("%s[-] WebServer couldn't get started", LoggerSetup.get_log_deep(2)) raise e
def test_debug_level(self): """ Test debug level :return: Test results """ LoggerSetup.setup(10, "logger.log", "", 5, None) deep = LoggerSetup._max_log_deep LoggerSetup.shutdown() self.assertEqual(True, deep == 5)
def _success_handling(self): """ Sets the Router in config-mode. """ if self.n: logging.info("%s[+]Router was set into config mode", LoggerSetup.get_log_deep(2)) self.router.mode = Mode.configuration else: logging.info("%s[+]Router was set into normal mode", LoggerSetup.get_log_deep(2)) self.router.mode = Mode.normal
def test_setup(self): """ Tests setup :return: Tests results """ LoggerSetup.setup(10) self.assertEqual(True, LoggerSetup.is_setup_loaded()) LoggerSetup.shutdown()
def test_debug(self): """ Tests debug :return: Tests results """ LoggerSetup.setup(10) logging.debug("Debug") self.assertEqual(True, LoggerSetup.is_setup_loaded()) LoggerSetup.shutdown()
def test_error(self): """ Tests error :return: Tests results """ LoggerSetup.setup(10) logging.error("Error") self.assertEqual(True, LoggerSetup.is_setup_loaded()) LoggerSetup.shutdown()
def test_warning(self): """ Tests warning :return: Tests results """ LoggerSetup.setup(10) logging.warning("Warning") self.assertEqual(True, LoggerSetup.is_setup_loaded()) LoggerSetup.shutdown()
def test_info(self): """ Tests info :return: Tests results """ LoggerSetup.setup(10) logging.info("Info") self.assertEqual(True, LoggerSetup.is_setup_loaded()) LoggerSetup.shutdown()
def test_critical(self): """ Tests critical :return: Tests results """ LoggerSetup.setup(10) logging.critical("Critical") self.assertEqual(True, LoggerSetup.is_setup_loaded()) LoggerSetup.shutdown()
def test_meshing(self): """ Test: 1. Router is in normal-mode 2. Mesh-connections exist """ logging.debug("%sTest: Existence of Mesh-Connections", LoggerSetup.get_log_deep(1)) assert self.remote_system.mode == Mode.normal logging.debug("%s[" + u"\u2714" + "] Correct Mode", LoggerSetup.get_log_deep(2)) bat_originators = self.remote_system.bat_originators self.assertTrue(len(bat_originators) > 0, "No connected Mesh-Nodes exist") logging.debug("%s[" + u"\u2714" + "] Connected Mesh-Nodes exist", LoggerSetup.get_log_deep(2))
def run(self): """ Uses the Dhlcient to get an IP from a given Router and tries to connect to. """ logging.info("%sCheck if Router is online ...", LoggerSetup.get_log_deep(1)) try: Dhclient.update_ip(self.router.vlan_iface_name) self._test_connection() except FileExistsError: self._test_connection() except Exception: logging.debug("%s[*] Try again in a minute", LoggerSetup.get_log_deep(2)) return
def _create_path(self, path: str): """ Creates directories if necessary :param path: """ try: logging.debug("%sCreate path " + path + " ...", LoggerSetup.get_log_deep(3)) os.makedirs(path) logging.debug("%s[+] Path successfully created", LoggerSetup.get_log_deep(4)) except OSError as exception: if exception.errno != errno.EEXIST: raise logging.debug("%s[+] Path allready exists", LoggerSetup.get_log_deep(4))
def _create_path(self, path: str): """ Creates directories if necessary. :param path: Path where the firmware-image should be stored on the device """ try: logging.debug("%sCreate path " + path + " ...", LoggerSetup.get_log_deep(4)) os.makedirs(path) logging.debug("%s[+] Path successfully created", LoggerSetup.get_log_deep(5)) except OSError as e: if e.errno != errno.EEXIST: raise e logging.debug("%s[+] Path allready exists", LoggerSetup.get_log_deep(5))
def run(self): """ Runs new thread and trys to send a command via ssh to reboot the Router. """ logging.info("%sReboot the Router(" + str(self.router.id) + ") ...", LoggerSetup.get_log_deep(1)) network_ctrl = NetworkCtrl(self.router) try: network_ctrl.connect_with_remote_system() except Exception as e: logging.error("%s[-] Couldn't reboot Router(" + str(self.router.id) + ")", LoggerSetup.get_log_deep(2)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) network_ctrl.exit() return # Reboot Router into configuration-mode if self.configmode: if self.router.mode == Mode.configuration: logging.info("%s[+] Router is already in " + str(Mode.configuration), LoggerSetup.get_log_deep(2)) network_ctrl.exit() return try: network_ctrl.send_command("uci set 'gluon-setup-mode.@setup_mode[0].enabled=1'") network_ctrl.send_command("uci commit") network_ctrl.send_command("reboot") logging.info("%sWait until Router rebooted (60sec) ...", LoggerSetup.get_log_deep(2)) time.sleep(60) Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception as e: self._execption_hanling() # Reboot Router into normal-mode else: if self.router.mode == Mode.normal: logging.info("%s[+] Router is already in " + str(Mode.normal), LoggerSetup.get_log_deep(2)) network_ctrl.exit() return try: network_ctrl.send_command("reboot") logging.info("%sWait until Router rebooted (90sec) ...", LoggerSetup.get_log_deep(2)) time.sleep(90) Dhclient.update_ip(self.router.vlan_iface_name) self._success_handling() except FileExistsError: self._success_handling() pass except Exception as e: self._execption_hanling() network_ctrl.exit()
def _wait_for_test_done(cls, test: FirmwareTestClass, router: Router, done_event: DoneEvent) -> None: """ Wait 2 minutes until the test is done. Handles the result from the tests. Triggers the next job/test. :param test: test to execute :param router: the Router :param done_event: event which will be triggered when the task is finished """ logging.debug("%sWait for test" + str(test), LoggerSetup.get_log_deep(2)) try: async_result = cls._task_pool.apply_async(func=cls._execute_test, args=(test, router, cls._routers)) result = async_result.get(120) # wait 2 minutes or raise an TimeoutError logging.debug("%sTest done " + str(test), LoggerSetup.get_log_deep(1)) logging.debug("%sFrom Router(" + str(router.id) + ")", LoggerSetup.get_log_deep(2)) cls._test_results.append((router.id, str(test), result)) try: length = len(cls._test_results) t = cls._test_results[(length - 1)] cls.write_in_db(str(length), t) except Exception as e: logging.error("Error at write test results into DB: {0}".format(e)) except Exception as e: logging.error("%sTest raised an Exception: " + str(e), LoggerSetup.get_log_deep(1)) result = TestResult() result._original_stdout = None result._original_stderr = None cls._test_results.append((router.id, str(test), result)) cls._task_errors.append((router.id, sys.exc_info())) try: length = len(cls._test_results) t = cls._test_results[(length - 1)] cls.write_in_db(str(length), t) except Exception as e: logging.error("Error at write test results into DB: {0}".format(e)) finally: cls.set_running_task(router, None) # logging.debug(str(cls._test_results)) # start next test in the queue done_event.set() cls.__start_task(router, None)
def connect_with_remote_system(self): """ Connects to the remote_system via SSH(Paramiko). Ignores a missing signatur. """ logging.info("%sConnect with RemoteSystem ...", LoggerSetup.get_log_deep(1)) try: self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(str(self.remote_system.ip), port=22, username=str(self.remote_system.usr_name), password=str(self.remote_system.usr_password)) logging.debug("%s[+] Successfully connected", LoggerSetup.get_log_deep(2)) except Exception as e: logging.error("%s[-] Couldn't connect", LoggerSetup.get_log_deep(2)) raise e
def _execute_job(cls, job: RemoteSystemJob, remote_sys: RemoteSystem, routers: List[Router]) -> {}: logging.debug("%sExecute job " + str(job) + " on Router(" + str(remote_sys.id) + ")", LoggerSetup.get_log_deep(2)) setproctitle(str(remote_sys.id) + " - " + str(job)) job.prepare(remote_sys, routers) cls.__setns(remote_sys) result = None try: result = job.run() except Exception as e: logging.error("%sError while execute job " + str(job), LoggerSetup.get_log_deep(1)) logging.error("%s" + str(e), LoggerSetup.get_log_deep(2)) return result