esx_storage_driver.c 14.4 KB
Newer Older
1
/*
2
 * esx_storage_driver.c: storage driver functions for managing VMware ESX
3 4
 *                       host storage
 *
5
 * Copyright (C) 2010-2011 Red Hat, Inc.
6 7
 * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte@googlemail.com>
 * Copyright (C) 2012 Ata E Husain Bohra <ata.husain@hotmail.com>
8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
20
 * License along with this library.  If not, see
O
Osier Yang 已提交
21
 * <http://www.gnu.org/licenses/>.
22 23 24 25 26
 *
 */

#include <config.h>

27
#include "viruuid.h"
28
#include "viralloc.h"
29
#include "storage_conf.h"
30 31
#include "esx_private.h"
#include "esx_storage_driver.h"
32
#include "esx_storage_backend_vmfs.h"
33
#include "esx_storage_backend_iscsi.h"
34 35 36

#define VIR_FROM_THIS VIR_FROM_ESX

37
/*
38 39 40 41
 * ESX storage driver implements a facade pattern;
 * the driver exposes the routines supported by libvirt
 * public interface to manage ESX storage devices. Internally
 * it uses backend drivers to perform the required task.
42
 */
43 44
enum {
    VMFS = 0,
45
    ISCSI,
46 47
    LAST_BACKEND
};
48

49
static virStorageDriverPtr backends[] = {
50 51
    &esxStorageBackendVMFS,
    &esxStorageBackendISCSI
52
};
53 54 55



56 57 58
static virDrvOpenStatus
esxStorageOpen(virConnectPtr conn,
               virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
59
               unsigned int flags)
60
{
E
Eric Blake 已提交
61 62
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

63
    if (conn->driver->no != VIR_DRV_ESX) {
64 65 66 67 68 69 70 71 72
        return VIR_DRV_OPEN_DECLINED;
    }

    return VIR_DRV_OPEN_SUCCESS;
}



static int
73
esxStorageClose(virConnectPtr conn ATTRIBUTE_UNUSED)
74 75 76 77 78 79
{
    return 0;
}



80
static int
81
esxConnectNumOfStoragePools(virConnectPtr conn)
82 83
{
    int count = 0;
84
    esxPrivate *priv = conn->privateData;
85
    size_t i;
86
    int tmp;
87

88
    if (esxVI_EnsureSession(priv->primary) < 0) {
89 90 91
        return -1;
    }

92
    for (i = 0; i < LAST_BACKEND; ++i) {
93
        tmp = backends[i]->connectNumOfStoragePools(conn);
94

95 96 97
        if (tmp < 0) {
            return -1;
        }
98

99 100
        count += tmp;
    }
101 102 103 104 105 106 107

    return count;
}



static int
108
esxConnectListStoragePools(virConnectPtr conn, char **const names, int maxnames)
109 110
{
    bool success = false;
111
    esxPrivate *priv = conn->privateData;
112
    int count = 0;
113
    size_t i;
114
    int tmp;
115 116 117 118 119

    if (maxnames == 0) {
        return 0;
    }

120
    if (esxVI_EnsureSession(priv->primary) < 0) {
121 122 123
        return -1;
    }

124
    for (i = 0; i < LAST_BACKEND; ++i) {
125
        tmp = backends[i]->connectListStoragePools(conn, &names[count], maxnames - count);
126

127 128
        if (tmp < 0) {
            goto cleanup;
129
        }
130 131

        count += tmp;
132 133 134 135
    }

    success = true;

136
 cleanup:
137 138 139 140 141 142 143 144 145 146 147 148 149 150
    if (! success) {
        for (i = 0; i < count; ++i) {
            VIR_FREE(names[i]);
        }

        count = -1;
    }

    return count;
}



static int
151
esxConnectNumOfDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED)
152 153 154 155 156 157 158 159
{
    /* ESX storage pools are always active */
    return 0;
}



static int
160 161 162
esxConnectListDefinedStoragePools(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  char **const names ATTRIBUTE_UNUSED,
                                  int maxnames ATTRIBUTE_UNUSED)
163 164 165 166 167 168 169 170 171 172
{
    /* ESX storage pools are always active */
    return 0;
}



