mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-13 20:08:55 +00:00
Allow virtual machines to use files in project directory as disk images.
This commit is contained in:
parent
3861d6a274
commit
3497deaa31
@ -469,12 +469,14 @@ class BaseManager:
|
||||
except PermissionError:
|
||||
raise aiohttp.web.HTTPForbidden()
|
||||
|
||||
def get_abs_image_path(self, path):
|
||||
def get_abs_image_path(self, path, extra_dir=None):
|
||||
"""
|
||||
Get the absolute path of an image
|
||||
|
||||
:param path: file path
|
||||
:return: file path
|
||||
:param extra_dir: an additional directory to be added to the search path
|
||||
|
||||
:returns: file path
|
||||
"""
|
||||
|
||||
if not path:
|
||||
@ -483,6 +485,9 @@ class BaseManager:
|
||||
|
||||
server_config = self.config.get_section_config("Server")
|
||||
img_directory = self.get_images_directory()
|
||||
valid_directory_prefices = images_directories(self._NODE_TYPE)
|
||||
if extra_dir:
|
||||
valid_directory_prefices.append(extra_dir)
|
||||
|
||||
# Windows path should not be send to a unix server
|
||||
if not sys.platform.startswith("win"):
|
||||
@ -490,7 +495,7 @@ class BaseManager:
|
||||
raise NodeError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, img_directory))
|
||||
|
||||
if not os.path.isabs(path):
|
||||
for directory in images_directories(self._NODE_TYPE):
|
||||
for directory in valid_directory_prefices:
|
||||
path = self._recursive_search_file_in_directory(directory, orig_path)
|
||||
if path:
|
||||
return force_unix_path(path)
|
||||
@ -502,15 +507,16 @@ class BaseManager:
|
||||
return path
|
||||
raise ImageMissingError(orig_path)
|
||||
|
||||
# For non local server we disallow using absolute path outside image directory
|
||||
# For local server we allow using absolute path outside image directory
|
||||
if server_config.getboolean("local", False) is True:
|
||||
path = force_unix_path(path)
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
raise ImageMissingError(orig_path)
|
||||
|
||||
# Check to see if path is an absolute path to a valid directory
|
||||
path = force_unix_path(path)
|
||||
for directory in images_directories(self._NODE_TYPE):
|
||||
for directory in valid_directory_prefices:
|
||||
if os.path.commonprefix([directory, path]) == directory:
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
@ -534,23 +540,29 @@ class BaseManager:
|
||||
return path
|
||||
return None
|
||||
|
||||
def get_relative_image_path(self, path):
|
||||
def get_relative_image_path(self, path, extra_dir=None):
|
||||
"""
|
||||
Get a path relative to images directory path
|
||||
or an abspath if the path is not located inside
|
||||
image directory
|
||||
|
||||
:param path: file path
|
||||
:return: file path
|
||||
:param extra_dir: an additional directory to be added to the search path
|
||||
|
||||
:returns: file path
|
||||
"""
|
||||
|
||||
if not path:
|
||||
return ""
|
||||
path = force_unix_path(self.get_abs_image_path(path))
|
||||
|
||||
path = force_unix_path(self.get_abs_image_path(path, extra_dir))
|
||||
img_directory = self.get_images_directory()
|
||||
|
||||
for directory in images_directories(self._NODE_TYPE):
|
||||
valid_directory_prefices = images_directories(self._NODE_TYPE)
|
||||
if extra_dir:
|
||||
valid_directory_prefices.append(extra_dir)
|
||||
|
||||
for directory in valid_directory_prefices:
|
||||
if os.path.commonprefix([directory, path]) == directory:
|
||||
relpath = os.path.relpath(path, directory)
|
||||
# We don't allow to recurse search from the top image directory just for image type directory (compatibility with old releases)
|
||||
|
@ -169,8 +169,7 @@ class Router(BaseNode):
|
||||
"mac_addr": self._mac_addr,
|
||||
"system_id": self._system_id}
|
||||
|
||||
# return the relative path if the IOS image is in the images_path directory
|
||||
router_info["image"] = self.manager.get_relative_image_path(self._image)
|
||||
router_info["image"] = self.manager.get_relative_image_path(self._image, self.project.path)
|
||||
|
||||
# add the slots
|
||||
slot_number = 0
|
||||
@ -484,7 +483,7 @@ class Router(BaseNode):
|
||||
:param image: path to IOS image file
|
||||
"""
|
||||
|
||||
image = self.manager.get_abs_image_path(image)
|
||||
image = self.manager.get_abs_image_path(image, self.project.path)
|
||||
|
||||
await self._hypervisor.send('vm set_ios "{name}" "{image}"'.format(name=self._name, image=image))
|
||||
|
||||
|
@ -75,7 +75,7 @@ class IOUVM(BaseNode):
|
||||
self._iou_stdout_file = ""
|
||||
self._started = False
|
||||
self._nvram_watcher = None
|
||||
self._path = self.manager.get_abs_image_path(path)
|
||||
self._path = self.manager.get_abs_image_path(path, project.path)
|
||||
self._license_check = True
|
||||
|
||||
# IOU settings
|
||||
@ -137,7 +137,7 @@ class IOUVM(BaseNode):
|
||||
:param path: path to the IOU image executable
|
||||
"""
|
||||
|
||||
self._path = self.manager.get_abs_image_path(path)
|
||||
self._path = self.manager.get_abs_image_path(path, self.project.path)
|
||||
log.info('IOU "{name}" [{id}]: IOU image updated to "{path}"'.format(name=self._name, id=self._id, path=self._path))
|
||||
|
||||
@property
|
||||
@ -232,8 +232,7 @@ class IOUVM(BaseNode):
|
||||
"command_line": self.command_line,
|
||||
"application_id": self.application_id}
|
||||
|
||||
# return the relative path if the IOU image is in the images_path directory
|
||||
iou_vm_info["path"] = self.manager.get_relative_image_path(self.path)
|
||||
iou_vm_info["path"] = self.manager.get_relative_image_path(self.path, self.project.path)
|
||||
return iou_vm_info
|
||||
|
||||
@property
|
||||
|
@ -212,7 +212,7 @@ class QemuVM(BaseNode):
|
||||
:param value: New disk value
|
||||
"""
|
||||
|
||||
value = self.manager.get_abs_image_path(value)
|
||||
value = self.manager.get_abs_image_path(value, self.project.path)
|
||||
if not self.linked_clone:
|
||||
for node in self.manager.nodes:
|
||||
if node != self and getattr(node, variable) == value:
|
||||
@ -412,7 +412,8 @@ class QemuVM(BaseNode):
|
||||
|
||||
:param cdrom_image: QEMU cdrom image path
|
||||
"""
|
||||
self._cdrom_image = self.manager.get_abs_image_path(cdrom_image)
|
||||
|
||||
self._cdrom_image = self.manager.get_abs_image_path(cdrom_image, self.project.path)
|
||||
log.info('QEMU VM "{name}" [{id}] has set the QEMU cdrom image path to {cdrom_image}'.format(name=self._name,
|
||||
id=self._id,
|
||||
cdrom_image=self._cdrom_image))
|
||||
@ -434,7 +435,8 @@ class QemuVM(BaseNode):
|
||||
|
||||
:param bios_image: QEMU bios image path
|
||||
"""
|
||||
self._bios_image = self.manager.get_abs_image_path(bios_image)
|
||||
|
||||
self._bios_image = self.manager.get_abs_image_path(bios_image, self.project.path)
|
||||
log.info('QEMU VM "{name}" [{id}] has set the QEMU bios image path to {bios_image}'.format(name=self._name,
|
||||
id=self._id,
|
||||
bios_image=self._bios_image))
|
||||
@ -739,7 +741,7 @@ class QemuVM(BaseNode):
|
||||
:param initrd: QEMU initrd path
|
||||
"""
|
||||
|
||||
initrd = self.manager.get_abs_image_path(initrd)
|
||||
initrd = self.manager.get_abs_image_path(initrd, self.project.path)
|
||||
|
||||
log.info('QEMU VM "{name}" [{id}] has set the QEMU initrd path to {initrd}'.format(name=self._name,
|
||||
id=self._id,
|
||||
@ -766,7 +768,7 @@ class QemuVM(BaseNode):
|
||||
:param kernel_image: QEMU kernel image path
|
||||
"""
|
||||
|
||||
kernel_image = self.manager.get_abs_image_path(kernel_image)
|
||||
kernel_image = self.manager.get_abs_image_path(kernel_image, self.project.path)
|
||||
log.info('QEMU VM "{name}" [{id}] has set the QEMU kernel image path to {kernel_image}'.format(name=self._name,
|
||||
id=self._id,
|
||||
kernel_image=kernel_image))
|
||||
@ -1938,22 +1940,20 @@ class QemuVM(BaseNode):
|
||||
answer[field] = getattr(self, field)
|
||||
except AttributeError:
|
||||
pass
|
||||
answer["hda_disk_image"] = self.manager.get_relative_image_path(self._hda_disk_image)
|
||||
answer["hda_disk_image"] = self.manager.get_relative_image_path(self._hda_disk_image, self.project.path)
|
||||
answer["hda_disk_image_md5sum"] = md5sum(self._hda_disk_image)
|
||||
answer["hdb_disk_image"] = self.manager.get_relative_image_path(self._hdb_disk_image)
|
||||
answer["hdb_disk_image"] = self.manager.get_relative_image_path(self._hdb_disk_image, self.project.path)
|
||||
answer["hdb_disk_image_md5sum"] = md5sum(self._hdb_disk_image)
|
||||
answer["hdc_disk_image"] = self.manager.get_relative_image_path(self._hdc_disk_image)
|
||||
answer["hdc_disk_image"] = self.manager.get_relative_image_path(self._hdc_disk_image, self.project.path)
|
||||
answer["hdc_disk_image_md5sum"] = md5sum(self._hdc_disk_image)
|
||||
answer["hdd_disk_image"] = self.manager.get_relative_image_path(self._hdd_disk_image)
|
||||
answer["hdd_disk_image"] = self.manager.get_relative_image_path(self._hdd_disk_image, self.project.path)
|
||||
answer["hdd_disk_image_md5sum"] = md5sum(self._hdd_disk_image)
|
||||
answer["cdrom_image"] = self.manager.get_relative_image_path(self._cdrom_image)
|
||||
answer["cdrom_image"] = self.manager.get_relative_image_path(self._cdrom_image, self.project.path)
|
||||
answer["cdrom_image_md5sum"] = md5sum(self._cdrom_image)
|
||||
answer["bios_image"] = self.manager.get_relative_image_path(self._bios_image)
|
||||
answer["bios_image"] = self.manager.get_relative_image_path(self._bios_image, self.project.path)
|
||||
answer["bios_image_md5sum"] = md5sum(self._bios_image)
|
||||
answer["initrd"] = self.manager.get_relative_image_path(self._initrd)
|
||||
answer["initrd"] = self.manager.get_relative_image_path(self._initrd, self.project.path)
|
||||
answer["initrd_md5sum"] = md5sum(self._initrd)
|
||||
|
||||
answer["kernel_image"] = self.manager.get_relative_image_path(self._kernel_image)
|
||||
answer["kernel_image"] = self.manager.get_relative_image_path(self._kernel_image, self.project.path)
|
||||
answer["kernel_image_md5sum"] = md5sum(self._kernel_image)
|
||||
|
||||
return answer
|
||||
|
@ -101,6 +101,17 @@ def test_qemu_create_with_params(http_compute, project, base_params, fake_qemu_v
|
||||
assert response.json["hda_disk_image_md5sum"] == "c4ca4238a0b923820dcc509a6f75849b"
|
||||
|
||||
|
||||
def test_qemu_create_with_project_file(http_compute, project, base_params, fake_qemu_vm):
|
||||
response = http_compute.post("/projects/{project_id}/files/hello.img".format(project_id=project.id), body="world", raw=True)
|
||||
assert response.status == 200
|
||||
params = base_params
|
||||
params["hda_disk_image"] = "hello.img"
|
||||
response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), params, example=True)
|
||||
assert response.status == 201
|
||||
assert response.json["hda_disk_image"] == "hello.img"
|
||||
assert response.json["hda_disk_image_md5sum"] == "7d793037a0760186574b0282f2f435e7"
|
||||
|
||||
|
||||
def test_qemu_get(http_compute, project, vm):
|
||||
response = http_compute.get("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
|
||||
assert response.status == 200
|
||||
|
Loading…
Reference in New Issue
Block a user