def test_execute_command(self, ssh_client_cls): # Arrange host = "localhost" cmd = "ls" ssh = SSHEntity(host) ssh._ssh_cls = ssh_client_cls session_mock = mock.Mock() session_mock.recv_ready.return_value = True session_mock.exit_status_ready.return_value = True session_mock.recv.return_value = "dummy" stream_mock = mock.Mock() stream_mock.channel = session_mock ssh.ssh_client.exec_command.return_value = None, stream_mock, None def change_status(y): session_mock.recv_ready.return_value = False return "dummy" session_mock.recv.side_effect = change_status ssh.get_new_session = lambda: session_mock # Act ssh.execute_command(cmd) # Assert ssh.ssh_client.exec_command.assert_called_once_with(cmd) self.assertTrue(session_mock.recv.call_count >= 1)
def test_execute_command_with_redirect(self, ssh_client_cls): # Arrange host = "localhost" cmd = "ls" ssh = SSHEntity(host, redirect_output=True) ssh._ssh_cls = ssh_client_cls ssh.ssh_client.exec_command.return_value = (StringIO(), StringIO(), StringIO()) # Act ssh.execute_command(cmd) # Assert ssh.ssh_client.exec_command.assert_called_once_with(cmd)
def test_execute_command_with_redirect(self): # Arrange host, port, username, password = get_ssh_config() home_dir = os.getcwd() # Act ssh = SSHEntity(host, port, username, password, redirect_output=True) ret = ssh.execute_command("ls " + home_dir) # Assert self.assertIsInstance(ret, basestring) self.assertEquals(ret, "")
def test_execute_command(self): # Arrange host, port, username, password = get_ssh_config() home_dir = os.getcwd() # Act ssh = SSHEntity(host, port, username, password) ret = ssh.execute_command("ls -a " + home_dir) # Assert self.assertIsInstance(ret, basestring) ret_list = ret.split() ret_list.sort() # ls -a returns . and .. but os.listdir doesn't ret_list.remove('.') ret_list.remove('..') current_list = os.listdir('.') current_list.sort() self.assertEquals(ret_list, current_list)
class VMController(Controller): """Controllers that are run in virtual machines rather than processes""" __metaclass__ = abc.ABCMeta def __init__(self, controller_config, cmd_executor=None, sync_connection_manager=None, snapshot_service=None, username=None, password=None): """ Args: controller_config: see ControllerConfig cmd_executer: a class that has execute_command method. If not specified SSHEntity will be used See SSHEntity and LocalEntity username: overrides the username specified in controller_config (if any) password: overrides the password specified in controller_config (if any) """ Controller.__init__(self, controller_config, sync_connection_manager, snapshot_service) self.username = username self.password = password if self.username is None and hasattr(self.config, 'username'): self.username = self.config.username if self.password is None and hasattr(self.config, 'password'): self.password = self.config.password self.cmd_executor = cmd_executor if self.cmd_executor is None and hasattr(self.config, 'cmd_executor'): self.cmd_executor = self.config.cmd_executer if self.cmd_executor is None: key_filename = getattr(self.config, 'key_filename', None) self.cmd_executor = SSHEntity(controller_config.address, username=self.username, password=self.password, key_filename=key_filename, cwd=getattr(self.config, "cwd", None), redirect_output=True, block=True) assert hasattr(self.cmd_executor, "execute_command") self.commands = {} self.populate_commands() self.welcome_msg = " =====> Starting VM Controller <===== " self.alive_status_string = "" # subclass dependent def populate_commands(self): if self.config.start_cmd == "": raise RuntimeError( "No command found to start controller %s!" % self.label) if self.config.kill_cmd == "": raise RuntimeError( "No command found to kill controller %s!" % self.label) if self.config.restart_cmd == "": raise RuntimeError( "No command found to restart controller %s!" % self.label) self.commands["start"] = " ".join(self.config.expanded_start_cmd) self.commands["kill"] = " ".join(self.config.expanded_kill_cmd) self.commands["restart"] = " ".join(self.config.expanded_restart_cmd) if hasattr(self.config, "expanded_check_cmd"): self.commands["check"] = " ".join(self.config.expanded_check_cmd) else: self.commands["check"] = getattr(self.config, "check_cmd", "") def kill(self): if self.state != ControllerState.ALIVE: self.log.warn( "Killing controller %s when controller is not alive!" % self.label) return kill_cmd = self.commands["kill"] self.log.info("Killing controller %s: %s" % (self.label, kill_cmd)) self.cmd_executor.execute_command(kill_cmd) self.state = ControllerState.DEAD def start(self, multiplex_sockets=False): self.log.info(self.welcome_msg) if self.state != ControllerState.DEAD: self.log.warn( "Starting controller %s when controller is not dead!" % self.label) return start_cmd = self.commands["start"] self.log.info("Launching controller %s: %s" % (self.label, start_cmd)) ret = self.cmd_executor.execute_command(start_cmd) if ret is not None: self.log.info(ret) self.state = ControllerState.ALIVE def restart(self): if self.state != ControllerState.DEAD: self.log.warn( "Restarting controller %s when controller is not dead!" % self.label) return restart_cmd = self.commands["restart"] self.log.info("Relaunching controller %s: %s" % (self.label, restart_cmd)) self.cmd_executor.execute_command(restart_cmd) self.state = ControllerState.ALIVE # SSH into the VM to check on controller process def check_status(self, simulation): check_cmd = self.commands["check"] self.log.info( "Checking status of controller %s: %s" % (self.label, check_cmd)) # By make sure the status cmd will return status rather than # printing it out on stdout. If the executor has redirect_output # set to True there is not way to check the return status because it's # printed out. old_redirect_status = self.cmd_executor.redirect_output self.cmd_executor.redirect_output = False # Execute the status command remote_status = self.cmd_executor.execute_command(check_cmd) # Restore to the old redirect status self.cmd_executor.redirect_output = old_redirect_status actual_state = ControllerState.DEAD # Alive means remote controller process exists if self.alive_status_string in remote_status: actual_state = ControllerState.ALIVE if (self.state == ControllerState.DEAD and actual_state == ControllerState.ALIVE): self.log.warn("%s is dead, but controller process found!" % self.label) self.state = ControllerState.ALIVE if (self.state == ControllerState.ALIVE and actual_state == ControllerState.DEAD): return (False, "Alive, but no controller process found!") return (True, "OK") def block_peer(self, peer_controller): for chain in ['INPUT', 'OUTPUT']: check_block_cmd = "sudo iptables -L %s | grep \"DROP.*%s\"" % ( chain, peer_controller.config.address) add_block_cmd = "sudo iptables -I %s 1 -s %s -j DROP" % ( chain, peer_controller.config.address) # If already blocked, do nothing if self.cmd_executor.execute_command(check_block_cmd) != "": continue self.cmd_executor.execute_command(add_block_cmd) def unblock_peer(self, peer_controller): for chain in ['INPUT', 'OUTPUT']: check_block_cmd = "sudo iptables -L %s | grep \"DROP.*%s\"" % ( chain, peer_controller.config.address) remove_block_cmd = "sudo iptables -D %s -s %s -j DROP" % ( chain, peer_controller.config.address) max_iterations = 10 while max_iterations > 0: # If already unblocked, do nothing if self.cmd_executor.execute_command(check_block_cmd) == "": break self.cmd_executor.execute_command(remove_block_cmd) max_iterations -= 1
class VMController(Controller): """Controllers that are run in virtual machines rather than processes""" __metaclass__ = abc.ABCMeta def __init__(self, controller_config, cmd_executor=None, sync_connection_manager=None, snapshot_service=None, username=None, password=None): """ Args: controller_config: see ControllerConfig cmd_executer: a class that has execute_command method. If not specified SSHEntity will be used See SSHEntity and LocalEntity username: overrides the username specified in controller_config (if any) password: overrides the password specified in controller_config (if any) """ Controller.__init__(self, controller_config, sync_connection_manager, snapshot_service) self.username = username self.password = password if self.username is None and hasattr(self.config, 'username'): self.username = self.config.username if self.password is None and hasattr(self.config, 'password'): self.password = self.config.password self.cmd_executor = cmd_executor if self.cmd_executor is None and hasattr(self.config, 'cmd_executor'): self.cmd_executor = self.config.cmd_executer if self.cmd_executor is None: key_filename = getattr(self.config, 'key_filename', None) self.cmd_executor = SSHEntity(controller_config.address, username=self.username, password=self.password, key_filename=key_filename, cwd=getattr(self.config, "cwd", None), redirect_output=True, block=True) assert hasattr(self.cmd_executor, "execute_command") self.commands = {} self.populate_commands() self.welcome_msg = " =====> Starting VM Controller <===== " self.alive_status_string = "" # subclass dependent def populate_commands(self): if self.config.start_cmd == "": raise RuntimeError("No command found to start controller %s!" % self.label) if self.config.kill_cmd == "": raise RuntimeError("No command found to kill controller %s!" % self.label) if self.config.restart_cmd == "": raise RuntimeError("No command found to restart controller %s!" % self.label) self.commands["start"] = " ".join(self.config.expanded_start_cmd) self.commands["kill"] = " ".join(self.config.expanded_kill_cmd) self.commands["restart"] = " ".join(self.config.expanded_restart_cmd) if hasattr(self.config, "expanded_check_cmd"): self.commands["check"] = " ".join(self.config.expanded_check_cmd) else: self.commands["check"] = getattr(self.config, "check_cmd", "") def kill(self): if self.state != ControllerState.ALIVE: self.log.warn( "Killing controller %s when controller is not alive!" % self.label) return kill_cmd = self.commands["kill"] self.log.info("Killing controller %s: %s" % (self.label, kill_cmd)) self.cmd_executor.execute_command(kill_cmd) self.state = ControllerState.DEAD def start(self, multiplex_sockets=False): self.log.info(self.welcome_msg) if self.state != ControllerState.DEAD: self.log.warn( "Starting controller %s when controller is not dead!" % self.label) return start_cmd = self.commands["start"] self.log.info("Launching controller %s: %s" % (self.label, start_cmd)) ret = self.cmd_executor.execute_command(start_cmd) if ret is not None: self.log.info(ret) self.state = ControllerState.ALIVE def restart(self): if self.state != ControllerState.DEAD: self.log.warn( "Restarting controller %s when controller is not dead!" % self.label) return restart_cmd = self.commands["restart"] self.log.info("Relaunching controller %s: %s" % (self.label, restart_cmd)) self.cmd_executor.execute_command(restart_cmd) self.state = ControllerState.ALIVE # SSH into the VM to check on controller process def check_status(self, simulation): check_cmd = self.commands["check"] self.log.info("Checking status of controller %s: %s" % (self.label, check_cmd)) # By make sure the status cmd will return status rather than # printing it out on stdout. If the executor has redirect_output # set to True there is not way to check the return status because it's # printed out. old_redirect_status = self.cmd_executor.redirect_output self.cmd_executor.redirect_output = False # Execute the status command remote_status = self.cmd_executor.execute_command(check_cmd) # Restore to the old redirect status self.cmd_executor.redirect_output = old_redirect_status actual_state = ControllerState.DEAD # Alive means remote controller process exists if self.alive_status_string in remote_status: actual_state = ControllerState.ALIVE if (self.state == ControllerState.DEAD and actual_state == ControllerState.ALIVE): self.log.warn("%s is dead, but controller process found!" % self.label) self.state = ControllerState.ALIVE if (self.state == ControllerState.ALIVE and actual_state == ControllerState.DEAD): return (False, "Alive, but no controller process found!") return (True, "OK") def block_peer(self, peer_controller): for chain in ['INPUT', 'OUTPUT']: check_block_cmd = "sudo iptables -L %s | grep \"DROP.*%s\"" % ( chain, peer_controller.config.address) add_block_cmd = "sudo iptables -I %s 1 -s %s -j DROP" % ( chain, peer_controller.config.address) # If already blocked, do nothing if self.cmd_executor.execute_command(check_block_cmd) != "": continue self.cmd_executor.execute_command(add_block_cmd) def unblock_peer(self, peer_controller): for chain in ['INPUT', 'OUTPUT']: check_block_cmd = "sudo iptables -L %s | grep \"DROP.*%s\"" % ( chain, peer_controller.config.address) remove_block_cmd = "sudo iptables -D %s -s %s -j DROP" % ( chain, peer_controller.config.address) max_iterations = 10 while max_iterations > 0: # If already unblocked, do nothing if self.cmd_executor.execute_command(check_block_cmd) == "": break self.cmd_executor.execute_command(remove_block_cmd) max_iterations -= 1