mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-28 11:18:11 +00:00
Allow to resize a Qemu VM disk (extend only).
This commit is contained in:
parent
6cec67f79f
commit
ff7911bd99
@ -296,7 +296,7 @@ class Qemu(BaseManager):
|
||||
raise QemuError("Could not create disk image {}:{}".format(path, e))
|
||||
|
||||
@asyncio.coroutine
|
||||
def resize_disk(self, qemu_img, path, size):
|
||||
def resize_disk(self, qemu_img, path, extend):
|
||||
"""
|
||||
Resize a Qemu disk with qemu-img
|
||||
|
||||
@ -305,11 +305,17 @@ class Qemu(BaseManager):
|
||||
:param size: size
|
||||
"""
|
||||
|
||||
if not os.path.isabs(path):
|
||||
directory = self.get_images_directory()
|
||||
os.makedirs(directory, exist_ok=True)
|
||||
path = os.path.join(directory, os.path.basename(path))
|
||||
|
||||
try:
|
||||
if not os.path.exists(path):
|
||||
raise QemuError("Qemu image '{}' does not exist".format(path))
|
||||
command = [qemu_img, "resize", path, "{}M".format(size)]
|
||||
raise QemuError("Qemu disk '{}' does not exist".format(path))
|
||||
command = [qemu_img, "resize", path, "+{}M".format(extend)]
|
||||
process = yield from asyncio.create_subprocess_exec(*command)
|
||||
yield from process.wait()
|
||||
log.info("Qemu disk '{}' extended by {} MB".format(path, extend))
|
||||
except (OSError, subprocess.SubprocessError) as e:
|
||||
raise QemuError("Could not create disk image {}:{}".format(path, e))
|
||||
raise QemuError("Could not update disk image {}:{}".format(path, e))
|
||||
|
@ -1586,6 +1586,22 @@ class QemuVM(BaseNode):
|
||||
|
||||
return options
|
||||
|
||||
@asyncio.coroutine
|
||||
def resize_disk(self, drive_name, extend):
|
||||
|
||||
if self.is_running():
|
||||
raise QemuError("Cannot resize {} while the VM is running".format(drive_name))
|
||||
|
||||
if self.linked_clone:
|
||||
disk_image_path = os.path.join(self.working_dir, "{}_disk.qcow2".format(drive_name))
|
||||
else:
|
||||
disk_image_path = getattr(self, "{}_disk_image".format(drive_name))
|
||||
|
||||
if not os.path.exists(disk_image_path):
|
||||
raise QemuError("Disk path '{}' does not exist".format(disk_image_path))
|
||||
qemu_img_path = self._get_qemu_img()
|
||||
yield from self.manager.resize_disk(qemu_img_path, disk_image_path, extend)
|
||||
|
||||
def _cdrom_option(self):
|
||||
|
||||
options = []
|
||||
|
@ -35,10 +35,12 @@ from gns3server.schemas.qemu import (
|
||||
QEMU_CREATE_SCHEMA,
|
||||
QEMU_UPDATE_SCHEMA,
|
||||
QEMU_OBJECT_SCHEMA,
|
||||
QEMU_RESIZE_SCHEMA,
|
||||
QEMU_BINARY_LIST_SCHEMA,
|
||||
QEMU_BINARY_FILTER_SCHEMA,
|
||||
QEMU_CAPABILITY_LIST_SCHEMA,
|
||||
QEMU_IMAGE_CREATE_SCHEMA
|
||||
QEMU_IMAGE_CREATE_SCHEMA,
|
||||
QEMU_IMAGE_UPDATE_SCHEMA
|
||||
)
|
||||
|
||||
|
||||
@ -163,6 +165,25 @@ class QEMUHandler:
|
||||
response.set_status(201)
|
||||
response.json(new_node)
|
||||
|
||||
@Route.post(
|
||||
r"/projects/{project_id}/qemu/nodes/{node_id}/resize_disk",
|
||||
parameters={
|
||||
"project_id": "Project UUID",
|
||||
"node_id": "Node UUID"
|
||||
},
|
||||
status_codes={
|
||||
201: "Instance updated",
|
||||
404: "Instance doesn't exist"
|
||||
},
|
||||
description="Resize a Qemu VM disk image",
|
||||
input=QEMU_RESIZE_SCHEMA)
|
||||
def resize_disk(request, response):
|
||||
|
||||
qemu_manager = Qemu.instance()
|
||||
vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
|
||||
yield from vm.resize_disk(request.json["drive_name"], request.json["extend"])
|
||||
response.set_status(201)
|
||||
|
||||
@Route.post(
|
||||
r"/projects/{project_id}/qemu/nodes/{node_id}/start",
|
||||
parameters={
|
||||
@ -458,6 +479,28 @@ class QEMUHandler:
|
||||
yield from Qemu.instance().create_disk(qemu_img, path, request.json)
|
||||
response.set_status(201)
|
||||
|
||||
@Route.put(
|
||||
r"/qemu/img",
|
||||
status_codes={
|
||||
201: "Image Updated",
|
||||
},
|
||||
description="Update a Qemu image",
|
||||
input=QEMU_IMAGE_UPDATE_SCHEMA
|
||||
)
|
||||
def update_img(request, response):
|
||||
|
||||
qemu_img = request.json.pop("qemu_img")
|
||||
path = request.json.pop("path")
|
||||
if os.path.isabs(path):
|
||||
config = Config.instance()
|
||||
if config.get_section_config("Server").getboolean("local", False) is False:
|
||||
response.set_status(403)
|
||||
return
|
||||
|
||||
if "extend" in request.json:
|
||||
yield from Qemu.instance().resize_disk(qemu_img, path, request.json.pop("extend"))
|
||||
response.set_status(201)
|
||||
|
||||
@Route.get(
|
||||
r"/qemu/images",
|
||||
status_codes={
|
||||
|
@ -155,6 +155,23 @@ class ComputeHandler:
|
||||
res = yield from compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=request.content)
|
||||
response.json(res)
|
||||
|
||||
@Route.put(
|
||||
r"/computes/{compute_id}/{emulator}/{action:.+}",
|
||||
parameters={
|
||||
"compute_id": "Compute UUID"
|
||||
},
|
||||
status_codes={
|
||||
200: "OK",
|
||||
404: "Instance doesn't exist"
|
||||
},
|
||||
raw=True,
|
||||
description="Forward call specific to compute node. Read the full compute API for available actions")
|
||||
def put_forward(request, response):
|
||||
controller = Controller.instance()
|
||||
compute = controller.get_compute(request.match_info["compute_id"])
|
||||
res = yield from compute.forward("PUT", request.match_info["emulator"], request.match_info["action"], data=request.content)
|
||||
response.json(res)
|
||||
|
||||
@Route.get(
|
||||
r"/computes/{compute_id}",
|
||||
description="Get a compute server information",
|
||||
|
@ -286,7 +286,7 @@ class NodeHandler:
|
||||
|
||||
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
|
||||
node = project.get_node(request.match_info["node_id"])
|
||||
yield from node.reload()
|
||||
#yield from node.reload()
|
||||
response.json(node)
|
||||
response.set_status(201)
|
||||
|
||||
@ -347,6 +347,25 @@ class NodeHandler:
|
||||
response.json(idle)
|
||||
response.set_status(200)
|
||||
|
||||
@Route.post(
|
||||
r"/projects/{project_id}/nodes/{node_id}/resize_disk",
|
||||
parameters={
|
||||
"project_id": "Project UUID",
|
||||
"node_id": "Node UUID"
|
||||
},
|
||||
status_codes={
|
||||
201: "Disk image resized",
|
||||
400: "Invalid request",
|
||||
404: "Instance doesn't exist"
|
||||
},
|
||||
description="Reload a node instance")
|
||||
def resize_disk(request, response):
|
||||
|
||||
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
|
||||
node = project.get_node(request.match_info["node_id"])
|
||||
yield from node.post("/resize_disk", request.json)
|
||||
response.set_status(201)
|
||||
|
||||
@Route.get(
|
||||
r"/projects/{project_id}/nodes/{node_id}/files/{path:.+}",
|
||||
parameters={
|
||||
|
@ -641,6 +641,25 @@ QEMU_OBJECT_SCHEMA = {
|
||||
"status"]
|
||||
}
|
||||
|
||||
QEMU_RESIZE_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Resize a disk in a QEMU VM",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"drive_name": {
|
||||
"description": "Absolute or relative path of the image",
|
||||
"enum": ["hda", "hdb", "hdc", "hdd"]
|
||||
},
|
||||
"extend": {
|
||||
"description": "Number of Megabytes to extend the image",
|
||||
"type": "integer"
|
||||
},
|
||||
# TODO: support shrink? (could be dangerous)
|
||||
},
|
||||
"required": ["drive_name", "extend"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
|
||||
QEMU_BINARY_FILTER_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Request validation for a list of QEMU capabilities",
|
||||
@ -758,3 +777,25 @@ QEMU_IMAGE_CREATE_SCHEMA = {
|
||||
"required": ["qemu_img", "path", "format", "size"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
|
||||
QEMU_IMAGE_UPDATE_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Update an existing QEMU image",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"qemu_img": {
|
||||
"description": "Path to the qemu-img binary",
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"description": "Absolute or relative path of the image",
|
||||
"type": "string"
|
||||
},
|
||||
"extend": {
|
||||
"description": "Number of Megabytes to extend the image",
|
||||
"type": "integer"
|
||||
},
|
||||
},
|
||||
"required": ["qemu_img", "path"],
|
||||
"additionalProperties": False
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user