2014-10-24 01:46:38 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Taowei Luo (uaedante@gmail.com)
|
|
|
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2008-2009 Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "datatypes.h"
|
|
|
|
#include "domain_conf.h"
|
|
|
|
#include "domain_event.h"
|
|
|
|
#include "virlog.h"
|
|
|
|
#include "virstring.h"
|
2014-10-24 01:46:46 +00:00
|
|
|
#include "storage_conf.h"
|
2020-02-16 21:59:28 +00:00
|
|
|
#include "virutil.h"
|
2014-10-24 01:46:38 +00:00
|
|
|
|
|
|
|
#include "vbox_common.h"
|
|
|
|
#include "vbox_uniformed_api.h"
|
2014-10-24 01:46:52 +00:00
|
|
|
#include "vbox_get_driver.h"
|
2014-10-24 01:46:38 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_VBOX
|
|
|
|
|
|
|
|
VIR_LOG_INIT("vbox.vbox_storage");
|
|
|
|
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
static vboxUniformedAPI gVBoxAPI;
|
|
|
|
|
2014-10-24 01:46:38 +00:00
|
|
|
/**
|
|
|
|
* The Storage Functions here on
|
|
|
|
*/
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int vboxConnectNumOfStoragePools(virConnectPtr conn G_GNUC_UNUSED)
|
2014-10-24 01:46:38 +00:00
|
|
|
{
|
|
|
|
/** Currently only one pool supported, the default one
|
|
|
|
* given by ISystemProperties::defaultHardDiskFolder()
|
|
|
|
*/
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-10-14 12:45:33 +00:00
|
|
|
static int vboxConnectListStoragePools(virConnectPtr conn G_GNUC_UNUSED,
|
2014-10-24 01:46:52 +00:00
|
|
|
char **const names, int nnames)
|
2014-10-24 01:46:38 +00:00
|
|
|
{
|
|
|
|
int numActive = 0;
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
if (nnames > 0) {
|
|
|
|
names[numActive] = g_strdup("default-pool");
|
2014-10-24 01:46:38 +00:00
|
|
|
numActive++;
|
2019-10-20 11:49:46 +00:00
|
|
|
}
|
2014-10-24 01:46:38 +00:00
|
|
|
return numActive;
|
|
|
|
}
|
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static virStoragePoolPtr
|
|
|
|
vboxStoragePoolLookupByName(virConnectPtr conn, const char *name)
|
2014-10-24 01:46:38 +00:00
|
|
|
{
|
|
|
|
virStoragePoolPtr ret = NULL;
|
|
|
|
|
|
|
|
/** Current limitation of the function: since
|
|
|
|
* the default pool doesn't have UUID just assign
|
|
|
|
* one till vbox can handle pools
|
|
|
|
*/
|
|
|
|
if (STREQ("default-pool", name)) {
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
const char *uuidstr = "1deff1ff-1481-464f-967f-a50fe8936cc4";
|
|
|
|
|
|
|
|
ignore_value(virUUIDParse(uuidstr, uuid));
|
|
|
|
|
|
|
|
ret = virGetStoragePool(conn, name, uuid, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static int vboxStoragePoolNumOfVolumes(virStoragePoolPtr pool)
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = pool->conn->privateData;
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
|
|
|
|
PRUint32 hardDiskAccessible = 0;
|
|
|
|
nsresult rc;
|
|
|
|
size_t i;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2019-10-17 08:10:10 +00:00
|
|
|
return -1;
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
|
|
|
|
rc = gVBoxAPI.UArray.vboxArrayGet(&hardDisks, data->vboxObj,
|
|
|
|
gVBoxAPI.UArray.handleGetHardDisks(data->vboxObj));
|
|
|
|
if (NS_FAILED(rc)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("could not get number of volumes in the pool: %s, rc=%08x"),
|
|
|
|
pool->name, (unsigned)rc);
|
2019-10-17 08:10:10 +00:00
|
|
|
return -1;
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < hardDisks.count; ++i) {
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = hardDisks.items[i];
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
PRUint32 hddstate;
|
|
|
|
|
|
|
|
if (!hardDisk)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate != MediaState_Inaccessible)
|
|
|
|
hardDiskAccessible++;
|
|
|
|
}
|
|
|
|
|
|
|
|
gVBoxAPI.UArray.vboxArrayRelease(&hardDisks);
|
|
|
|
|
2019-10-17 08:10:10 +00:00
|
|
|
return hardDiskAccessible;
|
vbox: Rewrite vboxStoragePoolNumOfVolumes
We use typedef IMedium IHardDisk to make IHardDisk hierachy from
IMedium (Actually it did on vbox 2.2 and 3.0's C++ API).
So when calling
VBOX_MEDIUM_FUNC_ARG*(IHardDisk, func, args)
we can directly replace it to
gVBoxAPI.UIMedium.func(IHardDisk, args)
When dealing with this two types, we get some rules from it's
hierachy relationship.
When using IHardDisk and IMedium as input, we can't transfer a
IMedium to IHardDisk. Like:
gVBoxAPI.UIHardDisk.func(IHardDisk *hardDisk, args)
Here, we can't put a *IMedium as a argument.
When using IHardDisk and IMedium as output, we can't transfer a
IHardDisk to IMedium. Like:
gVBoxAPI.UIMachine.GetMedium(IMedium **out)
Here, we can't put a **IHardDisk as a argument. If this case
do happen, we either change the API to GetHardDisk or write a
new one.
2014-10-24 01:46:39 +00:00
|
|
|
}
|
2014-10-24 01:46:40 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static int
|
|
|
|
vboxStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int nnames)
|
2014-10-24 01:46:40 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = pool->conn->privateData;
|
2014-10-24 01:46:40 +00:00
|
|
|
vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
|
|
|
|
PRUint32 numActive = 0;
|
|
|
|
nsresult rc;
|
|
|
|
size_t i;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2019-10-17 08:10:10 +00:00
|
|
|
return -1;
|
2014-10-24 01:46:40 +00:00
|
|
|
|
|
|
|
rc = gVBoxAPI.UArray.vboxArrayGet(&hardDisks, data->vboxObj,
|
|
|
|
gVBoxAPI.UArray.handleGetHardDisks(data->vboxObj));
|
|
|
|
if (NS_FAILED(rc)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("could not get the volume list in the pool: %s, rc=%08x"),
|
|
|
|
pool->name, (unsigned)rc);
|
2019-10-17 08:10:10 +00:00
|
|
|
return -1;
|
2014-10-24 01:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < hardDisks.count && numActive < nnames; ++i) {
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = hardDisks.items[i];
|
2014-10-24 01:46:40 +00:00
|
|
|
PRUint32 hddstate;
|
|
|
|
char *nameUtf8 = NULL;
|
|
|
|
PRUnichar *nameUtf16 = NULL;
|
|
|
|
|
|
|
|
if (!hardDisk)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetName(hardDisk, &nameUtf16);
|
|
|
|
|
|
|
|
VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
|
|
|
|
VBOX_UTF16_FREE(nameUtf16);
|
|
|
|
|
|
|
|
if (!nameUtf8)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VIR_DEBUG("nnames[%d]: %s", numActive, nameUtf8);
|
2019-10-20 11:49:46 +00:00
|
|
|
names[numActive] = g_strdup(nameUtf8);
|
|
|
|
numActive++;
|
2014-10-24 01:46:40 +00:00
|
|
|
|
|
|
|
VBOX_UTF8_FREE(nameUtf8);
|
|
|
|
}
|
|
|
|
|
|
|
|
gVBoxAPI.UArray.vboxArrayRelease(&hardDisks);
|
2019-10-17 08:10:10 +00:00
|
|
|
return numActive;
|
2014-10-24 01:46:40 +00:00
|
|
|
}
|
2014-10-24 01:46:41 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static virStorageVolPtr
|
|
|
|
vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
|
2014-10-24 01:46:41 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = pool->conn->privateData;
|
2014-10-24 01:46:41 +00:00
|
|
|
vboxArray hardDisks = VBOX_ARRAY_INITIALIZER;
|
|
|
|
nsresult rc;
|
|
|
|
size_t i;
|
|
|
|
virStorageVolPtr ret = NULL;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:41 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
rc = gVBoxAPI.UArray.vboxArrayGet(&hardDisks, data->vboxObj,
|
|
|
|
gVBoxAPI.UArray.handleGetHardDisks(data->vboxObj));
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
for (i = 0; i < hardDisks.count; ++i) {
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = hardDisks.items[i];
|
2014-10-24 01:46:41 +00:00
|
|
|
PRUint32 hddstate;
|
|
|
|
char *nameUtf8 = NULL;
|
|
|
|
PRUnichar *nameUtf16 = NULL;
|
|
|
|
|
|
|
|
if (!hardDisk)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetName(hardDisk, &nameUtf16);
|
|
|
|
|
|
|
|
if (nameUtf16) {
|
|
|
|
VBOX_UTF16_TO_UTF8(nameUtf16, &nameUtf8);
|
|
|
|
VBOX_UTF16_FREE(nameUtf16);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nameUtf8 && STREQ(nameUtf8, name)) {
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:41 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
char key[VIR_UUID_STRING_BUFLEN] = "";
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
|
|
|
|
if (NS_SUCCEEDED(rc)) {
|
|
|
|
vboxIIDToUUID(&hddIID, uuid);
|
|
|
|
virUUIDFormat(uuid, key);
|
|
|
|
|
|
|
|
ret = virGetStorageVol(pool->conn, pool->name, name, key,
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
VIR_DEBUG("virStorageVolPtr: %p", ret);
|
|
|
|
VIR_DEBUG("Storage Volume Name: %s", name);
|
|
|
|
VIR_DEBUG("Storage Volume key : %s", key);
|
|
|
|
VIR_DEBUG("Storage Volume Pool: %s", pool->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
VBOX_UTF8_FREE(nameUtf8);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VBOX_UTF8_FREE(nameUtf8);
|
|
|
|
}
|
|
|
|
|
|
|
|
gVBoxAPI.UArray.vboxArrayRelease(&hardDisks);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:42 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static virStorageVolPtr
|
|
|
|
vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
|
2014-10-24 01:46:42 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = conn->privateData;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:42 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:42 +00:00
|
|
|
PRUnichar *hddNameUtf16 = NULL;
|
|
|
|
char *hddNameUtf8 = NULL;
|
|
|
|
PRUint32 hddstate;
|
|
|
|
nsresult rc;
|
|
|
|
virStorageVolPtr ret = NULL;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:42 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
if (!key)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (virUUIDParse(key, uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Could not parse UUID from '%s'"), key);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vboxIIDFromUUID(&hddIID, uuid);
|
|
|
|
rc = gVBoxAPI.UIVirtualBox.GetHardDiskByIID(data->vboxObj, &hddIID, &hardDisk);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetName(hardDisk, &hddNameUtf16);
|
|
|
|
if (!hddNameUtf16)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
|
|
|
|
if (!hddNameUtf8) {
|
|
|
|
VBOX_UTF16_FREE(hddNameUtf16);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vboxConnectNumOfStoragePools(conn) == 1) {
|
|
|
|
ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
|
|
|
|
NULL, NULL);
|
|
|
|
VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
|
|
|
|
} else {
|
|
|
|
/* TODO: currently only one default pool and thus
|
|
|
|
* nothing here, change it when pools are supported
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Storage Volume Name: %s", key);
|
|
|
|
VIR_DEBUG("Storage Volume key : %s", hddNameUtf8);
|
|
|
|
|
|
|
|
VBOX_UTF8_FREE(hddNameUtf8);
|
|
|
|
VBOX_UTF16_FREE(hddNameUtf16);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VBOX_MEDIUM_RELEASE(hardDisk);
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:44 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static virStorageVolPtr
|
|
|
|
vboxStorageVolLookupByPath(virConnectPtr conn, const char *path)
|
2014-10-24 01:46:44 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = conn->privateData;
|
2014-10-24 01:46:44 +00:00
|
|
|
PRUnichar *hddPathUtf16 = NULL;
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:44 +00:00
|
|
|
PRUnichar *hddNameUtf16 = NULL;
|
|
|
|
char *hddNameUtf8 = NULL;
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
char key[VIR_UUID_STRING_BUFLEN] = "";
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:44 +00:00
|
|
|
PRUint32 hddstate;
|
|
|
|
nsresult rc;
|
|
|
|
virStorageVolPtr ret = NULL;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:44 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
|
|
|
|
if (!path)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
VBOX_UTF8_TO_UTF16(path, &hddPathUtf16);
|
|
|
|
|
|
|
|
if (!hddPathUtf16)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
rc = gVBoxAPI.UIVirtualBox.FindHardDisk(data->vboxObj, hddPathUtf16,
|
|
|
|
DeviceType_HardDisk, AccessMode_ReadWrite, &hardDisk);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetName(hardDisk, &hddNameUtf16);
|
|
|
|
|
|
|
|
if (!hddNameUtf16)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
|
|
|
|
VBOX_UTF16_FREE(hddNameUtf16);
|
|
|
|
|
|
|
|
if (!hddNameUtf8)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
|
|
|
|
if (NS_FAILED(rc)) {
|
|
|
|
VBOX_UTF8_FREE(hddNameUtf8);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
vboxIIDToUUID(&hddIID, uuid);
|
|
|
|
virUUIDFormat(uuid, key);
|
|
|
|
|
|
|
|
/* TODO: currently only one default pool and thus
|
|
|
|
* the check below, change it when pools are supported
|
|
|
|
*/
|
|
|
|
if (vboxConnectNumOfStoragePools(conn) == 1)
|
|
|
|
ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
|
|
|
|
VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8);
|
|
|
|
VIR_DEBUG("Storage Volume key : %s", key);
|
|
|
|
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
VBOX_UTF8_FREE(hddNameUtf8);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VBOX_MEDIUM_RELEASE(hardDisk);
|
|
|
|
VBOX_UTF16_FREE(hddPathUtf16);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:46 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static virStorageVolPtr
|
|
|
|
vboxStorageVolCreateXML(virStoragePoolPtr pool,
|
|
|
|
const char *xml, unsigned int flags)
|
2014-10-24 01:46:46 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = pool->conn->privateData;
|
2014-10-24 01:46:46 +00:00
|
|
|
PRUnichar *hddFormatUtf16 = NULL;
|
|
|
|
PRUnichar *hddNameUtf16 = NULL;
|
|
|
|
virStoragePoolDef poolDef;
|
|
|
|
nsresult rc;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:46 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
char key[VIR_UUID_STRING_BUFLEN] = "";
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:46 +00:00
|
|
|
IProgress *progress = NULL;
|
|
|
|
PRUint64 logicalSize = 0;
|
|
|
|
PRUint32 variant = HardDiskVariant_Standard;
|
|
|
|
resultCodeUnion resultCode;
|
|
|
|
virStorageVolPtr ret = NULL;
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virStorageVolDef) def = NULL;
|
2019-12-19 08:13:00 +00:00
|
|
|
g_autofree char *homedir = NULL;
|
2014-10-24 01:46:46 +00:00
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:46 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
|
|
|
/* since there is currently one default pool now
|
|
|
|
* and virStorageVolDefFormat() just checks it type
|
|
|
|
* so just assign it for now, change the behaviour
|
|
|
|
* when vbox supports pools.
|
|
|
|
*/
|
|
|
|
memset(&poolDef, 0, sizeof(poolDef));
|
|
|
|
poolDef.type = VIR_STORAGE_POOL_DIR;
|
|
|
|
|
2015-02-05 15:20:17 +00:00
|
|
|
if ((def = virStorageVolDefParseString(&poolDef, xml, 0)) == NULL)
|
2014-10-24 01:46:46 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!def->name ||
|
|
|
|
(def->type != VIR_STORAGE_VOL_FILE))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* For now only the vmdk, vpc and vdi type harddisk
|
|
|
|
* variants can be created. For historical reason, we default to vdi */
|
|
|
|
if (def->target.format == VIR_STORAGE_FILE_VMDK) {
|
|
|
|
VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
|
|
|
|
} else if (def->target.format == VIR_STORAGE_FILE_VPC) {
|
|
|
|
VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
|
|
|
|
} else {
|
|
|
|
VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If target.path isn't given, use default path ~/.VirtualBox/image_name */
|
2019-12-19 08:13:00 +00:00
|
|
|
if (!def->target.path) {
|
|
|
|
homedir = virGetUserDirectory();
|
|
|
|
def->target.path = g_strdup_printf("%s/.VirtualBox/%s", homedir, def->name);
|
|
|
|
}
|
2014-10-24 01:46:46 +00:00
|
|
|
VBOX_UTF8_TO_UTF16(def->target.path, &hddNameUtf16);
|
|
|
|
|
|
|
|
if (!hddFormatUtf16 || !hddNameUtf16)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
rc = gVBoxAPI.UIVirtualBox.CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
|
|
|
|
if (NS_FAILED(rc)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not create harddisk, rc=%08x"),
|
|
|
|
(unsigned)rc);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
logicalSize = VIR_DIV_UP(def->target.capacity, 1024 * 1024);
|
|
|
|
|
|
|
|
if (def->target.capacity == def->target.allocation)
|
|
|
|
variant = HardDiskVariant_Fixed;
|
|
|
|
|
2016-12-29 20:34:26 +00:00
|
|
|
rc = gVBoxAPI.UIMedium.CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
|
2014-10-24 01:46:46 +00:00
|
|
|
if (NS_FAILED(rc) || !progress) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not create base storage, rc=%08x"),
|
|
|
|
(unsigned)rc);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
gVBoxAPI.UIProgress.WaitForCompletion(progress, -1);
|
|
|
|
gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode);
|
|
|
|
if (RC_FAILED(resultCode)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not create base storage, rc=%08x"),
|
|
|
|
(unsigned)resultCode.uResultCode);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
rc = gVBoxAPI.UIMedium.GetId(hardDisk, &hddIID);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
vboxIIDToUUID(&hddIID, uuid);
|
|
|
|
virUUIDFormat(uuid, key);
|
|
|
|
|
|
|
|
ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
VBOX_RELEASE(progress);
|
|
|
|
VBOX_UTF16_FREE(hddFormatUtf16);
|
|
|
|
VBOX_UTF16_FREE(hddNameUtf16);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:48 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static int vboxStorageVolDelete(virStorageVolPtr vol, unsigned int flags)
|
2014-10-24 01:46:48 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = vol->conn->privateData;
|
2014-10-24 01:46:48 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:48 +00:00
|
|
|
int deregister = 0;
|
|
|
|
PRUint32 hddstate = 0;
|
|
|
|
size_t i = 0;
|
|
|
|
size_t j = 0;
|
2016-02-09 11:26:26 +00:00
|
|
|
PRUint32 machineIdsSize = 0;
|
2014-10-24 01:46:48 +00:00
|
|
|
vboxArray machineIds = VBOX_ARRAY_INITIALIZER;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:48 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:48 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
|
|
|
if (virUUIDParse(vol->key, uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Could not parse UUID from '%s'"), vol->key);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vboxIIDFromUUID(&hddIID, uuid);
|
2014-10-31 12:08:43 +00:00
|
|
|
if (NS_FAILED(gVBoxAPI.UIVirtualBox.GetHardDiskByIID(data->vboxObj,
|
|
|
|
&hddIID,
|
|
|
|
&hardDisk)))
|
2014-10-24 01:46:48 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UArray.vboxArrayGet(&machineIds, hardDisk,
|
|
|
|
gVBoxAPI.UArray.handleMediumGetMachineIds(hardDisk));
|
|
|
|
|
|
|
|
#if defined WIN32
|
|
|
|
/* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the
|
|
|
|
* machineIds array contains direct instances of the GUID struct
|
|
|
|
* instead of pointers to the actual struct instances. But there
|
|
|
|
* is no 128bit width simple item type for a SafeArray to fit a
|
|
|
|
* GUID in. The largest simple type it 64bit width and VirtualBox
|
|
|
|
* uses two of this 64bit items to represents one GUID. Therefore,
|
|
|
|
* we divide the size of the SafeArray by two, to compensate for
|
|
|
|
* this workaround in VirtualBox */
|
|
|
|
if (gVBoxAPI.uVersion >= 2001052 && gVBoxAPI.uVersion < 2002051)
|
|
|
|
machineIds.count /= 2;
|
|
|
|
#endif /* !defined WIN32 */
|
|
|
|
|
|
|
|
machineIdsSize = machineIds.count;
|
|
|
|
|
|
|
|
for (i = 0; i < machineIds.count; i++) {
|
|
|
|
IMachine *machine = NULL;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID machineId;
|
2014-10-24 01:46:48 +00:00
|
|
|
vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER;
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&machineId);
|
|
|
|
vboxIIDFromArrayItem(&machineId, &machineIds, i);
|
|
|
|
|
2016-12-29 20:34:27 +00:00
|
|
|
if (NS_FAILED(gVBoxAPI.UIVirtualBox.GetMachine(data->vboxObj,
|
|
|
|
&machineId,
|
|
|
|
&machine))) {
|
|
|
|
virReportError(VIR_ERR_NO_DOMAIN, "%s",
|
|
|
|
_("no domain with matching uuid"));
|
|
|
|
break;
|
2014-10-24 01:46:48 +00:00
|
|
|
}
|
|
|
|
|
2014-10-31 12:08:43 +00:00
|
|
|
if (NS_FAILED(gVBoxAPI.UISession.Open(data, &machineId, machine))) {
|
2014-10-24 01:46:48 +00:00
|
|
|
vboxIIDUnalloc(&machineId);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-10-31 12:08:43 +00:00
|
|
|
if (NS_FAILED(gVBoxAPI.UISession.GetMachine(data->vboxSession,
|
|
|
|
&machine)))
|
2014-10-24 01:46:48 +00:00
|
|
|
goto cleanupLoop;
|
|
|
|
|
|
|
|
gVBoxAPI.UArray.vboxArrayGet(&hddAttachments, machine,
|
|
|
|
gVBoxAPI.UArray.handleMachineGetMediumAttachments(machine));
|
|
|
|
|
|
|
|
for (j = 0; j < hddAttachments.count; j++) {
|
|
|
|
IMediumAttachment *hddAttachment = hddAttachments.items[j];
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hdd = NULL;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID iid;
|
2014-10-24 01:46:48 +00:00
|
|
|
|
|
|
|
if (!hddAttachment)
|
|
|
|
continue;
|
|
|
|
|
2014-10-31 12:08:43 +00:00
|
|
|
if (NS_FAILED(gVBoxAPI.UIMediumAttachment.GetMedium(hddAttachment,
|
|
|
|
&hdd)) || !hdd)
|
2014-10-24 01:46:48 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&iid);
|
2014-10-31 12:08:43 +00:00
|
|
|
if (NS_FAILED(gVBoxAPI.UIMedium.GetId(hdd, &iid))) {
|
2014-10-24 01:46:48 +00:00
|
|
|
VBOX_MEDIUM_RELEASE(hdd);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUGIID("HardDisk (to delete) UUID", &hddIID);
|
|
|
|
DEBUGIID("HardDisk (currently processing) UUID", &iid);
|
|
|
|
|
|
|
|
if (vboxIIDIsEqual(&hddIID, &iid)) {
|
|
|
|
PRUnichar *controller = NULL;
|
|
|
|
PRInt32 port = 0;
|
|
|
|
PRInt32 device = 0;
|
|
|
|
|
|
|
|
DEBUGIID("Found HardDisk to delete, UUID", &hddIID);
|
|
|
|
|
|
|
|
gVBoxAPI.UIMediumAttachment.GetController(hddAttachment, &controller);
|
|
|
|
gVBoxAPI.UIMediumAttachment.GetPort(hddAttachment, &port);
|
|
|
|
gVBoxAPI.UIMediumAttachment.GetDevice(hddAttachment, &device);
|
|
|
|
|
2014-10-31 12:08:43 +00:00
|
|
|
if (NS_SUCCEEDED(gVBoxAPI.UIMachine.DetachDevice(machine, controller, port, device))) {
|
|
|
|
ignore_value(gVBoxAPI.UIMachine.SaveSettings(machine));
|
2014-10-24 01:46:48 +00:00
|
|
|
VIR_DEBUG("saving machine settings");
|
|
|
|
deregister++;
|
|
|
|
VIR_DEBUG("deregistering hdd:%d", deregister);
|
|
|
|
}
|
|
|
|
|
|
|
|
VBOX_UTF16_FREE(controller);
|
|
|
|
}
|
|
|
|
vboxIIDUnalloc(&iid);
|
|
|
|
VBOX_MEDIUM_RELEASE(hdd);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanupLoop:
|
|
|
|
gVBoxAPI.UArray.vboxArrayRelease(&hddAttachments);
|
|
|
|
VBOX_RELEASE(machine);
|
|
|
|
gVBoxAPI.UISession.Close(data->vboxSession);
|
|
|
|
vboxIIDUnalloc(&machineId);
|
|
|
|
}
|
|
|
|
|
|
|
|
gVBoxAPI.UArray.vboxArrayUnalloc(&machineIds);
|
|
|
|
|
|
|
|
if (machineIdsSize == 0 || machineIdsSize == deregister) {
|
|
|
|
IProgress *progress = NULL;
|
2016-12-29 20:34:26 +00:00
|
|
|
if (NS_SUCCEEDED(gVBoxAPI.UIMedium.DeleteStorage(hardDisk, &progress)) &&
|
2014-10-31 12:08:43 +00:00
|
|
|
progress) {
|
2014-10-24 01:46:48 +00:00
|
|
|
gVBoxAPI.UIProgress.WaitForCompletion(progress, -1);
|
|
|
|
VBOX_RELEASE(progress);
|
|
|
|
DEBUGIID("HardDisk deleted, UUID", &hddIID);
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VBOX_MEDIUM_RELEASE(hardDisk);
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:49 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static int vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info)
|
2014-10-24 01:46:49 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = vol->conn->privateData;
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:49 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
PRUint32 hddstate;
|
|
|
|
PRUint64 hddLogicalSize = 0;
|
|
|
|
PRUint64 hddActualSize = 0;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:49 +00:00
|
|
|
nsresult rc;
|
|
|
|
int ret = -1;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:49 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (!info)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (virUUIDParse(vol->key, uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Could not parse UUID from '%s'"), vol->key);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
vboxIIDFromUUID(&hddIID, uuid);
|
|
|
|
rc = gVBoxAPI.UIVirtualBox.GetHardDiskByIID(data->vboxObj, &hddIID, &hardDisk);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
info->type = VIR_STORAGE_VOL_FILE;
|
|
|
|
|
2016-12-29 20:34:26 +00:00
|
|
|
gVBoxAPI.UIMedium.GetLogicalSize(hardDisk, &hddLogicalSize);
|
2014-10-24 01:46:49 +00:00
|
|
|
info->capacity = hddLogicalSize;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetSize(hardDisk, &hddActualSize);
|
|
|
|
info->allocation = hddActualSize;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
VIR_DEBUG("Storage Volume Name: %s", vol->name);
|
|
|
|
VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File");
|
|
|
|
VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity);
|
|
|
|
VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VBOX_MEDIUM_RELEASE(hardDisk);
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:50 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
|
2014-10-24 01:46:50 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = vol->conn->privateData;
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:50 +00:00
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
|
|
|
PRUnichar *hddFormatUtf16 = NULL;
|
|
|
|
char *hddFormatUtf8 = NULL;
|
|
|
|
PRUint64 hddLogicalSize = 0;
|
|
|
|
PRUint64 hddActualSize = 0;
|
|
|
|
virStoragePoolDef pool;
|
|
|
|
virStorageVolDef def;
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:50 +00:00
|
|
|
PRUint32 hddstate;
|
|
|
|
nsresult rc;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:50 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
virCheckFlags(0, NULL);
|
|
|
|
|
|
|
|
memset(&pool, 0, sizeof(pool));
|
|
|
|
memset(&def, 0, sizeof(def));
|
|
|
|
|
|
|
|
if (virUUIDParse(vol->key, uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Could not parse UUID from '%s'"), vol->key);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
vboxIIDFromUUID(&hddIID, uuid);
|
|
|
|
rc = gVBoxAPI.UIVirtualBox.GetHardDiskByIID(data->vboxObj, &hddIID, &hardDisk);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* since there is currently one default pool now
|
|
|
|
* and virStorageVolDefFormat() just checks it type
|
|
|
|
* so just assign it for now, change the behaviour
|
|
|
|
* when vbox supports pools.
|
|
|
|
*/
|
|
|
|
pool.type = VIR_STORAGE_POOL_DIR;
|
|
|
|
def.type = VIR_STORAGE_VOL_FILE;
|
|
|
|
|
2016-12-29 20:34:26 +00:00
|
|
|
rc = gVBoxAPI.UIMedium.GetLogicalSize(hardDisk, &hddLogicalSize);
|
2014-10-24 01:46:50 +00:00
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
def.target.capacity = hddLogicalSize;
|
|
|
|
|
|
|
|
rc = gVBoxAPI.UIMedium.GetSize(hardDisk, &hddActualSize);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
def.name = g_strdup(vol->name);
|
2014-10-24 01:46:50 +00:00
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
def.key = g_strdup(vol->key);
|
2014-10-24 01:46:50 +00:00
|
|
|
|
2016-12-29 20:34:26 +00:00
|
|
|
rc = gVBoxAPI.UIMedium.GetFormat(hardDisk, &hddFormatUtf16);
|
2014-10-24 01:46:50 +00:00
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8);
|
|
|
|
if (!hddFormatUtf8)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8);
|
|
|
|
|
|
|
|
if (STRCASEEQ("vmdk", hddFormatUtf8))
|
|
|
|
def.target.format = VIR_STORAGE_FILE_VMDK;
|
|
|
|
else if (STRCASEEQ("vhd", hddFormatUtf8))
|
|
|
|
def.target.format = VIR_STORAGE_FILE_VPC;
|
|
|
|
else if (STRCASEEQ("vdi", hddFormatUtf8))
|
|
|
|
def.target.format = VIR_STORAGE_FILE_VDI;
|
|
|
|
else
|
|
|
|
def.target.format = VIR_STORAGE_FILE_RAW;
|
|
|
|
ret = virStorageVolDefFormat(&pool, &def);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VBOX_UTF16_FREE(hddFormatUtf16);
|
|
|
|
VBOX_UTF8_FREE(hddFormatUtf8);
|
|
|
|
VBOX_MEDIUM_RELEASE(hardDisk);
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:51 +00:00
|
|
|
|
2014-10-24 01:46:52 +00:00
|
|
|
static char *vboxStorageVolGetPath(virStorageVolPtr vol)
|
2014-10-24 01:46:51 +00:00
|
|
|
{
|
2016-11-23 19:01:11 +00:00
|
|
|
vboxDriverPtr data = vol->conn->privateData;
|
2016-12-29 20:34:26 +00:00
|
|
|
IMedium *hardDisk = NULL;
|
2014-10-24 01:46:51 +00:00
|
|
|
PRUnichar *hddLocationUtf16 = NULL;
|
|
|
|
char *hddLocationUtf8 = NULL;
|
|
|
|
unsigned char uuid[VIR_UUID_BUFLEN];
|
2016-12-29 20:34:32 +00:00
|
|
|
vboxIID hddIID;
|
2014-10-24 01:46:51 +00:00
|
|
|
PRUint32 hddstate;
|
|
|
|
nsresult rc;
|
|
|
|
char *ret = NULL;
|
|
|
|
|
2014-11-13 14:21:37 +00:00
|
|
|
if (!data->vboxObj)
|
2014-10-24 01:46:51 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (virUUIDParse(vol->key, uuid) < 0) {
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("Could not parse UUID from '%s'"), vol->key);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
VBOX_IID_INITIALIZE(&hddIID);
|
|
|
|
vboxIIDFromUUID(&hddIID, uuid);
|
|
|
|
rc = gVBoxAPI.UIVirtualBox.GetHardDiskByIID(data->vboxObj, &hddIID, &hardDisk);
|
|
|
|
if (NS_FAILED(rc))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetState(hardDisk, &hddstate);
|
|
|
|
if (hddstate == MediaState_Inaccessible)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
gVBoxAPI.UIMedium.GetLocation(hardDisk, &hddLocationUtf16);
|
|
|
|
if (!hddLocationUtf16)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8);
|
|
|
|
if (!hddLocationUtf8)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-18 11:27:03 +00:00
|
|
|
ret = g_strdup(hddLocationUtf8);
|
2014-10-24 01:46:51 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("Storage Volume Name: %s", vol->name);
|
|
|
|
VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8);
|
|
|
|
VIR_DEBUG("Storage Volume Pool: %s", vol->pool);
|
|
|
|
|
|
|
|
VBOX_UTF8_FREE(hddLocationUtf8);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VBOX_UTF16_FREE(hddLocationUtf16);
|
|
|
|
VBOX_MEDIUM_RELEASE(hardDisk);
|
|
|
|
vboxIIDUnalloc(&hddIID);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-10-24 01:46:52 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Function Tables
|
|
|
|
*/
|
|
|
|
|
|
|
|
virStorageDriver vboxStorageDriver = {
|
|
|
|
.connectNumOfStoragePools = vboxConnectNumOfStoragePools, /* 0.7.1 */
|
|
|
|
.connectListStoragePools = vboxConnectListStoragePools, /* 0.7.1 */
|
|
|
|
.storagePoolLookupByName = vboxStoragePoolLookupByName, /* 0.7.1 */
|
|
|
|
.storagePoolNumOfVolumes = vboxStoragePoolNumOfVolumes, /* 0.7.1 */
|
|
|
|
.storagePoolListVolumes = vboxStoragePoolListVolumes, /* 0.7.1 */
|
|
|
|
|
|
|
|
.storageVolLookupByName = vboxStorageVolLookupByName, /* 0.7.1 */
|
|
|
|
.storageVolLookupByKey = vboxStorageVolLookupByKey, /* 0.7.1 */
|
|
|
|
.storageVolLookupByPath = vboxStorageVolLookupByPath, /* 0.7.1 */
|
|
|
|
.storageVolCreateXML = vboxStorageVolCreateXML, /* 0.7.1 */
|
|
|
|
.storageVolDelete = vboxStorageVolDelete, /* 0.7.1 */
|
|
|
|
.storageVolGetInfo = vboxStorageVolGetInfo, /* 0.7.1 */
|
|
|
|
.storageVolGetXMLDesc = vboxStorageVolGetXMLDesc, /* 0.7.1 */
|
|
|
|
.storageVolGetPath = vboxStorageVolGetPath /* 0.7.1 */
|
|
|
|
};
|
|
|
|
|
|
|
|
virStorageDriverPtr vboxGetStorageDriver(uint32_t uVersion)
|
|
|
|
{
|
|
|
|
/* Install gVBoxAPI according to the vbox API version.
|
|
|
|
* Return -1 for unsupported version.
|
|
|
|
*/
|
2020-04-17 11:03:50 +00:00
|
|
|
if (uVersion >= 5001051 && uVersion < 5002051) {
|
2017-11-07 22:36:34 +00:00
|
|
|
vbox52InstallUniformedAPI(&gVBoxAPI);
|
2020-04-17 10:57:54 +00:00
|
|
|
} else if (uVersion >= 6000000 && uVersion < 6000051) {
|
|
|
|
vbox60InstallUniformedAPI(&gVBoxAPI);
|
2014-10-24 01:46:52 +00:00
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return &vboxStorageDriver;
|
|
|
|
}
|