static virStoragePoolPtr
esxStoragePoolLookupByName(virConnectPtr conn, const char *name)
{
173
    esxPrivate *priv = conn->privateData;
174
    size_t i;
175 176 177
    virStoragePoolPtr pool;

    virCheckNonNullArgReturn(name, NULL);
178

179
    if (esxVI_EnsureSession(priv->primary) < 0) {
180 181 182
        return NULL;
    }

183
    for (i = 0; i < LAST_BACKEND; ++i) {
184
        pool = backends[i]->storagePoolLookupByName(conn, name);
185

186
        if (pool) {
187 188
            return pool;
        }
189 190
    }

191 192
    virReportError(VIR_ERR_NO_STORAGE_POOL,
                   _("Could not find storage pool with name '%s'"), name);
193

194
    return NULL;
195 196 197 198 199 200 201
}



static virStoragePoolPtr
esxStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
202
    esxPrivate *priv = conn->privateData;
203
    size_t i;
204
    virStoragePoolPtr pool;
205 206
    char uuid_string[VIR_UUID_STRING_BUFLEN] = "";

207
    if (esxVI_EnsureSession(priv->primary) < 0) {
208 209 210
        return NULL;
    }

211 212
    /* invoke backend drive method to search all known pools */
    for (i = 0; i < LAST_BACKEND; ++i) {
213
        pool = backends[i]->storagePoolLookupByUUID(conn, uuid);
214

215
        if (pool) {
216
            return pool;
217 218 219
        }
    }

220 221 222 223
    virUUIDFormat(uuid, uuid_string);
    virReportError(VIR_ERR_NO_STORAGE_POOL,
                   _("Could not find storage pool with uuid '%s'"),
                   uuid_string);
224

225
    return NULL;
226 227 228 229
}



230 231 232 233 234 235 236 237
static virStoragePoolPtr
esxStoragePoolLookupByVolume(virStorageVolPtr volume)
{
    return esxStoragePoolLookupByName(volume->conn, volume->pool);
}



238 239 240
static int
esxStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
241
    esxPrivate *priv = pool->conn->privateData;
242
    virStorageDriverPtr backend = pool->privateData;
243

244
    virCheckNonNullArgReturn(pool->privateData, -1);
245

246
    if (esxVI_EnsureSession(priv->primary) < 0) {
247 248 249
        return -1;
    }

250
    return backend->storagePoolRefresh(pool, flags);
251 252 253 254 255 256 257
}



static int
esxStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info)
{
258
    esxPrivate *priv = pool->conn->privateData;
259 260 261
    virStorageDriverPtr backend = pool->privateData;

    virCheckNonNullArgReturn(pool->privateData, -1);
262

263
    memset(info, 0, sizeof(*info));
264

265
    if (esxVI_EnsureSession(priv->primary) < 0) {
266 267 268
        return -1;
    }

269
    return backend->storagePoolGetInfo(pool, info);
270 271 272 273 274 275 276
}



static char *
esxStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
277
    esxPrivate *priv = pool->conn->privateData;
278
    virStorageDriverPtr backend = pool->privateData;
279

280
    virCheckNonNullArgReturn(pool->privateData, NULL);
281

282
    if (esxVI_EnsureSession(priv->primary) < 0) {
283 284 285
        return NULL;
    }

286
    return backend->storagePoolGetXMLDesc(pool, flags);
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
}



static int
esxStoragePoolGetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
                           int *autostart)
{
    /* ESX storage pools are always active */
    *autostart = 1;

    return 0;
}



static int
esxStoragePoolSetAutostart(virStoragePoolPtr pool ATTRIBUTE_UNUSED,
                           int autostart)
{
    /* Just accept autostart activation, but fail on autostart deactivation */
    autostart = (autostart != 0);

    if (! autostart) {
311 312
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Cannot deactivate storage pool autostart"));
313 314 315 316 317 318 319 320
        return -1;
    }

    return 0;
}



321
static int
322
esxStoragePoolNumOfVolumes(virStoragePoolPtr pool)
323
{
324
    esxPrivate *priv = pool->conn->privateData;
325 326 327
    virStorageDriverPtr backend = pool->privateData;

    virCheckNonNullArgReturn(pool->privateData, -1);
328 329 330 331 332

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return -1;
    }

333
    return backend->storagePoolNumOfVolumes(pool);
334 335 336 337 338
}



static int
339 340
esxStoragePoolListVolumes(virStoragePoolPtr pool, char **const names,
                          int maxnames)
341
{
342
    esxPrivate *priv = pool->conn->privateData;
343
    virStorageDriverPtr backend = pool->privateData;
344

345
    virCheckNonNullArgReturn(pool->privateData, -1);
346 347 348 349 350

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return -1;
    }

351
    return backend->storagePoolListVolumes(pool, names, maxnames);
352 353 354 355 356
}



