From db41076ce5a4f865ff7464a1ef3ae83b96d966bc Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Tue, 20 Jan 2015 14:31:47 +0100 Subject: [PATCH] Use the project working directory for VPCS VM --- docs/api/examples/post_project.txt | 8 ++++---- gns3server/config.py | 2 +- gns3server/modules/base_vm.py | 17 +++++++++++++++++ gns3server/modules/project.py | 20 +++++++++++++++++++- gns3server/modules/vpcs/vpcs_vm.py | 22 +++++----------------- tests/modules/test_project.py | 10 +++++++++- tests/modules/vpcs/test_vpcs_vm.py | 10 +++++----- 7 files changed, 60 insertions(+), 29 deletions(-) diff --git a/docs/api/examples/post_project.txt b/docs/api/examples/post_project.txt index 3a99e4e6..bc57a383 100644 --- a/docs/api/examples/post_project.txt +++ b/docs/api/examples/post_project.txt @@ -1,8 +1,8 @@ -curl -i -X POST 'http://localhost:8000/project' -d '{"location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-308/test_create_project_with_dir0"}' +curl -i -X POST 'http://localhost:8000/project' -d '{"location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-321/test_create_project_with_dir0"}' POST /project HTTP/1.1 { - "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-308/test_create_project_with_dir0" + "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-321/test_create_project_with_dir0" } @@ -15,6 +15,6 @@ SERVER: Python/3.4 aiohttp/0.13.1 X-ROUTE: /project { - "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-308/test_create_project_with_dir0", - "uuid": "7b9efb50-4909-4dc2-bb61-0bf443874c4c" + "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-321/test_create_project_with_dir0", + "uuid": "a00bbbdf-4088-4634-816d-513e0428275f" } diff --git a/gns3server/config.py b/gns3server/config.py index 57d61180..f2ef0353 100644 --- a/gns3server/config.py +++ b/gns3server/config.py @@ -118,7 +118,7 @@ class Config(object): :returns: configparser section """ - if section is not in self._config: + if section not in self._config: return self._config["DEFAULT"] return self._config[section] diff --git a/gns3server/modules/base_vm.py b/gns3server/modules/base_vm.py index ee232526..c205b00e 100644 --- a/gns3server/modules/base_vm.py +++ b/gns3server/modules/base_vm.py @@ -33,11 +33,13 @@ class BaseVM: # TODO: When delete release console ports + @property def project(self): """Return VM current project""" return self._project + @property def name(self): """ @@ -48,6 +50,7 @@ class BaseVM: return self._name + @name.setter def name(self, new_name): """ @@ -58,6 +61,7 @@ class BaseVM: self._name = new_name + @property def uuid(self): """ @@ -68,6 +72,7 @@ class BaseVM: return self._uuid + @property def manager(self): """ @@ -78,6 +83,16 @@ class BaseVM: return self._manager + + @property + def working_dir(self): + """ + Return VM working directory + """ + + return self._project.vm_working_directory(self._uuid) + + def create(self): """ Creates the VM. @@ -85,6 +100,7 @@ class BaseVM: return + def start(self): """ Starts the VM process. @@ -92,6 +108,7 @@ class BaseVM: raise NotImplementedError + def stop(self): """ Starts the VM process. diff --git a/gns3server/modules/project.py b/gns3server/modules/project.py index d03f090f..c6daa461 100644 --- a/gns3server/modules/project.py +++ b/gns3server/modules/project.py @@ -45,23 +45,41 @@ class Project: self._path = os.path.join(self._location, self._uuid) if os.path.exists(self._path) is False: os.mkdir(self._path) - os.mkdir(os.path.join(self._path, "files")) + os.mkdir(os.path.join(self._path, "vms")) + @property def uuid(self): return self._uuid + @property def location(self): return self._location + @property def path(self): return self._path + + def vm_working_directory(self, vm_identifier): + """ + Return a working directory for a specific VM. + If the directory doesn't exist, the directory is created. + + :param vm_identifier: UUID of VM + """ + + path = os.path.join(self._path, 'vms', vm_identifier) + if os.path.exists(path) is False: + os.mkdir(path) + return path + + def __json__(self): return { diff --git a/gns3server/modules/vpcs/vpcs_vm.py b/gns3server/modules/vpcs/vpcs_vm.py index 5184d5e1..a29aa32c 100644 --- a/gns3server/modules/vpcs/vpcs_vm.py +++ b/gns3server/modules/vpcs/vpcs_vm.py @@ -51,11 +51,10 @@ class VPCSVM(BaseVM): :param uuid: VPCS instance UUID :param project: Project instance :param manager: parent VM Manager - :param working_dir: path to a working directory :param console: TCP console port """ - def __init__(self, name, uuid, project, manager, working_dir=None, console=None): + def __init__(self, name, uuid, project, manager, console=None): super().__init__(name, uuid, project, manager) @@ -63,9 +62,6 @@ class VPCSVM(BaseVM): self._console = console - # TODO: remove working_dir - self._working_dir = "/tmp" - self._command = [] self._process = None self._vpcs_stdout_file = "" @@ -75,14 +71,6 @@ class VPCSVM(BaseVM): self._script_file = "" self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface - # working_dir_path = os.path.join(working_dir, "vpcs", "pc-{}".format(self._id)) - # - # if vpcs_id and not os.path.isdir(working_dir_path): - # raise VPCSError("Working directory {} doesn't exist".format(working_dir_path)) - # - # # create the vm own working directory - # self.working_dir = working_dir_path - # try: if not self._console: self._console = self._manager.port_manager.get_free_console_port() @@ -133,7 +121,7 @@ class VPCSVM(BaseVM): if self._script_file: # update the startup.vpc - config_path = os.path.join(self._working_dir, "startup.vpc") + config_path = os.path.join(self.working_dir, "startup.vpc") if os.path.isfile(config_path): try: with open(config_path, "r+", errors="replace") as f: @@ -155,7 +143,7 @@ class VPCSVM(BaseVM): """ # TODO: should be async try: - output = subprocess.check_output([self._path, "-v"], cwd=self._working_dir) + output = subprocess.check_output([self._path, "-v"], cwd=self.working_dir) match = re.search("Welcome to Virtual PC Simulator, version ([0-9a-z\.]+)", output.decode("utf-8")) if match: version = match.group(1) @@ -179,7 +167,7 @@ class VPCSVM(BaseVM): self._command = self._build_command() try: log.info("starting VPCS: {}".format(self._command)) - self._vpcs_stdout_file = os.path.join(self._working_dir, "vpcs.log") + self._vpcs_stdout_file = os.path.join(self.working_dir, "vpcs.log") log.info("logging to {}".format(self._vpcs_stdout_file)) flags = 0 if sys.platform.startswith("win32"): @@ -188,7 +176,7 @@ class VPCSVM(BaseVM): self._process = yield from asyncio.create_subprocess_exec(*self._command, stdout=fd, stderr=subprocess.STDOUT, - cwd=self._working_dir, + cwd=self.working_dir, creationflags=flags) log.info("VPCS instance {} started PID={}".format(self.name, self._process.pid)) self._started = True diff --git a/tests/modules/test_project.py b/tests/modules/test_project.py index 8ecbee42..23b4055f 100644 --- a/tests/modules/test_project.py +++ b/tests/modules/test_project.py @@ -32,7 +32,7 @@ def test_path(tmpdir): p = Project(location=str(tmpdir)) assert p.path == os.path.join(str(tmpdir), p.uuid) assert os.path.exists(os.path.join(str(tmpdir), p.uuid)) - assert os.path.exists(os.path.join(str(tmpdir), p.uuid, 'files')) + assert os.path.exists(os.path.join(str(tmpdir), p.uuid, 'vms')) def test_temporary_path(): @@ -43,3 +43,11 @@ def test_temporary_path(): def test_json(tmpdir): p = Project() assert p.__json__() == {"location": p.location, "uuid": p.uuid} + + +def test_vm_working_directory(tmpdir): + p = Project(location=str(tmpdir)) + assert os.path.exists(p.vm_working_directory('00010203-0405-0607-0809-0a0b0c0d0e0f')) + assert os.path.exists(os.path.join(str(tmpdir), p.uuid, 'vms', '00010203-0405-0607-0809-0a0b0c0d0e0f')) + + diff --git a/tests/modules/vpcs/test_vpcs_vm.py b/tests/modules/vpcs/test_vpcs_vm.py index 57cf71d8..08f80be4 100644 --- a/tests/modules/vpcs/test_vpcs_vm.py +++ b/tests/modules/vpcs/test_vpcs_vm.py @@ -37,7 +37,7 @@ def manager(): @patch("subprocess.check_output", return_value="Welcome to Virtual PC Simulator, version 0.6".encode("utf-8")) -def test_vm(manager): +def test_vm(project, manager): vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) assert vm.name == "test" assert vm.uuid == "00010203-0405-0607-0809-0a0b0c0d0e0f" @@ -81,20 +81,20 @@ def test_stop(project, loop, manager): process.terminate.assert_called_with() -def test_add_nio_binding_udp(manager): +def test_add_nio_binding_udp(manager, project): vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) nio = vm.port_add_nio_binding(0, {"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"}) assert nio.lport == 4242 def test_add_nio_binding_tap(project, manager): - vm = VPCSVM("test", 42, project, manager) + vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) with patch("gns3server.modules.vpcs.vpcs_vm.has_privileged_access", return_value=True): nio = vm.port_add_nio_binding(0, {"type": "nio_tap", "tap_device": "test"}) assert nio.tap_device == "test" -def test_add_nio_binding_tap_no_privileged_access(manager): +def test_add_nio_binding_tap_no_privileged_access(manager, project): vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) with patch("gns3server.modules.vpcs.vpcs_vm.has_privileged_access", return_value=False): with pytest.raises(VPCSError): @@ -102,7 +102,7 @@ def test_add_nio_binding_tap_no_privileged_access(manager): assert vm._ethernet_adapter.ports[0] is None -def test_port_remove_nio_binding(manager): +def test_port_remove_nio_binding(manager, project): vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) nio = vm.port_add_nio_binding(0, {"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"}) vm.port_remove_nio_binding(0)