2009-09-25 13:20:13 +00:00
|
|
|
/*
|
2012-12-13 15:25:48 +00:00
|
|
|
* virstoragefile.c: file utility functions for FS storage backend
|
2009-09-25 13:20:13 +00:00
|
|
|
*
|
2017-03-27 13:11:26 +00:00
|
|
|
* Copyright (C) 2007-2017 Red Hat, Inc.
|
2009-09-25 13:20:13 +00:00
|
|
|
* Copyright (C) 2007-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2009-09-25 13:20:13 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
2018-01-25 09:35:46 +00:00
|
|
|
#include "virstoragefilebackend.h"
|
2009-09-25 13:20:13 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
#include <unistd.h>
|
2009-09-29 08:41:23 +00:00
|
|
|
#include <fcntl.h>
|
2012-10-09 23:47:42 +00:00
|
|
|
#include <stdlib.h>
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2014-06-23 14:40:49 +00:00
|
|
|
#include "virxml.h"
|
|
|
|
#include "viruuid.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2011-07-20 09:40:53 +00:00
|
|
|
#include "c-ctype.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-10-13 16:47:15 +00:00
|
|
|
#include "virhash.h"
|
2013-02-07 01:57:13 +00:00
|
|
|
#include "virendian.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
|
|
|
#include "virutil.h"
|
2014-04-25 11:23:50 +00:00
|
|
|
#include "viruri.h"
|
|
|
|
#include "dirname.h"
|
2014-05-02 17:22:17 +00:00
|
|
|
#include "virbuffer.h"
|
2016-04-08 07:55:46 +00:00
|
|
|
#include "virjson.h"
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
#include "virstorageencryption.h"
|
2017-09-15 19:21:35 +00:00
|
|
|
#include "virsecret.h"
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.storagefile");
|
|
|
|
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
VIR_ENUM_IMPL(virStorage, VIR_STORAGE_TYPE_LAST,
|
2014-04-02 19:01:46 +00:00
|
|
|
"none",
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
"file",
|
2014-04-02 19:01:46 +00:00
|
|
|
"block",
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
"dir",
|
|
|
|
"network",
|
|
|
|
"volume")
|
|
|
|
|
2009-09-25 13:20:13 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageFileFormat,
|
|
|
|
VIR_STORAGE_FILE_LAST,
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
"none",
|
2010-11-22 20:08:17 +00:00
|
|
|
"raw", "dir", "bochs",
|
2014-04-14 22:54:14 +00:00
|
|
|
"cloop", "dmg", "iso",
|
|
|
|
"vpc", "vdi",
|
|
|
|
/* Not direct file formats, but used for various drivers */
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
"fat", "vhd", "ploop",
|
2014-04-14 22:54:14 +00:00
|
|
|
/* Formats with backing file below here */
|
|
|
|
"cow", "qcow", "qcow2", "qed", "vmdk")
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageFileFeature,
|
|
|
|
VIR_STORAGE_FILE_FEATURE_LAST,
|
|
|
|
"lazy_refcounts",
|
|
|
|
)
|
|
|
|
|
2014-03-27 22:47:39 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageNetProtocol, VIR_STORAGE_NET_PROTOCOL_LAST,
|
2014-04-24 14:11:44 +00:00
|
|
|
"none",
|
2014-03-27 22:47:39 +00:00
|
|
|
"nbd",
|
|
|
|
"rbd",
|
|
|
|
"sheepdog",
|
|
|
|
"gluster",
|
|
|
|
"iscsi",
|
|
|
|
"http",
|
|
|
|
"https",
|
|
|
|
"ftp",
|
|
|
|
"ftps",
|
2014-09-09 15:56:04 +00:00
|
|
|
"tftp",
|
2017-08-29 11:21:51 +00:00
|
|
|
"ssh",
|
|
|
|
"vxhs")
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
|
|
|
VIR_ENUM_IMPL(virStorageNetHostTransport, VIR_STORAGE_NET_HOST_TRANS_LAST,
|
|
|
|
"tcp",
|
|
|
|
"unix",
|
|
|
|
"rdma")
|
|
|
|
|
2014-03-28 04:33:45 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageSourcePoolMode,
|
|
|
|
VIR_STORAGE_SOURCE_POOL_MODE_LAST,
|
|
|
|
"default",
|
|
|
|
"host",
|
|
|
|
"direct")
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
2014-06-23 14:40:49 +00:00
|
|
|
VIR_ENUM_IMPL(virStorageAuth,
|
|
|
|
VIR_STORAGE_AUTH_TYPE_LAST,
|
|
|
|
"none", "chap", "ceph")
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
enum lv_endian {
|
|
|
|
LV_LITTLE_ENDIAN = 1, /* 1234 */
|
|
|
|
LV_BIG_ENDIAN /* 4321 */
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
BACKING_STORE_OK,
|
|
|
|
BACKING_STORE_INVALID,
|
|
|
|
BACKING_STORE_ERROR,
|
|
|
|
};
|
|
|
|
|
2017-05-08 09:05:09 +00:00
|
|
|
#define FILE_TYPE_VERSIONS_LAST 3
|
2013-05-07 15:27:43 +00:00
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
struct FileEncryptionInfo {
|
|
|
|
int format; /* Encryption format to assign */
|
|
|
|
|
|
|
|
int magicOffset; /* Byte offset of the magic */
|
|
|
|
const char *magic; /* Optional string of magic */
|
|
|
|
|
|
|
|
enum lv_endian endian; /* Endianness of file format */
|
|
|
|
|
|
|
|
int versionOffset; /* Byte offset from start of file
|
|
|
|
* where we find version number,
|
|
|
|
* -1 to always fail the version test,
|
|
|
|
* -2 to always pass the version test */
|
|
|
|
int versionSize; /* Size in bytes of version data (0, 2, or 4) */
|
|
|
|
int versionNumbers[FILE_TYPE_VERSIONS_LAST];
|
|
|
|
/* Version numbers to validate. Zeroes are ignored. */
|
|
|
|
|
|
|
|
int modeOffset; /* Byte offset of the format native encryption mode */
|
|
|
|
char modeValue; /* Value expected at offset */
|
2017-03-24 13:26:17 +00:00
|
|
|
|
|
|
|
int payloadOffset; /* start offset of the volume data (in 512 byte sectors) */
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
};
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
/* Either 'magic' or 'extension' *must* be provided */
|
|
|
|
struct FileTypeInfo {
|
2013-02-04 19:16:22 +00:00
|
|
|
int magicOffset; /* Byte offset of the magic */
|
2009-09-29 08:34:48 +00:00
|
|
|
const char *magic; /* Optional string of file magic
|
|
|
|
* to check at head of file */
|
|
|
|
const char *extension; /* Optional file extension to check */
|
|
|
|
enum lv_endian endian; /* Endianness of file format */
|
2016-06-21 17:47:21 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
int versionOffset; /* Byte offset from start of file
|
|
|
|
* where we find version number,
|
2013-06-10 09:44:31 +00:00
|
|
|
* -1 to always fail the version test,
|
|
|
|
* -2 to always pass the version test */
|
2016-06-21 17:47:21 +00:00
|
|
|
int versionSize; /* Size in bytes of version data (0, 2, or 4) */
|
2013-05-07 15:27:43 +00:00
|
|
|
int versionNumbers[FILE_TYPE_VERSIONS_LAST];
|
|
|
|
/* Version numbers to validate. Zeroes are ignored. */
|
2009-09-29 08:34:48 +00:00
|
|
|
int sizeOffset; /* Byte offset from start of file
|
|
|
|
* where we find capacity info,
|
|
|
|
* -1 to use st_size as capacity */
|
|
|
|
int sizeBytes; /* Number of bytes for size field */
|
|
|
|
int sizeMultiplier; /* A scaling factor if size is not in bytes */
|
|
|
|
/* Store a COW base image path (possibly relative),
|
|
|
|
* or NULL if there is no COW base image, to RES;
|
|
|
|
* return BACKING_STORE_* */
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
const struct FileEncryptionInfo *cryptInfo; /* Encryption info */
|
2010-06-14 14:53:59 +00:00
|
|
|
int (*getBackingStore)(char **res, int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf, size_t buf_size);
|
2013-05-07 15:27:43 +00:00
|
|
|
int (*getFeatures)(virBitmapPtr *features, int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf, ssize_t len);
|
2009-09-29 08:34:48 +00:00
|
|
|
};
|
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
static int cowGetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2010-06-14 14:53:59 +00:00
|
|
|
static int qcow1GetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2010-06-14 14:53:59 +00:00
|
|
|
static int qcow2GetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2013-05-07 15:27:43 +00:00
|
|
|
static int qcow2GetFeatures(virBitmapPtr *features, int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf, ssize_t len);
|
2010-06-14 14:53:59 +00:00
|
|
|
static int vmdk4GetBackingStore(char **, int *,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *, size_t);
|
2010-11-19 23:19:24 +00:00
|
|
|
static int
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
qedGetBackingStore(char **, int *, const char *, size_t);
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
#define QCOWX_HDR_VERSION (4)
|
|
|
|
#define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4)
|
|
|
|
#define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8)
|
|
|
|
#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4)
|
|
|
|
|
2015-01-23 12:29:48 +00:00
|
|
|
#define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1+2)
|
2010-06-14 14:53:59 +00:00
|
|
|
#define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8)
|
|
|
|
|
|
|
|
#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8)
|
|
|
|
#define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8)
|
|
|
|
|
|
|
|
#define QCOW2_HDR_EXTENSION_END 0
|
|
|
|
#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
|
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
#define QCOW2v3_HDR_FEATURES_INCOMPATIBLE (QCOW2_HDR_TOTAL_SIZE)
|
|
|
|
#define QCOW2v3_HDR_FEATURES_COMPATIBLE (QCOW2v3_HDR_FEATURES_INCOMPATIBLE+8)
|
|
|
|
#define QCOW2v3_HDR_FEATURES_AUTOCLEAR (QCOW2v3_HDR_FEATURES_COMPATIBLE+8)
|
|
|
|
|
|
|
|
/* The location of the header size [4 bytes] */
|
|
|
|
#define QCOW2v3_HDR_SIZE (QCOW2_HDR_TOTAL_SIZE+8+8+8+4)
|
|
|
|
|
2010-11-19 23:19:24 +00:00
|
|
|
#define QED_HDR_FEATURES_OFFSET (4+4+4+4)
|
2010-11-22 20:08:17 +00:00
|
|
|
#define QED_HDR_IMAGE_SIZE (QED_HDR_FEATURES_OFFSET+8+8+8+8)
|
|
|
|
#define QED_HDR_BACKING_FILE_OFFSET (QED_HDR_IMAGE_SIZE+8)
|
2010-11-19 23:19:24 +00:00
|
|
|
#define QED_HDR_BACKING_FILE_SIZE (QED_HDR_BACKING_FILE_OFFSET+4)
|
|
|
|
#define QED_F_BACKING_FILE 0x01
|
|
|
|
#define QED_F_BACKING_FORMAT_NO_PROBE 0x04
|
2010-11-19 16:18:16 +00:00
|
|
|
|
2016-04-11 16:16:24 +00:00
|
|
|
#define PLOOP_IMAGE_SIZE_OFFSET 36
|
|
|
|
#define PLOOP_SIZE_MULTIPLIER 512
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2016-06-21 16:59:54 +00:00
|
|
|
#define LUKS_HDR_MAGIC_LEN 6
|
|
|
|
#define LUKS_HDR_VERSION_LEN 2
|
2017-03-24 13:26:17 +00:00
|
|
|
#define LUKS_HDR_CIPHER_NAME_LEN 32
|
|
|
|
#define LUKS_HDR_CIPHER_MODE_LEN 32
|
|
|
|
#define LUKS_HDR_HASH_SPEC_LEN 32
|
|
|
|
#define LUKS_HDR_PAYLOAD_LEN 4
|
2016-06-21 16:59:54 +00:00
|
|
|
|
|
|
|
/* Format described by qemu commit id '3e308f20e' */
|
|
|
|
#define LUKS_HDR_VERSION_OFFSET LUKS_HDR_MAGIC_LEN
|
2017-03-24 13:26:17 +00:00
|
|
|
#define LUKS_HDR_PAYLOAD_OFFSET (LUKS_HDR_MAGIC_LEN+\
|
|
|
|
LUKS_HDR_VERSION_LEN+\
|
|
|
|
LUKS_HDR_CIPHER_NAME_LEN+\
|
|
|
|
LUKS_HDR_CIPHER_MODE_LEN+\
|
|
|
|
LUKS_HDR_HASH_SPEC_LEN)
|
2016-06-21 16:59:54 +00:00
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
static struct FileEncryptionInfo const luksEncryptionInfo[] = {
|
|
|
|
{
|
|
|
|
.format = VIR_STORAGE_ENCRYPTION_FORMAT_LUKS,
|
|
|
|
|
|
|
|
/* Magic is 'L','U','K','S', 0xBA, 0xBE */
|
|
|
|
.magicOffset = 0,
|
|
|
|
.magic = "\x4c\x55\x4b\x53\xba\xbe",
|
|
|
|
.endian = LV_BIG_ENDIAN,
|
|
|
|
|
|
|
|
.versionOffset = LUKS_HDR_VERSION_OFFSET,
|
|
|
|
.versionSize = LUKS_HDR_VERSION_LEN,
|
|
|
|
.versionNumbers = {1},
|
|
|
|
|
|
|
|
.modeOffset = -1,
|
|
|
|
.modeValue = -1,
|
2017-03-24 13:26:17 +00:00
|
|
|
|
|
|
|
.payloadOffset = LUKS_HDR_PAYLOAD_OFFSET,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
},
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct FileEncryptionInfo const qcow1EncryptionInfo[] = {
|
|
|
|
{
|
|
|
|
.format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW,
|
|
|
|
|
|
|
|
.magicOffset = 0,
|
|
|
|
.magic = NULL,
|
|
|
|
.endian = LV_BIG_ENDIAN,
|
|
|
|
|
|
|
|
.versionOffset = -1,
|
|
|
|
.versionSize = 0,
|
|
|
|
.versionNumbers = {},
|
|
|
|
|
|
|
|
.modeOffset = QCOW1_HDR_CRYPT,
|
|
|
|
.modeValue = 1,
|
2017-03-24 13:26:17 +00:00
|
|
|
|
|
|
|
.payloadOffset = -1,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
},
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct FileEncryptionInfo const qcow2EncryptionInfo[] = {
|
|
|
|
{
|
|
|
|
.format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW,
|
|
|
|
|
|
|
|
.magicOffset = 0,
|
|
|
|
.magic = NULL,
|
|
|
|
.endian = LV_BIG_ENDIAN,
|
|
|
|
|
|
|
|
.versionOffset = -1,
|
|
|
|
.versionSize = 0,
|
|
|
|
.versionNumbers = {},
|
|
|
|
|
|
|
|
.modeOffset = QCOW2_HDR_CRYPT,
|
|
|
|
.modeValue = 1,
|
2017-03-24 13:26:17 +00:00
|
|
|
|
|
|
|
.payloadOffset = -1,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
},
|
|
|
|
{ 0 }
|
|
|
|
};
|
2016-06-21 16:59:54 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static struct FileTypeInfo const fileTypeInfo[] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_NONE] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_RAW] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, {0}, 0, 0, 0,
|
|
|
|
luksEncryptionInfo,
|
|
|
|
NULL, NULL },
|
2013-02-04 19:16:22 +00:00
|
|
|
[VIR_STORAGE_FILE_DIR] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
|
2010-06-14 15:39:32 +00:00
|
|
|
[VIR_STORAGE_FILE_BOCHS] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
/*"Bochs Virtual HD Image", */ /* Untested */
|
|
|
|
0, NULL, NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_LITTLE_ENDIAN, 64, 4, {0x20000},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
32+16+16+4+4+4+4+4, 8, 1, NULL, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_CLOOP] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
/* #!/bin/sh
|
|
|
|
#V2.0 Format
|
|
|
|
modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1
|
|
|
|
*/ /* Untested */
|
|
|
|
0, NULL, NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_LITTLE_ENDIAN, -1, 0, {0},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, 0, NULL, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_DMG] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
/* XXX QEMU says there's no magic for dmg,
|
|
|
|
* /usr/share/misc/magic lists double magic (both offsets
|
|
|
|
* would have to match) but then disables that check. */
|
|
|
|
0, NULL, ".dmg",
|
2016-06-21 17:47:21 +00:00
|
|
|
0, -1, 0, {0},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, 0, NULL, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_ISO] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
32769, "CD001", ".iso",
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_LITTLE_ENDIAN, -2, 0, {0},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, 0, NULL, NULL, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
2014-04-14 22:54:14 +00:00
|
|
|
[VIR_STORAGE_FILE_VPC] = {
|
|
|
|
0, "conectix", NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_BIG_ENDIAN, 12, 4, {0x10000},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, NULL, NULL, NULL
|
2014-04-14 22:54:14 +00:00
|
|
|
},
|
|
|
|
/* TODO: add getBackingStore function */
|
|
|
|
[VIR_STORAGE_FILE_VDI] = {
|
|
|
|
64, "\x7f\x10\xda\xbe", ".vdi",
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_LITTLE_ENDIAN, 68, 4, {0x00010001},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
64 + 5 * 4 + 256 + 7 * 4, 8, 1, NULL, NULL, NULL},
|
2014-04-14 22:54:14 +00:00
|
|
|
|
|
|
|
/* Not direct file formats, but used for various drivers */
|
|
|
|
[VIR_STORAGE_FILE_FAT] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
|
2014-04-14 22:54:14 +00:00
|
|
|
[VIR_STORAGE_FILE_VHD] = { 0, NULL, NULL, LV_LITTLE_ENDIAN,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
-1, 0, {0}, 0, 0, 0, NULL, NULL, NULL },
|
2016-04-11 16:16:24 +00:00
|
|
|
[VIR_STORAGE_FILE_PLOOP] = { 0, "WithouFreSpacExt", NULL, LV_LITTLE_ENDIAN,
|
2016-06-21 17:47:21 +00:00
|
|
|
-2, 0, {0}, PLOOP_IMAGE_SIZE_OFFSET, 0,
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
PLOOP_SIZE_MULTIPLIER, NULL, NULL, NULL },
|
|
|
|
|
2014-04-14 22:54:14 +00:00
|
|
|
/* All formats with a backing store probe below here */
|
|
|
|
[VIR_STORAGE_FILE_COW] = {
|
|
|
|
0, "OOOM", NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_BIG_ENDIAN, 4, 4, {2},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
4+4+1024+4, 8, 1, NULL, cowGetBackingStore, NULL
|
2014-04-14 22:54:14 +00:00
|
|
|
},
|
2010-06-14 15:39:32 +00:00
|
|
|
[VIR_STORAGE_FILE_QCOW] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "QFI", NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_BIG_ENDIAN, 4, 4, {1},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
QCOWX_HDR_IMAGE_SIZE, 8, 1,
|
|
|
|
qcow1EncryptionInfo,
|
|
|
|
qcow1GetBackingStore, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
|
|
|
[VIR_STORAGE_FILE_QCOW2] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "QFI", NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_BIG_ENDIAN, 4, 4, {2, 3},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
QCOWX_HDR_IMAGE_SIZE, 8, 1,
|
|
|
|
qcow2EncryptionInfo,
|
|
|
|
qcow2GetBackingStore,
|
2013-05-07 15:27:43 +00:00
|
|
|
qcow2GetFeatures
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
2010-11-19 16:18:16 +00:00
|
|
|
[VIR_STORAGE_FILE_QED] = {
|
2017-10-13 15:30:41 +00:00
|
|
|
/* https://wiki.qemu.org/Features/QED */
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "QED", NULL,
|
2016-06-21 17:47:21 +00:00
|
|
|
LV_LITTLE_ENDIAN, -2, 0, {0},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
QED_HDR_IMAGE_SIZE, 8, 1, NULL, qedGetBackingStore, NULL
|
2010-11-19 16:18:16 +00:00
|
|
|
},
|
2010-06-14 15:39:32 +00:00
|
|
|
[VIR_STORAGE_FILE_VMDK] = {
|
2013-02-04 19:16:22 +00:00
|
|
|
0, "KDMV", NULL,
|
2017-05-08 09:05:09 +00:00
|
|
|
LV_LITTLE_ENDIAN, 4, 4, {1, 2, 3},
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
4+4+4, 8, 512, NULL, vmdk4GetBackingStore, NULL
|
2010-06-14 15:39:32 +00:00
|
|
|
},
|
2009-09-29 08:34:48 +00:00
|
|
|
};
|
2010-06-14 15:39:32 +00:00
|
|
|
verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST);
|
2009-09-29 08:34:48 +00:00
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
/* qcow2 compatible features in the order they appear on-disk */
|
|
|
|
enum qcow2CompatibleFeature {
|
|
|
|
QCOW2_COMPATIBLE_FEATURE_LAZY_REFCOUNTS = 0,
|
|
|
|
|
|
|
|
QCOW2_COMPATIBLE_FEATURE_LAST
|
|
|
|
};
|
|
|
|
|
|
|
|
/* conversion to virStorageFileFeature */
|
|
|
|
static const int qcow2CompatibleFeatureArray[] = {
|
|
|
|
VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS,
|
|
|
|
};
|
|
|
|
verify(ARRAY_CARDINALITY(qcow2CompatibleFeatureArray) ==
|
|
|
|
QCOW2_COMPATIBLE_FEATURE_LAST);
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
cowGetBackingStore(char **res,
|
2010-06-14 14:53:59 +00:00
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2009-09-29 08:34:48 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
#define COW_FILENAME_MAXLEN 1024
|
|
|
|
*res = NULL;
|
2010-06-14 14:53:59 +00:00
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
if (buf_size < 4+4+ COW_FILENAME_MAXLEN)
|
|
|
|
return BACKING_STORE_INVALID;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (buf[4+4] == '\0') { /* cow_header_v2.backing_file[0] */
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_OK;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-24 07:19:51 +00:00
|
|
|
if (VIR_STRNDUP(*res, (const char*)buf + 4 + 4, COW_FILENAME_MAXLEN) < 0)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_ERROR;
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
qcow2GetBackingStoreFormat(int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size,
|
|
|
|
size_t extension_start,
|
|
|
|
size_t extension_end)
|
|
|
|
{
|
|
|
|
size_t offset = extension_start;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The extensions take format of
|
|
|
|
*
|
|
|
|
* int32: magic
|
|
|
|
* int32: length
|
|
|
|
* byte[length]: payload
|
|
|
|
*
|
|
|
|
* Unknown extensions can be ignored by skipping
|
|
|
|
* over "length" bytes in the data stream.
|
|
|
|
*/
|
|
|
|
while (offset < (buf_size-8) &&
|
|
|
|
offset < (extension_end-8)) {
|
2013-02-07 01:57:13 +00:00
|
|
|
unsigned int magic = virReadBufInt32BE(buf + offset);
|
|
|
|
unsigned int len = virReadBufInt32BE(buf + offset + 4);
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
if ((offset + len) < offset)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ((offset + len) > buf_size)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (magic) {
|
|
|
|
case QCOW2_HDR_EXTENSION_END:
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
case QCOW2_HDR_EXTENSION_BACKING_FORMAT:
|
|
|
|
if (buf[offset+len] != '\0')
|
|
|
|
break;
|
|
|
|
*format = virStorageFileFormatTypeFromString(
|
|
|
|
((const char *)buf)+offset);
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (*format <= VIR_STORAGE_FILE_NONE)
|
|
|
|
return -1;
|
2010-06-14 14:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
offset += len;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
done:
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
qcowXGetBackingStore(char **res,
|
2010-06-14 14:53:59 +00:00
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size,
|
|
|
|
bool isQCow2)
|
2009-09-29 08:34:48 +00:00
|
|
|
{
|
|
|
|
unsigned long long offset;
|
2011-06-02 23:52:16 +00:00
|
|
|
unsigned int size;
|
2013-05-07 15:27:43 +00:00
|
|
|
unsigned long long start;
|
|
|
|
int version;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
*res = NULL;
|
2010-06-14 14:53:59 +00:00
|
|
|
if (format)
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
|
|
|
|
if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
offset = virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSET);
|
2009-09-29 08:34:48 +00:00
|
|
|
if (offset > buf_size)
|
|
|
|
return BACKING_STORE_INVALID;
|
2014-09-15 14:16:25 +00:00
|
|
|
|
|
|
|
if (offset == 0) {
|
|
|
|
if (format)
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
2013-02-07 01:57:13 +00:00
|
|
|
size = virReadBufInt32BE(buf + QCOWX_HDR_BACKING_FILE_SIZE);
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (size == 0) {
|
|
|
|
if (format)
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_OK;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
}
|
2014-09-15 14:16:25 +00:00
|
|
|
if (size > 1023)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_INVALID;
|
2014-09-15 14:16:25 +00:00
|
|
|
if (offset + size > buf_size || offset + size < offset)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_INVALID;
|
2013-07-04 10:17:18 +00:00
|
|
|
if (VIR_ALLOC_N(*res, size + 1) < 0)
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_ERROR;
|
|
|
|
memcpy(*res, buf + offset, size);
|
|
|
|
(*res)[size] = '\0';
|
2010-06-14 14:53:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Traditionally QCow2 files had a layout of
|
|
|
|
*
|
|
|
|
* [header]
|
|
|
|
* [backingStoreName]
|
|
|
|
*
|
|
|
|
* Although the backingStoreName typically followed
|
|
|
|
* the header immediately, this was not required by
|
|
|
|
* the format. By specifying a higher byte offset for
|
|
|
|
* the backing file offset in the header, it was
|
|
|
|
* possible to leave space between the header and
|
|
|
|
* start of backingStore.
|
|
|
|
*
|
|
|
|
* This hack is now used to store extensions to the
|
|
|
|
* qcow2 format:
|
|
|
|
*
|
|
|
|
* [header]
|
|
|
|
* [extensions]
|
|
|
|
* [backingStoreName]
|
|
|
|
*
|
|
|
|
* Thus the file region to search for extensions is
|
|
|
|
* between the end of the header (QCOW2_HDR_TOTAL_SIZE)
|
|
|
|
* and the start of the backingStoreName (offset)
|
2013-05-07 15:27:43 +00:00
|
|
|
*
|
|
|
|
* for qcow2 v3 images, the length of the header
|
|
|
|
* is stored at QCOW2v3_HDR_SIZE
|
2010-06-14 14:53:59 +00:00
|
|
|
*/
|
2013-05-07 15:27:43 +00:00
|
|
|
if (isQCow2 && format) {
|
|
|
|
version = virReadBufInt32BE(buf + QCOWX_HDR_VERSION);
|
|
|
|
if (version == 2)
|
|
|
|
start = QCOW2_HDR_TOTAL_SIZE;
|
|
|
|
else
|
|
|
|
start = virReadBufInt32BE(buf + QCOW2v3_HDR_SIZE);
|
|
|
|
if (qcow2GetBackingStoreFormat(format, buf, buf_size,
|
|
|
|
start, offset) < 0)
|
|
|
|
return BACKING_STORE_INVALID;
|
|
|
|
}
|
2010-06-14 14:53:59 +00:00
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
static int
|
|
|
|
qcow1GetBackingStore(char **res,
|
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
int ret;
|
|
|
|
|
2010-06-14 14:53:59 +00:00
|
|
|
/* QCow1 doesn't have the extensions capability
|
|
|
|
* used to store backing format */
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
ret = qcowXGetBackingStore(res, NULL, buf, buf_size, false);
|
|
|
|
if (ret == 0 && *buf == '\0')
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
|
|
|
return ret;
|
2010-06-14 14:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
qcow2GetBackingStore(char **res,
|
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-06-14 14:53:59 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
return qcowXGetBackingStore(res, format, buf, buf_size, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-29 08:34:48 +00:00
|
|
|
static int
|
2010-02-04 22:46:55 +00:00
|
|
|
vmdk4GetBackingStore(char **res,
|
2010-06-14 14:53:59 +00:00
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2009-09-29 08:34:48 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
static const char prefix[] = "parentFileNameHint=\"";
|
2010-06-15 13:58:10 +00:00
|
|
|
char *desc, *start, *end;
|
2009-09-29 08:34:48 +00:00
|
|
|
size_t len;
|
2010-06-15 13:58:10 +00:00
|
|
|
int ret = BACKING_STORE_ERROR;
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (VIR_ALLOC_N(desc, VIR_STORAGE_MAX_HEADER) < 0)
|
2010-06-15 13:58:10 +00:00
|
|
|
goto cleanup;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
|
|
|
*res = NULL;
|
2010-06-14 14:53:59 +00:00
|
|
|
/*
|
|
|
|
* Technically this should have been VMDK, since
|
2016-02-15 14:34:24 +00:00
|
|
|
* VMDK spec / VMware impl only support VMDK backed
|
2010-06-14 14:53:59 +00:00
|
|
|
* by VMDK. QEMU isn't following this though and
|
|
|
|
* does probing on VMDK backing files, hence we set
|
|
|
|
* AUTO
|
|
|
|
*/
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
if (buf_size <= 0x200) {
|
|
|
|
ret = BACKING_STORE_INVALID;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
len = buf_size - 0x200;
|
2013-11-05 21:12:02 +00:00
|
|
|
if (len > VIR_STORAGE_MAX_HEADER)
|
|
|
|
len = VIR_STORAGE_MAX_HEADER;
|
2009-09-29 08:34:48 +00:00
|
|
|
memcpy(desc, buf + 0x200, len);
|
|
|
|
desc[len] = '\0';
|
|
|
|
start = strstr(desc, prefix);
|
2010-06-15 13:58:10 +00:00
|
|
|
if (start == NULL) {
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2010-06-15 13:58:10 +00:00
|
|
|
ret = BACKING_STORE_OK;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
start += strlen(prefix);
|
|
|
|
end = strchr(start, '"');
|
2010-06-15 13:58:10 +00:00
|
|
|
if (end == NULL) {
|
|
|
|
ret = BACKING_STORE_INVALID;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (end == start) {
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2010-06-15 13:58:10 +00:00
|
|
|
ret = BACKING_STORE_OK;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
*end = '\0';
|
2013-05-24 07:19:51 +00:00
|
|
|
if (VIR_STRDUP(*res, start) < 0)
|
2010-06-15 13:58:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = BACKING_STORE_OK;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2010-06-15 13:58:10 +00:00
|
|
|
VIR_FREE(desc);
|
|
|
|
return ret;
|
2009-09-29 08:34:48 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 23:19:24 +00:00
|
|
|
static int
|
|
|
|
qedGetBackingStore(char **res,
|
|
|
|
int *format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
const char *buf,
|
2010-11-19 23:19:24 +00:00
|
|
|
size_t buf_size)
|
|
|
|
{
|
|
|
|
unsigned long long flags;
|
|
|
|
unsigned long offset, size;
|
|
|
|
|
|
|
|
*res = NULL;
|
|
|
|
/* Check if this image has a backing file */
|
|
|
|
if (buf_size < QED_HDR_FEATURES_OFFSET+8)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
flags = virReadBufInt64LE(buf + QED_HDR_FEATURES_OFFSET);
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (!(flags & QED_F_BACKING_FILE)) {
|
|
|
|
*format = VIR_STORAGE_FILE_NONE;
|
2010-11-19 23:19:24 +00:00
|
|
|
return BACKING_STORE_OK;
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
}
|
2010-11-19 23:19:24 +00:00
|
|
|
|
|
|
|
/* Parse the backing file */
|
|
|
|
if (buf_size < QED_HDR_BACKING_FILE_OFFSET+8)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
offset = virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_OFFSET);
|
2010-11-19 23:19:24 +00:00
|
|
|
if (offset > buf_size)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-02-07 01:57:13 +00:00
|
|
|
size = virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_SIZE);
|
2010-11-19 23:19:24 +00:00
|
|
|
if (size == 0)
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
if (offset + size > buf_size || offset + size < offset)
|
|
|
|
return BACKING_STORE_INVALID;
|
2013-07-04 10:17:18 +00:00
|
|
|
if (VIR_ALLOC_N(*res, size + 1) < 0)
|
2010-11-19 23:19:24 +00:00
|
|
|
return BACKING_STORE_ERROR;
|
|
|
|
memcpy(*res, buf + offset, size);
|
|
|
|
(*res)[size] = '\0';
|
|
|
|
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
if (flags & QED_F_BACKING_FORMAT_NO_PROBE)
|
|
|
|
*format = VIR_STORAGE_FILE_RAW;
|
|
|
|
else
|
|
|
|
*format = VIR_STORAGE_FILE_AUTO_SAFE;
|
2010-11-19 23:19:24 +00:00
|
|
|
|
|
|
|
return BACKING_STORE_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
static bool
|
2016-07-26 17:10:41 +00:00
|
|
|
virStorageFileMatchesMagic(int magicOffset,
|
|
|
|
const char *magic,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2010-06-15 13:58:10 +00:00
|
|
|
size_t buflen)
|
2009-09-29 08:34:48 +00:00
|
|
|
{
|
2010-06-15 13:58:10 +00:00
|
|
|
int mlen;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-02-04 19:16:22 +00:00
|
|
|
if (magic == NULL)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
2010-05-18 05:53:31 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/* Validate magic data */
|
2013-02-04 19:16:22 +00:00
|
|
|
mlen = strlen(magic);
|
|
|
|
if (magicOffset + mlen > buflen)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-02-04 19:16:22 +00:00
|
|
|
if (memcmp(buf + magicOffset, magic, mlen) != 0)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
2016-07-26 17:10:41 +00:00
|
|
|
virStorageFileMatchesExtension(const char *extension,
|
2010-06-15 13:58:10 +00:00
|
|
|
const char *path)
|
|
|
|
{
|
2016-07-26 17:10:41 +00:00
|
|
|
if (extension == NULL)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
|
|
|
|
2016-07-26 17:10:41 +00:00
|
|
|
if (virFileHasSuffix(path, extension))
|
2010-06-15 13:58:10 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
2016-07-26 17:10:41 +00:00
|
|
|
virStorageFileMatchesVersion(int versionOffset,
|
|
|
|
int versionSize,
|
|
|
|
const int *versionNumbers,
|
|
|
|
int endian,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2010-06-15 13:58:10 +00:00
|
|
|
size_t buflen)
|
|
|
|
{
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
int version;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
/* Validate version number info */
|
2016-07-26 17:10:41 +00:00
|
|
|
if (versionOffset == -1)
|
storage: list more file types
When an image has no backing file, using VIR_STORAGE_FILE_AUTO
for its type is a bit confusing. Additionally, a future patch
would like to reserve a default value for the case of no file
type specified in the XML, but different from the current use
of -1 to imply probing, since probing is not always safe.
Also, a couple of file types were missing compared to supported
code: libxl supports 'vhd', and qemu supports 'fat' for directories
passed through as a file system.
* src/util/storage_file.h (virStorageFileFormat): Add
VIR_STORAGE_FILE_NONE, VIR_STORAGE_FILE_FAT, VIR_STORAGE_FILE_VHD.
* src/util/storage_file.c (virStorageFileMatchesVersion): Match
documentation when version probing not supported.
(cowGetBackingStore, qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStoreFormat, qedGetBackingStore)
(virStorageFileGetMetadataFromBuf)
(virStorageFileGetMetadataFromFD): Take NONE into account.
* src/conf/domain_conf.c (virDomainDiskDefForeachPath): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Likewise.
* src/conf/storage_conf.c (virStorageVolumeFormatFromString): New
function.
(poolTypeInfo): Use it.
2012-09-28 17:11:07 +00:00
|
|
|
return false;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2012-12-13 14:25:10 +00:00
|
|
|
/* -2 == non-versioned file format, so trivially match */
|
2016-07-26 17:10:41 +00:00
|
|
|
if (versionOffset == -2)
|
2012-12-13 14:25:10 +00:00
|
|
|
return true;
|
|
|
|
|
2016-06-21 17:47:21 +00:00
|
|
|
/* A positive versionOffset, requires using a valid versionSize */
|
2016-07-26 17:10:41 +00:00
|
|
|
if (versionSize != 2 && versionSize != 4)
|
2010-06-15 13:58:10 +00:00
|
|
|
return false;
|
|
|
|
|
2016-07-26 17:10:41 +00:00
|
|
|
if ((versionOffset + versionSize) > buflen)
|
2016-06-21 17:47:21 +00:00
|
|
|
return false;
|
|
|
|
|
2016-07-26 17:10:41 +00:00
|
|
|
if (endian == LV_LITTLE_ENDIAN) {
|
|
|
|
if (versionSize == 4)
|
2016-06-21 17:47:21 +00:00
|
|
|
version = virReadBufInt32LE(buf +
|
2016-07-26 17:10:41 +00:00
|
|
|
versionOffset);
|
2016-06-21 17:47:21 +00:00
|
|
|
else
|
|
|
|
version = virReadBufInt16LE(buf +
|
2016-07-26 17:10:41 +00:00
|
|
|
versionOffset);
|
2016-06-21 17:47:21 +00:00
|
|
|
} else {
|
2016-07-26 17:10:41 +00:00
|
|
|
if (versionSize == 4)
|
2016-06-21 17:47:21 +00:00
|
|
|
version = virReadBufInt32BE(buf +
|
2016-07-26 17:10:41 +00:00
|
|
|
versionOffset);
|
2016-06-21 17:47:21 +00:00
|
|
|
else
|
|
|
|
version = virReadBufInt16BE(buf +
|
2016-07-26 17:10:41 +00:00
|
|
|
versionOffset);
|
2016-06-21 17:47:21 +00:00
|
|
|
}
|
2012-12-13 14:23:50 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
for (i = 0;
|
2016-07-26 17:10:41 +00:00
|
|
|
i < FILE_TYPE_VERSIONS_LAST && versionNumbers[i];
|
2013-05-07 15:27:43 +00:00
|
|
|
i++) {
|
|
|
|
VIR_DEBUG("Compare detected version %d vs one of the expected versions %d",
|
2016-07-26 17:10:41 +00:00
|
|
|
version, versionNumbers[i]);
|
|
|
|
if (version == versionNumbers[i])
|
2013-05-07 15:27:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
return false;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2014-04-09 22:08:42 +00:00
|
|
|
bool
|
|
|
|
virStorageIsFile(const char *backing)
|
2010-11-03 15:50:11 +00:00
|
|
|
{
|
2014-04-09 22:08:42 +00:00
|
|
|
char *colon;
|
|
|
|
char *slash;
|
|
|
|
|
|
|
|
if (!backing)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
colon = strchr(backing, ':');
|
|
|
|
slash = strchr(backing, '/');
|
2013-11-04 21:27:42 +00:00
|
|
|
|
|
|
|
/* Reject anything that looks like a protocol (such as nbd: or
|
|
|
|
* rbd:); if someone really does want a relative file name that
|
|
|
|
* includes ':', they can always prefix './'. */
|
|
|
|
if (colon && (!slash || colon < slash))
|
2010-11-03 15:50:11 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2014-04-29 03:40:22 +00:00
|
|
|
|
2017-06-19 16:06:34 +00:00
|
|
|
bool
|
2014-04-25 11:23:50 +00:00
|
|
|
virStorageIsRelative(const char *backing)
|
|
|
|
{
|
|
|
|
if (backing[0] == '/')
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!virStorageIsFile(backing))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-01 21:23:58 +00:00
|
|
|
static int
|
2013-02-06 23:54:08 +00:00
|
|
|
virStorageFileProbeFormatFromBuf(const char *path,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2013-02-06 23:54:08 +00:00
|
|
|
size_t buflen)
|
|
|
|
{
|
|
|
|
int format = VIR_STORAGE_FILE_RAW;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-02-06 23:54:08 +00:00
|
|
|
int possibleFormat = VIR_STORAGE_FILE_RAW;
|
2013-11-05 21:12:02 +00:00
|
|
|
VIR_DEBUG("path=%s, buf=%p, buflen=%zu", path, buf, buflen);
|
2013-02-06 23:54:08 +00:00
|
|
|
|
|
|
|
/* First check file magic */
|
2013-05-21 07:58:16 +00:00
|
|
|
for (i = 0; i < VIR_STORAGE_FILE_LAST; i++) {
|
2016-07-26 17:10:41 +00:00
|
|
|
if (virStorageFileMatchesMagic(
|
|
|
|
fileTypeInfo[i].magicOffset,
|
|
|
|
fileTypeInfo[i].magic,
|
|
|
|
buf, buflen)) {
|
|
|
|
if (!virStorageFileMatchesVersion(
|
|
|
|
fileTypeInfo[i].versionOffset,
|
|
|
|
fileTypeInfo[i].versionSize,
|
|
|
|
fileTypeInfo[i].versionNumbers,
|
|
|
|
fileTypeInfo[i].endian,
|
|
|
|
buf, buflen)) {
|
2013-02-06 23:54:08 +00:00
|
|
|
possibleFormat = i;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
format = i;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (possibleFormat != VIR_STORAGE_FILE_RAW)
|
|
|
|
VIR_WARN("File %s matches %s magic, but version is wrong. "
|
|
|
|
"Please report new version to libvir-list@redhat.com",
|
|
|
|
path, virStorageFileFormatTypeToString(possibleFormat));
|
|
|
|
|
|
|
|
/* No magic, so check file extension */
|
2013-05-21 07:58:16 +00:00
|
|
|
for (i = 0; i < VIR_STORAGE_FILE_LAST; i++) {
|
2016-07-26 17:10:41 +00:00
|
|
|
if (virStorageFileMatchesExtension(
|
|
|
|
fileTypeInfo[i].extension, path)) {
|
2013-02-06 23:54:08 +00:00
|
|
|
format = i;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-02-06 23:54:08 +00:00
|
|
|
VIR_DEBUG("format=%d", format);
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-05-07 15:27:43 +00:00
|
|
|
static int
|
|
|
|
qcow2GetFeatures(virBitmapPtr *features,
|
|
|
|
int format,
|
storage: use simpler 'char *'
'unsigned char *' makes sense if you are doing math on bytes and
don't want to worry about wraparound from a signed 'char'; but
since all we are doing is memcmp() or virReadBufInt*[LB]E(), which
are both safe on either type of char, and since read() prefers to
operate on 'char *', it's simpler to avoid casts by just typing
things as 'char *' from the get-go. [Technically, read can
operate on an 'unsigned char *' thanks to the C rule that any
pointer can be implicitly converted to 'char *' for legacy K&R
compatibility; but where this patch saves us is if we try to use
virfile.h functions that take 'char **' in order to allocate the
buffer, where the compiler would barf on type mismatch.]
* src/util/virstoragefile.c (FileTypeInfo): Avoid unsigned char.
(cowGetBackingStore, qcow2GetBackingStoreFormat)
(qcowXGetBackingStore, qcow1GetBackingStore)
(qcow2GetBackingStore, vmdk4GetBackingStore, qedGetBackingStore)
(virStorageFileMatchesMagic, virStorageFileMatchesVersion)
(virStorageFileProbeFormatFromBuf, qcow2GetFeatures)
(virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Simplify clients.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-11-05 17:44:14 +00:00
|
|
|
char *buf,
|
2013-05-07 15:27:43 +00:00
|
|
|
ssize_t len)
|
|
|
|
{
|
|
|
|
int version = -1;
|
|
|
|
virBitmapPtr feat = NULL;
|
|
|
|
uint64_t bits;
|
Convert 'int i' to 'size_t i' in src/util/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2013-05-07 15:27:43 +00:00
|
|
|
|
|
|
|
version = virReadBufInt32BE(buf + fileTypeInfo[format].versionOffset);
|
|
|
|
|
|
|
|
if (version == 2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (len < QCOW2v3_HDR_SIZE)
|
|
|
|
return -1;
|
|
|
|
|
2013-07-04 10:17:18 +00:00
|
|
|
if (!(feat = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST)))
|
2013-05-07 15:27:43 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* todo: check for incompatible or autoclear features? */
|
|
|
|
bits = virReadBufInt64BE(buf + QCOW2v3_HDR_FEATURES_COMPATIBLE);
|
|
|
|
for (i = 0; i < QCOW2_COMPATIBLE_FEATURE_LAST; i++) {
|
|
|
|
if (bits & ((uint64_t) 1 << i))
|
|
|
|
ignore_value(virBitmapSetBit(feat, qcow2CompatibleFeatureArray[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
*features = feat;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
static bool
|
|
|
|
virStorageFileHasEncryptionFormat(const struct FileEncryptionInfo *info,
|
|
|
|
char *buf,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
if (!info->magic && info->modeOffset == -1)
|
2016-09-06 21:00:30 +00:00
|
|
|
return false; /* Shouldn't happen - expect at least one */
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
|
|
|
|
if (info->magic) {
|
|
|
|
if (!virStorageFileMatchesMagic(info->magicOffset,
|
|
|
|
info->magic,
|
|
|
|
buf, len))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (info->versionOffset != -1 &&
|
|
|
|
!virStorageFileMatchesVersion(info->versionOffset,
|
|
|
|
info->versionSize,
|
|
|
|
info->versionNumbers,
|
|
|
|
info->endian,
|
|
|
|
buf, len))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} else if (info->modeOffset != -1) {
|
2016-09-06 21:00:30 +00:00
|
|
|
int crypt_format;
|
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
if (info->modeOffset >= len)
|
|
|
|
return false;
|
|
|
|
|
2016-09-06 21:00:30 +00:00
|
|
|
crypt_format = virReadBufInt32BE(buf + info->modeOffset);
|
|
|
|
if (crypt_format != info->modeValue)
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-24 13:26:17 +00:00
|
|
|
static int
|
|
|
|
virStorageFileGetEncryptionPayloadOffset(const struct FileEncryptionInfo *info,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
int payload_offset = -1;
|
|
|
|
|
|
|
|
if (info->payloadOffset != -1) {
|
|
|
|
if (info->endian == LV_LITTLE_ENDIAN)
|
|
|
|
payload_offset = virReadBufInt32LE(buf + info->payloadOffset);
|
|
|
|
else
|
|
|
|
payload_offset = virReadBufInt32BE(buf + info->payloadOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return payload_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-15 12:25:10 +00:00
|
|
|
/* Given a header in BUF with length LEN, as parsed from the storage file
|
|
|
|
* assuming it has the given FORMAT, populate information into META
|
|
|
|
* with information about the file and its backing store. Return format
|
|
|
|
* of the backing store as BACKING_FORMAT. PATH and FORMAT have to be
|
|
|
|
* pre-populated in META */
|
2014-04-25 19:38:40 +00:00
|
|
|
int
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageFileGetMetadataInternal(virStorageSourcePtr meta,
|
2013-11-05 20:50:29 +00:00
|
|
|
char *buf,
|
|
|
|
size_t len,
|
2014-04-16 13:44:06 +00:00
|
|
|
int *backingFormat)
|
2010-06-15 13:58:10 +00:00
|
|
|
{
|
2017-06-20 14:34:14 +00:00
|
|
|
int dummy;
|
2014-04-08 21:20:36 +00:00
|
|
|
int ret = -1;
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
size_t i;
|
2013-02-06 23:33:45 +00:00
|
|
|
|
2017-06-20 14:34:14 +00:00
|
|
|
if (!backingFormat)
|
|
|
|
backingFormat = &dummy;
|
|
|
|
|
2014-05-27 08:05:57 +00:00
|
|
|
VIR_DEBUG("path=%s, buf=%p, len=%zu, meta->format=%d",
|
|
|
|
meta->path, buf, len, meta->format);
|
2013-02-09 13:41:01 +00:00
|
|
|
|
2014-04-15 12:25:10 +00:00
|
|
|
if (meta->format == VIR_STORAGE_FILE_AUTO)
|
2014-05-27 08:05:57 +00:00
|
|
|
meta->format = virStorageFileProbeFormatFromBuf(meta->path, buf, len);
|
conf: track more fields in backing chain metadata
The current use of virStorageFileMetadata is awkward; to learn
some of the information about a child node, you have to read
fields in the parent node. This does not lend itself well to
modifying backing chains (whether inserting a new node in the
chain, or consolidating existing nodes); better would be to
learn about a child node directly in that node. This patch
sets up some new fields which contain redundant information,
although not necessarily in the final desired state for the
new fields (see the next patch for actual tests of what is there
now). Then later patches will do any refactoring necessary to
get the fields to their desired states, and update clients to
get the information from the new fields, so we can finally
delete the fields that are tracking information about the wrong
node.
More concretely, compare these three example backing chains:
good <- one
missing <- two
gluster://server/vol/img <- three
Pre-patch, querying the chains gives:
{ .backingStore = "/path/to/good",
.backingStoreRaw = "good",
.backingStoreIsFile = true,
.backingStoreFormat = VIR_STORAGE_FILE_RAW,
.backingMeta = {
.backingStore = NULL,
.backingStoreRaw = NULL,
.backingStoreIsFile = false,
.backingMeta = NULL,
}
}
{ .backingStore = NULL,
.backingStoreRaw = "missing",
.backingStoreIsFile = false,
.backingStoreFormat = VIR_STORAGE_FILE_NONE,
.backingMeta = NULL,
}
{ .backingStore = "gluster://server/vol/img",
.backingStoreRaw = NULL,
.backingStoreIsFile = false,
.backingStoreFormat = VIR_STORAGE_FILE_RAW,
.backingMeta = NULL,
}
Deciding whether to ignore a missing backing file (as in virsh
vol-dumpxml) or report an error (as in security manager sVirt
labeling) requires reading multiple fields. Plus, the format
is hard-coded to treat all network protocols as end-of-the-chain,
as if they were raw. By the end of this patch series, the goal
is to instead represent these three situations as:
{ .path = "one",
.canonPath = "/path/to/one",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "good",
.backingMeta = {
.path = "good",
.canonPath = "/path/to/good",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_RAW,
.backingStoreRaw = NULL,
.backingMeta = NULL,
}
}
{ .path = "two",
.canonPath = "/path/to/two",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "missing",
.backingMeta = NULL,
}
{ .path = "three",
.canonPath = "/path/to/three",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "gluster://server/vol/img",
.backingMeta = {
.path = "gluster://server/vol/img",
.canonPath = "gluster://server/vol/img",
.type = VIR_STORAGE_TYPE_NETWORK,
.format = VIR_STORAGE_FILE_RAW,
.backingStoreRaw = NULL,
.backingMeta = NULL,
}
}
or, for the second file, maybe also allowing:
{ .path = "two",
.canonPath = "/path/to/two",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "missing",
.backingMeta = {
.path = "missing",
.canonPath = NULL,
.type = VIR_STORAGE_TYPE_NONE,
.format = VIR_STORAGE_FILE_NONE,
.backingStoreRaw = NULL,
.backingMeta = NULL,
}
}
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
path, canonPath, relDir, type, and format fields. Reorder
existing fields, and add lots of comments.
* src/util/virstoragefile.c (virStorageFileFreeMetadata): Clean
new fields.
(virStorageFileGetMetadataInternal)
(virStorageFileGetMetadataFromFDInternal): Start populating new
fields.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-04-08 22:09:05 +00:00
|
|
|
|
2014-04-15 12:25:10 +00:00
|
|
|
if (meta->format <= VIR_STORAGE_FILE_NONE ||
|
|
|
|
meta->format >= VIR_STORAGE_FILE_LAST) {
|
|
|
|
virReportSystemError(EINVAL, _("unknown storage file meta->format %d"),
|
|
|
|
meta->format);
|
2013-02-06 23:33:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-12-13 14:23:50 +00:00
|
|
|
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
if (fileTypeInfo[meta->format].cryptInfo != NULL) {
|
|
|
|
for (i = 0; fileTypeInfo[meta->format].cryptInfo[i].format != 0; i++) {
|
|
|
|
if (virStorageFileHasEncryptionFormat(&fileTypeInfo[meta->format].cryptInfo[i],
|
|
|
|
buf, len)) {
|
qemu: Fix crash hot plugging luks volume
https://bugzilla.redhat.com/show_bug.cgi?id=1367259
Crash occurs because 'secrets' is being dereferenced in call:
if (qemuDomainSecretSetup(conn, priv, secinfo, disk->info.alias,
VIR_SECRET_USAGE_TYPE_VOLUME, NULL,
&src->encryption->secrets[0]->seclookupdef,
true) < 0)
(gdb) p *src->encryption
$1 = {format = 2, nsecrets = 0, secrets = 0x0, encinfo = {cipher_size = 0,
cipher_name = 0x0, cipher_mode = 0x0, cipher_hash = 0x0, ivgen_name = 0x0,
ivgen_hash = 0x0}}
(gdb) bt
priv=priv@entry=0x7fffc03be160, disk=disk@entry=0x7fffb4002ae0)
at qemu/qemu_domain.c:1087
disk=0x7fffb4002ae0, vm=0x7fffc03a2580, driver=0x7fffc02ca390,
conn=0x7fffb00009a0) at qemu/qemu_hotplug.c:355
Upon entry to qemuDomainAttachVirtioDiskDevice, src->encryption points
at a valid 'secret' buffer w/ nsecrets == 1; however, the call to
qemuDomainDetermineDiskChain will call virStorageFileGetMetadata
and eventually virStorageFileGetMetadataInternal where the src->encryption
was overwritten when probing the volume.
Commit id 'a48c7141' added code to virStorageFileGetMetadataInternal
to determine if the disk/volume would use/need encryption and allocated
a meta->encryption. This overwrote an existing encryption buffer
already provided by the XML
This patch adds a check for meta->encryption already present before
just allocating and overwriting an existing buffer. It then checks the
existing encryption data to ensure the XML provided format for the
disk matches the expected format read from the disk and errors if there
is a mismatch.
2016-08-17 14:25:43 +00:00
|
|
|
int expt_fmt = fileTypeInfo[meta->format].cryptInfo[i].format;
|
|
|
|
if (!meta->encryption) {
|
|
|
|
if (VIR_ALLOC(meta->encryption) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
meta->encryption->format = expt_fmt;
|
|
|
|
} else {
|
|
|
|
if (meta->encryption->format != expt_fmt) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("encryption format %d doesn't match "
|
|
|
|
"expected format %d"),
|
|
|
|
meta->encryption->format, expt_fmt);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2017-03-24 13:26:17 +00:00
|
|
|
meta->encryption->payload_offset =
|
|
|
|
virStorageFileGetEncryptionPayloadOffset(&fileTypeInfo[meta->format].cryptInfo[i], buf);
|
storage: remove "luks" storage volume type
The current LUKS support has a "luks" volume type which has
a "luks" encryption format.
This partially makes sense if you consider the QEMU shorthand
syntax only requires you to specify a format=luks, and it'll
automagically uses "raw" as the next level driver. QEMU will
however let you override the "raw" with any other driver it
supports (vmdk, qcow, rbd, iscsi, etc, etc)
IOW the intention though is that the "luks" encryption format
is applied to all disk formats (whether raw, qcow2, rbd, gluster
or whatever). As such it doesn't make much sense for libvirt
to say the volume type is "luks" - we should be saying that it
is a "raw" file, but with "luks" encryption applied.
IOW, when creating a storage volume we should use this XML
<volume>
<name>demo.raw</name>
<capacity>5368709120</capacity>
<target>
<format type='raw'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</target>
</volume>
and when configuring a guest disk we should use
<disk type='file' device='disk'>
<driver name='qemu' type='raw'/>
<source file='/home/berrange/VirtualMachines/demo.raw'/>
<target dev='sda' bus='scsi'/>
<encryption format='luks'>
<secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccd2f80d6f'/>
</encryption>
</disk>
This commit thus removes the "luks" storage volume type added
in
commit 318ebb36f1027b3357a32d6f781bd77d7a9043fd
Author: John Ferlan <jferlan@redhat.com>
Date: Tue Jun 21 12:59:54 2016 -0400
util: Add 'luks' to the FileTypeInfo
The storage file probing code is modified so that it can probe
the actual encryption formats explicitly, rather than merely
probing existance of encryption and letting the storage driver
guess the format.
The rest of the code is then adapted to deal with
VIR_STORAGE_FILE_RAW w/ VIR_STORAGE_ENCRYPTION_FORMAT_LUKS
instead of just VIR_STORAGE_FILE_LUKS.
The commit mentioned above was included in libvirt v2.0.0.
So when querying volume XML this will be a change in behaviour
vs the 2.0.0 release - it'll report 'raw' instead of 'luks'
for the volume format, but still report 'luks' for encryption
format. I think this change is OK because the storage driver
did not include any support for creating volumes, nor starting
guets with luks volumes in v2.0.0 - that only since then.
Clearly if we change this we must do it before v2.1.0 though.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2016-07-26 16:41:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/* XXX we should consider moving virStorageBackendUpdateVolInfo
|
|
|
|
* code into this method, for non-magic files
|
|
|
|
*/
|
2014-04-15 12:25:10 +00:00
|
|
|
if (!fileTypeInfo[meta->format].magic)
|
2013-02-09 13:41:01 +00:00
|
|
|
goto done;
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2010-06-15 13:58:10 +00:00
|
|
|
/* Optionally extract capacity from file */
|
2014-04-15 12:25:10 +00:00
|
|
|
if (fileTypeInfo[meta->format].sizeOffset != -1) {
|
|
|
|
if ((fileTypeInfo[meta->format].sizeOffset + 8) > len)
|
2013-02-09 13:41:01 +00:00
|
|
|
goto done;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2014-04-15 12:25:10 +00:00
|
|
|
if (fileTypeInfo[meta->format].endian == LV_LITTLE_ENDIAN)
|
2013-02-07 01:57:13 +00:00
|
|
|
meta->capacity = virReadBufInt64LE(buf +
|
2014-04-15 12:25:10 +00:00
|
|
|
fileTypeInfo[meta->format].sizeOffset);
|
2013-02-07 01:57:13 +00:00
|
|
|
else
|
|
|
|
meta->capacity = virReadBufInt64BE(buf +
|
2014-04-15 12:25:10 +00:00
|
|
|
fileTypeInfo[meta->format].sizeOffset);
|
2010-06-15 13:58:10 +00:00
|
|
|
/* Avoid unlikely, but theoretically possible overflow */
|
2013-02-07 01:57:13 +00:00
|
|
|
if (meta->capacity > (ULLONG_MAX /
|
2014-04-15 12:25:10 +00:00
|
|
|
fileTypeInfo[meta->format].sizeMultiplier))
|
2013-02-09 13:41:01 +00:00
|
|
|
goto done;
|
2014-04-15 12:25:10 +00:00
|
|
|
meta->capacity *= fileTypeInfo[meta->format].sizeMultiplier;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
2009-09-29 08:34:48 +00:00
|
|
|
|
2014-08-06 20:48:59 +00:00
|
|
|
VIR_FREE(meta->backingStoreRaw);
|
2014-04-15 12:25:10 +00:00
|
|
|
if (fileTypeInfo[meta->format].getBackingStore != NULL) {
|
|
|
|
int store = fileTypeInfo[meta->format].getBackingStore(&meta->backingStoreRaw,
|
2014-04-10 01:49:07 +00:00
|
|
|
backingFormat,
|
2013-02-09 13:41:01 +00:00
|
|
|
buf, len);
|
|
|
|
if (store == BACKING_STORE_INVALID)
|
|
|
|
goto done;
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2013-02-09 13:41:01 +00:00
|
|
|
if (store == BACKING_STORE_ERROR)
|
|
|
|
goto cleanup;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
2014-04-15 12:25:10 +00:00
|
|
|
if (fileTypeInfo[meta->format].getFeatures != NULL &&
|
|
|
|
fileTypeInfo[meta->format].getFeatures(&meta->features, meta->format, buf, len) < 0)
|
2013-05-07 15:27:43 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-04-15 12:25:10 +00:00
|
|
|
if (meta->format == VIR_STORAGE_FILE_QCOW2 && meta->features &&
|
2013-05-07 15:27:43 +00:00
|
|
|
VIR_STRDUP(meta->compat, "1.1") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
done:
|
2014-04-08 21:20:36 +00:00
|
|
|
ret = 0;
|
2013-02-06 23:33:45 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-02-09 13:41:01 +00:00
|
|
|
return ret;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2013-11-05 21:12:02 +00:00
|
|
|
* virStorageFileProbeFormat:
|
2010-06-15 13:58:10 +00:00
|
|
|
*
|
2013-11-05 21:12:02 +00:00
|
|
|
* Probe for the format of 'path', returning the detected
|
|
|
|
* disk format.
|
2010-06-15 13:58:10 +00:00
|
|
|
*
|
|
|
|
* Callers are advised never to trust the returned 'format'
|
|
|
|
* unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
2013-11-05 21:12:02 +00:00
|
|
|
* malicious guest can turn a raw file into any other non-raw
|
2010-06-15 13:58:10 +00:00
|
|
|
* format at will.
|
|
|
|
*
|
|
|
|
* Best option: Don't use this function
|
|
|
|
*/
|
|
|
|
int
|
2013-11-05 21:12:02 +00:00
|
|
|
virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid)
|
2010-06-15 13:58:10 +00:00
|
|
|
{
|
2013-11-05 21:12:02 +00:00
|
|
|
int fd;
|
2010-06-15 13:58:10 +00:00
|
|
|
int ret = -1;
|
2011-05-26 18:05:32 +00:00
|
|
|
struct stat sb;
|
2013-11-05 21:12:02 +00:00
|
|
|
ssize_t len = VIR_STORAGE_MAX_HEADER;
|
|
|
|
char *header = NULL;
|
2011-05-26 18:05:32 +00:00
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if ((fd = virFileOpenAs(path, O_RDONLY, 0, uid, gid, 0)) < 0) {
|
|
|
|
virReportSystemError(-fd, _("Failed to open file '%s'"), path);
|
2011-05-26 18:05:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if (fstat(fd, &sb) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot stat file '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-05-26 18:05:32 +00:00
|
|
|
/* No header to probe for directories */
|
|
|
|
if (S_ISDIR(sb.st_mode)) {
|
2013-11-05 21:12:02 +00:00
|
|
|
ret = VIR_STORAGE_FILE_DIR;
|
|
|
|
goto cleanup;
|
2011-05-26 18:05:32 +00:00
|
|
|
}
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
|
virReportSystemError(errno, _("cannot set to start of '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
if ((len = virFileReadHeaderFD(fd, len, &header)) < 0) {
|
2010-06-15 13:58:10 +00:00
|
|
|
virReportSystemError(errno, _("cannot read header '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-11-05 21:12:02 +00:00
|
|
|
ret = virStorageFileProbeFormatFromBuf(path, header, len);
|
2010-06-15 13:58:10 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2013-11-05 21:12:02 +00:00
|
|
|
VIR_FREE(header);
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2010-06-15 13:58:10 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
|
2014-04-17 14:05:16 +00:00
|
|
|
static virStorageSourcePtr
|
2014-04-15 12:25:10 +00:00
|
|
|
virStorageFileMetadataNew(const char *path,
|
|
|
|
int format)
|
|
|
|
{
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageSourcePtr ret = NULL;
|
2014-04-15 12:25:10 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret->format = format;
|
|
|
|
ret->type = VIR_STORAGE_TYPE_FILE;
|
|
|
|
|
2014-05-28 13:17:11 +00:00
|
|
|
if (VIR_STRDUP(ret->path, path) < 0)
|
|
|
|
goto error;
|
2014-04-15 12:25:10 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageSourceFree(ret);
|
2014-04-15 12:25:10 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadataFromBuf:
|
|
|
|
* @path: name of file, for error messages
|
|
|
|
* @buf: header bytes from @path
|
|
|
|
* @len: length of @buf
|
2014-07-07 09:38:28 +00:00
|
|
|
* @format: format of the storage file
|
2014-04-10 01:49:07 +00:00
|
|
|
* @backingFormat: format of @backing
|
2013-11-05 20:50:29 +00:00
|
|
|
*
|
2014-07-07 09:38:28 +00:00
|
|
|
* Extract metadata about the storage volume with the specified image format.
|
|
|
|
* If image format is VIR_STORAGE_FILE_AUTO, it will probe to automatically
|
|
|
|
* identify the format. Does not recurse.
|
2013-11-05 20:50:29 +00:00
|
|
|
*
|
2014-07-07 09:38:28 +00:00
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a format on a file
|
|
|
|
* that might be raw if that file will then be passed to a guest, since a
|
|
|
|
* malicious guest can turn a raw file into any other non-raw format at will.
|
|
|
|
*
|
|
|
|
* If the returned @backingFormat is VIR_STORAGE_FILE_AUTO it indicates the
|
|
|
|
* image didn't specify an explicit format for its backing store. Callers are
|
|
|
|
* advised against probing for the backing store format in this case.
|
2013-11-05 20:50:29 +00:00
|
|
|
*
|
2014-04-17 14:05:16 +00:00
|
|
|
* Caller MUST free the result after use via virStorageSourceFree.
|
2013-11-05 20:50:29 +00:00
|
|
|
*/
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageSourcePtr
|
2013-11-05 20:50:29 +00:00
|
|
|
virStorageFileGetMetadataFromBuf(const char *path,
|
|
|
|
char *buf,
|
|
|
|
size_t len,
|
2014-07-07 09:38:28 +00:00
|
|
|
int format,
|
2014-04-10 01:49:07 +00:00
|
|
|
int *backingFormat)
|
2013-11-05 20:50:29 +00:00
|
|
|
{
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageSourcePtr ret = NULL;
|
2014-07-09 08:00:58 +00:00
|
|
|
int dummy;
|
|
|
|
|
|
|
|
if (!backingFormat)
|
|
|
|
backingFormat = &dummy;
|
2014-04-08 20:26:02 +00:00
|
|
|
|
2014-07-07 09:38:28 +00:00
|
|
|
if (!(ret = virStorageFileMetadataNew(path, format)))
|
2014-04-08 20:26:02 +00:00
|
|
|
return NULL;
|
2014-04-08 21:20:36 +00:00
|
|
|
|
2014-07-07 09:38:28 +00:00
|
|
|
if (virStorageFileGetMetadataInternal(ret, buf, len,
|
|
|
|
backingFormat) < 0) {
|
|
|
|
virStorageSourceFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-04-15 12:28:10 +00:00
|
|
|
|
2014-04-08 20:26:02 +00:00
|
|
|
return ret;
|
2013-11-05 20:50:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-07 09:24:14 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadataFromFD:
|
|
|
|
*
|
|
|
|
* Extract metadata about the storage volume with the specified
|
|
|
|
* image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
|
|
|
* will probe to automatically identify the format. Does not recurse.
|
|
|
|
*
|
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
|
* format, since a malicious guest can turn a raw file into any
|
|
|
|
* other non-raw format at will.
|
|
|
|
*
|
|
|
|
* Caller MUST free the result after use via virStorageSourceFree.
|
|
|
|
*/
|
|
|
|
virStorageSourcePtr
|
|
|
|
virStorageFileGetMetadataFromFD(const char *path,
|
|
|
|
int fd,
|
|
|
|
int format,
|
|
|
|
int *backingFormat)
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
{
|
2014-07-07 09:24:14 +00:00
|
|
|
virStorageSourcePtr ret = NULL;
|
|
|
|
virStorageSourcePtr meta = NULL;
|
2013-11-05 20:50:29 +00:00
|
|
|
char *buf = NULL;
|
2013-11-05 21:12:02 +00:00
|
|
|
ssize_t len = VIR_STORAGE_MAX_HEADER;
|
2013-11-05 20:50:29 +00:00
|
|
|
struct stat sb;
|
2014-04-10 02:37:16 +00:00
|
|
|
int dummy;
|
2013-11-05 20:50:29 +00:00
|
|
|
|
2014-04-10 02:37:16 +00:00
|
|
|
if (!backingFormat)
|
|
|
|
backingFormat = &dummy;
|
2014-04-15 12:25:10 +00:00
|
|
|
|
2014-04-10 02:37:16 +00:00
|
|
|
*backingFormat = VIR_STORAGE_FILE_NONE;
|
2014-04-15 12:25:10 +00:00
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
if (fstat(fd, &sb) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2014-07-07 09:24:14 +00:00
|
|
|
_("cannot stat file '%s'"), path);
|
|
|
|
return NULL;
|
2013-11-05 20:50:29 +00:00
|
|
|
}
|
|
|
|
|
2014-07-07 09:24:14 +00:00
|
|
|
if (!(meta = virStorageFileMetadataNew(path, format)))
|
|
|
|
return NULL;
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
if (S_ISDIR(sb.st_mode)) {
|
2014-04-18 08:07:41 +00:00
|
|
|
/* No header to probe for directories, but also no backing file. Just
|
|
|
|
* update the metadata.*/
|
conf: track more fields in backing chain metadata
The current use of virStorageFileMetadata is awkward; to learn
some of the information about a child node, you have to read
fields in the parent node. This does not lend itself well to
modifying backing chains (whether inserting a new node in the
chain, or consolidating existing nodes); better would be to
learn about a child node directly in that node. This patch
sets up some new fields which contain redundant information,
although not necessarily in the final desired state for the
new fields (see the next patch for actual tests of what is there
now). Then later patches will do any refactoring necessary to
get the fields to their desired states, and update clients to
get the information from the new fields, so we can finally
delete the fields that are tracking information about the wrong
node.
More concretely, compare these three example backing chains:
good <- one
missing <- two
gluster://server/vol/img <- three
Pre-patch, querying the chains gives:
{ .backingStore = "/path/to/good",
.backingStoreRaw = "good",
.backingStoreIsFile = true,
.backingStoreFormat = VIR_STORAGE_FILE_RAW,
.backingMeta = {
.backingStore = NULL,
.backingStoreRaw = NULL,
.backingStoreIsFile = false,
.backingMeta = NULL,
}
}
{ .backingStore = NULL,
.backingStoreRaw = "missing",
.backingStoreIsFile = false,
.backingStoreFormat = VIR_STORAGE_FILE_NONE,
.backingMeta = NULL,
}
{ .backingStore = "gluster://server/vol/img",
.backingStoreRaw = NULL,
.backingStoreIsFile = false,
.backingStoreFormat = VIR_STORAGE_FILE_RAW,
.backingMeta = NULL,
}
Deciding whether to ignore a missing backing file (as in virsh
vol-dumpxml) or report an error (as in security manager sVirt
labeling) requires reading multiple fields. Plus, the format
is hard-coded to treat all network protocols as end-of-the-chain,
as if they were raw. By the end of this patch series, the goal
is to instead represent these three situations as:
{ .path = "one",
.canonPath = "/path/to/one",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "good",
.backingMeta = {
.path = "good",
.canonPath = "/path/to/good",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_RAW,
.backingStoreRaw = NULL,
.backingMeta = NULL,
}
}
{ .path = "two",
.canonPath = "/path/to/two",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "missing",
.backingMeta = NULL,
}
{ .path = "three",
.canonPath = "/path/to/three",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "gluster://server/vol/img",
.backingMeta = {
.path = "gluster://server/vol/img",
.canonPath = "gluster://server/vol/img",
.type = VIR_STORAGE_TYPE_NETWORK,
.format = VIR_STORAGE_FILE_RAW,
.backingStoreRaw = NULL,
.backingMeta = NULL,
}
}
or, for the second file, maybe also allowing:
{ .path = "two",
.canonPath = "/path/to/two",
.type = VIR_STORAGE_TYPE_FILE,
.format = VIR_STORAGE_FILE_QCOW2,
.backingStoreRaw = "missing",
.backingMeta = {
.path = "missing",
.canonPath = NULL,
.type = VIR_STORAGE_TYPE_NONE,
.format = VIR_STORAGE_FILE_NONE,
.backingStoreRaw = NULL,
.backingMeta = NULL,
}
}
* src/util/virstoragefile.h (_virStorageFileMetadata): Add
path, canonPath, relDir, type, and format fields. Reorder
existing fields, and add lots of comments.
* src/util/virstoragefile.c (virStorageFileFreeMetadata): Clean
new fields.
(virStorageFileGetMetadataInternal)
(virStorageFileGetMetadataFromFDInternal): Start populating new
fields.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-04-08 22:09:05 +00:00
|
|
|
meta->type = VIR_STORAGE_TYPE_DIR;
|
|
|
|
meta->format = VIR_STORAGE_FILE_DIR;
|
2014-07-07 09:24:14 +00:00
|
|
|
ret = meta;
|
|
|
|
meta = NULL;
|
2013-11-05 20:50:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
2015-02-19 12:32:41 +00:00
|
|
|
virReportSystemError(errno, _("cannot seek to start of '%s'"), meta->path);
|
2013-11-05 20:50:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) {
|
2015-02-19 12:32:41 +00:00
|
|
|
virReportSystemError(errno, _("cannot read header '%s'"), meta->path);
|
2013-11-05 20:50:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-07-07 09:24:14 +00:00
|
|
|
if (virStorageFileGetMetadataInternal(meta, buf, len, backingFormat) < 0)
|
|
|
|
goto cleanup;
|
2014-05-28 13:17:11 +00:00
|
|
|
|
2014-07-07 09:24:14 +00:00
|
|
|
if (S_ISREG(sb.st_mode))
|
|
|
|
meta->type = VIR_STORAGE_TYPE_FILE;
|
|
|
|
else if (S_ISBLK(sb.st_mode))
|
|
|
|
meta->type = VIR_STORAGE_TYPE_BLOCK;
|
2014-04-15 12:25:10 +00:00
|
|
|
|
2014-07-07 09:24:14 +00:00
|
|
|
ret = meta;
|
|
|
|
meta = NULL;
|
2014-04-08 21:20:36 +00:00
|
|
|
|
2014-07-07 09:24:14 +00:00
|
|
|
cleanup:
|
|
|
|
virStorageSourceFree(meta);
|
|
|
|
VIR_FREE(buf);
|
2014-04-08 20:26:02 +00:00
|
|
|
return ret;
|
2010-06-15 13:58:10 +00:00
|
|
|
}
|
|
|
|
|
2013-11-05 20:50:29 +00:00
|
|
|
|
2013-07-29 12:51:15 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileChainCheckBroken
|
|
|
|
*
|
|
|
|
* If CHAIN is broken, set *brokenFile to the broken file name,
|
|
|
|
* otherwise set it to NULL. Caller MUST free *brokenFile after use.
|
2014-04-09 21:36:30 +00:00
|
|
|
* Return 0 on success (including when brokenFile is set), negative on
|
|
|
|
* error (allocation failure).
|
2013-07-29 12:51:15 +00:00
|
|
|
*/
|
|
|
|
int
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageFileChainGetBroken(virStorageSourcePtr chain,
|
2013-07-29 12:51:15 +00:00
|
|
|
char **brokenFile)
|
|
|
|
{
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageSourcePtr tmp;
|
2013-07-29 12:51:15 +00:00
|
|
|
|
2014-04-09 21:36:30 +00:00
|
|
|
*brokenFile = NULL;
|
|
|
|
|
2013-07-29 12:51:15 +00:00
|
|
|
if (!chain)
|
|
|
|
return 0;
|
|
|
|
|
2017-10-12 17:27:40 +00:00
|
|
|
for (tmp = chain; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
|
2014-04-09 21:36:30 +00:00
|
|
|
/* Break when we hit end of chain; report error if we detected
|
|
|
|
* a missing backing file, infinite loop, or other error */
|
2014-04-17 20:46:18 +00:00
|
|
|
if (!tmp->backingStore && tmp->backingStoreRaw) {
|
2014-04-14 13:49:28 +00:00
|
|
|
if (VIR_STRDUP(*brokenFile, tmp->backingStoreRaw) < 0)
|
|
|
|
return -1;
|
2013-07-29 12:51:15 +00:00
|
|
|
|
2014-04-14 13:49:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2013-07-29 12:51:15 +00:00
|
|
|
|
2014-04-14 13:49:28 +00:00
|
|
|
return 0;
|
2013-07-29 12:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-30 07:40:00 +00:00
|
|
|
/**
|
|
|
|
* virStorageFileResize:
|
|
|
|
*
|
|
|
|
* Change the capacity of the raw storage file at 'path'.
|
|
|
|
*/
|
|
|
|
int
|
2013-05-31 05:16:14 +00:00
|
|
|
virStorageFileResize(const char *path,
|
|
|
|
unsigned long long capacity,
|
|
|
|
bool pre_allocate)
|
2012-01-30 07:40:00 +00:00
|
|
|
{
|
2012-02-08 14:03:29 +00:00
|
|
|
int fd = -1;
|
|
|
|
int ret = -1;
|
2017-09-25 14:29:34 +00:00
|
|
|
int rc;
|
2012-02-08 14:03:29 +00:00
|
|
|
|
|
|
|
if ((fd = open(path, O_RDWR)) < 0) {
|
|
|
|
virReportSystemError(errno, _("Unable to open '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-05-31 05:16:14 +00:00
|
|
|
if (pre_allocate) {
|
2017-09-25 14:35:42 +00:00
|
|
|
if ((rc = virFileAllocate(fd, 0, capacity)) != 0) {
|
2017-09-25 14:29:34 +00:00
|
|
|
if (rc == -2) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
|
|
|
_("preallocate is not supported on this platform"));
|
|
|
|
} else {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to pre-allocate space for "
|
|
|
|
"file '%s'"), path);
|
|
|
|
}
|
2013-05-31 05:16:14 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-08-16 10:29:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ftruncate(fd, capacity) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Failed to truncate file '%s'"), path);
|
|
|
|
goto cleanup;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
2012-02-08 14:03:29 +00:00
|
|
|
if (VIR_CLOSE(fd) < 0) {
|
|
|
|
virReportSystemError(errno, _("Unable to save '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-02-08 14:03:29 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
|
|
|
return ret;
|
2012-01-30 07:40:00 +00:00
|
|
|
}
|
|
|
|
|
2012-02-21 21:58:50 +00:00
|
|
|
|
|
|
|
int virStorageFileIsClusterFS(const char *path)
|
|
|
|
{
|
|
|
|
/* These are coherent cluster filesystems known to be safe for
|
|
|
|
* migration with cache != none
|
|
|
|
*/
|
2014-03-29 20:15:33 +00:00
|
|
|
return virFileIsSharedFSType(path,
|
|
|
|
VIR_FILE_SHFS_GFS2 |
|
|
|
|
VIR_FILE_SHFS_OCFS);
|
2012-02-21 21:58:50 +00:00
|
|
|
}
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
#ifdef LVS
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetLVMKey(const char *path,
|
|
|
|
char **key)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* # lvs --noheadings --unbuffered --nosuffix --options "uuid" LVNAME
|
|
|
|
* 06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky
|
|
|
|
*/
|
2012-12-11 19:10:51 +00:00
|
|
|
int status;
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandPtr cmd = virCommandNewArgList(
|
|
|
|
LVS,
|
|
|
|
"--noheadings", "--unbuffered", "--nosuffix",
|
|
|
|
"--options", "uuid", path,
|
|
|
|
NULL
|
|
|
|
);
|
2012-12-11 19:10:51 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*key = NULL;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Run the program and capture its output */
|
2012-12-11 19:10:51 +00:00
|
|
|
virCommandSetOutputBuffer(cmd, key);
|
|
|
|
if (virCommandRun(cmd, &status) < 0)
|
2011-07-20 09:40:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
/* Explicitly check status == 0, rather than passing NULL
|
|
|
|
* to virCommandRun because we don't want to raise an actual
|
|
|
|
* error in this scenario, just return a NULL key.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (status == 0 && *key) {
|
2011-07-20 09:40:53 +00:00
|
|
|
char *nl;
|
2012-12-11 19:10:51 +00:00
|
|
|
char *tmp = *key;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Find first non-space character */
|
2014-11-13 14:28:18 +00:00
|
|
|
while (*tmp && c_isspace(*tmp))
|
2011-07-20 09:40:53 +00:00
|
|
|
tmp++;
|
|
|
|
/* Kill leading spaces */
|
2012-12-11 19:10:51 +00:00
|
|
|
if (tmp != *key)
|
|
|
|
memmove(*key, tmp, strlen(tmp)+1);
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Kill trailing newline */
|
2012-12-11 19:10:51 +00:00
|
|
|
if ((nl = strchr(*key, '\n')))
|
2011-07-20 09:40:53 +00:00
|
|
|
*nl = '\0';
|
|
|
|
}
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
ret = 0;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-12-11 19:10:51 +00:00
|
|
|
if (*key && STREQ(*key, ""))
|
|
|
|
VIR_FREE(*key);
|
|
|
|
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandFree(cmd);
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
return ret;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#else
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetLVMKey(const char *path,
|
|
|
|
char **key ATTRIBUTE_UNUSED)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, _("Unable to get LVM key for %s"), path);
|
2012-12-11 19:10:51 +00:00
|
|
|
return -1;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-09-20 14:24:47 +00:00
|
|
|
#ifdef WITH_UDEV
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetSCSIKey(const char *path,
|
|
|
|
char **key)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
2012-12-11 19:10:51 +00:00
|
|
|
int status;
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandPtr cmd = virCommandNewArgList(
|
|
|
|
"/lib/udev/scsi_id",
|
|
|
|
"--replace-whitespace",
|
|
|
|
"--whitelisted",
|
|
|
|
"--device", path,
|
|
|
|
NULL
|
|
|
|
);
|
2012-12-11 19:10:51 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*key = NULL;
|
2011-07-20 09:40:53 +00:00
|
|
|
|
|
|
|
/* Run the program and capture its output */
|
2012-12-11 19:10:51 +00:00
|
|
|
virCommandSetOutputBuffer(cmd, key);
|
|
|
|
if (virCommandRun(cmd, &status) < 0)
|
2011-07-20 09:40:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
/* Explicitly check status == 0, rather than passing NULL
|
|
|
|
* to virCommandRun because we don't want to raise an actual
|
|
|
|
* error in this scenario, just return a NULL key.
|
|
|
|
*/
|
|
|
|
if (status == 0 && *key) {
|
|
|
|
char *nl = strchr(*key, '\n');
|
2011-07-20 09:40:53 +00:00
|
|
|
if (nl)
|
|
|
|
*nl = '\0';
|
|
|
|
}
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
cleanup:
|
2012-12-11 19:10:51 +00:00
|
|
|
if (*key && STREQ(*key, ""))
|
|
|
|
VIR_FREE(*key);
|
|
|
|
|
2011-07-20 09:40:53 +00:00
|
|
|
virCommandFree(cmd);
|
|
|
|
|
2012-12-11 19:10:51 +00:00
|
|
|
return ret;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#else
|
2012-12-11 19:10:51 +00:00
|
|
|
int virStorageFileGetSCSIKey(const char *path,
|
|
|
|
char **key ATTRIBUTE_UNUSED)
|
2011-07-20 09:40:53 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, _("Unable to get SCSI key for %s"), path);
|
2012-12-11 19:10:51 +00:00
|
|
|
return -1;
|
2011-07-20 09:40:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
2012-10-12 22:29:14 +00:00
|
|
|
|
2017-02-23 16:10:43 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileParseBackingStoreStr:
|
|
|
|
* @str: backing store specifier string to parse
|
|
|
|
* @target: returns target device portion of the string
|
|
|
|
* @chainIndex: returns the backing store portion of the string
|
|
|
|
*
|
|
|
|
* Parses the backing store specifier string such as vda[1], or sda into
|
|
|
|
* components and returns them via arguments. If the string did not specify an
|
|
|
|
* index, 0 is assumed.
|
|
|
|
*
|
|
|
|
* Returns 0 on success -1 on error
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileParseBackingStoreStr(const char *str,
|
|
|
|
char **target,
|
|
|
|
unsigned int *chainIndex)
|
|
|
|
{
|
|
|
|
char **strings = NULL;
|
|
|
|
size_t nstrings;
|
|
|
|
unsigned int idx = 0;
|
|
|
|
char *suffix;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
*chainIndex = 0;
|
|
|
|
|
|
|
|
if (!(strings = virStringSplitCount(str, "[", 2, &nstrings)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (nstrings == 2) {
|
|
|
|
if (virStrToLong_uip(strings[1], &suffix, 10, &idx) < 0 ||
|
|
|
|
STRNEQ(suffix, "]"))
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target &&
|
|
|
|
VIR_STRDUP(*target, strings[0]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
*chainIndex = idx;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virStringListFreeCount(strings, nstrings);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-18 12:35:33 +00:00
|
|
|
int
|
|
|
|
virStorageFileParseChainIndex(const char *diskTarget,
|
|
|
|
const char *name,
|
|
|
|
unsigned int *chainIndex)
|
|
|
|
{
|
|
|
|
unsigned int idx = 0;
|
2017-02-23 16:10:43 +00:00
|
|
|
char *target = NULL;
|
2014-04-18 12:35:33 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
*chainIndex = 0;
|
|
|
|
|
2017-02-23 16:10:43 +00:00
|
|
|
if (!name || !diskTarget)
|
|
|
|
return 0;
|
2014-04-18 12:35:33 +00:00
|
|
|
|
2017-02-23 16:10:43 +00:00
|
|
|
if (virStorageFileParseBackingStoreStr(name, &target, &idx) < 0)
|
|
|
|
return 0;
|
2014-04-18 12:35:33 +00:00
|
|
|
|
2017-02-23 16:10:43 +00:00
|
|
|
if (idx == 0)
|
2014-04-18 12:35:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2017-02-23 16:10:43 +00:00
|
|
|
if (STRNEQ(diskTarget, target)) {
|
2014-04-18 12:35:33 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("requested target '%s' does not match target '%s'"),
|
2017-02-23 16:10:43 +00:00
|
|
|
target, diskTarget);
|
2014-04-18 12:35:33 +00:00
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*chainIndex = idx;
|
|
|
|
|
|
|
|
cleanup:
|
2017-02-23 16:10:43 +00:00
|
|
|
VIR_FREE(target);
|
2014-04-18 12:35:33 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-10-12 17:27:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageSourceIsBacking:
|
|
|
|
* @src: storage source
|
|
|
|
*
|
|
|
|
* Returns true if @src is a eligible backing store structure. Useful
|
|
|
|
* for iterators.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virStorageSourceIsBacking(const virStorageSource *src)
|
|
|
|
{
|
2017-10-12 17:13:44 +00:00
|
|
|
return src && src->type != VIR_STORAGE_TYPE_NONE;
|
2017-10-12 17:27:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageSourceHasBacking:
|
|
|
|
* @src: storage source
|
|
|
|
*
|
|
|
|
* Returns true if @src has backing store/chain.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virStorageSourceHasBacking(const virStorageSource *src)
|
|
|
|
{
|
2017-10-12 17:13:44 +00:00
|
|
|
return virStorageSourceIsBacking(src) && src->backingStore &&
|
|
|
|
src->backingStore->type != VIR_STORAGE_TYPE_NONE;
|
2017-10-12 17:27:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
blockcommit: require base below top
The block commit code looks for an explicit base file relative
to the discovered top file; so for a chain of:
base <- snap1 <- snap2 <- snap3
and a command of:
virsh blockcommit $dom vda --base snap2 --top snap1
we got a sane message (here from libvirt 1.0.5):
error: invalid argument: could not find base 'snap2' below 'snap1' in chain for 'vda'
Meanwhile, recent refactoring has slightly reduced the quality of the
libvirt error messages, by losing the phrase 'below xyz':
error: invalid argument: could not find image 'snap2' in chain for 'snap3'
But we had a one-off, where we were not excluding the top file
itself in searching for the base; thankfully qemu still reports
the error, but the quality is worse:
virsh blockcommit $dom vda --base snap2 --top snap2
error: internal error unable to execute QEMU command 'block-commit': Base '/snap2' not found
Fix the one-off in blockcommit by changing the semantics of name
lookup - if a starting point is specified, then the result must
be below that point, rather than including that point. The only
other call to chain lookup was blockpull code, which was already
forcing the lookup to omit the active layer and only needs a
tweak to use the new semantics.
This also fixes the bug exposed in the testsuite, where when doing
a lookup pinned to an intermediate point in the chain, we were
unable to return the name of the parent also in the chain.
* src/util/virstoragefile.c (virStorageFileChainLookup): Change
semantics for non-NULL startFrom.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Adjust caller,
to keep existing semantics.
* tests/virstoragetest.c (mymain): Adjust to expose new semantics.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-11 22:22:57 +00:00
|
|
|
/* Given a @chain, look for the backing store @name that is a backing file
|
|
|
|
* of @startFrom (or any member of @chain if @startFrom is NULL) and return
|
|
|
|
* that location within the chain. @chain must always point to the top of
|
|
|
|
* the chain. Pass NULL for @name and 0 for @idx to find the base of the
|
|
|
|
* chain. Pass nonzero @idx to find the backing source according to its
|
|
|
|
* position in the backing chain. If @parent is not NULL, set *@parent to
|
|
|
|
* the preferred name of the parent (or to NULL if @name matches the start
|
|
|
|
* of the chain). Since the results point within @chain, they must not be
|
|
|
|
* independently freed. Reports an error and returns NULL if @name is not
|
|
|
|
* found.
|
2014-04-18 12:35:33 +00:00
|
|
|
*/
|
2014-04-18 13:25:19 +00:00
|
|
|
virStorageSourcePtr
|
2014-04-17 14:05:16 +00:00
|
|
|
virStorageFileChainLookup(virStorageSourcePtr chain,
|
2014-04-18 12:35:33 +00:00
|
|
|
virStorageSourcePtr startFrom,
|
2014-04-18 13:25:19 +00:00
|
|
|
const char *name,
|
2014-04-18 12:35:33 +00:00
|
|
|
unsigned int idx,
|
2014-06-25 13:43:04 +00:00
|
|
|
virStorageSourcePtr *parent)
|
2012-10-12 22:29:14 +00:00
|
|
|
{
|
2014-06-25 13:43:04 +00:00
|
|
|
virStorageSourcePtr prev;
|
2014-04-17 11:47:41 +00:00
|
|
|
const char *start = chain->path;
|
2014-05-27 13:32:21 +00:00
|
|
|
char *parentDir = NULL;
|
2014-04-11 03:44:45 +00:00
|
|
|
bool nameIsFile = virStorageIsFile(name);
|
2012-10-12 22:29:14 +00:00
|
|
|
|
|
|
|
if (!parent)
|
2014-06-25 13:43:04 +00:00
|
|
|
parent = &prev;
|
2012-10-12 22:29:14 +00:00
|
|
|
*parent = NULL;
|
2014-04-18 12:35:33 +00:00
|
|
|
|
|
|
|
if (startFrom) {
|
2017-10-12 17:27:40 +00:00
|
|
|
while (virStorageSourceIsBacking(chain) &&
|
|
|
|
chain != startFrom->backingStore)
|
2014-04-18 12:35:33 +00:00
|
|
|
chain = chain->backingStore;
|
2015-04-21 15:38:08 +00:00
|
|
|
|
2014-06-25 13:43:04 +00:00
|
|
|
*parent = startFrom;
|
2014-04-18 12:35:33 +00:00
|
|
|
}
|
|
|
|
|
2017-10-12 17:27:40 +00:00
|
|
|
while (virStorageSourceIsBacking(chain)) {
|
2014-04-18 12:35:33 +00:00
|
|
|
if (!name && !idx) {
|
2017-10-12 17:27:40 +00:00
|
|
|
if (!virStorageSourceHasBacking(chain))
|
2012-10-12 22:29:14 +00:00
|
|
|
break;
|
2014-04-18 12:35:33 +00:00
|
|
|
} else if (idx) {
|
2017-10-06 12:23:05 +00:00
|
|
|
VIR_DEBUG("%u: %s", chain->id, chain->path);
|
|
|
|
if (idx == chain->id)
|
2014-04-18 12:35:33 +00:00
|
|
|
break;
|
2014-04-11 03:44:45 +00:00
|
|
|
} else {
|
2014-05-27 08:05:57 +00:00
|
|
|
if (STREQ_NULLABLE(name, chain->relPath) ||
|
2017-10-12 17:26:10 +00:00
|
|
|
STREQ_NULLABLE(name, chain->path))
|
2012-10-12 22:29:14 +00:00
|
|
|
break;
|
2014-06-25 11:45:54 +00:00
|
|
|
|
|
|
|
if (nameIsFile && virStorageSourceIsLocalStorage(chain)) {
|
2014-06-25 13:43:04 +00:00
|
|
|
if (*parent && virStorageSourceIsLocalStorage(*parent))
|
|
|
|
parentDir = mdir_name((*parent)->path);
|
2014-06-25 11:45:54 +00:00
|
|
|
else
|
|
|
|
ignore_value(VIR_STRDUP_QUIET(parentDir, "."));
|
|
|
|
|
|
|
|
if (!parentDir) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
2014-05-27 13:32:21 +00:00
|
|
|
}
|
|
|
|
|
2014-04-11 03:44:45 +00:00
|
|
|
int result = virFileRelLinkPointsTo(parentDir, name,
|
2014-04-17 11:47:41 +00:00
|
|
|
chain->path);
|
2014-05-27 13:32:21 +00:00
|
|
|
|
|
|
|
VIR_FREE(parentDir);
|
2014-06-25 11:45:54 +00:00
|
|
|
|
2014-04-11 03:44:45 +00:00
|
|
|
if (result < 0)
|
|
|
|
goto error;
|
2014-06-25 11:45:54 +00:00
|
|
|
|
2014-04-11 03:44:45 +00:00
|
|
|
if (result > 0)
|
|
|
|
break;
|
|
|
|
}
|
2012-10-12 22:29:14 +00:00
|
|
|
}
|
2014-06-25 13:43:04 +00:00
|
|
|
*parent = chain;
|
2014-04-17 20:46:18 +00:00
|
|
|
chain = chain->backingStore;
|
2012-10-12 22:29:14 +00:00
|
|
|
}
|
2014-04-18 13:25:19 +00:00
|
|
|
|
2017-10-12 17:27:40 +00:00
|
|
|
if (!virStorageSourceIsBacking(chain))
|
2012-10-12 22:29:14 +00:00
|
|
|
goto error;
|
2014-06-25 11:45:54 +00:00
|
|
|
|
2014-04-18 13:25:19 +00:00
|
|
|
return chain;
|
2012-10-12 22:29:14 +00:00
|
|
|
|
2014-03-25 06:53:22 +00:00
|
|
|
error:
|
2014-04-18 12:35:33 +00:00
|
|
|
if (idx) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
2015-04-21 15:48:17 +00:00
|
|
|
_("could not find backing store index %u in chain "
|
|
|
|
"for '%s'"),
|
2015-04-21 15:35:23 +00:00
|
|
|
idx, NULLSTR(start));
|
2014-04-18 12:35:33 +00:00
|
|
|
} else if (name) {
|
blockcommit: require base below top
The block commit code looks for an explicit base file relative
to the discovered top file; so for a chain of:
base <- snap1 <- snap2 <- snap3
and a command of:
virsh blockcommit $dom vda --base snap2 --top snap1
we got a sane message (here from libvirt 1.0.5):
error: invalid argument: could not find base 'snap2' below 'snap1' in chain for 'vda'
Meanwhile, recent refactoring has slightly reduced the quality of the
libvirt error messages, by losing the phrase 'below xyz':
error: invalid argument: could not find image 'snap2' in chain for 'snap3'
But we had a one-off, where we were not excluding the top file
itself in searching for the base; thankfully qemu still reports
the error, but the quality is worse:
virsh blockcommit $dom vda --base snap2 --top snap2
error: internal error unable to execute QEMU command 'block-commit': Base '/snap2' not found
Fix the one-off in blockcommit by changing the semantics of name
lookup - if a starting point is specified, then the result must
be below that point, rather than including that point. The only
other call to chain lookup was blockpull code, which was already
forcing the lookup to omit the active layer and only needs a
tweak to use the new semantics.
This also fixes the bug exposed in the testsuite, where when doing
a lookup pinned to an intermediate point in the chain, we were
unable to return the name of the parent also in the chain.
* src/util/virstoragefile.c (virStorageFileChainLookup): Change
semantics for non-NULL startFrom.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Adjust caller,
to keep existing semantics.
* tests/virstoragetest.c (mymain): Adjust to expose new semantics.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-11 22:22:57 +00:00
|
|
|
if (startFrom)
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("could not find image '%s' beneath '%s' in "
|
2015-04-21 15:35:23 +00:00
|
|
|
"chain for '%s'"), name, NULLSTR(startFrom->path),
|
|
|
|
NULLSTR(start));
|
blockcommit: require base below top
The block commit code looks for an explicit base file relative
to the discovered top file; so for a chain of:
base <- snap1 <- snap2 <- snap3
and a command of:
virsh blockcommit $dom vda --base snap2 --top snap1
we got a sane message (here from libvirt 1.0.5):
error: invalid argument: could not find base 'snap2' below 'snap1' in chain for 'vda'
Meanwhile, recent refactoring has slightly reduced the quality of the
libvirt error messages, by losing the phrase 'below xyz':
error: invalid argument: could not find image 'snap2' in chain for 'snap3'
But we had a one-off, where we were not excluding the top file
itself in searching for the base; thankfully qemu still reports
the error, but the quality is worse:
virsh blockcommit $dom vda --base snap2 --top snap2
error: internal error unable to execute QEMU command 'block-commit': Base '/snap2' not found
Fix the one-off in blockcommit by changing the semantics of name
lookup - if a starting point is specified, then the result must
be below that point, rather than including that point. The only
other call to chain lookup was blockpull code, which was already
forcing the lookup to omit the active layer and only needs a
tweak to use the new semantics.
This also fixes the bug exposed in the testsuite, where when doing
a lookup pinned to an intermediate point in the chain, we were
unable to return the name of the parent also in the chain.
* src/util/virstoragefile.c (virStorageFileChainLookup): Change
semantics for non-NULL startFrom.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Adjust caller,
to keep existing semantics.
* tests/virstoragetest.c (mymain): Adjust to expose new semantics.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-11 22:22:57 +00:00
|
|
|
else
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("could not find image '%s' in chain for '%s'"),
|
2015-04-21 15:35:23 +00:00
|
|
|
name, NULLSTR(start));
|
2014-04-18 13:25:19 +00:00
|
|
|
} else {
|
2014-04-11 01:03:01 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("could not find base image in chain for '%s'"),
|
2015-04-21 15:35:23 +00:00
|
|
|
NULLSTR(start));
|
2014-04-18 13:25:19 +00:00
|
|
|
}
|
2012-10-12 22:29:14 +00:00
|
|
|
*parent = NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageNetHostDefClear(virStorageNetHostDefPtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
VIR_FREE(def->socket);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageNetHostDefFree(size_t nhosts,
|
|
|
|
virStorageNetHostDefPtr hosts)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!hosts)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < nhosts; i++)
|
|
|
|
virStorageNetHostDefClear(&hosts[i]);
|
|
|
|
|
|
|
|
VIR_FREE(hosts);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-12 14:11:43 +00:00
|
|
|
static void
|
|
|
|
virStoragePermsFree(virStoragePermsPtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->label);
|
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
virStorageNetHostDefPtr
|
|
|
|
virStorageNetHostDefCopy(size_t nhosts,
|
|
|
|
virStorageNetHostDefPtr hosts)
|
|
|
|
{
|
|
|
|
virStorageNetHostDefPtr ret = NULL;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(ret, nhosts) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0; i < nhosts; i++) {
|
|
|
|
virStorageNetHostDefPtr src = &hosts[i];
|
|
|
|
virStorageNetHostDefPtr dst = &ret[i];
|
|
|
|
|
|
|
|
dst->transport = src->transport;
|
2017-07-20 10:45:42 +00:00
|
|
|
dst->port = src->port;
|
conf: split network host structs to util/
Continuing the refactoring of host-side storage descriptions out
of conf/domain_conf and into util/virstoragefile, this patch
focuses on details about a host name/port/transport as used by
a network storage volume.
* src/conf/domain_conf.h (virDomainDiskProtocolTransport)
(virDomainDiskHostDef, virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): Move...
* src/util/virstoragefile.h (virStorageNetHostTransport)
(virStorageNetHostDef, virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): ...here,
with better names.
* src/util/virstoragefile.c (virStorageNetHostDefClear)
(virStorageNetHostDefFree, virStorageNetHostDefCopy): Moved from...
* src/conf/domain_conf.c (virDomainDiskHostDefClear)
(virDomainDiskHostDefFree, virDomainDiskHostDefCopy): ...here.
(virDomainDiskSourceDefClear, virDomainDiskSourceDefParse)
(virDomainDiskSourceDefFormatInternal): Adjust callers.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefClear):
Likewise.
* src/qemu/qemu_command.c (qemuAddRBDHost)
(qemuParseDriveURIString, qemuParseNBDString)
(qemuBuildNetworkDriveURI, qemuParseCommandLineDisk)
(qemuParseCommandLine, qemuGetDriveSourceString): Likewise.
* src/qemu/qemu_command.h: Likewise.
* src/qemu/qemu_conf.c (qemuAddISCSIPoolSourceHost)
(qemuTranslateDiskSourcePool): Likewise.
* src/qemu/qemu_driver.c
(qemuDomainSnapshotCreateSingleDiskActive)
(qemuDomainSnapshotUndoSingleDiskActive): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGlusterInit): Likewise.
* src/storage/storage_driver.c (virStorageFileFree)
(virStorageFileInitInternal): Likewise.
* src/storage/storage_driver.h (_virStorageFile): Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-26 22:33:08 +00:00
|
|
|
|
|
|
|
if (VIR_STRDUP(dst->name, src->name) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(dst->socket, src->socket) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageNetHostDefFree(nhosts, ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-03-29 18:00:38 +00:00
|
|
|
|
|
|
|
|
2014-06-23 14:40:49 +00:00
|
|
|
void
|
|
|
|
virStorageAuthDefFree(virStorageAuthDefPtr authdef)
|
|
|
|
{
|
|
|
|
if (!authdef)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(authdef->username);
|
|
|
|
VIR_FREE(authdef->secrettype);
|
2016-05-28 12:43:23 +00:00
|
|
|
virSecretLookupDefClear(&authdef->seclookupdef);
|
2014-06-23 14:40:49 +00:00
|
|
|
VIR_FREE(authdef);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virStorageAuthDefPtr
|
|
|
|
virStorageAuthDefCopy(const virStorageAuthDef *src)
|
|
|
|
{
|
|
|
|
virStorageAuthDefPtr ret;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(ret->username, src->username) < 0)
|
|
|
|
goto error;
|
|
|
|
/* Not present for storage pool, but used for disk source */
|
|
|
|
if (VIR_STRDUP(ret->secrettype, src->secrettype) < 0)
|
|
|
|
goto error;
|
|
|
|
ret->authType = src->authType;
|
2016-05-28 12:43:23 +00:00
|
|
|
|
|
|
|
if (virSecretLookupDefCopy(&ret->seclookupdef, &src->seclookupdef) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-06-23 14:40:49 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageAuthDefFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-06 13:17:59 +00:00
|
|
|
virStorageAuthDefPtr
|
|
|
|
virStorageAuthDefParse(xmlNodePtr node,
|
|
|
|
xmlXPathContextPtr ctxt)
|
2014-06-23 14:40:49 +00:00
|
|
|
{
|
2018-03-06 13:17:59 +00:00
|
|
|
xmlNodePtr saveNode = ctxt->node;
|
2014-06-23 14:40:49 +00:00
|
|
|
virStorageAuthDefPtr authdef = NULL;
|
2018-03-06 13:03:27 +00:00
|
|
|
virStorageAuthDefPtr ret = NULL;
|
2016-06-13 20:23:42 +00:00
|
|
|
xmlNodePtr secretnode = NULL;
|
2014-06-23 14:40:49 +00:00
|
|
|
char *authtype = NULL;
|
|
|
|
|
2018-03-06 13:17:59 +00:00
|
|
|
ctxt->node = node;
|
|
|
|
|
2014-06-23 14:40:49 +00:00
|
|
|
if (VIR_ALLOC(authdef) < 0)
|
2018-03-06 13:17:59 +00:00
|
|
|
goto cleanup;
|
2014-06-23 14:40:49 +00:00
|
|
|
|
2018-03-06 13:03:27 +00:00
|
|
|
if (!(authdef->username = virXPathString("string(./@username)", ctxt))) {
|
2014-06-23 14:40:49 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("missing username for auth"));
|
2018-03-06 13:03:27 +00:00
|
|
|
goto cleanup;
|
2014-06-23 14:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
authdef->authType = VIR_STORAGE_AUTH_TYPE_NONE;
|
|
|
|
authtype = virXPathString("string(./@type)", ctxt);
|
|
|
|
if (authtype) {
|
|
|
|
/* Used by the storage pool instead of the secret type field
|
|
|
|
* to define whether chap or ceph being used
|
|
|
|
*/
|
|
|
|
if ((authdef->authType = virStorageAuthTypeFromString(authtype)) < 0) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("unknown auth type '%s'"), authtype);
|
2018-03-06 13:03:27 +00:00
|
|
|
goto cleanup;
|
2014-06-23 14:40:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-13 20:23:42 +00:00
|
|
|
if (!(secretnode = virXPathNode("./secret ", ctxt))) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("Missing <secret> element in auth"));
|
2018-03-06 13:03:27 +00:00
|
|
|
goto cleanup;
|
2016-06-13 20:23:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Used by the domain disk xml parsing in order to ensure the
|
|
|
|
* <secret type='%s' value matches the expected secret type for
|
|
|
|
* the style of disk (iscsi is chap, nbd is ceph). For some reason
|
|
|
|
* the virSecretUsageType{From|To}String() cannot be linked here
|
|
|
|
* and because only the domain parsing code cares - just keep
|
|
|
|
* it as a string.
|
|
|
|
*/
|
|
|
|
authdef->secrettype = virXMLPropString(secretnode, "type");
|
|
|
|
|
|
|
|
if (virSecretLookupParseSecret(secretnode, &authdef->seclookupdef) < 0)
|
2018-03-06 13:03:27 +00:00
|
|
|
goto cleanup;
|
2014-06-23 14:40:49 +00:00
|
|
|
|
2018-03-06 13:03:27 +00:00
|
|
|
VIR_STEAL_PTR(ret, authdef);
|
2014-06-23 14:40:49 +00:00
|
|
|
|
2018-03-06 13:03:27 +00:00
|
|
|
cleanup:
|
2014-06-23 14:40:49 +00:00
|
|
|
VIR_FREE(authtype);
|
|
|
|
virStorageAuthDefFree(authdef);
|
2018-03-06 13:17:59 +00:00
|
|
|
ctxt->node = saveNode;
|
2018-03-06 13:03:27 +00:00
|
|
|
|
|
|
|
return ret;
|
2014-06-23 14:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-20 11:24:36 +00:00
|
|
|
void
|
2014-06-23 14:40:49 +00:00
|
|
|
virStorageAuthDefFormat(virBufferPtr buf,
|
|
|
|
virStorageAuthDefPtr authdef)
|
|
|
|
{
|
|
|
|
if (authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE) {
|
|
|
|
virBufferEscapeString(buf, "<auth username='%s'>\n", authdef->username);
|
|
|
|
} else {
|
|
|
|
virBufferAsprintf(buf, "<auth type='%s' ",
|
|
|
|
virStorageAuthTypeToString(authdef->authType));
|
|
|
|
virBufferEscapeString(buf, "username='%s'>\n", authdef->username);
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
2016-06-13 23:40:34 +00:00
|
|
|
virSecretLookupFormatSecret(buf, authdef->secrettype,
|
|
|
|
&authdef->seclookupdef);
|
2014-06-23 14:40:49 +00:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</auth>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-27 10:54:33 +00:00
|
|
|
void
|
|
|
|
virStoragePRDefFree(virStoragePRDefPtr prd)
|
|
|
|
{
|
|
|
|
if (!prd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(prd->path);
|
2018-05-11 14:39:21 +00:00
|
|
|
VIR_FREE(prd->mgralias);
|
2017-11-27 10:54:33 +00:00
|
|
|
VIR_FREE(prd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virStoragePRDefPtr
|
|
|
|
virStoragePRDefParseXML(xmlXPathContextPtr ctxt)
|
|
|
|
{
|
2018-05-11 13:50:57 +00:00
|
|
|
virStoragePRDefPtr prd;
|
|
|
|
virStoragePRDefPtr ret = NULL;
|
2017-11-27 10:54:33 +00:00
|
|
|
char *managed = NULL;
|
|
|
|
char *type = NULL;
|
|
|
|
char *path = NULL;
|
|
|
|
char *mode = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(prd) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2018-05-11 13:50:57 +00:00
|
|
|
if (!(managed = virXPathString("string(./@managed)", ctxt))) {
|
2017-11-27 10:54:33 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
2018-05-11 13:50:57 +00:00
|
|
|
_("missing @managed attribute for <reservations/>"));
|
2017-11-27 10:54:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-05-11 13:50:57 +00:00
|
|
|
if ((prd->managed = virTristateBoolTypeFromString(managed)) <= 0) {
|
2017-11-27 10:54:33 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
2018-05-11 13:50:57 +00:00
|
|
|
_("invalid value for 'managed': %s"), managed);
|
2017-11-27 10:54:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-05-14 05:25:43 +00:00
|
|
|
type = virXPathString("string(./source[1]/@type)", ctxt);
|
|
|
|
path = virXPathString("string(./source[1]/@path)", ctxt);
|
|
|
|
mode = virXPathString("string(./source[1]/@mode)", ctxt);
|
2018-05-11 13:50:57 +00:00
|
|
|
|
2018-05-14 05:25:43 +00:00
|
|
|
if (prd->managed == VIR_TRISTATE_BOOL_NO || type || path || mode) {
|
2018-05-11 13:50:57 +00:00
|
|
|
if (!type) {
|
2017-11-27 10:54:33 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
2018-05-11 13:50:57 +00:00
|
|
|
_("missing connection type for <reservations/>"));
|
2017-11-27 10:54:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-05-11 13:50:57 +00:00
|
|
|
if (!path) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("missing path for <reservations/>"));
|
2017-11-27 10:54:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-05-11 13:50:57 +00:00
|
|
|
if (!mode) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("missing connection mode for <reservations/>"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-05-14 05:25:43 +00:00
|
|
|
}
|
2017-11-27 10:54:33 +00:00
|
|
|
|
2018-05-14 05:25:43 +00:00
|
|
|
if (type && STRNEQ(type, "unix")) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unsupported connection type for <reservations/>: %s"),
|
|
|
|
type);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-05-11 13:50:57 +00:00
|
|
|
|
2018-05-14 05:25:43 +00:00
|
|
|
if (mode && STRNEQ(mode, "client")) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unsupported connection mode for <reservations/>: %s"),
|
|
|
|
mode);
|
|
|
|
goto cleanup;
|
2017-11-27 10:54:33 +00:00
|
|
|
}
|
|
|
|
|
2018-05-14 05:25:43 +00:00
|
|
|
VIR_STEAL_PTR(prd->path, path);
|
2018-05-11 13:50:57 +00:00
|
|
|
VIR_STEAL_PTR(ret, prd);
|
2017-11-27 10:54:33 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(mode);
|
|
|
|
VIR_FREE(path);
|
|
|
|
VIR_FREE(type);
|
|
|
|
VIR_FREE(managed);
|
|
|
|
virStoragePRDefFree(prd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStoragePRDefFormat(virBufferPtr buf,
|
|
|
|
virStoragePRDefPtr prd)
|
|
|
|
{
|
2018-05-11 13:50:57 +00:00
|
|
|
virBufferAsprintf(buf, "<reservations managed='%s'",
|
|
|
|
virTristateBoolTypeToString(prd->managed));
|
2018-05-14 05:25:43 +00:00
|
|
|
if (prd->path) {
|
2018-05-11 13:50:57 +00:00
|
|
|
virBufferAddLit(buf, ">\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferAddLit(buf, "<source type='unix'");
|
|
|
|
virBufferEscapeString(buf, " path='%s'", prd->path);
|
|
|
|
virBufferAddLit(buf, " mode='client'/>\n");
|
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</reservations>\n");
|
2017-11-27 10:54:33 +00:00
|
|
|
} else {
|
|
|
|
virBufferAddLit(buf, "/>\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-14 10:47:02 +00:00
|
|
|
bool
|
|
|
|
virStoragePRDefIsEqual(virStoragePRDefPtr a,
|
|
|
|
virStoragePRDefPtr b)
|
|
|
|
{
|
|
|
|
if (!a && !b)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!a || !b)
|
|
|
|
return false;
|
|
|
|
|
2018-05-11 13:50:57 +00:00
|
|
|
if (a->managed != b->managed ||
|
2017-12-14 10:47:02 +00:00
|
|
|
STRNEQ_NULLABLE(a->path, b->path))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-18 14:55:14 +00:00
|
|
|
bool
|
|
|
|
virStoragePRDefIsManaged(virStoragePRDefPtr prd)
|
|
|
|
{
|
|
|
|
return prd && prd->managed == VIR_TRISTATE_BOOL_YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-18 16:39:47 +00:00
|
|
|
virSecurityDeviceLabelDefPtr
|
|
|
|
virStorageSourceGetSecurityLabelDef(virStorageSourcePtr src,
|
|
|
|
const char *model)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < src->nseclabels; i++) {
|
|
|
|
if (STREQ_NULLABLE(src->seclabels[i]->model, model))
|
|
|
|
return src->seclabels[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-16 11:10:42 +00:00
|
|
|
static void
|
|
|
|
virStorageSourceSeclabelsClear(virStorageSourcePtr def)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (def->seclabels) {
|
|
|
|
for (i = 0; i < def->nseclabels; i++)
|
|
|
|
virSecurityDeviceLabelDefFree(def->seclabels[i]);
|
|
|
|
VIR_FREE(def->seclabels);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageSourceSeclabelsCopy(virStorageSourcePtr to,
|
|
|
|
const virStorageSource *from)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (from->nseclabels == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(to->seclabels, from->nseclabels) < 0)
|
|
|
|
return -1;
|
|
|
|
to->nseclabels = from->nseclabels;
|
|
|
|
|
|
|
|
for (i = 0; i < to->nseclabels; i++) {
|
|
|
|
if (!(to->seclabels[i] = virSecurityDeviceLabelDefCopy(from->seclabels[i])))
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageSourceSeclabelsClear(to);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virStorageTimestampsPtr
|
|
|
|
virStorageTimestampsCopy(const virStorageTimestamps *src)
|
|
|
|
{
|
|
|
|
virStorageTimestampsPtr ret;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memcpy(ret, src, sizeof(*src));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virStoragePermsPtr
|
|
|
|
virStoragePermsCopy(const virStoragePerms *src)
|
|
|
|
{
|
|
|
|
virStoragePermsPtr ret;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret->mode = src->mode;
|
|
|
|
ret->uid = src->uid;
|
|
|
|
ret->gid = src->gid;
|
|
|
|
|
2017-06-02 01:58:06 +00:00
|
|
|
if (VIR_STRDUP(ret->label, src->label) < 0)
|
2014-06-16 11:10:42 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStoragePermsFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virStorageSourcePoolDefPtr
|
|
|
|
virStorageSourcePoolDefCopy(const virStorageSourcePoolDef *src)
|
|
|
|
{
|
|
|
|
virStorageSourcePoolDefPtr ret;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret->voltype = src->voltype;
|
|
|
|
ret->pooltype = src->pooltype;
|
|
|
|
ret->actualtype = src->actualtype;
|
|
|
|
ret->mode = src->mode;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(ret->pool, src->pool) < 0 ||
|
|
|
|
VIR_STRDUP(ret->volume, src->volume) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageSourcePoolDefFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageSourcePtr:
|
|
|
|
*
|
|
|
|
* Deep-copies a virStorageSource structure. If @backing chain is true
|
|
|
|
* then also copies the backing chain recursively, otherwise just
|
|
|
|
* the top element is copied. This function doesn't copy the
|
|
|
|
* storage driver access structure and thus the struct needs to be initialized
|
|
|
|
* separately.
|
|
|
|
*/
|
|
|
|
virStorageSourcePtr
|
|
|
|
virStorageSourceCopy(const virStorageSource *src,
|
|
|
|
bool backingChain)
|
|
|
|
{
|
|
|
|
virStorageSourcePtr ret = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2017-10-06 11:35:24 +00:00
|
|
|
ret->id = src->id;
|
2014-06-16 11:10:42 +00:00
|
|
|
ret->type = src->type;
|
|
|
|
ret->protocol = src->protocol;
|
|
|
|
ret->format = src->format;
|
|
|
|
ret->capacity = src->capacity;
|
qemu: let blockinfo reuse virStorageSource
Right now, grabbing blockinfo always calls stat on the disk, then
opens the image to determine the capacity, using a throw-away
virStorageSourcePtr. This has a couple of drawbacks:
1. We are calling stat and opening a file on every invocation of
the API. However, there are cases where the stats should NOT be
changing between successive calls (if a domain is running, no
one should be changing the physical size of a block device or raw
image behind our backs; capacity of read-only files should not
be changing; and we are the gateway to the block-resize command
to know when the capacity of read-write files should be changing).
True, we still have to use stat in some cases (a sparse raw file
changes allocation if it is read-write and the amount of holes is
changing, and a read-write qcow2 image stored in a file changes
physical size if it was not fully pre-allocated). But for
read-only images, even this should be something we can remember
from the previous time, rather than repeating every call.
2. We want to enhance the power of virDomainListGetStats, by
sharing code. But we already have a virStorageSourcePtr for
each disk, and it would be easier to reuse the common structure
than to have to worry about the one-off virDomainBlockInfoPtr.
While this patch does not optimize reuse of information in point
1, it does get us closer to being able to do so; by updating a
structure that survives between consecutive calls.
* src/util/virstoragefile.h (_virStorageSource): Add physical, to
mirror virDomainBlockInfo; rearrange fields to match public struct.
(virStorageSourceCopy): Copy the new field.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Store into
storage source, then copy to block info.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-16 04:54:33 +00:00
|
|
|
ret->allocation = src->allocation;
|
2016-04-29 11:43:57 +00:00
|
|
|
ret->has_allocation = src->has_allocation;
|
qemu: let blockinfo reuse virStorageSource
Right now, grabbing blockinfo always calls stat on the disk, then
opens the image to determine the capacity, using a throw-away
virStorageSourcePtr. This has a couple of drawbacks:
1. We are calling stat and opening a file on every invocation of
the API. However, there are cases where the stats should NOT be
changing between successive calls (if a domain is running, no
one should be changing the physical size of a block device or raw
image behind our backs; capacity of read-only files should not
be changing; and we are the gateway to the block-resize command
to know when the capacity of read-write files should be changing).
True, we still have to use stat in some cases (a sparse raw file
changes allocation if it is read-write and the amount of holes is
changing, and a read-write qcow2 image stored in a file changes
physical size if it was not fully pre-allocated). But for
read-only images, even this should be something we can remember
from the previous time, rather than repeating every call.
2. We want to enhance the power of virDomainListGetStats, by
sharing code. But we already have a virStorageSourcePtr for
each disk, and it would be easier to reuse the common structure
than to have to worry about the one-off virDomainBlockInfoPtr.
While this patch does not optimize reuse of information in point
1, it does get us closer to being able to do so; by updating a
structure that survives between consecutive calls.
* src/util/virstoragefile.h (_virStorageSource): Add physical, to
mirror virDomainBlockInfo; rearrange fields to match public struct.
(virStorageSourceCopy): Copy the new field.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo): Store into
storage source, then copy to block info.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-11-16 04:54:33 +00:00
|
|
|
ret->physical = src->physical;
|
2014-06-16 11:10:42 +00:00
|
|
|
ret->readonly = src->readonly;
|
|
|
|
ret->shared = src->shared;
|
2017-08-30 15:35:34 +00:00
|
|
|
ret->haveTLS = src->haveTLS;
|
|
|
|
ret->tlsFromConfig = src->tlsFromConfig;
|
2017-08-30 19:29:59 +00:00
|
|
|
ret->tlsVerify = src->tlsVerify;
|
2017-09-26 11:52:43 +00:00
|
|
|
ret->detected = src->detected;
|
2017-11-23 15:06:33 +00:00
|
|
|
ret->debugLevel = src->debugLevel;
|
|
|
|
ret->debug = src->debug;
|
2017-12-05 13:06:13 +00:00
|
|
|
ret->iomode = src->iomode;
|
|
|
|
ret->cachemode = src->cachemode;
|
|
|
|
ret->discard = src->discard;
|
|
|
|
ret->detect_zeroes = src->detect_zeroes;
|
2014-06-16 11:10:42 +00:00
|
|
|
|
|
|
|
/* storage driver metadata are not copied */
|
|
|
|
ret->drv = NULL;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(ret->path, src->path) < 0 ||
|
|
|
|
VIR_STRDUP(ret->volume, src->volume) < 0 ||
|
|
|
|
VIR_STRDUP(ret->relPath, src->relPath) < 0 ||
|
|
|
|
VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 ||
|
2014-11-11 10:35:25 +00:00
|
|
|
VIR_STRDUP(ret->snapshot, src->snapshot) < 0 ||
|
2014-11-11 16:31:24 +00:00
|
|
|
VIR_STRDUP(ret->configFile, src->configFile) < 0 ||
|
2017-02-22 15:20:00 +00:00
|
|
|
VIR_STRDUP(ret->nodeformat, src->nodeformat) < 0 ||
|
2017-07-25 16:11:58 +00:00
|
|
|
VIR_STRDUP(ret->nodestorage, src->nodestorage) < 0 ||
|
2017-08-30 19:29:59 +00:00
|
|
|
VIR_STRDUP(ret->compat, src->compat) < 0 ||
|
|
|
|
VIR_STRDUP(ret->tlsAlias, src->tlsAlias) < 0 ||
|
|
|
|
VIR_STRDUP(ret->tlsCertdir, src->tlsCertdir) < 0)
|
2014-06-16 11:10:42 +00:00
|
|
|
goto error;
|
|
|
|
|
2014-10-30 10:52:17 +00:00
|
|
|
if (src->nhosts) {
|
|
|
|
if (!(ret->hosts = virStorageNetHostDefCopy(src->nhosts, src->hosts)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ret->nhosts = src->nhosts;
|
|
|
|
}
|
2014-06-16 11:10:42 +00:00
|
|
|
|
|
|
|
if (src->srcpool &&
|
|
|
|
!(ret->srcpool = virStorageSourcePoolDefCopy(src->srcpool)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (src->features &&
|
|
|
|
!(ret->features = virBitmapNewCopy(src->features)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (src->encryption &&
|
|
|
|
!(ret->encryption = virStorageEncryptionCopy(src->encryption)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (src->perms &&
|
|
|
|
!(ret->perms = virStoragePermsCopy(src->perms)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (src->timestamps &&
|
|
|
|
!(ret->timestamps = virStorageTimestampsCopy(src->timestamps)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (virStorageSourceSeclabelsCopy(ret, src) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (src->auth &&
|
|
|
|
!(ret->auth = virStorageAuthDefCopy(src->auth)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (backingChain && src->backingStore) {
|
|
|
|
if (!(ret->backingStore = virStorageSourceCopy(src->backingStore,
|
|
|
|
true)))
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageSourceFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-25 16:48:27 +00:00
|
|
|
/**
|
|
|
|
* virStorageSourceInitChainElement:
|
|
|
|
* @newelem: New backing chain element disk source
|
|
|
|
* @old: Existing top level disk source
|
2016-11-15 14:00:08 +00:00
|
|
|
* @transferLabels: Transfer security labels.
|
2014-06-25 16:48:27 +00:00
|
|
|
*
|
|
|
|
* Transfers relevant information from the existing disk source to the new
|
|
|
|
* backing chain element if they weren't supplied so that labelling info
|
|
|
|
* and possibly other stuff is correct.
|
|
|
|
*
|
2014-11-19 17:54:43 +00:00
|
|
|
* If @transferLabels is true, security labels from the existing disk are copied
|
|
|
|
* to the new disk. Otherwise the default domain imagelabel label will be used.
|
2014-06-25 16:48:27 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageSourceInitChainElement(virStorageSourcePtr newelem,
|
|
|
|
virStorageSourcePtr old,
|
2014-11-19 17:54:43 +00:00
|
|
|
bool transferLabels)
|
2014-06-25 16:48:27 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
2014-11-19 17:54:43 +00:00
|
|
|
if (transferLabels &&
|
|
|
|
!newelem->seclabels &&
|
2014-06-25 16:48:27 +00:00
|
|
|
virStorageSourceSeclabelsCopy(newelem, old) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
newelem->shared = old->shared;
|
|
|
|
newelem->readonly = old->readonly;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-29 18:00:38 +00:00
|
|
|
void
|
|
|
|
virStorageSourcePoolDefFree(virStorageSourcePoolDefPtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->pool);
|
|
|
|
VIR_FREE(def->volume);
|
|
|
|
|
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-08 06:51:06 +00:00
|
|
|
int
|
2016-05-02 11:42:32 +00:00
|
|
|
virStorageSourceGetActualType(const virStorageSource *def)
|
2014-04-08 06:51:06 +00:00
|
|
|
{
|
|
|
|
if (def->type == VIR_STORAGE_TYPE_VOLUME && def->srcpool)
|
|
|
|
return def->srcpool->actualtype;
|
|
|
|
|
|
|
|
return def->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-25 11:47:32 +00:00
|
|
|
bool
|
2016-12-14 14:25:22 +00:00
|
|
|
virStorageSourceIsLocalStorage(const virStorageSource *src)
|
2014-06-25 11:47:32 +00:00
|
|
|
{
|
2014-09-03 16:54:56 +00:00
|
|
|
virStorageType type = virStorageSourceGetActualType(src);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case VIR_STORAGE_TYPE_FILE:
|
|
|
|
case VIR_STORAGE_TYPE_BLOCK:
|
|
|
|
case VIR_STORAGE_TYPE_DIR:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case VIR_STORAGE_TYPE_NETWORK:
|
|
|
|
case VIR_STORAGE_TYPE_VOLUME:
|
|
|
|
case VIR_STORAGE_TYPE_LAST:
|
|
|
|
case VIR_STORAGE_TYPE_NONE:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2014-06-25 11:47:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-11 17:43:53 +00:00
|
|
|
/**
|
|
|
|
* virStorageSourceIsEmpty:
|
|
|
|
*
|
|
|
|
* @src: disk source to check
|
|
|
|
*
|
|
|
|
* Returns true if the guest disk has no associated host storage source
|
|
|
|
* (such as an empty cdrom drive).
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virStorageSourceIsEmpty(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
if (virStorageSourceIsLocalStorage(src) && !src->path)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (src->type == VIR_STORAGE_TYPE_NONE)
|
|
|
|
return true;
|
|
|
|
|
2015-03-12 16:53:01 +00:00
|
|
|
if (src->type == VIR_STORAGE_TYPE_NETWORK &&
|
|
|
|
src->protocol == VIR_STORAGE_NET_PROTOCOL_NONE)
|
|
|
|
return true;
|
|
|
|
|
2014-09-11 17:43:53 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-02 11:42:32 +00:00
|
|
|
/**
|
|
|
|
* virStorageSourceIsBlockLocal:
|
|
|
|
* @src: disk source definition
|
|
|
|
*
|
|
|
|
* Returns true if @src describes a locally accessible block storage source.
|
|
|
|
* This includes block devices and host-mapped iSCSI volumes.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virStorageSourceIsBlockLocal(const virStorageSource *src)
|
|
|
|
{
|
|
|
|
return virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-26 06:27:58 +00:00
|
|
|
/**
|
2014-06-20 08:40:45 +00:00
|
|
|
* virStorageSourceBackingStoreClear:
|
2014-04-26 06:27:58 +00:00
|
|
|
*
|
|
|
|
* @src: disk source to clear
|
|
|
|
*
|
|
|
|
* Clears information about backing store of the current storage file.
|
|
|
|
*/
|
|
|
|
void
|
2014-06-20 08:40:45 +00:00
|
|
|
virStorageSourceBackingStoreClear(virStorageSourcePtr def)
|
2014-04-26 06:27:58 +00:00
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->relPath);
|
|
|
|
VIR_FREE(def->backingStoreRaw);
|
|
|
|
|
|
|
|
/* recursively free backing chain */
|
|
|
|
virStorageSourceFree(def->backingStore);
|
|
|
|
def->backingStore = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-29 18:00:38 +00:00
|
|
|
void
|
|
|
|
virStorageSourceClear(virStorageSourcePtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->path);
|
2014-05-02 14:17:42 +00:00
|
|
|
VIR_FREE(def->volume);
|
2015-04-27 09:26:31 +00:00
|
|
|
VIR_FREE(def->snapshot);
|
|
|
|
VIR_FREE(def->configFile);
|
2014-03-29 18:00:38 +00:00
|
|
|
virStorageSourcePoolDefFree(def->srcpool);
|
2014-03-30 03:21:06 +00:00
|
|
|
virBitmapFree(def->features);
|
|
|
|
VIR_FREE(def->compat);
|
2014-03-29 18:00:38 +00:00
|
|
|
virStorageEncryptionFree(def->encryption);
|
2017-11-27 10:54:33 +00:00
|
|
|
virStoragePRDefFree(def->pr);
|
2014-06-16 11:10:42 +00:00
|
|
|
virStorageSourceSeclabelsClear(def);
|
2014-06-12 14:11:43 +00:00
|
|
|
virStoragePermsFree(def->perms);
|
2014-03-30 03:21:06 +00:00
|
|
|
VIR_FREE(def->timestamps);
|
2014-03-29 18:00:38 +00:00
|
|
|
|
|
|
|
virStorageNetHostDefFree(def->nhosts, def->hosts);
|
2014-06-24 13:46:23 +00:00
|
|
|
virStorageAuthDefFree(def->auth);
|
2017-10-05 13:22:09 +00:00
|
|
|
virObjectUnref(def->privateData);
|
2014-04-17 14:04:33 +00:00
|
|
|
|
2017-07-25 16:11:58 +00:00
|
|
|
VIR_FREE(def->nodestorage);
|
2017-02-22 15:20:00 +00:00
|
|
|
VIR_FREE(def->nodeformat);
|
|
|
|
|
2014-06-20 08:40:45 +00:00
|
|
|
virStorageSourceBackingStoreClear(def);
|
2017-04-05 07:59:25 +00:00
|
|
|
|
2017-08-30 19:29:59 +00:00
|
|
|
VIR_FREE(def->tlsAlias);
|
|
|
|
VIR_FREE(def->tlsCertdir);
|
|
|
|
|
2017-04-05 07:59:25 +00:00
|
|
|
memset(def, 0, sizeof(*def));
|
2014-03-29 18:00:38 +00:00
|
|
|
}
|
2014-04-07 15:58:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageSourceFree(virStorageSourcePtr def)
|
|
|
|
{
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virStorageSourceClear(def);
|
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
static virStorageSourcePtr
|
|
|
|
virStorageSourceNewFromBackingRelative(virStorageSourcePtr parent,
|
|
|
|
const char *rel)
|
|
|
|
{
|
|
|
|
char *dirname = NULL;
|
|
|
|
virStorageSourcePtr ret;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2014-05-27 08:05:57 +00:00
|
|
|
/* store relative name */
|
|
|
|
if (VIR_STRDUP(ret->relPath, parent->backingStoreRaw) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-05-27 13:32:21 +00:00
|
|
|
if (!(dirname = mdir_name(parent->path))) {
|
|
|
|
virReportOOMError();
|
2014-04-25 11:23:50 +00:00
|
|
|
goto error;
|
2014-05-27 13:32:21 +00:00
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2014-05-27 13:32:21 +00:00
|
|
|
if (STRNEQ(dirname, "/")) {
|
|
|
|
if (virAsprintf(&ret->path, "%s/%s", dirname, rel) < 0)
|
2014-04-25 11:23:50 +00:00
|
|
|
goto error;
|
|
|
|
} else {
|
2014-05-27 13:32:21 +00:00
|
|
|
if (virAsprintf(&ret->path, "/%s", rel) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStorageSourceGetActualType(parent) == VIR_STORAGE_TYPE_NETWORK) {
|
2014-04-25 11:23:50 +00:00
|
|
|
ret->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
|
|
|
|
/* copy the host network part */
|
|
|
|
ret->protocol = parent->protocol;
|
2014-10-30 10:52:17 +00:00
|
|
|
if (parent->nhosts) {
|
|
|
|
if (!(ret->hosts = virStorageNetHostDefCopy(parent->nhosts,
|
|
|
|
parent->hosts)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ret->nhosts = parent->nhosts;
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
|
|
|
if (VIR_STRDUP(ret->volume, parent->volume) < 0)
|
|
|
|
goto error;
|
2014-05-27 13:32:21 +00:00
|
|
|
} else {
|
|
|
|
/* set the type to _FILE, the caller shall update it to the actual type */
|
|
|
|
ret->type = VIR_STORAGE_TYPE_FILE;
|
2014-04-25 11:23:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(dirname);
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageSourceFree(ret);
|
|
|
|
ret = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingURI(virStorageSourcePtr src,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
virURIPtr uri = NULL;
|
|
|
|
char **scheme = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(uri = virURIParse(path))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("failed to parse backing file location '%s'"),
|
|
|
|
path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-10-29 09:55:23 +00:00
|
|
|
if (VIR_ALLOC(src->hosts) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
src->nhosts = 1;
|
|
|
|
|
2014-04-25 11:23:50 +00:00
|
|
|
if (!(scheme = virStringSplit(uri->scheme, "+", 2)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!scheme[0] ||
|
|
|
|
(src->protocol = virStorageNetProtocolTypeFromString(scheme[0])) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid backing protocol '%s'"),
|
|
|
|
NULLSTR(scheme[0]));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scheme[1] &&
|
|
|
|
(src->hosts->transport = virStorageNetHostTransportTypeFromString(scheme[1])) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid protocol transport type '%s'"),
|
|
|
|
scheme[1]);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handle socket stored as a query */
|
|
|
|
if (uri->query) {
|
|
|
|
if (VIR_STRDUP(src->hosts->socket, STRSKIP(uri->query, "socket=")) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX We currently don't support auth, so don't bother parsing it */
|
|
|
|
|
|
|
|
/* possibly skip the leading slash */
|
2015-02-03 17:03:41 +00:00
|
|
|
if (uri->path &&
|
|
|
|
VIR_STRDUP(src->path,
|
2014-04-25 11:23:50 +00:00
|
|
|
*uri->path == '/' ? uri->path + 1 : uri->path) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) {
|
|
|
|
char *tmp;
|
2015-02-26 09:28:21 +00:00
|
|
|
|
|
|
|
if (!src->path) {
|
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("missing volume name and path for gluster volume"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-04-25 11:23:50 +00:00
|
|
|
if (!(tmp = strchr(src->path, '/')) ||
|
|
|
|
tmp == src->path) {
|
2015-02-26 09:35:47 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
2014-04-25 11:23:50 +00:00
|
|
|
_("missing volume name or file name in "
|
|
|
|
"gluster source path '%s'"), src->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->volume = src->path;
|
|
|
|
|
2017-10-23 14:39:49 +00:00
|
|
|
if (VIR_STRDUP(src->path, tmp + 1) < 0)
|
2014-04-25 11:23:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
tmp[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
src->hosts->port = uri->port;
|
2014-04-25 11:23:50 +00:00
|
|
|
|
|
|
|
if (VIR_STRDUP(src->hosts->name, uri->server) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virURIFree(uri);
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(scheme);
|
2014-04-25 11:23:50 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-31 16:49:56 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceRBDAddHost(virStorageSourcePtr src,
|
|
|
|
char *hostport)
|
|
|
|
{
|
|
|
|
char *port;
|
|
|
|
size_t skip;
|
|
|
|
char **parts;
|
|
|
|
|
|
|
|
if (VIR_EXPAND_N(src->hosts, src->nhosts, 1) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((port = strchr(hostport, ']'))) {
|
|
|
|
/* ipv6, strip brackets */
|
|
|
|
hostport += 1;
|
|
|
|
skip = 3;
|
|
|
|
} else {
|
|
|
|
port = strstr(hostport, "\\:");
|
|
|
|
skip = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (port) {
|
|
|
|
*port = '\0';
|
|
|
|
port += skip;
|
2017-07-20 10:45:42 +00:00
|
|
|
if (virStringParsePort(port, &src->hosts[src->nhosts - 1].port) < 0)
|
2014-10-31 16:49:56 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
parts = virStringSplit(hostport, "\\:", 0);
|
|
|
|
if (!parts)
|
|
|
|
goto error;
|
2016-11-25 08:18:35 +00:00
|
|
|
src->hosts[src->nhosts-1].name = virStringListJoin((const char **)parts, ":");
|
|
|
|
virStringListFree(parts);
|
2014-10-31 16:49:56 +00:00
|
|
|
if (!src->hosts[src->nhosts-1].name)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
src->hosts[src->nhosts-1].transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
|
|
|
src->hosts[src->nhosts-1].socket = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(src->hosts[src->nhosts-1].name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageSourceParseRBDColonString(const char *rbdstr,
|
|
|
|
virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
char *options = NULL;
|
|
|
|
char *p, *e, *next;
|
|
|
|
virStorageAuthDefPtr authdef = NULL;
|
|
|
|
|
|
|
|
/* optionally skip the "rbd:" prefix if provided */
|
|
|
|
if (STRPREFIX(rbdstr, "rbd:"))
|
|
|
|
rbdstr += strlen("rbd:");
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->path, rbdstr) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
p = strchr(src->path, ':');
|
|
|
|
if (p) {
|
|
|
|
if (VIR_STRDUP(options, p + 1) < 0)
|
|
|
|
goto error;
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
|
2014-11-11 10:35:25 +00:00
|
|
|
/* snapshot name */
|
|
|
|
if ((p = strchr(src->path, '@'))) {
|
|
|
|
if (VIR_STRDUP(src->snapshot, p + 1) < 0)
|
|
|
|
goto error;
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
|
2017-10-23 14:23:45 +00:00
|
|
|
/* pool vs. image name */
|
|
|
|
if ((p = strchr(src->path, '/'))) {
|
|
|
|
VIR_STEAL_PTR(src->volume, src->path);
|
|
|
|
if (VIR_STRDUP(src->path, p + 1) < 0)
|
|
|
|
goto error;
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
|
2014-10-31 16:49:56 +00:00
|
|
|
/* options */
|
|
|
|
if (!options)
|
|
|
|
return 0; /* all done */
|
|
|
|
|
|
|
|
p = options;
|
|
|
|
while (*p) {
|
|
|
|
/* find : delimiter or end of string */
|
|
|
|
for (e = p; *e && *e != ':'; ++e) {
|
|
|
|
if (*e == '\\') {
|
|
|
|
e++;
|
|
|
|
if (*e == '\0')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*e == '\0') {
|
|
|
|
next = e; /* last kv pair */
|
|
|
|
} else {
|
|
|
|
next = e + 1;
|
|
|
|
*e = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (STRPREFIX(p, "id=")) {
|
|
|
|
/* formulate authdef for src->auth */
|
|
|
|
if (VIR_ALLOC(authdef) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(authdef->username, p + strlen("id=")) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(authdef->secrettype,
|
2017-09-15 19:21:35 +00:00
|
|
|
virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_CEPH)) < 0)
|
2014-10-31 16:49:56 +00:00
|
|
|
goto error;
|
|
|
|
src->auth = authdef;
|
2017-09-13 14:25:25 +00:00
|
|
|
src->authInherited = true;
|
2014-10-31 16:49:56 +00:00
|
|
|
authdef = NULL;
|
|
|
|
|
|
|
|
/* Cannot formulate a secretType (eg, usage or uuid) given
|
|
|
|
* what is provided.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
if (STRPREFIX(p, "mon_host=")) {
|
|
|
|
char *h, *sep;
|
|
|
|
|
|
|
|
h = p + strlen("mon_host=");
|
|
|
|
while (h < e) {
|
|
|
|
for (sep = h; sep < e; ++sep) {
|
|
|
|
if (*sep == '\\' && (sep[1] == ',' ||
|
|
|
|
sep[1] == ';' ||
|
|
|
|
sep[1] == ' ')) {
|
|
|
|
*sep = '\0';
|
|
|
|
sep += 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStorageSourceRBDAddHost(src, h) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
h = sep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-11 16:31:24 +00:00
|
|
|
if (STRPREFIX(p, "conf=") &&
|
|
|
|
VIR_STRDUP(src->configFile, p + strlen("conf=")) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2014-10-31 16:49:56 +00:00
|
|
|
p = next;
|
|
|
|
}
|
|
|
|
VIR_FREE(options);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(options);
|
|
|
|
virStorageAuthDefFree(authdef);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-25 11:23:50 +00:00
|
|
|
static int
|
2014-11-04 13:07:53 +00:00
|
|
|
virStorageSourceParseNBDColonString(const char *nbdstr,
|
|
|
|
virStorageSourcePtr src)
|
2014-04-25 11:23:50 +00:00
|
|
|
{
|
|
|
|
char **backing = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
if (!(backing = virStringSplit(nbdstr, ":", 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* we know that backing[0] now equals to "nbd" */
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, 1) < 0)
|
2014-04-25 11:23:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
src->nhosts = 1;
|
|
|
|
src->hosts->transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
|
|
|
|
|
|
|
/* format: [] denotes optional sections, uppercase are variable strings
|
|
|
|
* nbd:unix:/PATH/TO/SOCKET[:exportname=EXPORTNAME]
|
|
|
|
* nbd:HOSTNAME:PORT[:exportname=EXPORTNAME]
|
|
|
|
*/
|
|
|
|
if (!backing[1]) {
|
2014-04-25 11:23:50 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2014-11-04 13:07:53 +00:00
|
|
|
_("missing remote information in '%s' for protocol nbd"),
|
|
|
|
nbdstr);
|
2014-04-25 11:23:50 +00:00
|
|
|
goto cleanup;
|
2014-11-04 13:07:53 +00:00
|
|
|
} else if (STREQ(backing[1], "unix")) {
|
|
|
|
if (!backing[2]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing unix socket path in nbd backing string %s"),
|
|
|
|
nbdstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
if (VIR_STRDUP(src->hosts->socket, backing[2]) < 0)
|
2014-04-25 11:23:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
} else {
|
|
|
|
if (VIR_STRDUP(src->hosts->name, backing[1]) < 0)
|
|
|
|
goto cleanup;
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
if (!backing[2]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing port in nbd string '%s'"),
|
|
|
|
nbdstr);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
if (virStringParsePort(backing[2], &src->hosts->port) < 0)
|
2014-11-04 13:07:53 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
if (backing[3] && STRPREFIX(backing[3], "exportname=")) {
|
|
|
|
if (VIR_STRDUP(src->path, backing[3] + strlen("exportname=")) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
ret = 0;
|
2014-04-25 11:23:50 +00:00
|
|
|
|
2014-11-04 13:07:53 +00:00
|
|
|
cleanup:
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(backing);
|
2014-11-04 13:07:53 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingColon(virStorageSourcePtr src,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
char *protocol = NULL;
|
|
|
|
const char *p;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(p = strchr(path, ':'))) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid backing protocol string '%s'"),
|
|
|
|
path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRNDUP(protocol, path, p - path) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((src->protocol = virStorageNetProtocolTypeFromString(protocol)) < 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("invalid backing protocol '%s'"),
|
|
|
|
protocol);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ((virStorageNetProtocol) src->protocol) {
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
|
|
|
if (virStorageSourceParseNBDColonString(path, src) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
break;
|
2014-04-25 11:23:50 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
2014-11-04 16:35:16 +00:00
|
|
|
if (virStorageSourceParseRBDColonString(path, src) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
2014-04-25 11:23:50 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("backing store parser is not implemented for protocol %s"),
|
2014-11-04 13:07:53 +00:00
|
|
|
protocol);
|
2014-04-25 11:23:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTPS:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_TFTP:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
2014-09-09 15:56:04 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
2017-08-29 11:21:51 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
2014-04-25 11:23:50 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("malformed backing store path for protocol %s"),
|
2014-11-04 13:07:53 +00:00
|
|
|
protocol);
|
2014-04-25 11:23:50 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2014-11-04 13:07:53 +00:00
|
|
|
VIR_FREE(protocol);
|
2014-04-25 11:23:50 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-13 22:53:43 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONInternal(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json);
|
|
|
|
|
|
|
|
|
2016-04-08 07:55:46 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONPath(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int type)
|
|
|
|
{
|
|
|
|
const char *path;
|
|
|
|
|
|
|
|
if (!(path = virJSONValueObjectGetString(json, "filename"))) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing 'filename' field in JSON backing volume "
|
|
|
|
"definition"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->path, path) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
src->type = type;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-12 15:59:58 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONUriStr(virStorageSourcePtr src,
|
|
|
|
const char *uri,
|
|
|
|
int protocol)
|
|
|
|
{
|
|
|
|
if (virStorageSourceParseBackingURI(src, uri) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (src->protocol != protocol) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("expected protocol '%s' but got '%s' in URI JSON volume "
|
|
|
|
"definition"),
|
|
|
|
virStorageNetProtocolTypeToString(protocol),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONUri(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int protocol)
|
|
|
|
{
|
|
|
|
const char *uri;
|
|
|
|
|
2016-08-16 07:24:12 +00:00
|
|
|
if (!(uri = virJSONValueObjectGetString(json, "url"))) {
|
2016-07-12 15:59:58 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2016-08-16 07:24:12 +00:00
|
|
|
_("missing 'url' in JSON backing volume definition"));
|
2016-07-12 15:59:58 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virStorageSourceParseBackingJSONUriStr(src, uri, protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-19 12:42:18 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONInetSocketAddress(virStorageNetHostDefPtr host,
|
|
|
|
virJSONValuePtr json)
|
|
|
|
{
|
2017-06-19 12:47:41 +00:00
|
|
|
const char *hostname;
|
|
|
|
const char *port;
|
|
|
|
|
|
|
|
if (!json) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing remote server specification in JSON "
|
|
|
|
"backing volume definition"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
hostname = virJSONValueObjectGetString(json, "host");
|
|
|
|
port = virJSONValueObjectGetString(json, "port");
|
2017-06-19 12:42:18 +00:00
|
|
|
|
|
|
|
if (!hostname) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing hostname for tcp backing server in "
|
|
|
|
"JSON backing volume definition"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
host->transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(host->name, hostname) < 0 ||
|
2017-07-20 10:45:42 +00:00
|
|
|
virStringParsePort(port, &host->port) < 0)
|
2017-06-19 12:42:18 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-13 13:35:29 +00:00
|
|
|
static int
|
2017-06-15 15:23:15 +00:00
|
|
|
virStorageSourceParseBackingJSONSocketAddress(virStorageNetHostDefPtr host,
|
|
|
|
virJSONValuePtr json)
|
2016-07-13 13:35:29 +00:00
|
|
|
{
|
2017-06-19 12:47:41 +00:00
|
|
|
const char *type;
|
|
|
|
const char *socket;
|
|
|
|
|
|
|
|
if (!json) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing remote server specification in JSON "
|
|
|
|
"backing volume definition"));
|
|
|
|
return -1;
|
|
|
|
}
|
2016-07-13 13:35:29 +00:00
|
|
|
|
2017-06-19 12:47:41 +00:00
|
|
|
if (!(type = virJSONValueObjectGetString(json, "type"))) {
|
2017-06-19 12:37:47 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing socket address type in "
|
|
|
|
"JSON backing volume definition"));
|
2016-07-13 13:35:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-06-19 12:37:47 +00:00
|
|
|
if (STREQ(type, "tcp") || STREQ(type, "inet")) {
|
2017-06-19 12:42:18 +00:00
|
|
|
return virStorageSourceParseBackingJSONInetSocketAddress(host, json);
|
2016-07-13 13:35:29 +00:00
|
|
|
|
2017-06-19 12:37:47 +00:00
|
|
|
} else if (STREQ(type, "unix")) {
|
|
|
|
host->transport = VIR_STORAGE_NET_HOST_TRANS_UNIX;
|
2016-07-13 13:35:29 +00:00
|
|
|
|
2018-02-12 14:44:11 +00:00
|
|
|
socket = virJSONValueObjectGetString(json, "path");
|
|
|
|
|
|
|
|
/* check for old spelling for gluster protocol */
|
|
|
|
if (!socket)
|
|
|
|
socket = virJSONValueObjectGetString(json, "socket");
|
|
|
|
|
|
|
|
if (!socket) {
|
2016-07-13 13:35:29 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing socket path for udp backing server in "
|
2017-06-15 15:23:15 +00:00
|
|
|
"JSON backing volume definition"));
|
2016-07-13 13:35:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(host->socket, socket) < 0)
|
|
|
|
return -1;
|
2017-06-19 12:37:47 +00:00
|
|
|
} else {
|
2016-07-13 13:35:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("backing store protocol '%s' is not yet supported"),
|
|
|
|
type);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONGluster(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
const char *uri = virJSONValueObjectGetString(json, "filename");
|
|
|
|
const char *volume = virJSONValueObjectGetString(json, "volume");
|
|
|
|
const char *path = virJSONValueObjectGetString(json, "path");
|
|
|
|
virJSONValuePtr server = virJSONValueObjectGetArray(json, "server");
|
|
|
|
size_t nservers;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* legacy URI based syntax passed via 'filename' option */
|
|
|
|
if (uri)
|
|
|
|
return virStorageSourceParseBackingJSONUriStr(src, uri,
|
|
|
|
VIR_STORAGE_NET_PROTOCOL_GLUSTER);
|
|
|
|
|
|
|
|
if (!volume || !path || !server) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing 'volume', 'path' or 'server' attribute in "
|
|
|
|
"JSON backing definition for gluster volume"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-09-05 13:31:44 +00:00
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_GLUSTER;
|
|
|
|
|
2016-07-13 13:35:29 +00:00
|
|
|
if (VIR_STRDUP(src->volume, volume) < 0 ||
|
2017-10-23 14:39:49 +00:00
|
|
|
VIR_STRDUP(src->path, path) < 0)
|
2016-07-13 13:35:29 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
nservers = virJSONValueArraySize(server);
|
2018-04-19 21:29:02 +00:00
|
|
|
if (nservers == 0) {
|
2016-07-13 13:35:29 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("at least 1 server is necessary in "
|
|
|
|
"JSON backing definition for gluster volume"));
|
2017-06-15 15:09:26 +00:00
|
|
|
|
|
|
|
return -1;
|
2016-07-13 13:35:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, nservers) < 0)
|
|
|
|
return -1;
|
|
|
|
src->nhosts = nservers;
|
|
|
|
|
|
|
|
for (i = 0; i < nservers; i++) {
|
2017-06-15 15:23:15 +00:00
|
|
|
if (virStorageSourceParseBackingJSONSocketAddress(src->hosts + i,
|
|
|
|
virJSONValueArrayGet(server, i)) < 0)
|
2016-07-13 13:35:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-13 13:40:33 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONiSCSI(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2017-06-15 15:12:01 +00:00
|
|
|
const char *transport = virJSONValueObjectGetString(json, "transport");
|
|
|
|
const char *portal = virJSONValueObjectGetString(json, "portal");
|
|
|
|
const char *target = virJSONValueObjectGetString(json, "target");
|
2018-01-31 11:00:42 +00:00
|
|
|
const char *lun = virJSONValueObjectGetStringOrNumber(json, "lun");
|
2016-07-13 13:40:33 +00:00
|
|
|
const char *uri;
|
2017-06-15 15:12:01 +00:00
|
|
|
char *port;
|
|
|
|
int ret = -1;
|
2016-07-13 13:40:33 +00:00
|
|
|
|
|
|
|
/* legacy URI based syntax passed via 'filename' option */
|
|
|
|
if ((uri = virJSONValueObjectGetString(json, "filename")))
|
|
|
|
return virStorageSourceParseBackingJSONUriStr(src, uri,
|
|
|
|
VIR_STORAGE_NET_PROTOCOL_ISCSI);
|
|
|
|
|
2017-06-15 15:12:01 +00:00
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
|
2016-07-13 13:40:33 +00:00
|
|
|
|
2018-01-31 11:00:42 +00:00
|
|
|
if (!lun)
|
|
|
|
lun = "0";
|
|
|
|
|
2017-06-15 15:12:01 +00:00
|
|
|
if (VIR_ALLOC(src->hosts) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
src->nhosts = 1;
|
|
|
|
|
|
|
|
if (STRNEQ_NULLABLE(transport, "tcp")) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("only TCP transport is supported for iSCSI volumes"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->hosts->transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
|
|
|
|
|
|
|
if (!portal) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing 'portal' address in iSCSI backing definition"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!target) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing 'target' in iSCSI backing definition"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->hosts->name, portal) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2017-11-07 15:20:23 +00:00
|
|
|
if ((port = strrchr(src->hosts->name, ':')) &&
|
|
|
|
!strchr(port, ']')) {
|
2017-07-20 10:45:42 +00:00
|
|
|
if (virStringParsePort(port + 1, &src->hosts->port) < 0)
|
2017-06-15 15:12:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
*port = '\0';
|
|
|
|
}
|
|
|
|
|
2018-01-31 11:00:42 +00:00
|
|
|
if (virAsprintf(&src->path, "%s/%s", target, lun) < 0)
|
2017-06-15 15:12:01 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
2016-07-13 13:40:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-14 06:10:31 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONNbd(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
const char *path = virJSONValueObjectGetString(json, "path");
|
|
|
|
const char *host = virJSONValueObjectGetString(json, "host");
|
|
|
|
const char *port = virJSONValueObjectGetString(json, "port");
|
|
|
|
const char *export = virJSONValueObjectGetString(json, "export");
|
2017-06-15 15:44:18 +00:00
|
|
|
virJSONValuePtr server = virJSONValueObjectGetObject(json, "server");
|
2016-07-14 06:10:31 +00:00
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (!path && !host && !server) {
|
2016-07-14 06:10:31 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2017-06-15 15:44:18 +00:00
|
|
|
_("missing host specification of NBD server in JSON "
|
|
|
|
"backing volume definition"));
|
2016-07-14 06:10:31 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_NBD;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->path, export) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, 1) < 0)
|
|
|
|
return -1;
|
|
|
|
src->nhosts = 1;
|
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (server) {
|
|
|
|
if (virStorageSourceParseBackingJSONSocketAddress(src->hosts, server) < 0)
|
2016-07-14 06:10:31 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
2017-06-15 15:44:18 +00:00
|
|
|
if (path) {
|
|
|
|
src->hosts[0].transport = VIR_STORAGE_NET_HOST_TRANS_UNIX;
|
|
|
|
if (VIR_STRDUP(src->hosts[0].socket, path) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
src->hosts[0].transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
|
|
|
if (VIR_STRDUP(src->hosts[0].name, host) < 0)
|
|
|
|
return -1;
|
2016-07-14 06:10:31 +00:00
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
if (virStringParsePort(port, &src->hosts[0].port) < 0)
|
2017-06-15 15:44:18 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2016-07-14 06:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-14 11:07:46 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONSheepdog(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
const char *filename;
|
2017-06-15 15:44:18 +00:00
|
|
|
const char *vdi = virJSONValueObjectGetString(json, "vdi");
|
|
|
|
virJSONValuePtr server = virJSONValueObjectGetObject(json, "server");
|
2016-07-14 11:07:46 +00:00
|
|
|
|
|
|
|
/* legacy URI based syntax passed via 'filename' option */
|
|
|
|
if ((filename = virJSONValueObjectGetString(json, "filename"))) {
|
|
|
|
if (strstr(filename, "://"))
|
|
|
|
return virStorageSourceParseBackingJSONUriStr(src, filename,
|
|
|
|
VIR_STORAGE_NET_PROTOCOL_SHEEPDOG);
|
|
|
|
|
|
|
|
/* libvirt doesn't implement a parser for the legacy non-URI syntax */
|
2017-06-15 15:44:18 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing sheepdog URI in JSON backing volume definition"));
|
|
|
|
return -1;
|
2016-07-14 11:07:46 +00:00
|
|
|
}
|
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_SHEEPDOG;
|
2016-07-14 11:07:46 +00:00
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (!vdi) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", _("missing sheepdog vdi name"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->path, vdi) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(src->hosts) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
src->nhosts = 1;
|
|
|
|
|
|
|
|
if (virStorageSourceParseBackingJSONSocketAddress(src->hosts, server) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
2016-07-14 11:07:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-15 13:12:10 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONSSH(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
const char *path = virJSONValueObjectGetString(json, "path");
|
|
|
|
const char *host = virJSONValueObjectGetString(json, "host");
|
|
|
|
const char *port = virJSONValueObjectGetString(json, "port");
|
2017-06-15 15:44:18 +00:00
|
|
|
virJSONValuePtr server = virJSONValueObjectGetObject(json, "server");
|
2016-07-15 13:12:10 +00:00
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (!(host || server) || !path) {
|
2016-07-15 13:12:10 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
2017-06-15 15:44:18 +00:00
|
|
|
_("missing host/server or path of SSH JSON backing "
|
2016-07-15 13:12:10 +00:00
|
|
|
"volume definition"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_SSH;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->path, path) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, 1) < 0)
|
|
|
|
return -1;
|
|
|
|
src->nhosts = 1;
|
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (server) {
|
|
|
|
if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts,
|
|
|
|
server) < 0)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
src->hosts[0].transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
|
2017-07-20 10:45:42 +00:00
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (VIR_STRDUP(src->hosts[0].name, host) < 0 ||
|
2017-07-20 10:45:42 +00:00
|
|
|
virStringParsePort(port, &src->hosts[0].port) < 0)
|
2017-06-15 15:44:18 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2016-07-15 13:12:10 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-05 13:15:22 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONRBD(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
const char *filename;
|
2017-06-15 15:44:18 +00:00
|
|
|
const char *pool = virJSONValueObjectGetString(json, "pool");
|
|
|
|
const char *image = virJSONValueObjectGetString(json, "image");
|
|
|
|
const char *conf = virJSONValueObjectGetString(json, "conf");
|
|
|
|
const char *snapshot = virJSONValueObjectGetString(json, "snapshot");
|
|
|
|
virJSONValuePtr servers = virJSONValueObjectGetArray(json, "server");
|
|
|
|
size_t nservers;
|
|
|
|
size_t i;
|
|
|
|
int ret = -1;
|
2016-09-05 13:15:22 +00:00
|
|
|
|
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD;
|
|
|
|
|
|
|
|
/* legacy syntax passed via 'filename' option */
|
|
|
|
if ((filename = virJSONValueObjectGetString(json, "filename")))
|
|
|
|
return virStorageSourceParseRBDColonString(filename, src);
|
|
|
|
|
2017-06-15 15:44:18 +00:00
|
|
|
if (!pool || !image) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing pool or image name in ceph backing volume "
|
|
|
|
"JSON specification"));
|
|
|
|
return -1;
|
|
|
|
}
|
2016-09-05 13:15:22 +00:00
|
|
|
|
2017-10-23 14:23:45 +00:00
|
|
|
if (VIR_STRDUP(src->volume, pool) < 0 ||
|
|
|
|
VIR_STRDUP(src->path, image) < 0 ||
|
|
|
|
VIR_STRDUP(src->snapshot, snapshot) < 0 ||
|
2017-06-15 15:44:18 +00:00
|
|
|
VIR_STRDUP(src->configFile, conf) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (servers) {
|
|
|
|
nservers = virJSONValueArraySize(servers);
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, nservers) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
src->nhosts = nservers;
|
|
|
|
|
|
|
|
for (i = 0; i < nservers; i++) {
|
|
|
|
if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts + i,
|
|
|
|
virJSONValueArrayGet(servers, i)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
2016-09-05 13:15:22 +00:00
|
|
|
}
|
|
|
|
|
2017-02-13 22:53:43 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONRaw(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
/* There are no interesting attributes in raw driver.
|
|
|
|
* Treat it as pass-through.
|
|
|
|
*/
|
|
|
|
return virStorageSourceParseBackingJSONInternal(src, json);
|
|
|
|
}
|
2016-09-05 13:15:22 +00:00
|
|
|
|
2017-08-30 13:46:50 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSONVxHS(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json,
|
|
|
|
int opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
const char *vdisk_id = virJSONValueObjectGetString(json, "vdisk-id");
|
|
|
|
virJSONValuePtr server = virJSONValueObjectGetObject(json, "server");
|
|
|
|
|
|
|
|
if (!vdisk_id || !server) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("missing 'vdisk-id' or 'server' attribute in "
|
|
|
|
"JSON backing definition for VxHS volume"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
src->protocol = VIR_STORAGE_NET_PROTOCOL_VXHS;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(src->path, vdisk_id) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(src->hosts, 1) < 0)
|
|
|
|
return -1;
|
|
|
|
src->nhosts = 1;
|
|
|
|
|
|
|
|
if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts,
|
|
|
|
server) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-08 07:55:46 +00:00
|
|
|
struct virStorageSourceJSONDriverParser {
|
|
|
|
const char *drvname;
|
|
|
|
int (*func)(virStorageSourcePtr src, virJSONValuePtr json, int opaque);
|
|
|
|
int opaque;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct virStorageSourceJSONDriverParser jsonParsers[] = {
|
|
|
|
{"file", virStorageSourceParseBackingJSONPath, VIR_STORAGE_TYPE_FILE},
|
2016-07-14 11:58:26 +00:00
|
|
|
{"host_device", virStorageSourceParseBackingJSONPath, VIR_STORAGE_TYPE_BLOCK},
|
|
|
|
{"host_cdrom", virStorageSourceParseBackingJSONPath, VIR_STORAGE_TYPE_BLOCK},
|
2016-07-12 15:59:58 +00:00
|
|
|
{"http", virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PROTOCOL_HTTP},
|
|
|
|
{"https", virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PROTOCOL_HTTPS},
|
|
|
|
{"ftp", virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PROTOCOL_FTP},
|
|
|
|
{"ftps", virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PROTOCOL_FTPS},
|
|
|
|
{"tftp", virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PROTOCOL_TFTP},
|
2016-07-13 13:35:29 +00:00
|
|
|
{"gluster", virStorageSourceParseBackingJSONGluster, 0},
|
2016-07-13 13:40:33 +00:00
|
|
|
{"iscsi", virStorageSourceParseBackingJSONiSCSI, 0},
|
2016-07-14 06:10:31 +00:00
|
|
|
{"nbd", virStorageSourceParseBackingJSONNbd, 0},
|
2016-07-14 11:07:46 +00:00
|
|
|
{"sheepdog", virStorageSourceParseBackingJSONSheepdog, 0},
|
2016-07-15 13:12:10 +00:00
|
|
|
{"ssh", virStorageSourceParseBackingJSONSSH, 0},
|
2016-09-05 13:15:22 +00:00
|
|
|
{"rbd", virStorageSourceParseBackingJSONRBD, 0},
|
2017-02-13 22:53:43 +00:00
|
|
|
{"raw", virStorageSourceParseBackingJSONRaw, 0},
|
2017-08-30 13:46:50 +00:00
|
|
|
{"vxhs", virStorageSourceParseBackingJSONVxHS, 0},
|
2016-04-08 07:55:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-02-13 22:53:42 +00:00
|
|
|
virStorageSourceParseBackingJSONInternal(virStorageSourcePtr src,
|
|
|
|
virJSONValuePtr json)
|
2016-04-08 07:55:46 +00:00
|
|
|
{
|
2017-07-11 12:23:08 +00:00
|
|
|
virJSONValuePtr deflattened = NULL;
|
2016-04-08 07:55:46 +00:00
|
|
|
virJSONValuePtr file;
|
|
|
|
const char *drvname;
|
2017-02-13 22:53:42 +00:00
|
|
|
char *str = NULL;
|
2016-04-08 07:55:46 +00:00
|
|
|
size_t i;
|
|
|
|
int ret = -1;
|
|
|
|
|
2017-07-11 12:23:08 +00:00
|
|
|
if (!(deflattened = virJSONValueObjectDeflatten(json)))
|
|
|
|
goto cleanup;
|
2016-04-08 07:55:46 +00:00
|
|
|
|
2017-07-11 12:23:08 +00:00
|
|
|
if (!(file = virJSONValueObjectGetObject(deflattened, "file"))) {
|
|
|
|
str = virJSONValueToString(json, false);
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
2017-09-08 14:25:40 +00:00
|
|
|
_("JSON backing volume definition '%s' lacks 'file' object"),
|
2017-07-11 12:23:08 +00:00
|
|
|
NULLSTR(str));
|
|
|
|
goto cleanup;
|
2016-04-08 07:55:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(drvname = virJSONValueObjectGetString(file, "driver"))) {
|
2017-02-13 22:53:42 +00:00
|
|
|
str = virJSONValueToString(json, false);
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
2017-09-08 14:25:40 +00:00
|
|
|
_("JSON backing volume definition '%s' lacks driver name"),
|
2017-02-13 22:53:42 +00:00
|
|
|
NULLSTR(str));
|
2016-04-08 07:55:46 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_CARDINALITY(jsonParsers); i++) {
|
|
|
|
if (STREQ(drvname, jsonParsers[i].drvname)) {
|
|
|
|
ret = jsonParsers[i].func(src, file, jsonParsers[i].opaque);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing parser implementation for JSON backing volume "
|
|
|
|
"driver '%s'"), drvname);
|
|
|
|
|
|
|
|
cleanup:
|
2017-02-13 22:53:42 +00:00
|
|
|
VIR_FREE(str);
|
2017-07-11 12:23:08 +00:00
|
|
|
virJSONValueFree(deflattened);
|
2016-04-08 07:55:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-13 22:53:42 +00:00
|
|
|
static int
|
|
|
|
virStorageSourceParseBackingJSON(virStorageSourcePtr src,
|
|
|
|
const char *json)
|
|
|
|
{
|
|
|
|
virJSONValuePtr root = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(root = virJSONValueFromString(json)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = virStorageSourceParseBackingJSONInternal(src, root);
|
|
|
|
|
|
|
|
virJSONValueFree(root);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-12 15:04:16 +00:00
|
|
|
virStorageSourcePtr
|
2014-04-25 11:23:50 +00:00
|
|
|
virStorageSourceNewFromBackingAbsolute(const char *path)
|
|
|
|
{
|
2016-04-08 07:55:46 +00:00
|
|
|
const char *json;
|
2014-04-25 11:23:50 +00:00
|
|
|
virStorageSourcePtr ret;
|
2016-04-08 07:55:46 +00:00
|
|
|
int rc;
|
2014-04-25 11:23:50 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(ret) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (virStorageIsFile(path)) {
|
|
|
|
ret->type = VIR_STORAGE_TYPE_FILE;
|
|
|
|
|
2014-05-27 12:49:41 +00:00
|
|
|
if (VIR_STRDUP(ret->path, path) < 0)
|
|
|
|
goto error;
|
2014-04-25 11:23:50 +00:00
|
|
|
} else {
|
|
|
|
ret->type = VIR_STORAGE_TYPE_NETWORK;
|
|
|
|
|
2017-06-16 15:07:55 +00:00
|
|
|
VIR_DEBUG("parsing backing store string: '%s'", path);
|
|
|
|
|
2014-04-25 11:23:50 +00:00
|
|
|
/* handle URI formatted backing stores */
|
2016-04-08 07:55:46 +00:00
|
|
|
if ((json = STRSKIP(path, "json:")))
|
|
|
|
rc = virStorageSourceParseBackingJSON(ret, json);
|
|
|
|
else if (strstr(path, "://"))
|
|
|
|
rc = virStorageSourceParseBackingURI(ret, path);
|
|
|
|
else
|
|
|
|
rc = virStorageSourceParseBackingColon(ret, path);
|
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
goto error;
|
2017-07-20 12:18:04 +00:00
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
virStorageSourceNetworkAssignDefaultPorts(ret);
|
2018-02-14 13:12:23 +00:00
|
|
|
|
|
|
|
/* Some of the legacy parsers parse authentication data since they are
|
|
|
|
* also used in other places. For backing store detection the
|
|
|
|
* authentication data would be invalid anyways, so we clear it */
|
|
|
|
if (ret->auth) {
|
|
|
|
virStorageAuthDefFree(ret->auth);
|
|
|
|
ret->auth = NULL;
|
|
|
|
}
|
2014-04-25 11:23:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageSourceFree(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virStorageSourcePtr
|
|
|
|
virStorageSourceNewFromBacking(virStorageSourcePtr parent)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
virStorageSourcePtr ret;
|
|
|
|
|
|
|
|
if (virStorageIsRelative(parent->backingStoreRaw))
|
|
|
|
ret = virStorageSourceNewFromBackingRelative(parent,
|
|
|
|
parent->backingStoreRaw);
|
|
|
|
else
|
|
|
|
ret = virStorageSourceNewFromBackingAbsolute(parent->backingStoreRaw);
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
/* possibly update local type */
|
|
|
|
if (ret->type == VIR_STORAGE_TYPE_FILE) {
|
|
|
|
if (stat(ret->path, &st) == 0) {
|
|
|
|
if (S_ISDIR(st.st_mode)) {
|
|
|
|
ret->type = VIR_STORAGE_TYPE_DIR;
|
|
|
|
ret->format = VIR_STORAGE_FILE_DIR;
|
|
|
|
} else if (S_ISBLK(st.st_mode)) {
|
|
|
|
ret->type = VIR_STORAGE_TYPE_BLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-27 12:33:01 +00:00
|
|
|
|
|
|
|
/* copy parent's labelling and other top level stuff */
|
2014-11-19 17:54:43 +00:00
|
|
|
if (virStorageSourceInitChainElement(ret, parent, true) < 0)
|
2014-06-27 12:33:01 +00:00
|
|
|
goto error;
|
2017-09-26 11:52:43 +00:00
|
|
|
|
2018-04-11 13:35:02 +00:00
|
|
|
ret->readonly = true;
|
2017-09-26 11:52:43 +00:00
|
|
|
ret->detected = true;
|
2014-04-25 11:23:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2014-06-27 12:33:01 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
virStorageSourceFree(ret);
|
|
|
|
return NULL;
|
2014-04-25 11:23:50 +00:00
|
|
|
}
|
2014-05-02 17:22:17 +00:00
|
|
|
|
|
|
|
|
2015-08-07 09:01:49 +00:00
|
|
|
/**
|
2016-12-01 21:19:26 +00:00
|
|
|
* @src: disk source definition structure
|
|
|
|
* @fd: file descriptor
|
|
|
|
* @sb: stat buffer
|
2015-08-07 09:01:49 +00:00
|
|
|
*
|
2016-12-01 21:19:26 +00:00
|
|
|
* Updates src->physical depending on the actual type of storage being used.
|
|
|
|
* To be called for domain storage source reporting as the volume code does
|
|
|
|
* not set/use the 'type' field for the voldef->source.target
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
2015-08-07 09:01:49 +00:00
|
|
|
*/
|
|
|
|
int
|
2016-12-01 21:19:26 +00:00
|
|
|
virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src,
|
|
|
|
int fd,
|
|
|
|
struct stat const *sb)
|
2015-08-07 09:01:49 +00:00
|
|
|
{
|
|
|
|
off_t end;
|
2016-12-01 21:19:26 +00:00
|
|
|
virStorageType actual_type = virStorageSourceGetActualType(src);
|
2015-08-07 09:01:49 +00:00
|
|
|
|
2016-12-01 21:19:26 +00:00
|
|
|
switch (actual_type) {
|
|
|
|
case VIR_STORAGE_TYPE_FILE:
|
|
|
|
case VIR_STORAGE_TYPE_NETWORK:
|
|
|
|
src->physical = sb->st_size;
|
|
|
|
break;
|
2015-08-07 09:01:49 +00:00
|
|
|
|
2016-12-01 21:19:26 +00:00
|
|
|
case VIR_STORAGE_TYPE_BLOCK:
|
|
|
|
if ((end = lseek(fd, 0, SEEK_END)) == (off_t) -1) {
|
|
|
|
virReportSystemError(errno, _("failed to seek to end of '%s'"),
|
2015-08-07 09:01:49 +00:00
|
|
|
src->path);
|
2016-12-01 21:19:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-08-07 09:01:49 +00:00
|
|
|
|
|
|
|
src->physical = end;
|
2016-12-01 21:19:26 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_STORAGE_TYPE_DIR:
|
|
|
|
src->physical = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* We shouldn't get VOLUME, but the switch requires all cases */
|
|
|
|
case VIR_STORAGE_TYPE_VOLUME:
|
|
|
|
case VIR_STORAGE_TYPE_NONE:
|
|
|
|
case VIR_STORAGE_TYPE_LAST:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot retrieve physical for path '%s' type '%s'"),
|
|
|
|
NULLSTR(src->path),
|
|
|
|
virStorageTypeToString(actual_type));
|
|
|
|
return -1;
|
|
|
|
break;
|
2015-08-07 09:01:49 +00:00
|
|
|
}
|
|
|
|
|
2016-12-01 21:19:26 +00:00
|
|
|
return 0;
|
2015-08-07 09:01:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-01 21:39:36 +00:00
|
|
|
/**
|
|
|
|
* @src: disk source definition structure
|
|
|
|
* @fd: file descriptor
|
|
|
|
* @sb: stat buffer
|
|
|
|
*
|
|
|
|
* Update the capacity, allocation, physical values for the storage @src
|
|
|
|
* Shared between the domain storage source for an inactive domain and the
|
|
|
|
* voldef source target as the result is not affected by the 'type' field.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageSourceUpdateBackingSizes(virStorageSourcePtr src,
|
|
|
|
int fd,
|
|
|
|
struct stat const *sb)
|
|
|
|
{
|
|
|
|
/* Get info for normal formats */
|
|
|
|
if (S_ISREG(sb->st_mode) || fd == -1) {
|
|
|
|
#ifndef WIN32
|
|
|
|
src->allocation = (unsigned long long)sb->st_blocks *
|
|
|
|
(unsigned long long)DEV_BSIZE;
|
|
|
|
#else
|
|
|
|
src->allocation = sb->st_size;
|
|
|
|
#endif
|
|
|
|
/* Regular files may be sparse, so logical size (capacity) is not same
|
|
|
|
* as actual allocation above
|
|
|
|
*/
|
|
|
|
src->capacity = sb->st_size;
|
|
|
|
|
|
|
|
/* Allocation tracks when the file is sparse, physical is the
|
|
|
|
* last offset of the file. */
|
|
|
|
src->physical = sb->st_size;
|
|
|
|
} else if (S_ISDIR(sb->st_mode)) {
|
|
|
|
src->allocation = 0;
|
|
|
|
src->capacity = 0;
|
|
|
|
src->physical = 0;
|
|
|
|
} else if (fd >= 0) {
|
|
|
|
off_t end;
|
|
|
|
|
|
|
|
/* XXX this is POSIX compliant, but doesn't work for CHAR files,
|
|
|
|
* only BLOCK. There is a Linux specific ioctl() for getting
|
|
|
|
* size of both CHAR / BLOCK devices we should check for in
|
|
|
|
* configure
|
|
|
|
*
|
|
|
|
* NB. Because we configure with AC_SYS_LARGEFILE, off_t
|
|
|
|
* should be 64 bits on all platforms. For block devices, we
|
|
|
|
* have to seek (safe even if someone else is writing) to
|
|
|
|
* determine physical size, and assume that allocation is the
|
|
|
|
* same as physical (but can refine that assumption later if
|
|
|
|
* qemu is still running).
|
|
|
|
*/
|
|
|
|
if ((end = lseek(fd, 0, SEEK_END)) == (off_t)-1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("failed to seek to end of %s"), src->path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
src->physical = end;
|
|
|
|
src->allocation = end;
|
|
|
|
src->capacity = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-01 21:23:58 +00:00
|
|
|
/**
|
|
|
|
* @src: disk source definition structure
|
|
|
|
* @buf: buffer to the storage file header
|
|
|
|
* @len: length of the storage file header
|
|
|
|
* @probe: allow probe
|
|
|
|
*
|
|
|
|
* Update the storage @src capacity. This may involve probing the storage
|
|
|
|
* @src in order to "see" if we can recognize what exists.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageSourceUpdateCapacity(virStorageSourcePtr src,
|
|
|
|
char *buf,
|
|
|
|
ssize_t len,
|
|
|
|
bool probe)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
virStorageSourcePtr meta = NULL;
|
|
|
|
int format = src->format;
|
|
|
|
|
|
|
|
/* Raw files: capacity is physical size. For all other files: if
|
|
|
|
* the metadata has a capacity, use that, otherwise fall back to
|
|
|
|
* physical size. */
|
|
|
|
if (format == VIR_STORAGE_FILE_NONE) {
|
|
|
|
if (!probe) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("no disk format for %s and probing is disabled"),
|
|
|
|
src->path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((format = virStorageFileProbeFormatFromBuf(src->path,
|
|
|
|
buf, len)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
src->format = format;
|
|
|
|
}
|
|
|
|
|
2017-06-15 18:32:43 +00:00
|
|
|
if (format == VIR_STORAGE_FILE_RAW && !src->encryption) {
|
2016-12-01 21:23:58 +00:00
|
|
|
src->capacity = src->physical;
|
2017-06-15 18:32:43 +00:00
|
|
|
} else if ((meta = virStorageFileGetMetadataFromBuf(src->path, buf,
|
|
|
|
len, format, NULL))) {
|
2016-12-01 21:23:58 +00:00
|
|
|
src->capacity = meta->capacity ? meta->capacity : src->physical;
|
2017-06-15 18:32:43 +00:00
|
|
|
if (src->encryption && meta->encryption)
|
|
|
|
src->encryption->payload_offset = meta->encryption->payload_offset;
|
|
|
|
} else {
|
2016-12-01 21:23:58 +00:00
|
|
|
goto cleanup;
|
2017-06-15 18:32:43 +00:00
|
|
|
}
|
2016-12-01 21:23:58 +00:00
|
|
|
|
2017-03-24 13:26:17 +00:00
|
|
|
if (src->encryption && src->encryption->payload_offset != -1)
|
|
|
|
src->capacity -= src->encryption->payload_offset * 512;
|
|
|
|
|
2016-12-01 21:23:58 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virStorageSourceFree(meta);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-02 17:22:17 +00:00
|
|
|
static char *
|
|
|
|
virStorageFileCanonicalizeFormatPath(char **components,
|
|
|
|
size_t ncomponents,
|
|
|
|
bool beginSlash,
|
|
|
|
bool beginDoubleSlash)
|
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
size_t i;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
if (beginSlash)
|
|
|
|
virBufferAddLit(&buf, "/");
|
|
|
|
|
|
|
|
if (beginDoubleSlash)
|
|
|
|
virBufferAddLit(&buf, "/");
|
|
|
|
|
|
|
|
for (i = 0; i < ncomponents; i++) {
|
|
|
|
if (i != 0)
|
|
|
|
virBufferAddLit(&buf, "/");
|
|
|
|
|
|
|
|
virBufferAdd(&buf, components[i], -1);
|
|
|
|
}
|
|
|
|
|
2014-06-27 08:40:15 +00:00
|
|
|
if (virBufferCheckError(&buf) < 0)
|
2014-05-02 17:22:17 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* if the output string is empty just return an empty string */
|
|
|
|
if (!(ret = virBufferContentAndReset(&buf)))
|
|
|
|
ignore_value(VIR_STRDUP(ret, ""));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virStorageFileCanonicalizeInjectSymlink(const char *path,
|
|
|
|
size_t at,
|
|
|
|
char ***components,
|
|
|
|
size_t *ncomponents)
|
|
|
|
{
|
|
|
|
char **tmp = NULL;
|
|
|
|
char **next;
|
|
|
|
size_t ntmp = 0;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(tmp = virStringSplitCount(path, "/", 0, &ntmp)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* prepend */
|
|
|
|
for (next = tmp; *next; next++) {
|
|
|
|
if (VIR_INSERT_ELEMENT(*components, at, *ncomponents, *next) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
at++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFreeCount(tmp, ntmp);
|
2014-05-02 17:22:17 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
virStorageFileCanonicalizePath(const char *path,
|
|
|
|
virStorageFileSimplifyPathReadlinkCallback cb,
|
|
|
|
void *cbdata)
|
|
|
|
{
|
|
|
|
virHashTablePtr cycle = NULL;
|
|
|
|
bool beginSlash = false;
|
|
|
|
bool beginDoubleSlash = false;
|
|
|
|
char **components = NULL;
|
|
|
|
size_t ncomponents = 0;
|
|
|
|
char *linkpath = NULL;
|
|
|
|
char *currentpath = NULL;
|
|
|
|
size_t i = 0;
|
|
|
|
size_t j = 0;
|
|
|
|
int rc;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
if (path[0] == '/') {
|
|
|
|
beginSlash = true;
|
|
|
|
|
|
|
|
if (path[1] == '/' && path[2] != '/')
|
|
|
|
beginDoubleSlash = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cycle = virHashCreate(10, NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(components = virStringSplitCount(path, "/", 0, &ncomponents)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < ncomponents) {
|
|
|
|
/* skip slashes */
|
|
|
|
if (STREQ(components[j], "")) {
|
|
|
|
VIR_FREE(components[j]);
|
|
|
|
VIR_DELETE_ELEMENT(components, j, ncomponents);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (i < ncomponents) {
|
|
|
|
/* skip '.'s unless it's the last one remaining */
|
|
|
|
if (STREQ(components[i], ".") &&
|
|
|
|
(beginSlash || ncomponents > 1)) {
|
|
|
|
VIR_FREE(components[i]);
|
|
|
|
VIR_DELETE_ELEMENT(components, i, ncomponents);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* resolve changes to parent directory */
|
|
|
|
if (STREQ(components[i], "..")) {
|
|
|
|
if (!beginSlash &&
|
|
|
|
(i == 0 || STREQ(components[i - 1], ".."))) {
|
|
|
|
i++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(components[i]);
|
|
|
|
VIR_DELETE_ELEMENT(components, i, ncomponents);
|
|
|
|
|
|
|
|
if (i != 0) {
|
|
|
|
VIR_FREE(components[i - 1]);
|
|
|
|
VIR_DELETE_ELEMENT(components, i - 1, ncomponents);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if the actual path isn't resulting into a symlink */
|
|
|
|
if (!(currentpath = virStorageFileCanonicalizeFormatPath(components,
|
|
|
|
i + 1,
|
|
|
|
beginSlash,
|
|
|
|
beginDoubleSlash)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((rc = cb(currentpath, &linkpath, cbdata)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (rc == 0) {
|
|
|
|
if (virHashLookup(cycle, currentpath)) {
|
|
|
|
virReportSystemError(ELOOP,
|
|
|
|
_("Failed to canonicalize path '%s'"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virHashAddEntry(cycle, currentpath, (void *) 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (linkpath[0] == '/') {
|
|
|
|
/* kill everything from the beginning including the actual component */
|
|
|
|
i++;
|
|
|
|
while (i--) {
|
|
|
|
VIR_FREE(components[0]);
|
|
|
|
VIR_DELETE_ELEMENT(components, 0, ncomponents);
|
|
|
|
}
|
|
|
|
beginSlash = true;
|
|
|
|
|
|
|
|
if (linkpath[1] == '/' && linkpath[2] != '/')
|
|
|
|
beginDoubleSlash = true;
|
|
|
|
else
|
|
|
|
beginDoubleSlash = false;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
} else {
|
|
|
|
VIR_FREE(components[i]);
|
|
|
|
VIR_DELETE_ELEMENT(components, i, ncomponents);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStorageFileCanonicalizeInjectSymlink(linkpath,
|
|
|
|
i,
|
|
|
|
&components,
|
|
|
|
&ncomponents) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while (j < ncomponents) {
|
|
|
|
/* skip slashes */
|
|
|
|
if (STREQ(components[j], "")) {
|
|
|
|
VIR_FREE(components[j]);
|
|
|
|
VIR_DELETE_ELEMENT(components, j, ncomponents);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(linkpath);
|
|
|
|
VIR_FREE(currentpath);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(currentpath);
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virStorageFileCanonicalizeFormatPath(components, ncomponents,
|
|
|
|
beginSlash, beginDoubleSlash);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virHashFree(cycle);
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFreeCount(components, ncomponents);
|
2014-05-02 17:22:17 +00:00
|
|
|
VIR_FREE(linkpath);
|
|
|
|
VIR_FREE(currentpath);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-05-13 08:10:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileRemoveLastPathComponent:
|
|
|
|
*
|
|
|
|
* @path: Path string to remove the last component from
|
|
|
|
*
|
|
|
|
* Removes the last path component of a path. This function is designed to be
|
|
|
|
* called on file paths only (no trailing slashes in @path). Caller is
|
|
|
|
* responsible to free the returned string.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
virStorageFileRemoveLastPathComponent(const char *path)
|
|
|
|
{
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(ret, path ? path : "") < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2016-05-12 11:05:37 +00:00
|
|
|
virFileRemoveLastComponent(ret);
|
2014-05-13 08:10:56 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virStorageFileGetRelativeBackingPath:
|
|
|
|
*
|
|
|
|
* Resolve relative path to be written to the overlay of @top image when
|
|
|
|
* collapsing the backing chain between @top and @base.
|
|
|
|
*
|
|
|
|
* Returns 0 on success; 1 if backing chain isn't relative and -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileGetRelativeBackingPath(virStorageSourcePtr top,
|
|
|
|
virStorageSourcePtr base,
|
|
|
|
char **relpath)
|
|
|
|
{
|
|
|
|
virStorageSourcePtr next;
|
|
|
|
char *tmp = NULL;
|
|
|
|
char *path = NULL;
|
|
|
|
char ret = -1;
|
|
|
|
|
|
|
|
*relpath = NULL;
|
|
|
|
|
2017-10-12 17:27:40 +00:00
|
|
|
for (next = top; virStorageSourceIsBacking(next); next = next->backingStore) {
|
2014-05-27 08:40:59 +00:00
|
|
|
if (!next->relPath) {
|
2014-05-13 08:10:56 +00:00
|
|
|
ret = 1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(tmp = virStorageFileRemoveLastPathComponent(path)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_FREE(path);
|
|
|
|
|
|
|
|
if (virAsprintf(&path, "%s%s", tmp, next->relPath) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
|
|
|
|
if (next == base)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next != base) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("failed to resolve relative backing name: "
|
|
|
|
"base image is not in backing chain"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
*relpath = path;
|
|
|
|
path = NULL;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(path);
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-04-09 08:48:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virStorageFileCheckCompat
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileCheckCompat(const char *compat)
|
|
|
|
{
|
|
|
|
char **version;
|
|
|
|
unsigned int result;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!compat)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
version = virStringSplit(compat, ".", 2);
|
|
|
|
if (!version || !version[1] ||
|
|
|
|
virStrToLong_ui(version[0], NULL, 10, &result) < 0 ||
|
|
|
|
virStrToLong_ui(version[1], NULL, 10, &result) < 0) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("forbidden characters in 'compat' attribute"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-11-25 08:18:35 +00:00
|
|
|
virStringListFree(version);
|
2015-04-09 08:48:49 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2016-12-16 17:30:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageSourceIsRelative:
|
|
|
|
* @src: storage source to check
|
|
|
|
*
|
|
|
|
* Returns true if given storage source definition is a relative path.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
virStorageSourceIsRelative(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
virStorageType actual_type = virStorageSourceGetActualType(src);
|
|
|
|
|
|
|
|
if (!src->path)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (actual_type) {
|
|
|
|
case VIR_STORAGE_TYPE_FILE:
|
|
|
|
case VIR_STORAGE_TYPE_BLOCK:
|
|
|
|
case VIR_STORAGE_TYPE_DIR:
|
|
|
|
return src->path[0] != '/';
|
|
|
|
|
|
|
|
case VIR_STORAGE_TYPE_NETWORK:
|
|
|
|
case VIR_STORAGE_TYPE_VOLUME:
|
|
|
|
case VIR_STORAGE_TYPE_NONE:
|
|
|
|
case VIR_STORAGE_TYPE_LAST:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2017-02-22 15:20:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageSourceFindByNodeName:
|
|
|
|
* @top: backing chain top
|
|
|
|
* @nodeName: node name to find in backing chain
|
|
|
|
* @index: if provided the index in the backing chain
|
|
|
|
*
|
|
|
|
* Looks up the given storage source in the backing chain and returns the
|
|
|
|
* pointer to it. If @index is passed then it's filled by the index in the
|
|
|
|
* backing chain. On failure NULL is returned and no error is reported.
|
|
|
|
*/
|
|
|
|
virStorageSourcePtr
|
|
|
|
virStorageSourceFindByNodeName(virStorageSourcePtr top,
|
|
|
|
const char *nodeName,
|
2017-03-27 13:11:26 +00:00
|
|
|
unsigned int *idx)
|
2017-02-22 15:20:00 +00:00
|
|
|
{
|
|
|
|
virStorageSourcePtr tmp;
|
|
|
|
|
2017-03-27 13:11:26 +00:00
|
|
|
if (idx)
|
|
|
|
*idx = 0;
|
2017-02-22 15:20:00 +00:00
|
|
|
|
2017-10-12 17:27:40 +00:00
|
|
|
for (tmp = top; virStorageSourceIsBacking(tmp); tmp = tmp->backingStore) {
|
2017-03-27 10:29:27 +00:00
|
|
|
if ((tmp->nodeformat && STREQ(tmp->nodeformat, nodeName)) ||
|
2017-07-25 16:11:58 +00:00
|
|
|
(tmp->nodestorage && STREQ(tmp->nodestorage, nodeName)))
|
2017-02-22 15:20:00 +00:00
|
|
|
return tmp;
|
|
|
|
|
2017-03-27 13:11:26 +00:00
|
|
|
if (idx)
|
|
|
|
(*idx)++;
|
2017-02-22 15:20:00 +00:00
|
|
|
}
|
|
|
|
|
2017-03-27 13:11:26 +00:00
|
|
|
if (idx)
|
|
|
|
*idx = 0;
|
2017-02-22 15:20:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
static unsigned int
|
2017-07-07 13:21:04 +00:00
|
|
|
virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol)
|
|
|
|
{
|
|
|
|
switch (protocol) {
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 80;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 443;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 21;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_FTPS:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 990;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_TFTP:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 69;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 7000;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 10809;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_SSH:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 22;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 3260;
|
2017-07-07 13:26:22 +00:00
|
|
|
|
2017-07-07 13:21:04 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 24007;
|
2017-07-07 13:21:04 +00:00
|
|
|
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_RBD:
|
2017-07-07 13:26:22 +00:00
|
|
|
/* we don't provide a default for RBD */
|
2017-07-20 10:45:42 +00:00
|
|
|
return 0;
|
2017-07-07 13:26:22 +00:00
|
|
|
|
2017-08-29 11:21:51 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
2017-08-30 13:46:50 +00:00
|
|
|
return 9999;
|
|
|
|
|
2017-07-07 13:21:04 +00:00
|
|
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
|
|
|
case VIR_STORAGE_NET_PROTOCOL_NONE:
|
2017-07-20 10:45:42 +00:00
|
|
|
return 0;
|
2017-07-07 13:21:04 +00:00
|
|
|
}
|
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
return 0;
|
2017-07-07 13:21:04 +00:00
|
|
|
}
|
2017-07-10 11:41:43 +00:00
|
|
|
|
|
|
|
|
2017-07-20 10:45:42 +00:00
|
|
|
void
|
2017-07-10 11:41:43 +00:00
|
|
|
virStorageSourceNetworkAssignDefaultPorts(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < src->nhosts; i++) {
|
|
|
|
if (src->hosts[i].transport == VIR_STORAGE_NET_HOST_TRANS_TCP &&
|
2017-07-20 10:45:42 +00:00
|
|
|
src->hosts[i].port == 0)
|
|
|
|
src->hosts[i].port = virStorageSourceNetworkDefaultPort(src->protocol);
|
2017-07-10 11:41:43 +00:00
|
|
|
}
|
|
|
|
}
|
2017-12-13 16:04:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt,
|
|
|
|
virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
src->relPath = virXPathString("string(./relPath)", ctxt);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src,
|
|
|
|
virBufferPtr buf)
|
|
|
|
{
|
|
|
|
if (src->relPath)
|
|
|
|
virBufferEscapeString(buf, "<relPath>%s</relPath>\n", src->relPath);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
static bool
|
|
|
|
virStorageFileIsInitialized(const virStorageSource *src)
|
|
|
|
{
|
|
|
|
return src && src->drv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
static int
|
|
|
|
virStorageFileGetBackendForSupportCheck(const virStorageSource *src,
|
|
|
|
virStorageFileBackendPtr *backend)
|
2018-01-25 09:35:46 +00:00
|
|
|
{
|
|
|
|
int actualType;
|
|
|
|
|
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
if (!src) {
|
|
|
|
*backend = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->drv) {
|
|
|
|
*backend = src->drv->backend;
|
|
|
|
return 0;
|
|
|
|
}
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
actualType = virStorageSourceGetActualType(src);
|
|
|
|
|
2018-04-25 13:37:07 +00:00
|
|
|
if (virStorageFileBackendForType(actualType, src->protocol, false, backend) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
return 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
static int
|
2018-01-25 09:35:46 +00:00
|
|
|
virStorageFileSupportsBackingChainTraversal(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
virStorageFileBackendPtr backend;
|
2018-04-25 13:09:24 +00:00
|
|
|
int rv;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
rv = virStorageFileGetBackendForSupportCheck(src, &backend);
|
|
|
|
if (rv < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!backend)
|
|
|
|
return 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
return backend->storageFileGetUniqueIdentifier &&
|
|
|
|
backend->storageFileRead &&
|
2018-04-25 13:09:24 +00:00
|
|
|
backend->storageFileAccess ? 1 : 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileSupportsSecurityDriver:
|
|
|
|
*
|
|
|
|
* @src: a storage file structure
|
|
|
|
*
|
|
|
|
* Check if a storage file supports operations needed by the security
|
|
|
|
* driver to perform labelling
|
|
|
|
*/
|
2018-04-25 13:09:24 +00:00
|
|
|
int
|
2018-01-25 09:35:46 +00:00
|
|
|
virStorageFileSupportsSecurityDriver(const virStorageSource *src)
|
|
|
|
{
|
|
|
|
virStorageFileBackendPtr backend;
|
2018-04-25 13:09:24 +00:00
|
|
|
int rv;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
rv = virStorageFileGetBackendForSupportCheck(src, &backend);
|
|
|
|
if (rv < 0)
|
|
|
|
return -1;
|
|
|
|
if (backend == NULL)
|
|
|
|
return 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
return backend->storageFileChown ? 1 : 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileSupportsAccess:
|
|
|
|
*
|
|
|
|
* @src: a storage file structure
|
|
|
|
*
|
|
|
|
* Check if a storage file supports checking if the storage source is accessible
|
|
|
|
* for the given vm.
|
|
|
|
*/
|
2018-04-25 13:09:24 +00:00
|
|
|
int
|
2018-01-25 09:35:46 +00:00
|
|
|
virStorageFileSupportsAccess(const virStorageSource *src)
|
|
|
|
{
|
|
|
|
virStorageFileBackendPtr backend;
|
2018-04-25 13:09:24 +00:00
|
|
|
int ret;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
ret = virStorageFileGetBackendForSupportCheck(src, &backend);
|
|
|
|
if (ret < 0)
|
|
|
|
return -1;
|
|
|
|
if (backend == NULL)
|
|
|
|
return 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
2018-04-25 13:09:24 +00:00
|
|
|
return backend->storageFileAccess ? 1 : 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virStorageFileDeinit(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (src->drv->backend &&
|
|
|
|
src->drv->backend->backendDeinit)
|
|
|
|
src->drv->backend->backendDeinit(src);
|
|
|
|
|
|
|
|
VIR_FREE(src->drv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileInitAs:
|
|
|
|
*
|
|
|
|
* @src: storage source definition
|
|
|
|
* @uid: uid used to access the file, or -1 for current uid
|
|
|
|
* @gid: gid used to access the file, or -1 for current gid
|
|
|
|
*
|
|
|
|
* Initialize a storage source to be used with storage driver. Use the provided
|
|
|
|
* uid and gid if possible for the operations.
|
|
|
|
*
|
|
|
|
* Returns 0 if the storage file was successfully initialized, -1 if the
|
|
|
|
* initialization failed. Libvirt error is reported.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileInitAs(virStorageSourcePtr src,
|
|
|
|
uid_t uid, gid_t gid)
|
|
|
|
{
|
|
|
|
int actualType = virStorageSourceGetActualType(src);
|
|
|
|
if (VIR_ALLOC(src->drv) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (uid == (uid_t) -1)
|
|
|
|
src->drv->uid = geteuid();
|
|
|
|
else
|
|
|
|
src->drv->uid = uid;
|
|
|
|
|
|
|
|
if (gid == (gid_t) -1)
|
|
|
|
src->drv->gid = getegid();
|
|
|
|
else
|
|
|
|
src->drv->gid = gid;
|
|
|
|
|
2018-04-25 13:37:07 +00:00
|
|
|
if (virStorageFileBackendForType(actualType,
|
|
|
|
src->protocol,
|
|
|
|
true,
|
|
|
|
&src->drv->backend) < 0)
|
2018-01-25 09:35:46 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (src->drv->backend->backendInit &&
|
|
|
|
src->drv->backend->backendInit(src) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(src->drv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileInit:
|
|
|
|
*
|
|
|
|
* See virStorageFileInitAs. The file is initialized to be accessed by the
|
|
|
|
* current user.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileInit(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
return virStorageFileInitAs(src, -1, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileCreate: Creates an empty storage file via storage driver
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -2 if the function isn't supported by the backend,
|
|
|
|
* -1 on other failure. Errno is set in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileCreate(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileCreate) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = src->drv->backend->storageFileCreate(src);
|
|
|
|
|
|
|
|
VIR_DEBUG("created storage file %p: ret=%d, errno=%d",
|
|
|
|
src, ret, errno);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileUnlink: Unlink storage file via storage driver
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
*
|
|
|
|
* Unlinks the file described by the @file structure.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -2 if the function isn't supported by the backend,
|
|
|
|
* -1 on other failure. Errno is set in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileUnlink(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileUnlink) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = src->drv->backend->storageFileUnlink(src);
|
|
|
|
|
|
|
|
VIR_DEBUG("unlinked storage file %p: ret=%d, errno=%d",
|
|
|
|
src, ret, errno);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileStat: returns stat struct of a file via storage driver
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
* @stat: stat structure to return data
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -2 if the function isn't supported by the backend,
|
|
|
|
* -1 on other failure. Errno is set in case of failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileStat(virStorageSourcePtr src,
|
|
|
|
struct stat *st)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileStat) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = src->drv->backend->storageFileStat(src, st);
|
|
|
|
|
|
|
|
VIR_DEBUG("stat of storage file %p: ret=%d, errno=%d",
|
|
|
|
src, ret, errno);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileRead: read bytes from a file into a buffer
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
* @offset: number of bytes to skip in the storage file
|
|
|
|
* @len: maximum number of bytes read from the storage file
|
|
|
|
* @buf: buffer to read the data into. (buffer shall be freed by caller)
|
|
|
|
*
|
|
|
|
* Returns the count of bytes read on success and -1 on failure, -2 if the
|
|
|
|
* function isn't supported by the backend.
|
|
|
|
* Libvirt error is reported on failure.
|
|
|
|
*/
|
|
|
|
ssize_t
|
|
|
|
virStorageFileRead(virStorageSourcePtr src,
|
|
|
|
size_t offset,
|
|
|
|
size_t len,
|
|
|
|
char **buf)
|
|
|
|
{
|
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
if (!virStorageFileIsInitialized(src)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("storage file backend not initialized"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-04-25 11:50:27 +00:00
|
|
|
if (!src->drv->backend->storageFileRead)
|
2018-01-25 09:35:46 +00:00
|
|
|
return -2;
|
|
|
|
|
|
|
|
ret = src->drv->backend->storageFileRead(src, offset, len, buf);
|
|
|
|
|
|
|
|
VIR_DEBUG("read '%zd' bytes from storage '%p' starting at offset '%zu'",
|
|
|
|
ret, src, offset);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virStorageFileGetUniqueIdentifier: Get a unique string describing the volume
|
|
|
|
*
|
|
|
|
* @src: file structure pointing to the file
|
|
|
|
*
|
|
|
|
* Returns a string uniquely describing a single volume (canonical path).
|
|
|
|
* The string shall not be freed and is valid until the storage file is
|
|
|
|
* deinitialized. Returns NULL on error and sets a libvirt error code */
|
|
|
|
const char *
|
|
|
|
virStorageFileGetUniqueIdentifier(virStorageSourcePtr src)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("storage file backend not initialized"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!src->drv->backend->storageFileGetUniqueIdentifier) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unique storage file identifier not implemented for "
|
|
|
|
"storage type %s (protocol: %s)'"),
|
|
|
|
virStorageTypeToString(src->type),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return src->drv->backend->storageFileGetUniqueIdentifier(src);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileAccess: Check accessibility of a storage file
|
|
|
|
*
|
|
|
|
* @src: storage file to check access permissions
|
|
|
|
* @mode: accessibility check options (see man 2 access)
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and sets errno. No libvirt
|
|
|
|
* error is reported. Returns -2 if the operation isn't supported
|
|
|
|
* by libvirt storage backend.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileAccess(virStorageSourcePtr src,
|
|
|
|
int mode)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileAccess) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return src->drv->backend->storageFileAccess(src, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileChown: Change owner of a storage file
|
|
|
|
*
|
|
|
|
* @src: storage file to change owner of
|
|
|
|
* @uid: new owner id
|
|
|
|
* @gid: new group id
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error and sets errno. No libvirt
|
|
|
|
* error is reported. Returns -2 if the operation isn't supported
|
|
|
|
* by libvirt storage backend.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileChown(const virStorageSource *src,
|
|
|
|
uid_t uid,
|
|
|
|
gid_t gid)
|
|
|
|
{
|
|
|
|
if (!virStorageFileIsInitialized(src) ||
|
|
|
|
!src->drv->backend->storageFileChown) {
|
|
|
|
errno = ENOSYS;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("chown of storage file %p to %u:%u",
|
|
|
|
src, (unsigned int)uid, (unsigned int)gid);
|
|
|
|
|
|
|
|
return src->drv->backend->storageFileChown(src, uid, gid);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileReportBrokenChain:
|
|
|
|
*
|
|
|
|
* @errcode: errno when accessing @src
|
|
|
|
* @src: inaccessible file in the backing chain of @parent
|
|
|
|
* @parent: root virStorageSource being checked
|
|
|
|
*
|
|
|
|
* Reports the correct error message if @src is missing in the backing chain
|
|
|
|
* for @parent.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virStorageFileReportBrokenChain(int errcode,
|
|
|
|
virStorageSourcePtr src,
|
|
|
|
virStorageSourcePtr parent)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (src->drv) {
|
|
|
|
unsigned int access_user = src->drv->uid;
|
|
|
|
unsigned int access_group = src->drv->gid;
|
|
|
|
|
|
|
|
if (src == parent) {
|
|
|
|
virReportSystemError(errcode,
|
|
|
|
_("Cannot access storage file '%s' "
|
|
|
|
"(as uid:%u, gid:%u)"),
|
|
|
|
src->path, access_user, access_group);
|
|
|
|
} else {
|
|
|
|
virReportSystemError(errcode,
|
|
|
|
_("Cannot access backing file '%s' "
|
|
|
|
"of storage file '%s' (as uid:%u, gid:%u)"),
|
|
|
|
src->path, parent->path, access_user, access_group);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (src == parent) {
|
|
|
|
virReportSystemError(errcode,
|
|
|
|
_("Cannot access storage file '%s'"),
|
|
|
|
src->path);
|
|
|
|
} else {
|
|
|
|
virReportSystemError(errcode,
|
|
|
|
_("Cannot access backing file '%s' "
|
|
|
|
"of storage file '%s'"),
|
|
|
|
src->path, parent->path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Recursive workhorse for virStorageFileGetMetadata. */
|
|
|
|
static int
|
|
|
|
virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
|
|
|
|
virStorageSourcePtr parent,
|
|
|
|
uid_t uid, gid_t gid,
|
|
|
|
bool allow_probe,
|
|
|
|
bool report_broken,
|
|
|
|
virHashTablePtr cycle,
|
|
|
|
unsigned int depth)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
const char *uniqueName;
|
|
|
|
char *buf = NULL;
|
|
|
|
ssize_t headerLen;
|
|
|
|
virStorageSourcePtr backingStore = NULL;
|
|
|
|
int backingFormat;
|
2018-04-25 13:09:24 +00:00
|
|
|
int rv;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("path=%s format=%d uid=%u gid=%u probe=%d",
|
|
|
|
src->path, src->format,
|
|
|
|
(unsigned int)uid, (unsigned int)gid, allow_probe);
|
|
|
|
|
|
|
|
/* exit if we can't load information about the current image */
|
2018-04-25 13:09:24 +00:00
|
|
|
rv = virStorageFileSupportsBackingChainTraversal(src);
|
|
|
|
if (rv <= 0)
|
|
|
|
return rv;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
if (virStorageFileInitAs(src, uid, gid) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (virStorageFileAccess(src, F_OK) < 0) {
|
|
|
|
virStorageFileReportBrokenChain(errno, src, parent);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(uniqueName = virStorageFileGetUniqueIdentifier(src)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virHashLookup(cycle, uniqueName)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("backing store for %s (%s) is self-referential"),
|
|
|
|
src->path, uniqueName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virHashAddEntry(cycle, uniqueName, (void *)1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((headerLen = virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER,
|
2018-04-25 11:50:27 +00:00
|
|
|
&buf)) < 0) {
|
|
|
|
if (headerLen == -2)
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("storage file reading is not supported for "
|
|
|
|
"storage type %s (protocol: %s)"),
|
|
|
|
virStorageTypeToString(src->type),
|
|
|
|
virStorageNetProtocolTypeToString(src->protocol));
|
2018-01-25 09:35:46 +00:00
|
|
|
goto cleanup;
|
2018-04-25 11:50:27 +00:00
|
|
|
}
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
if (virStorageFileGetMetadataInternal(src, buf, headerLen,
|
|
|
|
&backingFormat) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (src->backingStoreRaw) {
|
|
|
|
if (!(backingStore = virStorageSourceNewFromBacking(src)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (backingFormat == VIR_STORAGE_FILE_AUTO && !allow_probe)
|
|
|
|
backingStore->format = VIR_STORAGE_FILE_RAW;
|
|
|
|
else if (backingFormat == VIR_STORAGE_FILE_AUTO_SAFE)
|
|
|
|
backingStore->format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
else
|
|
|
|
backingStore->format = backingFormat;
|
|
|
|
|
|
|
|
if ((ret = virStorageFileGetMetadataRecurse(backingStore, parent,
|
|
|
|
uid, gid,
|
|
|
|
allow_probe, report_broken,
|
|
|
|
cycle, depth + 1)) < 0) {
|
|
|
|
if (report_broken)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* if we fail somewhere midway, just accept and return a
|
|
|
|
* broken chain */
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* add terminator */
|
|
|
|
if (VIR_ALLOC(backingStore) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
src->backingStore = backingStore;
|
|
|
|
backingStore = NULL;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (virStorageSourceHasBacking(src))
|
|
|
|
src->backingStore->id = depth;
|
|
|
|
VIR_FREE(buf);
|
|
|
|
virStorageFileDeinit(src);
|
|
|
|
virStorageSourceFree(backingStore);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileGetMetadata:
|
|
|
|
*
|
|
|
|
* Extract metadata about the storage volume with the specified
|
|
|
|
* image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
|
|
|
* will probe to automatically identify the format. Recurses through
|
|
|
|
* the entire chain.
|
|
|
|
*
|
|
|
|
* Open files using UID and GID (or pass -1 for the current user/group).
|
|
|
|
* Treat any backing files without explicit type as raw, unless ALLOW_PROBE.
|
|
|
|
*
|
|
|
|
* Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
|
|
|
* format, since a malicious guest can turn a raw file into any
|
|
|
|
* other non-raw format at will.
|
|
|
|
*
|
|
|
|
* If @report_broken is true, the whole function fails with a possibly sane
|
|
|
|
* error instead of just returning a broken chain.
|
|
|
|
*
|
|
|
|
* Caller MUST free result after use via virStorageSourceFree.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virStorageFileGetMetadata(virStorageSourcePtr src,
|
|
|
|
uid_t uid, gid_t gid,
|
|
|
|
bool allow_probe,
|
|
|
|
bool report_broken)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("path=%s format=%d uid=%u gid=%u probe=%d, report_broken=%d",
|
|
|
|
src->path, src->format, (unsigned int)uid, (unsigned int)gid,
|
|
|
|
allow_probe, report_broken);
|
|
|
|
|
|
|
|
virHashTablePtr cycle = NULL;
|
|
|
|
virStorageType actualType = virStorageSourceGetActualType(src);
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(cycle = virHashCreate(5, NULL)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (src->format <= VIR_STORAGE_FILE_NONE) {
|
|
|
|
if (actualType == VIR_STORAGE_TYPE_DIR)
|
|
|
|
src->format = VIR_STORAGE_FILE_DIR;
|
|
|
|
else if (allow_probe)
|
|
|
|
src->format = VIR_STORAGE_FILE_AUTO;
|
|
|
|
else
|
|
|
|
src->format = VIR_STORAGE_FILE_RAW;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virStorageFileGetMetadataRecurse(src, src, uid, gid,
|
|
|
|
allow_probe, report_broken, cycle, 1);
|
|
|
|
|
|
|
|
virHashFree(cycle);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virStorageFileGetBackingStoreStr:
|
|
|
|
* @src: storage object
|
|
|
|
*
|
|
|
|
* Extracts the backing store string as stored in the storage volume described
|
|
|
|
* by @src and returns it to the user. Caller is responsible for freeing it.
|
|
|
|
* In case when the string can't be retrieved or does not exist NULL is
|
|
|
|
* returned.
|
|
|
|
*/
|
2018-04-25 11:50:27 +00:00
|
|
|
int
|
|
|
|
virStorageFileGetBackingStoreStr(virStorageSourcePtr src,
|
|
|
|
char **backing)
|
2018-01-25 09:35:46 +00:00
|
|
|
{
|
|
|
|
virStorageSourcePtr tmp = NULL;
|
|
|
|
char *buf = NULL;
|
|
|
|
ssize_t headerLen;
|
2018-04-25 11:50:27 +00:00
|
|
|
int ret = -1;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
*backing = NULL;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
/* exit if we can't load information about the current image */
|
|
|
|
if (!virStorageFileSupportsBackingChainTraversal(src))
|
2018-04-25 11:50:27 +00:00
|
|
|
return 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
2018-04-25 11:50:27 +00:00
|
|
|
rv = virStorageFileAccess(src, F_OK);
|
|
|
|
if (rv == -2)
|
|
|
|
return 0;
|
|
|
|
if (rv < 0) {
|
|
|
|
virStorageFileReportBrokenChain(errno, src, src);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
if ((headerLen = virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER,
|
2018-04-25 11:50:27 +00:00
|
|
|
&buf)) < 0) {
|
|
|
|
if (headerLen == -2)
|
|
|
|
return 0;
|
|
|
|
return -1;
|
|
|
|
}
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
if (!(tmp = virStorageSourceCopy(src, false)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virStorageFileGetMetadataInternal(tmp, buf, headerLen, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-04-25 11:50:27 +00:00
|
|
|
VIR_STEAL_PTR(*backing, tmp->backingStoreRaw);
|
|
|
|
|
|
|
|
ret = 0;
|
2018-01-25 09:35:46 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(buf);
|
|
|
|
virStorageSourceFree(tmp);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|