static virStorageVolPtr
357
esxStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
358
{
359
    esxPrivate *priv = pool->conn->privateData;
360 361 362
    virStorageDriverPtr backend = pool->privateData;

    virCheckNonNullArgReturn(pool->privateData, NULL);
363 364 365 366 367

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return NULL;
    }

368
    return backend->storageVolLookupByName(pool, name);
369 370 371 372 373
}



static virStorageVolPtr
374
esxStorageVolLookupByPath(virConnectPtr conn, const char *path)
375
{
376
    esxPrivate *priv = conn->privateData;
377 378 379 380 381

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return NULL;
    }

382 383 384
    /*
     * FIXME: calling backends blindly may set unwanted error codes
     *
N
Nehal J Wani 已提交
385
     * VMFS Datastore path follows canonical format i.e.:
386
     * [<datastore_name>] <file_path>
387 388
     *          WHEREAS
     * iSCSI LUNs device path follows normal linux path convention
389 390
     */
    if (STRPREFIX(path, "[")) {
391
        return backends[VMFS]->storageVolLookupByPath(conn, path);
392
    } else if (STRPREFIX(path, "/")) {
393
        return backends[ISCSI]->storageVolLookupByPath(conn, path);
394 395 396
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Unexpected volume path format: %s"), path);
397

398
        return NULL;
399
    }
400 401 402 403 404
}



static virStorageVolPtr
405
esxStorageVolLookupByKey(virConnectPtr conn, const char *key)
406
{
407
    virStorageVolPtr volume;
408
    esxPrivate *priv = conn->privateData;
409
    size_t i;
410

411 412 413 414
    if (esxVI_EnsureSession(priv->primary) < 0) {
        return NULL;
    }

415
    for (i = 0; i < LAST_BACKEND; ++i) {
416
        volume = backends[i]->storageVolLookupByKey(conn, key);
417

418
        if (volume) {
419
            return volume;
420 421 422
        }
    }

423 424 425 426 427
    virReportError(VIR_ERR_NO_STORAGE_VOL,
                   _("Could not find storage volume with key '%s'"),
                   key);

    return NULL;
428 429 430 431
}



432
static virStorageVolPtr
433 434
esxStorageVolCreateXML(virStoragePoolPtr pool, const char *xmldesc,
                       unsigned int flags)
435
{
436
    esxPrivate *priv = pool->conn->privateData;
437
    virStorageDriverPtr backend = pool->privateData;
438

439
    virCheckNonNullArgReturn(pool->privateData, NULL);
440

441
    if (esxVI_EnsureSession(priv->primary) < 0) {
442
        return NULL;
443 444
    }

445
    return backend->storageVolCreateXML(pool, xmldesc, flags);
446 447 448 449
}



450
static virStorageVolPtr
451 452
esxStorageVolCreateXMLFrom(virStoragePoolPtr pool, const char *xmldesc,
                           virStorageVolPtr sourceVolume, unsigned int flags)
453
{
454
    esxPrivate *priv = pool->conn->privateData;
455
    virStorageDriverPtr backend = pool->privateData;
456

457
    virCheckNonNullArgReturn(pool->privateData, NULL);
458

459
    if (esxVI_EnsureSession(priv->primary) < 0) {
460 461 462
        return NULL;
    }

463
    return backend->storageVolCreateXMLFrom(pool, xmldesc, sourceVolume, flags);
464 465 466 467
}



468
static int
469
esxStorageVolDelete(virStorageVolPtr volume, unsigned int flags)
470
{
471
    esxPrivate *priv = volume->conn->privateData;
472
    virStorageDriverPtr backend = volume->privateData;
473

474
    virCheckNonNullArgReturn(volume->privateData, -1);
475 476 477 478 479

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return -1;
    }

480
    return backend->storageVolDelete(volume, flags);
481 482 483 484
}



485
static int
486
esxStorageVolWipe(virStorageVolPtr volume, unsigned int flags)
487
{
488
    esxPrivate *priv = volume->conn->privateData;
489
    virStorageDriverPtr backend = volume->privateData;
490

491
    virCheckNonNullArgReturn(volume->privateData, -1);
492 493 494 495 496

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return -1;
    }

497
    return backend->storageVolWipe(volume, flags);
498 499 500 501
}



502
static int
503
esxStorageVolGetInfo(virStorageVolPtr volume, virStorageVolInfoPtr info)
504
{
505
    esxPrivate *priv = volume->conn->privateData;
506
    virStorageDriverPtr backend = volume->privateData;
507

508
    virCheckNonNullArgReturn(volume->privateData, -1);
509 510 511 512 513

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return -1;
    }

