mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Added iSCSI storage pool backend
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
Wed Feb 20 10:44:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* configure.in: Added check for iscsiadm tool
|
||||||
|
* libvirt.spec.in: Added dep on iscsi-initiator-utils
|
||||||
|
* po/POTFILES.in: Added storage_backend_iscsi.c
|
||||||
|
* src/Makefile.am, src/storage_backend.c,
|
||||||
|
src/storage_backend_iscsi.c, src/storage_backend_iscsi.h:
|
||||||
|
Added iSCSI storage pool backend
|
||||||
|
|
||||||
Wed Feb 20 10:42:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
|
Wed Feb 20 10:42:27 EST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
* qemud/qemud.c: Set close-on-exec flag for signal pipe
|
* qemud/qemud.c: Set close-on-exec flag for signal pipe
|
||||||
|
|||||||
22
configure.in
22
configure.in
@@ -561,6 +561,8 @@ AC_ARG_WITH(storage-fs,
|
|||||||
[ --with-storage-fs with FileSystem backend for the storage driver (on)],[],[with_storage_fs=check])
|
[ --with-storage-fs with FileSystem backend for the storage driver (on)],[],[with_storage_fs=check])
|
||||||
AC_ARG_WITH(storage-lvm,
|
AC_ARG_WITH(storage-lvm,
|
||||||
[ --with-storage-lvm with LVM backend for the storage driver (on)],[],[with_storage_lvm=check])
|
[ --with-storage-lvm with LVM backend for the storage driver (on)],[],[with_storage_lvm=check])
|
||||||
|
AC_ARG_WITH(storage-iscsi,
|
||||||
|
[ --with-storage-iscsi with iSCSI backend for the storage driver (on)],[],[with_storage_iscsi=check])
|
||||||
|
|
||||||
if test "$with_storage_fs" = "yes" -o "$with_storage_fs" = "check"; then
|
if test "$with_storage_fs" = "yes" -o "$with_storage_fs" = "check"; then
|
||||||
AC_PATH_PROG(MOUNT, [mount], [], [$PATH:/sbin:/usr/sbin])
|
AC_PATH_PROG(MOUNT, [mount], [], [$PATH:/sbin:/usr/sbin])
|
||||||
@@ -655,6 +657,25 @@ fi
|
|||||||
AM_CONDITIONAL(WITH_STORAGE_LVM, [test "$with_storage_lvm" = "yes"])
|
AM_CONDITIONAL(WITH_STORAGE_LVM, [test "$with_storage_lvm" = "yes"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if test "$with_storage_iscsi" = "yes" -o "$with_storage_iscsi" = "check"; then
|
||||||
|
AC_PATH_PROG(ISCSIADM, [iscsiadm], [], [$PATH:/sbin:/usr/sbin])
|
||||||
|
if test "$with_storage_iscsi" = "yes" ; then
|
||||||
|
if test -z "$ISCSIADM" ; then AC_MSG_ERROR(We need iscsiadm for iSCSI storage driver) ; fi
|
||||||
|
else
|
||||||
|
if test -z "$ISCSIADM" ; then with_storage_iscsi=no ; fi
|
||||||
|
|
||||||
|
if test "$with_storage_iscsi" = "check" ; then with_storage_iscsi=yes ; fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$with_storage_iscsi" = "yes" ; then
|
||||||
|
AC_DEFINE_UNQUOTED(WITH_STORAGE_ISCSI, 1, [whether iSCSI backend for storage driver is enabled])
|
||||||
|
AC_DEFINE_UNQUOTED([ISCSIADM],["$ISCSIADM"],[Location of iscsiadm program])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(WITH_STORAGE_ISCSI, [test "$with_storage_iscsi" = "yes"])
|
||||||
|
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl check for python
|
dnl check for python
|
||||||
dnl
|
dnl
|
||||||
@@ -869,6 +890,7 @@ AC_MSG_NOTICE([ Dir: yes])
|
|||||||
AC_MSG_NOTICE([ FS: $with_storage_fs])
|
AC_MSG_NOTICE([ FS: $with_storage_fs])
|
||||||
AC_MSG_NOTICE([ NetFS: $with_storage_fs])
|
AC_MSG_NOTICE([ NetFS: $with_storage_fs])
|
||||||
AC_MSG_NOTICE([ LVM: $with_storage_lvm])
|
AC_MSG_NOTICE([ LVM: $with_storage_lvm])
|
||||||
|
AC_MSG_NOTICE([ iSCSI: $with_storage_iscsi])
|
||||||
AC_MSG_NOTICE([])
|
AC_MSG_NOTICE([])
|
||||||
AC_MSG_NOTICE([Libraries])
|
AC_MSG_NOTICE([Libraries])
|
||||||
AC_MSG_NOTICE([])
|
AC_MSG_NOTICE([])
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ Requires: /usr/sbin/qcow-create
|
|||||||
%endif
|
%endif
|
||||||
# For LVM drivers
|
# For LVM drivers
|
||||||
Requires: lvm2
|
Requires: lvm2
|
||||||
|
# For ISCSI driver
|
||||||
|
Requires: iscsi-initiator-utils
|
||||||
BuildRequires: xen-devel
|
BuildRequires: xen-devel
|
||||||
BuildRequires: libxml2-devel
|
BuildRequires: libxml2-devel
|
||||||
BuildRequires: readline-devel
|
BuildRequires: readline-devel
|
||||||
@@ -77,6 +79,8 @@ BuildRequires: /usr/sbin/qcow-create
|
|||||||
%endif
|
%endif
|
||||||
# For LVM drivers
|
# For LVM drivers
|
||||||
BuildRequires: lvm2
|
BuildRequires: lvm2
|
||||||
|
# For ISCSI driver
|
||||||
|
BuildRequires: iscsi-initiator-utils
|
||||||
Obsoletes: libvir
|
Obsoletes: libvir
|
||||||
ExclusiveArch: i386 x86_64 ia64
|
ExclusiveArch: i386 x86_64 ia64
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ src/remote_internal.c
|
|||||||
src/storage_backend.c
|
src/storage_backend.c
|
||||||
src/storage_backend_fs.c
|
src/storage_backend_fs.c
|
||||||
src/storage_backend_logical.c
|
src/storage_backend_logical.c
|
||||||
|
src/storage_backend_iscsi.c
|
||||||
src/storage_conf.c
|
src/storage_conf.c
|
||||||
src/storage_driver.c
|
src/storage_driver.c
|
||||||
src/sexpr.c
|
src/sexpr.c
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ else
|
|||||||
EXTRA_DIST += storage_backend_logical.h storage_backend_logical.c
|
EXTRA_DIST += storage_backend_logical.h storage_backend_logical.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if WITH_STORAGE_ISCSI
|
||||||
|
CLIENT_SOURCES += storage_backend_iscsi.h storage_backend_iscsi.c
|
||||||
|
else
|
||||||
|
EXTRA_DIST += storage_backend_iscsi.h storage_backend_iscsi.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
|
libvirt_la_SOURCES = $(CLIENT_SOURCES) $(SERVER_SOURCES)
|
||||||
|
|||||||
@@ -39,6 +39,10 @@
|
|||||||
#if WITH_STORAGE_LVM
|
#if WITH_STORAGE_LVM
|
||||||
#include "storage_backend_logical.h"
|
#include "storage_backend_logical.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if WITH_STORAGE_ISCSI
|
||||||
|
#include "storage_backend_iscsi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -54,6 +58,9 @@ static virStorageBackendPtr backends[] = {
|
|||||||
#if WITH_STORAGE_LVM
|
#if WITH_STORAGE_LVM
|
||||||
&virStorageBackendLogical,
|
&virStorageBackendLogical,
|
||||||
#endif
|
#endif
|
||||||
|
#if WITH_STORAGE_ISCSI
|
||||||
|
&virStorageBackendISCSI,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -100,6 +107,10 @@ virStorageBackendFromString(const char *type) {
|
|||||||
if (STREQ(type, "logical"))
|
if (STREQ(type, "logical"))
|
||||||
return VIR_STORAGE_POOL_LOGICAL;
|
return VIR_STORAGE_POOL_LOGICAL;
|
||||||
#endif
|
#endif
|
||||||
|
#if WITH_STORAGE_ISCSI
|
||||||
|
if (STREQ(type, "iscsi"))
|
||||||
|
return VIR_STORAGE_POOL_ISCSI;
|
||||||
|
#endif
|
||||||
|
|
||||||
virStorageReportError(NULL, VIR_ERR_INTERNAL_ERROR,
|
virStorageReportError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("unknown storage backend type %s"), type);
|
_("unknown storage backend type %s"), type);
|
||||||
@@ -120,6 +131,10 @@ virStorageBackendToString(int type) {
|
|||||||
#if WITH_STORAGE_LVM
|
#if WITH_STORAGE_LVM
|
||||||
case VIR_STORAGE_POOL_LOGICAL:
|
case VIR_STORAGE_POOL_LOGICAL:
|
||||||
return "logical";
|
return "logical";
|
||||||
|
#endif
|
||||||
|
#if WITH_STORAGE_ISCSI
|
||||||
|
case VIR_STORAGE_POOL_ISCSI:
|
||||||
|
return "iscsi";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
455
src/storage_backend_iscsi.c
Normal file
455
src/storage_backend_iscsi.c
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
/*
|
||||||
|
* storage_backend_iscsi.c: storage backend for iSCSI handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 Red Hat, Inc.
|
||||||
|
* 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
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "storage_backend_iscsi.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSITargetIP(virConnectPtr conn,
|
||||||
|
const char *hostname,
|
||||||
|
char *ipaddr,
|
||||||
|
size_t ipaddrlen)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof hints);
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
|
||||||
|
ret = getaddrinfo(hostname, NULL, &hints, &result);
|
||||||
|
if (ret != 0) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("host lookup failed %s"),
|
||||||
|
gai_strerror(ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("no IP address for target %s"),
|
||||||
|
hostname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getnameinfo(result->ai_addr, result->ai_addrlen,
|
||||||
|
ipaddr, ipaddrlen, NULL, 0,
|
||||||
|
NI_NUMERICHOST) < 0) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot format ip addr for %s"),
|
||||||
|
hostname);
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIExtractSession(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool,
|
||||||
|
char **const groups,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
char **session = data;
|
||||||
|
|
||||||
|
if (STREQ(groups[1], pool->def->source.devices[0].path)) {
|
||||||
|
if ((*session = strdup(groups[0])) == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("session"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
virStorageBackendISCSISession(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* # iscsiadm --mode session -P 0
|
||||||
|
* tcp: [1] 192.168.122.170:3260,1 demo-tgt-b
|
||||||
|
* tcp: [2] 192.168.122.170:3260,1 demo-tgt-a
|
||||||
|
*
|
||||||
|
* Pull out 2nd and 4th fields
|
||||||
|
*/
|
||||||
|
const char *regexes[] = {
|
||||||
|
"^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+)\\s*$"
|
||||||
|
};
|
||||||
|
int vars[] = {
|
||||||
|
2,
|
||||||
|
};
|
||||||
|
const char *prog[] = {
|
||||||
|
ISCSIADM, "--mode", "session", "-P", "0", NULL
|
||||||
|
};
|
||||||
|
char *session = NULL;
|
||||||
|
|
||||||
|
if (virStorageBackendRunProgRegex(conn, pool,
|
||||||
|
prog,
|
||||||
|
1,
|
||||||
|
regexes,
|
||||||
|
vars,
|
||||||
|
virStorageBackendISCSIExtractSession,
|
||||||
|
&session) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (session == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot find session"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIConnection(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool,
|
||||||
|
const char *portal,
|
||||||
|
const char *action)
|
||||||
|
{
|
||||||
|
const char *cmdargv[] = {
|
||||||
|
ISCSIADM, "--mode", "node", "--portal", portal,
|
||||||
|
"--targetname", pool->def->source.devices[0].path, action, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (virRun(conn, (char **)cmdargv, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIMakeLUN(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool,
|
||||||
|
char **const groups,
|
||||||
|
void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virStorageVolDefPtr vol;
|
||||||
|
int fd = -1;
|
||||||
|
char lunid[100];
|
||||||
|
char *dev = groups[4];
|
||||||
|
int opentries = 0;
|
||||||
|
char *devpath = NULL;
|
||||||
|
|
||||||
|
snprintf(lunid, sizeof(lunid)-1, "lun-%s", groups[3]);
|
||||||
|
|
||||||
|
if ((vol = calloc(1, sizeof(virStorageVolDef))) == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("volume"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vol->name = strdup(lunid)) == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("name"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((devpath = malloc(5 + strlen(dev) + 1)) == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("devpath"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
strcpy(devpath, "/dev/");
|
||||||
|
strcat(devpath, dev);
|
||||||
|
/* It can take a little while between logging into the ISCSI
|
||||||
|
* server and udev creating the /dev nodes, so if we get ENOENT
|
||||||
|
* we must retry a few times - they should eventually appear.
|
||||||
|
* We currently wait for upto 5 seconds. Is this good enough ?
|
||||||
|
* Perhaps not on a very heavily loaded system Any other
|
||||||
|
* options... ?
|
||||||
|
*/
|
||||||
|
reopen:
|
||||||
|
if ((fd = open(devpath, O_RDONLY)) < 0) {
|
||||||
|
opentries++;
|
||||||
|
if (errno == ENOENT && opentries < 50) {
|
||||||
|
usleep(100 * 1000);
|
||||||
|
goto reopen;
|
||||||
|
}
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot open %s: %s"),
|
||||||
|
devpath, strerror(errno));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now figure out the stable path
|
||||||
|
*
|
||||||
|
* XXX this method is O(N) because it scans the pool target
|
||||||
|
* dir every time its run. Should figure out a more efficient
|
||||||
|
* way of doing this...
|
||||||
|
*/
|
||||||
|
if ((vol->target.path = virStorageBackendStablePath(conn,
|
||||||
|
pool,
|
||||||
|
devpath)) == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (devpath != vol->target.path)
|
||||||
|
free(devpath);
|
||||||
|
devpath = NULL;
|
||||||
|
|
||||||
|
if (virStorageBackendUpdateVolInfoFD(conn, vol, fd, 1) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* XXX use unique iSCSI id instead */
|
||||||
|
vol->key = strdup(vol->target.path);
|
||||||
|
if (vol->key == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("key"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pool->def->capacity += vol->capacity;
|
||||||
|
pool->def->allocation += vol->allocation;
|
||||||
|
|
||||||
|
vol->next = pool->volumes;
|
||||||
|
pool->volumes = vol;
|
||||||
|
pool->nvolumes++;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (fd != -1) close(fd);
|
||||||
|
free(devpath);
|
||||||
|
virStorageVolDefFree(vol);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIFindLUNs(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool,
|
||||||
|
const char *session)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* # iscsiadm --mode session -r $session -P 3
|
||||||
|
*
|
||||||
|
* scsi1 Channel 00 Id 0 Lun: 0
|
||||||
|
* scsi1 Channel 00 Id 0 Lun: 1
|
||||||
|
* Attached scsi disk sdc State: running
|
||||||
|
* scsi1 Channel 00 Id 0 Lun: 2
|
||||||
|
* Attached scsi disk sdd State: running
|
||||||
|
* scsi1 Channel 00 Id 0 Lun: 3
|
||||||
|
* Attached scsi disk sde State: running
|
||||||
|
* scsi1 Channel 00 Id 0 Lun: 4
|
||||||
|
* Attached scsi disk sdf State: running
|
||||||
|
* scsi1 Channel 00 Id 0 Lun: 5
|
||||||
|
* Attached scsi disk sdg State: running
|
||||||
|
*
|
||||||
|
* Need 2 regex to match alternating lines
|
||||||
|
*/
|
||||||
|
const char *regexes[] = {
|
||||||
|
"^\\s*scsi(\\S+)\\s+Channel\\s+(\\S+)\\s+Id\\s+(\\S+)\\s+Lun:\\s+(\\S+)\\s*$",
|
||||||
|
"^\\s*Attached\\s+scsi\\s+disk\\s+(\\S+)\\s+State:\\s+running\\s*$"
|
||||||
|
};
|
||||||
|
int vars[] = {
|
||||||
|
4, 1
|
||||||
|
};
|
||||||
|
const char *prog[] = {
|
||||||
|
ISCSIADM, "--mode", "session", "-r", session, "-P", "3", NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
return virStorageBackendRunProgRegex(conn, pool,
|
||||||
|
prog,
|
||||||
|
2,
|
||||||
|
regexes,
|
||||||
|
vars,
|
||||||
|
virStorageBackendISCSIMakeLUN,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIRescanLUNs(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
|
||||||
|
const char *session)
|
||||||
|
{
|
||||||
|
const char *cmdargv[] = {
|
||||||
|
ISCSIADM, "--mode", "session", "-r", session, "-R", NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (virRun(conn, (char **)cmdargv, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSILogin(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool,
|
||||||
|
const char *portal)
|
||||||
|
{
|
||||||
|
return virStorageBackendISCSIConnection(conn, pool, portal, "--login");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSILogout(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool,
|
||||||
|
const char *portal)
|
||||||
|
{
|
||||||
|
return virStorageBackendISCSIConnection(conn, pool, portal, "--logout");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
virStorageBackendISCSIPortal(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool)
|
||||||
|
{
|
||||||
|
char ipaddr[NI_MAXHOST];
|
||||||
|
char *portal;
|
||||||
|
|
||||||
|
if (virStorageBackendISCSITargetIP(conn,
|
||||||
|
pool->def->source.host.name,
|
||||||
|
ipaddr, sizeof(ipaddr)) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
portal = malloc(strlen(ipaddr) + 1 + 4 + 2 + 1);
|
||||||
|
if (portal == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("portal"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(portal, ipaddr);
|
||||||
|
strcat(portal, ":3260,1");
|
||||||
|
|
||||||
|
return portal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIStartPool(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool)
|
||||||
|
{
|
||||||
|
char *portal = NULL;
|
||||||
|
|
||||||
|
if (pool->def->source.host.name == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("missing source host"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool->def->source.ndevice != 1 ||
|
||||||
|
pool->def->source.devices[0].path == NULL) {
|
||||||
|
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("missing source device"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((portal = virStorageBackendISCSIPortal(conn, pool)) == NULL)
|
||||||
|
return -1;
|
||||||
|
if (virStorageBackendISCSILogin(conn, pool, portal) < 0) {
|
||||||
|
free(portal);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(portal);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIRefreshPool(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool)
|
||||||
|
{
|
||||||
|
char *session = NULL;
|
||||||
|
|
||||||
|
pool->def->allocation = pool->def->capacity = pool->def->available = 0;
|
||||||
|
|
||||||
|
if ((session = virStorageBackendISCSISession(conn, pool)) == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
if (virStorageBackendISCSIRescanLUNs(conn, pool, session) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if (virStorageBackendISCSIFindLUNs(conn, pool, session) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
free(session);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(session);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageBackendISCSIStopPool(virConnectPtr conn,
|
||||||
|
virStoragePoolObjPtr pool)
|
||||||
|
{
|
||||||
|
char *portal;
|
||||||
|
|
||||||
|
if ((portal = virStorageBackendISCSIPortal(conn, pool)) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (virStorageBackendISCSILogout(conn, pool, portal) < 0) {
|
||||||
|
free(portal);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(portal);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virStorageBackend virStorageBackendISCSI = {
|
||||||
|
.type = VIR_STORAGE_POOL_ISCSI,
|
||||||
|
|
||||||
|
.startPool = virStorageBackendISCSIStartPool,
|
||||||
|
.refreshPool = virStorageBackendISCSIRefreshPool,
|
||||||
|
.stopPool = virStorageBackendISCSIStopPool,
|
||||||
|
|
||||||
|
.poolOptions = {
|
||||||
|
.flags = (VIR_STORAGE_BACKEND_POOL_SOURCE_HOST |
|
||||||
|
VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE)
|
||||||
|
},
|
||||||
|
|
||||||
|
.volType = VIR_STORAGE_VOL_BLOCK,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vim: set tabstop=4:
|
||||||
|
* vim: set shiftwidth=4:
|
||||||
|
* vim: set expandtab:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* c-indent-level: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
45
src/storage_backend_iscsi.h
Normal file
45
src/storage_backend_iscsi.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* storage_backend_iscsi.h: storage backend for iSCSI handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 Red Hat, Inc.
|
||||||
|
* 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
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIR_STORAGE_BACKEND_ISCSI_H__
|
||||||
|
#define __VIR_STORAGE_BACKEND_ISCSI_H__
|
||||||
|
|
||||||
|
#include "storage_backend.h"
|
||||||
|
|
||||||
|
extern virStorageBackend virStorageBackendISCSI;
|
||||||
|
|
||||||
|
#endif /* __VIR_STORAGE_BACKEND_ISCSI_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vim: set tabstop=4:
|
||||||
|
* vim: set shiftwidth=4:
|
||||||
|
* vim: set expandtab:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* c-indent-level: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user