mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 09:53:10 +00:00
conf: Introduce storage_adapter_conf
Move code from storage_conf into storage_adapter_conf Pure code motion Signed-off-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
2dd9b94531
commit
f632e017c0
@ -40,6 +40,7 @@ src/conf/nwfilter_params.c
|
|||||||
src/conf/object_event.c
|
src/conf/object_event.c
|
||||||
src/conf/secret_conf.c
|
src/conf/secret_conf.c
|
||||||
src/conf/snapshot_conf.c
|
src/conf/snapshot_conf.c
|
||||||
|
src/conf/storage_adapter_conf.c
|
||||||
src/conf/storage_conf.c
|
src/conf/storage_conf.c
|
||||||
src/conf/virchrdev.c
|
src/conf/virchrdev.c
|
||||||
src/conf/virdomainobjlist.c
|
src/conf/virdomainobjlist.c
|
||||||
|
@ -379,6 +379,7 @@ NWFILTER_CONF_SOURCES = \
|
|||||||
|
|
||||||
# Storage driver generic impl APIs
|
# Storage driver generic impl APIs
|
||||||
STORAGE_CONF_SOURCES = \
|
STORAGE_CONF_SOURCES = \
|
||||||
|
conf/storage_adapter_conf.h conf/storage_adapter_conf.c \
|
||||||
conf/storage_conf.h conf/storage_conf.c
|
conf/storage_conf.h conf/storage_conf.c
|
||||||
|
|
||||||
# Interface driver generic impl APIs
|
# Interface driver generic impl APIs
|
||||||
|
298
src/conf/storage_adapter_conf.c
Normal file
298
src/conf/storage_adapter_conf.c
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* storage_adapter_conf.c: helpers to handle storage pool adapter manipulation
|
||||||
|
* (derived from storage_conf.c)
|
||||||
|
*
|
||||||
|
* 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 "storage_adapter_conf.h"
|
||||||
|
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
#include "virutil.h"
|
||||||
|
#include "virxml.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
||||||
|
|
||||||
|
VIR_LOG_INIT("conf.storage_adapter_conf");
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(virStoragePoolSourceAdapter,
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_LAST,
|
||||||
|
"default", "scsi_host", "fc_host")
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virStoragePoolSourceAdapterClear(virStoragePoolSourceAdapterPtr adapter)
|
||||||
|
{
|
||||||
|
if (adapter->type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
||||||
|
VIR_FREE(adapter->data.fchost.wwnn);
|
||||||
|
VIR_FREE(adapter->data.fchost.wwpn);
|
||||||
|
VIR_FREE(adapter->data.fchost.parent);
|
||||||
|
VIR_FREE(adapter->data.fchost.parent_wwnn);
|
||||||
|
VIR_FREE(adapter->data.fchost.parent_wwpn);
|
||||||
|
VIR_FREE(adapter->data.fchost.parent_fabric_wwn);
|
||||||
|
} else if (adapter->type ==
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
||||||
|
VIR_FREE(adapter->data.scsi_host.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virStoragePoolDefParseSourceAdapter(virStoragePoolSourcePtr source,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlXPathContextPtr ctxt)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
xmlNodePtr relnode = ctxt->node;
|
||||||
|
char *adapter_type = NULL;
|
||||||
|
char *managed = NULL;
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
if ((adapter_type = virXMLPropString(node, "type"))) {
|
||||||
|
if ((source->adapter.type =
|
||||||
|
virStoragePoolSourceAdapterTypeFromString(adapter_type)) <= 0) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Unknown pool adapter type '%s'"),
|
||||||
|
adapter_type);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source->adapter.type ==
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
||||||
|
source->adapter.data.fchost.parent =
|
||||||
|
virXMLPropString(node, "parent");
|
||||||
|
managed = virXMLPropString(node, "managed");
|
||||||
|
if (managed) {
|
||||||
|
source->adapter.data.fchost.managed =
|
||||||
|
virTristateBoolTypeFromString(managed);
|
||||||
|
if (source->adapter.data.fchost.managed < 0) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unknown fc_host managed setting '%s'"),
|
||||||
|
managed);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
source->adapter.data.fchost.parent_wwnn =
|
||||||
|
virXMLPropString(node, "parent_wwnn");
|
||||||
|
source->adapter.data.fchost.parent_wwpn =
|
||||||
|
virXMLPropString(node, "parent_wwpn");
|
||||||
|
source->adapter.data.fchost.parent_fabric_wwn =
|
||||||
|
virXMLPropString(node, "parent_fabric_wwn");
|
||||||
|
|
||||||
|
source->adapter.data.fchost.wwpn = virXMLPropString(node, "wwpn");
|
||||||
|
source->adapter.data.fchost.wwnn = virXMLPropString(node, "wwnn");
|
||||||
|
} else if (source->adapter.type ==
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
||||||
|
|
||||||
|
source->adapter.data.scsi_host.name =
|
||||||
|
virXMLPropString(node, "name");
|
||||||
|
if (virXPathNode("./parentaddr", ctxt)) {
|
||||||
|
xmlNodePtr addrnode = virXPathNode("./parentaddr/address",
|
||||||
|
ctxt);
|
||||||
|
virPCIDeviceAddressPtr addr =
|
||||||
|
&source->adapter.data.scsi_host.parentaddr;
|
||||||
|
|
||||||
|
if (!addrnode) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Missing scsi_host PCI address element"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
source->adapter.data.scsi_host.has_parent = true;
|
||||||
|
if (virPCIDeviceAddressParseXML(addrnode, addr) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if ((virXPathInt("string(./parentaddr/@unique_id)",
|
||||||
|
ctxt,
|
||||||
|
&source->adapter.data.scsi_host.unique_id) < 0) ||
|
||||||
|
(source->adapter.data.scsi_host.unique_id < 0)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Missing or invalid scsi adapter "
|
||||||
|
"'unique_id' value"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char *wwnn = virXMLPropString(node, "wwnn");
|
||||||
|
char *wwpn = virXMLPropString(node, "wwpn");
|
||||||
|
char *parent = virXMLPropString(node, "parent");
|
||||||
|
|
||||||
|
/* "type" was not specified in the XML, so we must verify that
|
||||||
|
* "wwnn", "wwpn", "parent", or "parentaddr" are also not in the
|
||||||
|
* XML. If any are found, then we cannot just use "name" alone".
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (wwnn || wwpn || parent) {
|
||||||
|
VIR_FREE(wwnn);
|
||||||
|
VIR_FREE(wwpn);
|
||||||
|
VIR_FREE(parent);
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Use of 'wwnn', 'wwpn', and 'parent' attributes "
|
||||||
|
"requires use of the adapter 'type'"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virXPathNode("./parentaddr", ctxt)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Use of 'parent' element requires use "
|
||||||
|
"of the adapter 'type'"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To keep back-compat, 'type' is not required to specify
|
||||||
|
* for scsi_host adapter.
|
||||||
|
*/
|
||||||
|
if ((source->adapter.data.scsi_host.name =
|
||||||
|
virXMLPropString(node, "name")))
|
||||||
|
source->adapter.type =
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
ctxt->node = relnode;
|
||||||
|
VIR_FREE(adapter_type);
|
||||||
|
VIR_FREE(managed);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virStoragePoolSourceAdapterValidate(virStoragePoolDefPtr ret)
|
||||||
|
{
|
||||||
|
if (!ret->source.adapter.type) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("missing storage pool source adapter"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret->source.adapter.type ==
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
||||||
|
if (!ret->source.adapter.data.fchost.wwnn ||
|
||||||
|
!ret->source.adapter.data.fchost.wwpn) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("'wwnn' and 'wwpn' must be specified for adapter "
|
||||||
|
"type 'fchost'"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!virValidateWWN(ret->source.adapter.data.fchost.wwnn) ||
|
||||||
|
!virValidateWWN(ret->source.adapter.data.fchost.wwpn))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((ret->source.adapter.data.fchost.parent_wwnn &&
|
||||||
|
!ret->source.adapter.data.fchost.parent_wwpn)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("when providing parent_wwnn='%s', the "
|
||||||
|
"parent_wwpn must also be provided"),
|
||||||
|
ret->source.adapter.data.fchost.parent_wwnn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret->source.adapter.data.fchost.parent_wwnn &&
|
||||||
|
ret->source.adapter.data.fchost.parent_wwpn) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("when providing parent_wwpn='%s', the "
|
||||||
|
"parent_wwnn must also be provided"),
|
||||||
|
ret->source.adapter.data.fchost.parent_wwpn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret->source.adapter.data.fchost.parent_wwnn &&
|
||||||
|
!virValidateWWN(ret->source.adapter.data.fchost.parent_wwnn))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ret->source.adapter.data.fchost.parent_wwpn &&
|
||||||
|
!virValidateWWN(ret->source.adapter.data.fchost.parent_wwpn))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ret->source.adapter.data.fchost.parent_fabric_wwn &&
|
||||||
|
!virValidateWWN(ret->source.adapter.data.fchost.parent_fabric_wwn))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
} else if (ret->source.adapter.type ==
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
||||||
|
if (!ret->source.adapter.data.scsi_host.name &&
|
||||||
|
!ret->source.adapter.data.scsi_host.has_parent) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Either 'name' or 'parent' must be specified "
|
||||||
|
"for the 'scsi_host' adapter"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret->source.adapter.data.scsi_host.name &&
|
||||||
|
ret->source.adapter.data.scsi_host.has_parent) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("Both 'name' and 'parent' cannot be specified "
|
||||||
|
"for the 'scsi_host' adapter"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virStoragePoolSourceAdapterFormat(virBufferPtr buf,
|
||||||
|
virStoragePoolSourcePtr src)
|
||||||
|
{
|
||||||
|
virBufferAsprintf(buf, "<adapter type='%s'",
|
||||||
|
virStoragePoolSourceAdapterTypeToString(src->adapter.type));
|
||||||
|
|
||||||
|
if (src->adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
||||||
|
virBufferEscapeString(buf, " parent='%s'",
|
||||||
|
src->adapter.data.fchost.parent);
|
||||||
|
if (src->adapter.data.fchost.managed)
|
||||||
|
virBufferAsprintf(buf, " managed='%s'",
|
||||||
|
virTristateBoolTypeToString(src->adapter.data.fchost.managed));
|
||||||
|
virBufferEscapeString(buf, " parent_wwnn='%s'",
|
||||||
|
src->adapter.data.fchost.parent_wwnn);
|
||||||
|
virBufferEscapeString(buf, " parent_wwpn='%s'",
|
||||||
|
src->adapter.data.fchost.parent_wwpn);
|
||||||
|
virBufferEscapeString(buf, " parent_fabric_wwn='%s'",
|
||||||
|
src->adapter.data.fchost.parent_fabric_wwn);
|
||||||
|
|
||||||
|
virBufferAsprintf(buf, " wwnn='%s' wwpn='%s'/>\n",
|
||||||
|
src->adapter.data.fchost.wwnn,
|
||||||
|
src->adapter.data.fchost.wwpn);
|
||||||
|
} else if (src->adapter.type ==
|
||||||
|
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
||||||
|
if (src->adapter.data.scsi_host.name) {
|
||||||
|
virBufferAsprintf(buf, " name='%s'/>\n",
|
||||||
|
src->adapter.data.scsi_host.name);
|
||||||
|
} else {
|
||||||
|
virPCIDeviceAddress addr;
|
||||||
|
virBufferAddLit(buf, ">\n");
|
||||||
|
virBufferAdjustIndent(buf, 2);
|
||||||
|
virBufferAsprintf(buf, "<parentaddr unique_id='%d'>\n",
|
||||||
|
src->adapter.data.scsi_host.unique_id);
|
||||||
|
virBufferAdjustIndent(buf, 2);
|
||||||
|
addr = src->adapter.data.scsi_host.parentaddr;
|
||||||
|
ignore_value(virPCIDeviceAddressFormat(buf, addr, false));
|
||||||
|
virBufferAdjustIndent(buf, -2);
|
||||||
|
virBufferAddLit(buf, "</parentaddr>\n");
|
||||||
|
virBufferAdjustIndent(buf, -2);
|
||||||
|
virBufferAddLit(buf, "</adapter>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
src/conf/storage_adapter_conf.h
Normal file
43
src/conf/storage_adapter_conf.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* storage_adapter_conf.h: helpers to handle storage pool adapter manipulation
|
||||||
|
* (derived from storage_conf.h)
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIR_STORAGE_ADAPTER_CONF_H__
|
||||||
|
# define __VIR_STORAGE_ADAPTER_CONF_H__
|
||||||
|
|
||||||
|
# include "virpci.h"
|
||||||
|
# include "virxml.h"
|
||||||
|
|
||||||
|
# include "storage_conf.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
virStoragePoolSourceAdapterClear(virStoragePoolSourceAdapterPtr adapter);
|
||||||
|
|
||||||
|
int
|
||||||
|
virStoragePoolDefParseSourceAdapter(virStoragePoolSourcePtr source,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlXPathContextPtr ctxt);
|
||||||
|
|
||||||
|
int
|
||||||
|
virStoragePoolSourceAdapterValidate(virStoragePoolDefPtr ret);
|
||||||
|
|
||||||
|
void
|
||||||
|
virStoragePoolSourceAdapterFormat(virBufferPtr buf,
|
||||||
|
virStoragePoolSourcePtr src);
|
||||||
|
|
||||||
|
#endif /* __VIR_STORAGE_ADAPTER_CONF_H__ */
|
@ -36,6 +36,7 @@
|
|||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "node_device_conf.h"
|
#include "node_device_conf.h"
|
||||||
|
#include "storage_adapter_conf.h"
|
||||||
#include "storage_conf.h"
|
#include "storage_conf.h"
|
||||||
#include "virstoragefile.h"
|
#include "virstoragefile.h"
|
||||||
|
|
||||||
@ -100,10 +101,6 @@ VIR_ENUM_IMPL(virStoragePartedFs,
|
|||||||
"ext2", "ext2",
|
"ext2", "ext2",
|
||||||
"extended")
|
"extended")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virStoragePoolSourceAdapter,
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_LAST,
|
|
||||||
"default", "scsi_host", "fc_host")
|
|
||||||
|
|
||||||
typedef const char *(*virStorageVolFormatToString)(int format);
|
typedef const char *(*virStorageVolFormatToString)(int format);
|
||||||
typedef int (*virStorageVolFormatFromString)(const char *format);
|
typedef int (*virStorageVolFormatFromString)(const char *format);
|
||||||
|
|
||||||
@ -342,22 +339,6 @@ virStorageVolDefFree(virStorageVolDefPtr def)
|
|||||||
VIR_FREE(def);
|
VIR_FREE(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
virStoragePoolSourceAdapterClear(virStoragePoolSourceAdapterPtr adapter)
|
|
||||||
{
|
|
||||||
if (adapter->type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
|
||||||
VIR_FREE(adapter->data.fchost.wwnn);
|
|
||||||
VIR_FREE(adapter->data.fchost.wwpn);
|
|
||||||
VIR_FREE(adapter->data.fchost.parent);
|
|
||||||
VIR_FREE(adapter->data.fchost.parent_wwnn);
|
|
||||||
VIR_FREE(adapter->data.fchost.parent_wwpn);
|
|
||||||
VIR_FREE(adapter->data.fchost.parent_fabric_wwn);
|
|
||||||
} else if (adapter->type ==
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
|
||||||
VIR_FREE(adapter->data.scsi_host.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
|
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevicePtr dev)
|
||||||
{
|
{
|
||||||
@ -462,127 +443,6 @@ virStoragePoolObjRemove(virStoragePoolObjListPtr pools,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
virStoragePoolDefParseSourceAdapter(virStoragePoolSourcePtr source,
|
|
||||||
xmlNodePtr node,
|
|
||||||
xmlXPathContextPtr ctxt)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
xmlNodePtr relnode = ctxt->node;
|
|
||||||
char *adapter_type = NULL;
|
|
||||||
char *managed = NULL;
|
|
||||||
|
|
||||||
ctxt->node = node;
|
|
||||||
|
|
||||||
if ((adapter_type = virXMLPropString(node, "type"))) {
|
|
||||||
if ((source->adapter.type =
|
|
||||||
virStoragePoolSourceAdapterTypeFromString(adapter_type)) <= 0) {
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("Unknown pool adapter type '%s'"),
|
|
||||||
adapter_type);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source->adapter.type ==
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
|
||||||
source->adapter.data.fchost.parent =
|
|
||||||
virXMLPropString(node, "parent");
|
|
||||||
managed = virXMLPropString(node, "managed");
|
|
||||||
if (managed) {
|
|
||||||
source->adapter.data.fchost.managed =
|
|
||||||
virTristateBoolTypeFromString(managed);
|
|
||||||
if (source->adapter.data.fchost.managed < 0) {
|
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
||||||
_("unknown fc_host managed setting '%s'"),
|
|
||||||
managed);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
source->adapter.data.fchost.parent_wwnn =
|
|
||||||
virXMLPropString(node, "parent_wwnn");
|
|
||||||
source->adapter.data.fchost.parent_wwpn =
|
|
||||||
virXMLPropString(node, "parent_wwpn");
|
|
||||||
source->adapter.data.fchost.parent_fabric_wwn =
|
|
||||||
virXMLPropString(node, "parent_fabric_wwn");
|
|
||||||
|
|
||||||
source->adapter.data.fchost.wwpn = virXMLPropString(node, "wwpn");
|
|
||||||
source->adapter.data.fchost.wwnn = virXMLPropString(node, "wwnn");
|
|
||||||
} else if (source->adapter.type ==
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
|
||||||
|
|
||||||
source->adapter.data.scsi_host.name =
|
|
||||||
virXMLPropString(node, "name");
|
|
||||||
if (virXPathNode("./parentaddr", ctxt)) {
|
|
||||||
xmlNodePtr addrnode = virXPathNode("./parentaddr/address",
|
|
||||||
ctxt);
|
|
||||||
virPCIDeviceAddressPtr addr =
|
|
||||||
&source->adapter.data.scsi_host.parentaddr;
|
|
||||||
|
|
||||||
if (!addrnode) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("Missing scsi_host PCI address element"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
source->adapter.data.scsi_host.has_parent = true;
|
|
||||||
if (virPCIDeviceAddressParseXML(addrnode, addr) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
if ((virXPathInt("string(./parentaddr/@unique_id)",
|
|
||||||
ctxt,
|
|
||||||
&source->adapter.data.scsi_host.unique_id) < 0) ||
|
|
||||||
(source->adapter.data.scsi_host.unique_id < 0)) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("Missing or invalid scsi adapter "
|
|
||||||
"'unique_id' value"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char *wwnn = virXMLPropString(node, "wwnn");
|
|
||||||
char *wwpn = virXMLPropString(node, "wwpn");
|
|
||||||
char *parent = virXMLPropString(node, "parent");
|
|
||||||
|
|
||||||
/* "type" was not specified in the XML, so we must verify that
|
|
||||||
* "wwnn", "wwpn", "parent", or "parentaddr" are also not in the
|
|
||||||
* XML. If any are found, then we cannot just use "name" alone".
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (wwnn || wwpn || parent) {
|
|
||||||
VIR_FREE(wwnn);
|
|
||||||
VIR_FREE(wwpn);
|
|
||||||
VIR_FREE(parent);
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("Use of 'wwnn', 'wwpn', and 'parent' attributes "
|
|
||||||
"requires use of the adapter 'type'"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virXPathNode("./parentaddr", ctxt)) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("Use of 'parent' element requires use "
|
|
||||||
"of the adapter 'type'"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To keep back-compat, 'type' is not required to specify
|
|
||||||
* for scsi_host adapter.
|
|
||||||
*/
|
|
||||||
if ((source->adapter.data.scsi_host.name =
|
|
||||||
virXMLPropString(node, "name")))
|
|
||||||
source->adapter.type =
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
ctxt->node = relnode;
|
|
||||||
VIR_FREE(adapter_type);
|
|
||||||
VIR_FREE(managed);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
|
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
|
||||||
@ -850,81 +710,6 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
virStoragePoolSourceAdapterValidate(virStoragePoolDefPtr ret)
|
|
||||||
{
|
|
||||||
if (!ret->source.adapter.type) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("missing storage pool source adapter"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret->source.adapter.type ==
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
|
||||||
if (!ret->source.adapter.data.fchost.wwnn ||
|
|
||||||
!ret->source.adapter.data.fchost.wwpn) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("'wwnn' and 'wwpn' must be specified for adapter "
|
|
||||||
"type 'fchost'"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!virValidateWWN(ret->source.adapter.data.fchost.wwnn) ||
|
|
||||||
!virValidateWWN(ret->source.adapter.data.fchost.wwpn))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((ret->source.adapter.data.fchost.parent_wwnn &&
|
|
||||||
!ret->source.adapter.data.fchost.parent_wwpn)) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
|
||||||
_("when providing parent_wwnn='%s', the "
|
|
||||||
"parent_wwpn must also be provided"),
|
|
||||||
ret->source.adapter.data.fchost.parent_wwnn);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret->source.adapter.data.fchost.parent_wwnn &&
|
|
||||||
ret->source.adapter.data.fchost.parent_wwpn) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
|
||||||
_("when providing parent_wwpn='%s', the "
|
|
||||||
"parent_wwnn must also be provided"),
|
|
||||||
ret->source.adapter.data.fchost.parent_wwpn);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret->source.adapter.data.fchost.parent_wwnn &&
|
|
||||||
!virValidateWWN(ret->source.adapter.data.fchost.parent_wwnn))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ret->source.adapter.data.fchost.parent_wwpn &&
|
|
||||||
!virValidateWWN(ret->source.adapter.data.fchost.parent_wwpn))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ret->source.adapter.data.fchost.parent_fabric_wwn &&
|
|
||||||
!virValidateWWN(ret->source.adapter.data.fchost.parent_fabric_wwn))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
} else if (ret->source.adapter.type ==
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
|
||||||
if (!ret->source.adapter.data.scsi_host.name &&
|
|
||||||
!ret->source.adapter.data.scsi_host.has_parent) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("Either 'name' or 'parent' must be specified "
|
|
||||||
"for the 'scsi_host' adapter"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret->source.adapter.data.scsi_host.name &&
|
|
||||||
ret->source.adapter.data.scsi_host.has_parent) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("Both 'name' and 'parent' cannot be specified "
|
|
||||||
"for the 'scsi_host' adapter"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static virStoragePoolDefPtr
|
static virStoragePoolDefPtr
|
||||||
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
|
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
|
||||||
@ -1122,50 +907,6 @@ virStoragePoolDefParseFile(const char *filename)
|
|||||||
return virStoragePoolDefParse(NULL, filename);
|
return virStoragePoolDefParse(NULL, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
virStoragePoolSourceAdapterFormat(virBufferPtr buf,
|
|
||||||
virStoragePoolSourcePtr src)
|
|
||||||
{
|
|
||||||
virBufferAsprintf(buf, "<adapter type='%s'",
|
|
||||||
virStoragePoolSourceAdapterTypeToString(src->adapter.type));
|
|
||||||
|
|
||||||
if (src->adapter.type == VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
|
|
||||||
virBufferEscapeString(buf, " parent='%s'",
|
|
||||||
src->adapter.data.fchost.parent);
|
|
||||||
if (src->adapter.data.fchost.managed)
|
|
||||||
virBufferAsprintf(buf, " managed='%s'",
|
|
||||||
virTristateBoolTypeToString(src->adapter.data.fchost.managed));
|
|
||||||
virBufferEscapeString(buf, " parent_wwnn='%s'",
|
|
||||||
src->adapter.data.fchost.parent_wwnn);
|
|
||||||
virBufferEscapeString(buf, " parent_wwpn='%s'",
|
|
||||||
src->adapter.data.fchost.parent_wwpn);
|
|
||||||
virBufferEscapeString(buf, " parent_fabric_wwn='%s'",
|
|
||||||
src->adapter.data.fchost.parent_fabric_wwn);
|
|
||||||
|
|
||||||
virBufferAsprintf(buf, " wwnn='%s' wwpn='%s'/>\n",
|
|
||||||
src->adapter.data.fchost.wwnn,
|
|
||||||
src->adapter.data.fchost.wwpn);
|
|
||||||
} else if (src->adapter.type ==
|
|
||||||
VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
|
|
||||||
if (src->adapter.data.scsi_host.name) {
|
|
||||||
virBufferAsprintf(buf, " name='%s'/>\n",
|
|
||||||
src->adapter.data.scsi_host.name);
|
|
||||||
} else {
|
|
||||||
virPCIDeviceAddress addr;
|
|
||||||
virBufferAddLit(buf, ">\n");
|
|
||||||
virBufferAdjustIndent(buf, 2);
|
|
||||||
virBufferAsprintf(buf, "<parentaddr unique_id='%d'>\n",
|
|
||||||
src->adapter.data.scsi_host.unique_id);
|
|
||||||
virBufferAdjustIndent(buf, 2);
|
|
||||||
addr = src->adapter.data.scsi_host.parentaddr;
|
|
||||||
ignore_value(virPCIDeviceAddressFormat(buf, addr, false));
|
|
||||||
virBufferAdjustIndent(buf, -2);
|
|
||||||
virBufferAddLit(buf, "</parentaddr>\n");
|
|
||||||
virBufferAdjustIndent(buf, -2);
|
|
||||||
virBufferAddLit(buf, "</adapter>\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virStoragePoolSourceFormat(virBufferPtr buf,
|
virStoragePoolSourceFormat(virBufferPtr buf,
|
||||||
|
@ -847,6 +847,13 @@ virDomainSnapshotStateTypeToString;
|
|||||||
virDomainSnapshotUpdateRelations;
|
virDomainSnapshotUpdateRelations;
|
||||||
|
|
||||||
|
|
||||||
|
# conf/storage_adapter_conf.h
|
||||||
|
virStoragePoolDefParseSourceAdapter;
|
||||||
|
virStoragePoolSourceAdapterClear;
|
||||||
|
virStoragePoolSourceAdapterFormat;
|
||||||
|
virStoragePoolSourceAdapterValidate;
|
||||||
|
|
||||||
|
|
||||||
# conf/storage_conf.h
|
# conf/storage_conf.h
|
||||||
virStoragePartedFsTypeToString;
|
virStoragePartedFsTypeToString;
|
||||||
virStoragePoolDefFormat;
|
virStoragePoolDefFormat;
|
||||||
|
Loading…
Reference in New Issue
Block a user