514
    return backend->storageVolGetInfo(volume, info);
515 516 517 518 519
}



static char *
520
esxStorageVolGetXMLDesc(virStorageVolPtr volume, unsigned int flags)
521
{
522
    esxPrivate *priv = volume->conn->privateData;
523
    virStorageDriverPtr backend = volume->privateData;
524

525
    virCheckNonNullArgReturn(volume->privateData, NULL);
526 527 528 529 530

    if (esxVI_EnsureSession(priv->primary) < 0) {
        return NULL;
    }

531
    return backend->storageVolGetXMLDesc(volume, flags);
532 533 534 535 536
}



static char *
537
esxStorageVolGetPath(virStorageVolPtr volume)
538
{
539
    esxPrivate *priv = volume->conn->privateData;
540 541 542
    virStorageDriverPtr backend = volume->privateData;

    virCheckNonNullArgReturn(volume->privateData, NULL);
543

544
    if (esxVI_EnsureSession(priv->primary) < 0) {
545 546 547
        return NULL;
    }

548
    return backend->storageVolGetPath(volume);
549 550 551 552
}



553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
static int
esxStoragePoolIsActive(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
    /* ESX storage pools are always active */
    return 1;
}



static int
esxStoragePoolIsPersistent(virStoragePoolPtr pool ATTRIBUTE_UNUSED)
{
    /* ESX has no concept of transient pools, so all of them are persistent */
    return 1;
}


570

571
static virStorageDriver esxStorageDriver = {
572
    .name = "ESX",
573 574
    .storageOpen = esxStorageOpen, /* 0.7.6 */
    .storageClose = esxStorageClose, /* 0.7.6 */
575 576 577 578
    .connectNumOfStoragePools = esxConnectNumOfStoragePools, /* 0.8.2 */
    .connectListStoragePools = esxConnectListStoragePools, /* 0.8.2 */
    .connectNumOfDefinedStoragePools = esxConnectNumOfDefinedStoragePools, /* 0.8.2 */
    .connectListDefinedStoragePools = esxConnectListDefinedStoragePools, /* 0.8.2 */
579 580 581 582 583 584 585 586
    .storagePoolLookupByName = esxStoragePoolLookupByName, /* 0.8.2 */
    .storagePoolLookupByUUID = esxStoragePoolLookupByUUID, /* 0.8.2 */
    .storagePoolLookupByVolume = esxStoragePoolLookupByVolume, /* 0.8.4 */
    .storagePoolRefresh = esxStoragePoolRefresh, /* 0.8.2 */
    .storagePoolGetInfo = esxStoragePoolGetInfo, /* 0.8.2 */
    .storagePoolGetXMLDesc = esxStoragePoolGetXMLDesc, /* 0.8.2 */
    .storagePoolGetAutostart = esxStoragePoolGetAutostart, /* 0.8.2 */
    .storagePoolSetAutostart = esxStoragePoolSetAutostart, /* 0.8.2 */
587 588 589 590 591 592 593 594 595 596 597 598
    .storagePoolNumOfVolumes = esxStoragePoolNumOfVolumes, /* 0.8.4 */
    .storagePoolListVolumes = esxStoragePoolListVolumes, /* 0.8.4 */
    .storageVolLookupByName = esxStorageVolLookupByName, /* 0.8.4 */
    .storageVolLookupByPath = esxStorageVolLookupByPath, /* 0.8.4 */
    .storageVolLookupByKey = esxStorageVolLookupByKey, /* 0.8.4 */
    .storageVolCreateXML = esxStorageVolCreateXML, /* 0.8.4 */
    .storageVolCreateXMLFrom = esxStorageVolCreateXMLFrom, /* 0.8.7 */
    .storageVolDelete = esxStorageVolDelete, /* 0.8.7 */
    .storageVolWipe = esxStorageVolWipe, /* 0.8.7 */
    .storageVolGetInfo = esxStorageVolGetInfo, /* 0.8.4 */
    .storageVolGetXMLDesc = esxStorageVolGetXMLDesc, /* 0.8.4 */
    .storageVolGetPath = esxStorageVolGetPath, /* 0.8.4 */
599 600
    .storagePoolIsActive = esxStoragePoolIsActive, /* 0.8.2 */
    .storagePoolIsPersistent = esxStoragePoolIsPersistent, /* 0.8.2 */
601 602 603 604 605 606 607 608 609
};



int
esxStorageRegister(void)
{
    return virRegisterStorageDriver(&esxStorageDriver);
}