summaryrefslogtreecommitdiff
path: root/usr.sbin/vmctl/vmctl.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2018-10-19 10:12:40 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2018-10-19 10:12:40 +0000
commite014ce92dbc428864aef9723a6d3bde4319f06bc (patch)
tree72a90057790b5a8544c1402e812405577dfbe64f /usr.sbin/vmctl/vmctl.c
parentdc388d4163b5f0cf447d8f1d605a6b3bd1da6346 (diff)
Add support to create and convert disk images from existing images
The -i option to vmctl create (eg. vmctl create output.qcow2 -i input.img) lets you create a new image from an input file and convert it if it is a different format. This allows to convert qcow2 images from raw images, raw from qcow2, or even qcow2 from qcow2 and raw from raw to re-optimize the disk. This re-uses Ori's vioqcow2.c from vmd by reaching into it and compiling it in. The API has been adjust to be used from both vmctl and vmd accordingly. OK mlarkin@
Diffstat (limited to 'usr.sbin/vmctl/vmctl.c')
-rw-r--r--usr.sbin/vmctl/vmctl.c117
1 files changed, 113 insertions, 4 deletions
diff --git a/usr.sbin/vmctl/vmctl.c b/usr.sbin/vmctl/vmctl.c
index a311ed0a512..1feca4754d4 100644
--- a/usr.sbin/vmctl/vmctl.c
+++ b/usr.sbin/vmctl/vmctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmctl.c,v 1.61 2018/10/08 16:32:01 reyk Exp $ */
+/* $OpenBSD: vmctl.c,v 1.62 2018/10/19 10:12:39 reyk Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
@@ -39,6 +39,7 @@
#include <grp.h>
#include "vmd.h"
+#include "virtio.h"
#include "vmctl.h"
#include "atomicio.h"
@@ -794,6 +795,116 @@ vm_console(struct vmop_info_result *list, size_t ct)
}
/*
+ * open_imagefile
+ *
+ * Open an imagefile with the specified type, path and size.
+ *
+ * Parameters:
+ * type : format of the image file
+ * imgfile_path: path to the image file to create
+ * flags : flags for open(2), e.g. O_RDONLY
+ * file : file structure
+ * sz : size of the image file
+ *
+ * Return:
+ * fd : Returns file descriptor of the new image file
+ * -1 : Operation failed. errno is set.
+ */
+int
+open_imagefile(int type, const char *imgfile_path, int flags,
+ struct virtio_backing *file, off_t *sz)
+{
+ int fd, ret, basefd[VM_MAX_BASE_PER_DISK], nfd, i;
+ char path[PATH_MAX];
+
+ *sz = 0;
+ if ((fd = open(imgfile_path, flags)) == -1)
+ return (-1);
+
+ basefd[0] = fd;
+ nfd = 1;
+
+ errno = 0;
+ switch (type) {
+ case VMDF_QCOW2:
+ if (strlcpy(path, imgfile_path, sizeof(path)) >= sizeof(path))
+ return (-1);
+ for (i = 0; i < VM_MAX_BASE_PER_DISK - 1; i++, nfd++) {
+ if ((ret = virtio_qcow2_get_base(basefd[i],
+ path, sizeof(path), imgfile_path)) == -1) {
+ log_debug("%s: failed to get base %d", __func__, i);
+ return -1;
+ } else if (ret == 0)
+ break;
+
+ /*
+ * This might be called after unveil is already
+ * locked but it is save to ignore the EPERM error
+ * here as the subsequent open would fail as well.
+ */
+ if ((ret = unveil(path, "r")) != 0 &&
+ (ret != EPERM))
+ err(1, "unveil");
+ if ((basefd[i + 1] = open(path, O_RDONLY)) == -1) {
+ log_warn("%s: failed to open base %s",
+ __func__, path);
+ return (-1);
+ }
+ }
+ ret = virtio_init_qcow2(file, sz, basefd, nfd);
+ break;
+ default:
+ ret = virtio_init_raw(file, sz, &fd, 1);
+ break;
+ }
+
+ if (ret == -1) {
+ for (i = 0; i < nfd; i++)
+ close(basefd[i]);
+ return (-1);
+ }
+
+ return (fd);
+}
+
+/*
+ * create_imagefile
+ *
+ * Create an empty imagefile with the specified type, path and size.
+ *
+ * Parameters:
+ * type : format of the image file
+ * imgfile_path: path to the image file to create
+ * base_path : path to the qcow2 base image
+ * imgsize : size of the image file to create (in MB)
+ * format : string identifying the format
+ *
+ * Return:
+ * EEXIST: The requested image file already exists
+ * 0 : Image file successfully created
+ * Exxxx : Various other Exxxx errno codes due to other I/O errors
+ */
+int
+create_imagefile(int type, const char *imgfile_path, const char *base_path,
+ long imgsize, const char **format)
+{
+ int ret;
+
+ switch (type) {
+ case VMDF_QCOW2:
+ *format = "qcow2";
+ ret = create_qc2_imagefile(imgfile_path, base_path, imgsize);
+ break;
+ default:
+ *format = "raw";
+ ret = create_raw_imagefile(imgfile_path, imgsize);
+ break;
+ }
+
+ return (ret);
+}
+
+/*
* create_raw_imagefile
*
* Create an empty imagefile with the specified path and size.
@@ -831,7 +942,7 @@ create_raw_imagefile(const char *imgfile_path, long imgsize)
}
/*
- * create_imagefile
+ * create_qc2_imagefile
*
* Create an empty qcow2 imagefile with the specified path and size.
*
@@ -844,8 +955,6 @@ create_raw_imagefile(const char *imgfile_path, long imgsize)
* 0 : Image file successfully created
* Exxxx : Various other Exxxx errno codes due to other I/O errors
*/
-#define ALIGN(sz, align) \
- ((sz + align - 1) & ~(align - 1))
int
create_qc2_imagefile(const char *imgfile_path,
const char *base_path, long imgsize)