phyp_driver.c 108.9 KB
Newer Older
1
/*
2
 * Copyright (C) 2010-2013 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * Copyright IBM Corp. 2009
 *
 * phyp_driver.c: ssh layer to access Power Hypervisors
 *
 * Authors:
 *  Eduardo Otubo <otubo at linux.vnet.ibm.com>
 *
 * 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
21
 * License along with this library.  If not, see
O
Osier Yang 已提交
22
 * <http://www.gnu.org/licenses/>.
23 24 25 26 27
 */

#include <config.h>

#include <sys/types.h>
28
#include <sys/stat.h>
29 30 31 32 33 34 35
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
36 37 38 39 40
#include <libssh2.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
41 42
#include <fcntl.h>
#include <domain_event.h>
43 44

#include "internal.h"
45
#include "virauth.h"
46
#include "virutil.h"
47
#include "datatypes.h"
48
#include "virbuffer.h"
49
#include "viralloc.h"
50
#include "virlog.h"
51
#include "driver.h"
52
#include "virerror.h"
53
#include "viruuid.h"
54
#include "domain_conf.h"
55
#include "storage_conf.h"
56
#include "nodeinfo.h"
E
Eric Blake 已提交
57
#include "virfile.h"
E
Eduardo Otubo 已提交
58
#include "interface_conf.h"
59 60 61 62 63 64 65 66 67

#include "phyp_driver.h"

#define VIR_FROM_THIS VIR_FROM_PHYP

/*
 * URI: phyp://user@[hmc|ivm]/managed_system
 * */

68 69
static unsigned const int HMC = 0;
static unsigned const int IVM = 127;
E
Eduardo Otubo 已提交
70 71
static unsigned const int PHYP_IFACENAME_SIZE = 24;
static unsigned const int PHYP_MAC_SIZE= 12;
72

73 74 75 76 77 78 79 80
static int
waitsocket(int socket_fd, LIBSSH2_SESSION * session)
{
    struct timeval timeout;
    fd_set fd;
    fd_set *writefd = NULL;
    fd_set *readfd = NULL;
    int dir;
81

82 83
    timeout.tv_sec = 0;
    timeout.tv_usec = 1000;
84

85
    FD_ZERO(&fd);
86

87
    FD_SET(socket_fd, &fd);
88

89 90
    /* now make sure we wait in the correct direction */
    dir = libssh2_session_block_directions(session);
91

92 93
    if (dir & LIBSSH2_SESSION_BLOCK_INBOUND)
        readfd = &fd;
94

95 96
    if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
        writefd = &fd;
97

98
    return select(socket_fd + 1, readfd, writefd, NULL, &timeout);
99
}
100

101 102
/* this function is the layer that manipulates the ssh channel itself
 * and executes the commands on the remote machine */
103 104 105
static char *phypExec(LIBSSH2_SESSION *, const char *, int *, virConnectPtr)
    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
    ATTRIBUTE_NONNULL(4);
106
static char *
107
phypExec(LIBSSH2_SESSION *session, const char *cmd, int *exit_status,
108 109 110 111 112
         virConnectPtr conn)
{
    LIBSSH2_CHANNEL *channel;
    ConnectionData *connection_data = conn->networkPrivateData;
    virBuffer tex_ret = VIR_BUFFER_INITIALIZER;
113 114
    char *buffer = NULL;
    size_t buffer_size = 16384;
115 116 117 118
    int exitcode;
    int bytecount = 0;
    int sock = connection_data->sock;
    int rc = 0;
119

120 121 122 123 124
    if (VIR_ALLOC_N(buffer, buffer_size) < 0) {
        virReportOOMError();
        return NULL;
    }

125 126 127 128
    /* Exec non-blocking on the remove host */
    while ((channel = libssh2_channel_open_session(session)) == NULL &&
           libssh2_session_last_error(session, NULL, NULL, 0) ==
           LIBSSH2_ERROR_EAGAIN) {
129 130 131 132 133
        if (waitsocket(sock, session) < 0 && errno != EINTR) {
            virReportSystemError(errno, "%s",
                                 _("unable to wait on libssh2 socket"));
            goto err;
        }
134 135
    }

136 137
    if (channel == NULL) {
        goto err;
138
    }
139

140 141
    while ((rc = libssh2_channel_exec(channel, cmd)) ==
           LIBSSH2_ERROR_EAGAIN) {
142 143 144 145 146
        if (waitsocket(sock, session) < 0 && errno != EINTR) {
            virReportSystemError(errno, "%s",
                                 _("unable to wait on libssh2 socket"));
            goto err;
        }
147
    }
148

149 150 151
    if (rc != 0) {
        goto err;
    }
152

153 154 155
    for (;;) {
        /* loop until we block */
        do {
156
            rc = libssh2_channel_read(channel, buffer, buffer_size);
157 158
            if (rc > 0) {
                bytecount += rc;
159
                virBufferAdd(&tex_ret, buffer, -1);
160 161 162
            }
        }
        while (rc > 0);
163

164 165 166
        /* this is due to blocking that would occur otherwise so we loop on
         * this condition */
        if (rc == LIBSSH2_ERROR_EAGAIN) {
167 168 169 170 171
            if (waitsocket(sock, session) < 0 && errno != EINTR) {
                virReportSystemError(errno, "%s",
                                     _("unable to wait on libssh2 socket"));
                goto err;
            }
172 173 174
        } else {
            break;
        }
E
Eduardo Otubo 已提交
175 176
    }

177
    exitcode = 127;
178

179
    while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) {
180 181 182 183 184
        if (waitsocket(sock, session) < 0 && errno != EINTR) {
            virReportSystemError(errno, "%s",
                                 _("unable to wait on libssh2 socket"));
            goto err;
        }
185 186
    }

187 188
    if (rc == 0) {
        exitcode = libssh2_channel_get_exit_status(channel);
189 190
    }

191 192 193
    (*exit_status) = exitcode;
    libssh2_channel_free(channel);
    channel = NULL;
194 195
    VIR_FREE(buffer);

196 197 198 199 200 201
    if (virBufferError(&tex_ret)) {
        virBufferFreeAndReset(&tex_ret);
        virReportOOMError();
        return NULL;
    }
    return virBufferContentAndReset(&tex_ret);
202 203 204 205 206 207

err:
    (*exit_status) = SSH_CMD_ERR;
    virBufferFreeAndReset(&tex_ret);
    VIR_FREE(buffer);
    return NULL;
208 209
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
/* Convenience wrapper function */
static char *phypExecBuffer(LIBSSH2_SESSION *, virBufferPtr buf, int *,
                            virConnectPtr, bool) ATTRIBUTE_NONNULL(1)
    ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
static char *
phypExecBuffer(LIBSSH2_SESSION *session, virBufferPtr buf, int *exit_status,
               virConnectPtr conn, bool strip_newline)
{
    char *cmd;
    char *ret;

    if (virBufferError(buf)) {
        virBufferFreeAndReset(buf);
        virReportOOMError();
        return NULL;
    }
    cmd = virBufferContentAndReset(buf);
    ret = phypExec(session, cmd, exit_status, conn);
    VIR_FREE(cmd);
    if (ret && *exit_status == 0 && strip_newline) {
        char *nl = strchr(ret, '\n');
        if (nl)
            *nl = '\0';
    }
    return ret;
}

E
Eric Blake 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
/* Convenience wrapper function */
static int phypExecInt(LIBSSH2_SESSION *, virBufferPtr, virConnectPtr, int *)
    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
static int
phypExecInt(LIBSSH2_SESSION *session, virBufferPtr buf, virConnectPtr conn,
            int *result)
{
    char *str;
    int ret;
    char *char_ptr;

    str = phypExecBuffer(session, buf, &ret, conn, true);
    if (!str || ret) {
        VIR_FREE(str);
        return -1;
    }
    ret = virStrToLong_i(str, &char_ptr, 10, result);
    if (ret == 0 && *char_ptr)
        VIR_WARN("ignoring suffix during integer parsing of '%s'", str);
    VIR_FREE(str);
    return ret;
}

260
static int
261
phypGetSystemType(virConnectPtr conn)
262 263
{
    ConnectionData *connection_data = conn->networkPrivateData;
264
    LIBSSH2_SESSION *session = connection_data->session;
265 266 267
    char *cmd = NULL;
    char *ret = NULL;
    int exit_status = 0;
268

269 270
    if (virAsprintf(&cmd, "lshmc -V") < 0) {
        virReportOOMError();
271
        return -1;
272 273
    }
    ret = phypExec(session, cmd, &exit_status, conn);
274

275 276 277
    VIR_FREE(cmd);
    VIR_FREE(ret);
    return exit_status;
278 279
}

280
static int
281
phypGetVIOSPartitionID(virConnectPtr conn)
282
{
283 284 285 286 287 288 289
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    int id = -1;
    char *managed_system = phyp_driver->managed_system;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
290

291 292
    virBufferAddLit(&buf, "lssyscfg");
    if (system_type == HMC)
293
        virBufferAsprintf(&buf, " -m %s", managed_system);
E
Eric Blake 已提交
294 295
    virBufferAddLit(&buf, " -r lpar -F lpar_id,lpar_env"
                    "|sed -n '/vioserver/ {\n s/,.*$//\n p\n}'");
E
Eric Blake 已提交
296
    phypExecInt(session, &buf, conn, &id);
297
    return id;
298
}
299

300

301 302 303 304 305
static virCapsPtr
phypCapsInit(void)
{
    virCapsPtr caps;
    virCapsGuestPtr guest;
306

307 308
    if ((caps = virCapabilitiesNew(virArchFromHost(),
                                   0, 0)) == NULL)
309
        goto no_memory;
310

311 312 313 314 315 316
    /* Some machines have problematic NUMA toplogy causing
     * unexpected failures. We don't want to break the QEMU
     * driver in this scenario, so log errors & carry on
     */
    if (nodeCapsInitNUMA(caps) < 0) {
        virCapabilitiesFreeNUMAInfo(caps);
317
        VIR_WARN
318
            ("Failed to query host NUMA topology, disabling NUMA capabilities");
319 320
    }

321 322
    if ((guest = virCapabilitiesAddGuest(caps,
                                         "linux",
323
                                         caps->host.arch,
324 325
                                         NULL, NULL, 0, NULL)) == NULL)
        goto no_memory;
326

327 328 329
    if (virCapabilitiesAddGuestDomain(guest,
                                      "phyp", NULL, NULL, 0, NULL) == NULL)
        goto no_memory;
330

331
    return caps;
332

333
no_memory:
334
    virObjectUnref(caps);
335 336
    return NULL;
}
337

338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
/* This is a generic function that won't be used directly by
 * libvirt api. The function returns the number of domains
 * in different states: Running, Not Activated and all:
 *
 * type: 0 - Running
 *       1 - Not Activated
 *       * - All
 * */
static int
phypNumDomainsGeneric(virConnectPtr conn, unsigned int type)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
353
    int ndom = -1;
354 355 356
    char *managed_system = phyp_driver->managed_system;
    const char *state;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
357

358 359 360 361 362 363 364
    if (type == 0)
        state = "|grep Running";
    else if (type == 1) {
        if (system_type == HMC) {
            state = "|grep \"Not Activated\"";
        } else {
            state = "|grep \"Open Firmware\"";
365
        }
366 367
    } else
        state = " ";
368

369 370
    virBufferAddLit(&buf, "lssyscfg -r lpar");
    if (system_type == HMC)
371 372
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -F lpar_id,state %s |grep -c '^[0-9][0-9]*'",
373
                      state);
E
Eric Blake 已提交
374
    phypExecInt(session, &buf, conn, &ndom);
375
    return ndom;
376 377
}

378 379 380 381 382 383 384 385 386 387
/* This is a generic function that won't be used directly by
 * libvirt api. The function returns the ids of domains
 * in different states: Running, and all:
 *
 * type: 0 - Running
 *       1 - all
 * */
static int
phypListDomainsGeneric(virConnectPtr conn, int *ids, int nids,
                       unsigned int type)
388
{
389
    ConnectionData *connection_data = conn->networkPrivateData;
E
Eduardo Otubo 已提交
390
    phyp_driverPtr phyp_driver = conn->privateData;
391
    LIBSSH2_SESSION *session = connection_data->session;
E
Eduardo Otubo 已提交
392
    int system_type = phyp_driver->system_type;
393
    char *managed_system = phyp_driver->managed_system;
394
    int exit_status = 0;
395
    int got = -1;
396
    char *ret = NULL;
397
    char *line, *next_line;
398
    const char *state;
E
Eduardo Otubo 已提交
399 400
    virBuffer buf = VIR_BUFFER_INITIALIZER;

401 402 403 404 405
    if (type == 0)
        state = "|grep Running";
    else
        state = " ";

E
Eduardo Otubo 已提交
406 407
    virBufferAddLit(&buf, "lssyscfg -r lpar");
    if (system_type == HMC)
408 409
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -F lpar_id,state %s | sed -e 's/,.*$//'",
410
                      state);
411
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
412

413
    if (exit_status < 0 || ret == NULL)
414
        goto cleanup;
415 416 417 418 419 420 421 422

    /* I need to parse the textual return in order to get the ids */
    line = ret;
    got = 0;
    while (*line && got < nids) {
        if (virStrToLong_i(line, &next_line, 10, &ids[got]) == -1) {
            VIR_ERROR(_("Cannot parse number from '%s'"), line);
            got = -1;
423
            goto cleanup;
424
        }
425 426 427 428
        got++;
        line = next_line;
        while (*line == '\n')
            line++; /* skip \n */
429
    }
430

431
cleanup:
432
    VIR_FREE(ret);
433
    return got;
434 435
}

436 437
static int
phypUUIDTable_WriteFile(virConnectPtr conn)
438
{
439 440
    phyp_driverPtr phyp_driver = conn->privateData;
    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
441
    unsigned int i = 0;
442 443 444 445 446
    int fd = -1;
    char local_file[] = "./uuid_table";

    if ((fd = creat(local_file, 0755)) == -1)
        goto err;
447

448
    for (i = 0; i < uuid_table->nlpars; i++) {
449 450 451
        if (safewrite(fd, &uuid_table->lpars[i]->id,
                      sizeof(uuid_table->lpars[i]->id)) !=
            sizeof(uuid_table->lpars[i]->id)) {
452
            VIR_ERROR(_("Unable to write information to local file."));
453 454 455 456 457
            goto err;
        }

        if (safewrite(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN) !=
            VIR_UUID_BUFLEN) {
458
            VIR_ERROR(_("Unable to write information to local file."));
459
            goto err;
460 461 462
        }
    }

463 464 465 466 467
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("Could not close %s"),
                             local_file);
        goto err;
    }
468 469
    return 0;

470
err:
471
    VIR_FORCE_CLOSE(fd);
472 473 474
    return -1;
}

475 476
static int
phypUUIDTable_Push(virConnectPtr conn)
477 478
{
    ConnectionData *connection_data = conn->networkPrivateData;
479
    LIBSSH2_SESSION *session = connection_data->session;
480 481 482 483
    LIBSSH2_CHANNEL *channel = NULL;
    struct stat local_fileinfo;
    char buffer[1024];
    int rc = 0;
484
    FILE *f = NULL;
485 486 487 488
    size_t nread, sent;
    char *ptr;
    char local_file[] = "./uuid_table";
    char *remote_file = NULL;
489
    int ret = -1;
490

491 492
    if (virAsprintf(&remote_file, "/home/%s/libvirt_uuid_table",
                    NULLSTR(conn->uri->user)) < 0) {
E
Eduardo Otubo 已提交
493
        virReportOOMError();
494
        goto cleanup;
495 496
    }

497
    if (stat(local_file, &local_fileinfo) == -1) {
498
        VIR_WARN("Unable to stat local file.");
499
        goto cleanup;
500
    }
501

502
    if (!(f = fopen(local_file, "rb"))) {
503
        VIR_WARN("Unable to open local file.");
504
        goto cleanup;
505
    }
506

507 508 509 510 511
    do {
        channel =
            libssh2_scp_send(session, remote_file,
                             0x1FF & local_fileinfo.st_mode,
                             (unsigned long) local_fileinfo.st_size);
512

513 514
        if ((!channel) && (libssh2_session_last_errno(session) !=
                           LIBSSH2_ERROR_EAGAIN))
515
            goto cleanup;
516
    } while (!channel);
517

518
    do {
519
        nread = fread(buffer, 1, sizeof(buffer), f);
520
        if (nread <= 0) {
521
            if (feof(f)) {
522 523 524 525
                /* end of file */
                break;
            } else {
                VIR_ERROR(_("Failed to read from %s"), local_file);
526
                goto cleanup;
527 528 529 530
            }
        }
        ptr = buffer;
        sent = 0;
531

532 533 534 535 536 537 538 539 540 541 542 543 544
        do {
            /* write the same data over and over, until error or completion */
            rc = libssh2_channel_write(channel, ptr, nread);
            if (LIBSSH2_ERROR_EAGAIN == rc) {   /* must loop around */
                continue;
            } else if (rc > 0) {
                /* rc indicates how many bytes were written this time */
                sent += rc;
            }
            ptr += sent;
            nread -= sent;
        } while (rc > 0 && sent < nread);
    } while (1);
545

546
    ret = 0;
547

548
cleanup:
549 550 551 552 553 554 555
    if (channel) {
        libssh2_channel_send_eof(channel);
        libssh2_channel_wait_eof(channel);
        libssh2_channel_wait_closed(channel);
        libssh2_channel_free(channel);
        channel = NULL;
    }
556 557
    VIR_FORCE_FCLOSE(f);
    return ret;
558 559 560
}

static int
561
phypUUIDTable_RemLpar(virConnectPtr conn, int id)
562
{
E
Eduardo Otubo 已提交
563
    phyp_driverPtr phyp_driver = conn->privateData;
564 565
    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
    unsigned int i = 0;
E
Eduardo Otubo 已提交
566

567 568 569 570 571
    for (i = 0; i <= uuid_table->nlpars; i++) {
        if (uuid_table->lpars[i]->id == id) {
            uuid_table->lpars[i]->id = -1;
            memset(uuid_table->lpars[i]->uuid, 0, VIR_UUID_BUFLEN);
        }
572 573
    }

574
    if (phypUUIDTable_WriteFile(conn) == -1)
575 576
        goto err;

577
    if (phypUUIDTable_Push(conn) == -1)
578 579
        goto err;

580
    return 0;
581

582
err:
583
    return -1;
584 585
}

586 587
static int
phypUUIDTable_AddLpar(virConnectPtr conn, unsigned char *uuid, int id)
588
{
E
Eduardo Otubo 已提交
589
    phyp_driverPtr phyp_driver = conn->privateData;
590
    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
E
Eduardo Otubo 已提交
591

592 593 594 595 596
    uuid_table->nlpars++;
    unsigned int i = uuid_table->nlpars;
    i--;

    if (VIR_REALLOC_N(uuid_table->lpars, uuid_table->nlpars) < 0) {
597
        virReportOOMError();
598
        goto err;
599 600
    }

601 602
    if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
        virReportOOMError();
603
        goto err;
604
    }
605

606
    uuid_table->lpars[i]->id = id;
607
    memcpy(uuid_table->lpars[i]->uuid, uuid, VIR_UUID_BUFLEN);
608

609 610
    if (phypUUIDTable_WriteFile(conn) == -1)
        goto err;
611

612
    if (phypUUIDTable_Push(conn) == -1)
613 614
        goto err;

615
    return 0;
616

617
err:
618
    return -1;
619 620
}

621 622
static int
phypUUIDTable_ReadFile(virConnectPtr conn)
623
{
E
Eduardo Otubo 已提交
624
    phyp_driverPtr phyp_driver = conn->privateData;
625 626 627 628 629 630
    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
    unsigned int i = 0;
    int fd = -1;
    char local_file[] = "./uuid_table";
    int rc = 0;
    int id;
631

632
    if ((fd = open(local_file, O_RDONLY)) == -1) {
633
        VIR_WARN("Unable to read information from local file.");
634
        goto err;
635 636
    }

637 638 639
    /* Creating a new data base and writing to local file */
    if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) {
        for (i = 0; i < uuid_table->nlpars; i++) {
640

641 642 643 644 645 646 647 648
            rc = read(fd, &id, sizeof(int));
            if (rc == sizeof(int)) {
                if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
                    virReportOOMError();
                    goto err;
                }
                uuid_table->lpars[i]->id = id;
            } else {
649
                VIR_WARN
650
                    ("Unable to read from information from local file.");
651 652
                goto err;
            }
653

654 655
            rc = read(fd, uuid_table->lpars[i]->uuid, VIR_UUID_BUFLEN);
            if (rc != VIR_UUID_BUFLEN) {
656
                VIR_WARN("Unable to read information from local file.");
657 658
                goto err;
            }
659
        }
660 661
    } else
        virReportOOMError();
662

663
    VIR_FORCE_CLOSE(fd);
664
    return 0;
665

666
err:
667
    VIR_FORCE_CLOSE(fd);
668
    return -1;
669 670
}

671 672
static int
phypUUIDTable_Pull(virConnectPtr conn)
673 674
{
    ConnectionData *connection_data = conn->networkPrivateData;
675
    LIBSSH2_SESSION *session = connection_data->session;
676 677 678 679
    LIBSSH2_CHANNEL *channel = NULL;
    struct stat fileinfo;
    char buffer[1024];
    int rc = 0;
680
    int fd = -1;
681 682 683 684 685 686
    int got = 0;
    int amount = 0;
    int total = 0;
    int sock = 0;
    char local_file[] = "./uuid_table";
    char *remote_file = NULL;
687
    int ret = -1;
E
Eduardo Otubo 已提交
688

689 690
    if (virAsprintf(&remote_file, "/home/%s/libvirt_uuid_table",
                    NULLSTR(conn->uri->user)) < 0) {
691
        virReportOOMError();
692
        goto cleanup;
693
    }
694

695 696 697
    /* Trying to stat the remote file. */
    do {
        channel = libssh2_scp_recv(session, remote_file, &fileinfo);
698

699 700 701
        if (!channel) {
            if (libssh2_session_last_errno(session) !=
                LIBSSH2_ERROR_EAGAIN) {
702
                goto cleanup;
703
            } else {
704 705 706
                if (waitsocket(sock, session) < 0 && errno != EINTR) {
                    virReportSystemError(errno, "%s",
                                         _("unable to wait on libssh2 socket"));
707
                    goto cleanup;
708
                }
709 710 711
            }
        }
    } while (!channel);
712

713 714
    /* Creating a new data base based on remote file */
    if ((fd = creat(local_file, 0755)) == -1)
715
        goto cleanup;
716

717 718 719 720
    /* Request a file via SCP */
    while (got < fileinfo.st_size) {
        do {
            amount = sizeof(buffer);
721

722 723 724
            if ((fileinfo.st_size - got) < amount) {
                amount = fileinfo.st_size - got;
            }
E
Eduardo Otubo 已提交
725

726 727 728
            rc = libssh2_channel_read(channel, buffer, amount);
            if (rc > 0) {
                if (safewrite(fd, buffer, rc) != rc)
729
                    VIR_WARN
730
                        ("Unable to write information to local file.");
731

732 733 734 735
                got += rc;
                total += rc;
            }
        } while (rc > 0);
736

737 738 739 740
        if ((rc == LIBSSH2_ERROR_EAGAIN)
            && (got < fileinfo.st_size)) {
            /* this is due to blocking that would occur otherwise
             * so we loop on this condition */
741

742 743 744 745
            /* now we wait */
            if (waitsocket(sock, session) < 0 && errno != EINTR) {
                virReportSystemError(errno, "%s",
                                     _("unable to wait on libssh2 socket"));
746
                goto cleanup;
747
            }
748 749 750 751
            continue;
        }
        break;
    }
752 753 754
    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("Could not close %s"),
                             local_file);
755
        goto cleanup;
756
    }
757

758
    ret = 0;
759

760
cleanup:
761 762 763 764 765 766 767
    if (channel) {
        libssh2_channel_send_eof(channel);
        libssh2_channel_wait_eof(channel);
        libssh2_channel_wait_closed(channel);
        libssh2_channel_free(channel);
        channel = NULL;
    }
768 769
    VIR_FORCE_CLOSE(fd);
    return ret;
770 771
}

772 773
static int
phypUUIDTable_Init(virConnectPtr conn)
774
{
E
Eric Blake 已提交
775
    uuid_tablePtr uuid_table = NULL;
776 777 778 779 780
    phyp_driverPtr phyp_driver;
    int nids_numdomains = 0;
    int nids_listdomains = 0;
    int *ids = NULL;
    unsigned int i = 0;
E
Eric Blake 已提交
781 782
    int ret = -1;
    bool table_created = false;
E
Eduardo Otubo 已提交
783

784
    if ((nids_numdomains = phypNumDomainsGeneric(conn, 2)) < 0)
E
Eric Blake 已提交
785
        goto cleanup;
786 787

    if (VIR_ALLOC_N(ids, nids_numdomains) < 0) {
788
        virReportOOMError();
E
Eric Blake 已提交
789
        goto cleanup;
790 791
    }

792 793
    if ((nids_listdomains =
         phypListDomainsGeneric(conn, ids, nids_numdomains, 1)) < 0)
E
Eric Blake 已提交
794
        goto cleanup;
795

796
    /* exit early if there are no domains */
E
Eric Blake 已提交
797 798 799 800 801
    if (nids_numdomains == 0 && nids_listdomains == 0) {
        ret = 0;
        goto cleanup;
    }
    if (nids_numdomains != nids_listdomains) {
802
        VIR_ERROR(_("Unable to determine number of domains."));
E
Eric Blake 已提交
803
        goto cleanup;
804
    }
805

806 807 808
    phyp_driver = conn->privateData;
    uuid_table = phyp_driver->uuid_table;
    uuid_table->nlpars = nids_listdomains;
809

810 811 812
    /* try to get the table from server */
    if (phypUUIDTable_Pull(conn) == -1) {
        /* file not found in the server, creating a new one */
E
Eric Blake 已提交
813
        table_created = true;
814 815 816 817
        if (VIR_ALLOC_N(uuid_table->lpars, uuid_table->nlpars) >= 0) {
            for (i = 0; i < uuid_table->nlpars; i++) {
                if (VIR_ALLOC(uuid_table->lpars[i]) < 0) {
                    virReportOOMError();
E
Eric Blake 已提交
818
                    goto cleanup;
819 820
                }
                uuid_table->lpars[i]->id = ids[i];
821

822 823 824 825
                if (virUUIDGenerate(uuid_table->lpars[i]->uuid) < 0)
                    VIR_WARN("Unable to generate UUID for domain %d",
                             ids[i]);
            }
E
Eduardo Otubo 已提交
826
        } else {
827
            virReportOOMError();
E
Eric Blake 已提交
828
            goto cleanup;
E
Eduardo Otubo 已提交
829
        }
830

831
        if (phypUUIDTable_WriteFile(conn) == -1)
E
Eric Blake 已提交
832
            goto cleanup;
833

834
        if (phypUUIDTable_Push(conn) == -1)
E
Eric Blake 已提交
835
            goto cleanup;
836 837
    } else {
        if (phypUUIDTable_ReadFile(conn) == -1)
E
Eric Blake 已提交
838
            goto cleanup;
839
    }
840

E
Eric Blake 已提交
841
    ret = 0;
842

E
Eric Blake 已提交
843 844 845 846 847 848 849
cleanup:
    if (ret < 0 && table_created) {
        for (i = 0; i < uuid_table->nlpars; i++) {
            VIR_FREE(uuid_table->lpars[i]);
        }
        VIR_FREE(uuid_table->lpars);
    }
850
    VIR_FREE(ids);
E
Eric Blake 已提交
851
    return ret;
852 853
}

854 855
static void
phypUUIDTable_Free(uuid_tablePtr uuid_table)
856
{
857
    int i;
858

859 860 861 862 863 864 865 866
    if (uuid_table == NULL)
        return;

    for (i = 0; i < uuid_table->nlpars; i++)
        VIR_FREE(uuid_table->lpars[i]);

    VIR_FREE(uuid_table->lpars);
    VIR_FREE(uuid_table);
867 868
}

869 870 871 872 873 874 875 876
#define SPECIALCHARACTER_CASES                                                \
    case '&': case ';': case '`': case '@': case '"': case '|': case '*':     \
    case '?': case '~': case '<': case '>': case '^': case '(': case ')':     \
    case '[': case ']': case '{': case '}': case '$': case '%': case '#':     \
    case '\\': case '\n': case '\r': case '\t':

static bool
contains_specialcharacters(const char *src)
877
{
878
    size_t len = strlen(src);
879 880
    size_t i = 0;

881
    if (len == 0)
882
        return false;
883

884 885
    for (i = 0; i < len; i++) {
        switch (src[i]) {
886 887 888 889
        SPECIALCHARACTER_CASES
            return true;
        default:
            continue;
890 891 892
        }
    }

893 894
    return false;
}
895

896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
static char *
escape_specialcharacters(const char *src)
{
    size_t len = strlen(src);
    size_t i = 0, j = 0;
    char *dst;

    if (len == 0)
        return NULL;

    if (VIR_ALLOC_N(dst, len + 1) < 0) {
        virReportOOMError();
        return NULL;
    }

    for (i = 0; i < len; i++) {
        switch (src[i]) {
        SPECIALCHARACTER_CASES
            continue;
        default:
            dst[j] = src[i];
            j++;
        }
    }

    dst[j] = '\0';

    return dst;
924 925
}

926 927 928
static LIBSSH2_SESSION *
openSSHSession(virConnectPtr conn, virConnectAuthPtr auth,
               int *internal_socket)
929
{
930 931 932 933
    LIBSSH2_SESSION *session;
    const char *hostname = conn->uri->server;
    char *username = NULL;
    char *password = NULL;
934
    int sock = -1;
935 936 937 938 939 940
    int rc;
    struct addrinfo *ai = NULL, *cur;
    struct addrinfo hints;
    int ret;
    char *pubkey = NULL;
    char *pvtkey = NULL;
941
    char *userhome = virGetUserDirectory();
942
    struct stat pvt_stat, pub_stat;
943

944 945
    if (userhome == NULL)
        goto err;
E
Eduardo Otubo 已提交
946

947
    if (virAsprintf(&pubkey, "%s/.ssh/id_rsa.pub", userhome) < 0) {
948
        virReportOOMError();
949
        goto err;
950 951
    }

952 953
    if (virAsprintf(&pvtkey, "%s/.ssh/id_rsa", userhome) < 0) {
        virReportOOMError();
954 955 956
        goto err;
    }

957 958
    if (conn->uri->user != NULL) {
        username = strdup(conn->uri->user);
959

960 961 962 963 964 965
        if (username == NULL) {
            virReportOOMError();
            goto err;
        }
    } else {
        if (auth == NULL || auth->cb == NULL) {
966 967
            virReportError(VIR_ERR_AUTH_FAILED,
                           "%s", _("No authentication callback provided."));
968 969
            goto err;
        }
970

971
        username = virAuthGetUsername(conn, auth, "ssh", NULL, conn->uri->server);
972

973
        if (username == NULL) {
974 975
            virReportError(VIR_ERR_AUTH_FAILED, "%s",
                           _("Username request failed"));
976 977 978
            goto err;
        }
    }
979

980 981 982 983
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = 0;
984

985 986
    ret = getaddrinfo(hostname, "22", &hints, &ai);
    if (ret != 0) {
987 988
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Error while getting %s address info"), hostname);
989 990
        goto err;
    }
991

992 993 994 995 996 997 998
    cur = ai;
    while (cur != NULL) {
        sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
        if (sock >= 0) {
            if (connect(sock, cur->ai_addr, cur->ai_addrlen) == 0) {
                goto connected;
            }
999
            VIR_FORCE_CLOSE(sock);
1000 1001 1002
        }
        cur = cur->ai_next;
    }
1003

1004 1005
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to connect to %s"), hostname);
1006 1007
    freeaddrinfo(ai);
    goto err;
1008

1009
connected:
1010

1011
    (*internal_socket) = sock;
1012

1013 1014 1015
    /* Create a session instance */
    session = libssh2_session_init();
    if (!session)
1016 1017
        goto err;

1018 1019
    /* tell libssh2 we want it all done non-blocking */
    libssh2_session_set_blocking(session, 0);
1020

1021 1022 1023
    while ((rc = libssh2_session_startup(session, sock)) ==
           LIBSSH2_ERROR_EAGAIN) ;
    if (rc) {
1024 1025
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Failure establishing SSH session."));
1026 1027
        goto disconnect;
    }
1028

1029 1030 1031 1032 1033
    /* Trying authentication by pubkey */
    if (stat(pvtkey, &pvt_stat) || stat(pubkey, &pub_stat)) {
        rc = LIBSSH2_ERROR_SOCKET_NONE;
        goto keyboard_interactive;
    }
1034

1035 1036 1037 1038 1039 1040
    while ((rc =
            libssh2_userauth_publickey_fromfile(session, username,
                                                pubkey,
                                                pvtkey,
                                                NULL)) ==
           LIBSSH2_ERROR_EAGAIN) ;
1041

1042
keyboard_interactive:
1043 1044 1045 1046
    if (rc == LIBSSH2_ERROR_SOCKET_NONE
        || rc == LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED
        || rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) {
        if (auth == NULL || auth->cb == NULL) {
1047 1048
            virReportError(VIR_ERR_AUTH_FAILED,
                           "%s", _("No authentication callback provided."));
1049 1050
            goto disconnect;
        }
1051

1052
        password = virAuthGetPassword(conn, auth, "ssh", username, conn->uri->server);
1053

1054
        if (password == NULL) {
1055 1056
            virReportError(VIR_ERR_AUTH_FAILED, "%s",
                           _("Password request failed"));
1057 1058
            goto disconnect;
        }
1059

1060 1061 1062 1063
        while ((rc =
                libssh2_userauth_password(session, username,
                                          password)) ==
               LIBSSH2_ERROR_EAGAIN) ;
1064

1065
        if (rc) {
1066 1067
            virReportError(VIR_ERR_AUTH_FAILED,
                           "%s", _("Authentication failed"));
1068 1069 1070
            goto disconnect;
        } else
            goto exit;
1071

1072 1073
    } else if (rc == LIBSSH2_ERROR_NONE) {
        goto exit;
1074

1075 1076
    } else if (rc == LIBSSH2_ERROR_ALLOC || rc == LIBSSH2_ERROR_SOCKET_SEND
               || rc == LIBSSH2_ERROR_SOCKET_TIMEOUT) {
1077 1078 1079
        goto err;
    }

1080
disconnect:
1081 1082
    libssh2_session_disconnect(session, "Disconnecting...");
    libssh2_session_free(session);
1083
err:
1084
    VIR_FORCE_CLOSE(sock);
1085 1086 1087 1088 1089
    VIR_FREE(userhome);
    VIR_FREE(pubkey);
    VIR_FREE(pvtkey);
    VIR_FREE(username);
    VIR_FREE(password);
1090
    return NULL;
1091

1092
exit:
1093 1094 1095 1096 1097 1098
    VIR_FREE(userhome);
    VIR_FREE(pubkey);
    VIR_FREE(pvtkey);
    VIR_FREE(username);
    VIR_FREE(password);
    return session;
1099 1100
}

1101 1102
static virDrvOpenStatus
phypOpen(virConnectPtr conn,
E
Eric Blake 已提交
1103
         virConnectAuthPtr auth, unsigned int flags)
1104 1105 1106 1107 1108 1109 1110 1111
{
    LIBSSH2_SESSION *session = NULL;
    ConnectionData *connection_data = NULL;
    int internal_socket;
    uuid_tablePtr uuid_table = NULL;
    phyp_driverPtr phyp_driver = NULL;
    char *char_ptr;
    char *managed_system = NULL;
E
Eduardo Otubo 已提交
1112

E
Eric Blake 已提交
1113 1114
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

1115 1116 1117 1118 1119 1120 1121
    if (!conn || !conn->uri)
        return VIR_DRV_OPEN_DECLINED;

    if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "phyp"))
        return VIR_DRV_OPEN_DECLINED;

    if (conn->uri->server == NULL) {
1122 1123
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Missing server name in phyp:// URI"));
1124 1125 1126 1127
        return VIR_DRV_OPEN_ERROR;
    }

    if (VIR_ALLOC(phyp_driver) < 0) {
1128
        virReportOOMError();
1129
        goto failure;
1130 1131
    }

1132 1133 1134 1135
    if (VIR_ALLOC(uuid_table) < 0) {
        virReportOOMError();
        goto failure;
    }
1136

1137 1138 1139 1140
    if (VIR_ALLOC(connection_data) < 0) {
        virReportOOMError();
        goto failure;
    }
1141
    connection_data->sock = -1;
1142

1143 1144 1145 1146 1147 1148
    if (conn->uri->path) {
        /* need to shift one byte in order to remove the first "/" of URI component */
        if (conn->uri->path[0] == '/')
            managed_system = strdup(conn->uri->path + 1);
        else
            managed_system = strdup(conn->uri->path);
E
Eduardo Otubo 已提交
1149

1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
        if (!managed_system) {
            virReportOOMError();
            goto failure;
        }

        /* here we are handling only the first component of the path,
         * so skipping the second:
         * */
        char_ptr = strchr(managed_system, '/');

        if (char_ptr)
            *char_ptr = '\0';

1163
        if (contains_specialcharacters(conn->uri->path)) {
1164 1165 1166
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s",
                           _("Error parsing 'path'. Invalid characters."));
1167 1168 1169 1170 1171
            goto failure;
        }
    }

    if ((session = openSSHSession(conn, auth, &internal_socket)) == NULL) {
1172 1173
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Error while opening SSH session."));
1174 1175 1176 1177
        goto failure;
    }

    connection_data->session = session;
1178
    connection_data->sock = internal_socket;
1179 1180 1181 1182 1183 1184 1185 1186 1187

    uuid_table->nlpars = 0;
    uuid_table->lpars = NULL;

    if (conn->uri->path)
        phyp_driver->managed_system = managed_system;

    phyp_driver->uuid_table = uuid_table;
    if ((phyp_driver->caps = phypCapsInit()) == NULL) {
1188
        virReportOOMError();
1189
        goto failure;
1190 1191
    }

1192
    if (!(phyp_driver->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL)))
1193 1194
        goto failure;

1195 1196
    conn->privateData = phyp_driver;
    conn->networkPrivateData = connection_data;
1197

1198 1199
    if ((phyp_driver->system_type = phypGetSystemType(conn)) == -1)
        goto failure;
1200

1201 1202
    if (phypUUIDTable_Init(conn) == -1)
        goto failure;
1203

1204 1205 1206 1207 1208 1209 1210
    if (phyp_driver->system_type == HMC) {
        if ((phyp_driver->vios_id = phypGetVIOSPartitionID(conn)) == -1)
            goto failure;
    }

    return VIR_DRV_OPEN_SUCCESS;

1211
failure:
1212
    if (phyp_driver != NULL) {
1213
        virObjectUnref(phyp_driver->caps);
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
        VIR_FREE(phyp_driver->managed_system);
        VIR_FREE(phyp_driver);
    }

    phypUUIDTable_Free(uuid_table);

    if (session != NULL) {
        libssh2_session_disconnect(session, "Disconnecting...");
        libssh2_session_free(session);
    }

1225 1226
    if (connection_data)
        VIR_FORCE_CLOSE(connection_data->sock);
1227 1228 1229
    VIR_FREE(connection_data);

    return VIR_DRV_OPEN_ERROR;
1230 1231 1232
}

static int
1233
phypClose(virConnectPtr conn)
1234
{
1235 1236 1237
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
1238

1239 1240
    libssh2_session_disconnect(session, "Disconnecting...");
    libssh2_session_free(session);
1241

1242
    virObjectUnref(phyp_driver->caps);
1243
    virObjectUnref(phyp_driver->xmlopt);
1244 1245 1246
    phypUUIDTable_Free(phyp_driver->uuid_table);
    VIR_FREE(phyp_driver->managed_system);
    VIR_FREE(phyp_driver);
1247 1248

    VIR_FORCE_CLOSE(connection_data->sock);
1249 1250 1251
    VIR_FREE(connection_data);
    return 0;
}
1252 1253


1254 1255 1256 1257 1258 1259
static int
phypIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Phyp uses an SSH tunnel, so is always encrypted */
    return 1;
}
1260

1261 1262 1263 1264 1265 1266

static int
phypIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    /* Phyp uses an SSH tunnel, so is always secure */
    return 1;
1267 1268
}

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285

static int
phypIsAlive(virConnectPtr conn)
{
    ConnectionData *connection_data = conn->networkPrivateData;

    /* XXX we should be able to do something better but this is simple, safe,
     * and good enough for now. In worst case, the function will return true
     * even though the connection is not alive.
     */
    if (connection_data && connection_data->session)
        return 1;
    else
        return 0;
}


1286 1287 1288 1289 1290
static int
phypIsUpdated(virDomainPtr conn ATTRIBUTE_UNUSED)
{
    return 0;
}
1291 1292

/* return the lpar_id given a name and a managed system name */
1293
static int
1294 1295
phypGetLparID(LIBSSH2_SESSION * session, const char *managed_system,
              const char *name, virConnectPtr conn)
1296
{
1297
    phyp_driverPtr phyp_driver = conn->privateData;
E
Eduardo Otubo 已提交
1298
    int system_type = phyp_driver->system_type;
1299
    int lpar_id = -1;
E
Eduardo Otubo 已提交
1300 1301
    virBuffer buf = VIR_BUFFER_INITIALIZER;

1302
    virBufferAddLit(&buf, "lssyscfg -r lpar");
E
Eduardo Otubo 已提交
1303
    if (system_type == HMC)
1304 1305
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " --filter lpar_names=%s -F lpar_id", name);
E
Eric Blake 已提交
1306
    phypExecInt(session, &buf, conn, &lpar_id);
1307
    return lpar_id;
1308 1309
}

1310 1311 1312 1313
/* return the lpar name given a lpar_id and a managed system name */
static char *
phypGetLparNAME(LIBSSH2_SESSION * session, const char *managed_system,
                unsigned int lpar_id, virConnectPtr conn)
1314 1315
{
    phyp_driverPtr phyp_driver = conn->privateData;
1316 1317 1318 1319
    int system_type = phyp_driver->system_type;
    char *ret = NULL;
    int exit_status = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1320

1321 1322
    virBufferAddLit(&buf, "lssyscfg -r lpar");
    if (system_type == HMC)
1323 1324
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " --filter lpar_ids=%d -F name", lpar_id);
1325
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
1326

1327
    if (exit_status < 0)
1328 1329
        VIR_FREE(ret);
    return ret;
1330 1331
}

1332 1333 1334 1335 1336 1337 1338 1339 1340

/* Search into the uuid_table for a lpar_uuid given a lpar_id
 * and a managed system name
 *
 * return:  0 - record found
 *         -1 - not found
 * */
static int
phypGetLparUUID(unsigned char *uuid, int lpar_id, virConnectPtr conn)
1341 1342
{
    phyp_driverPtr phyp_driver = conn->privateData;
1343 1344 1345
    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
    lparPtr *lpars = uuid_table->lpars;
    unsigned int i = 0;
1346

1347 1348
    for (i = 0; i < uuid_table->nlpars; i++) {
        if (lpars[i]->id == lpar_id) {
1349
            memcpy(uuid, lpars[i]->uuid, VIR_UUID_BUFLEN);
1350 1351 1352
            return 0;
        }
    }
1353

1354
    return -1;
1355 1356
}

1357 1358 1359 1360 1361 1362 1363 1364
/*
 * type:
 * 0 - maxmem
 * 1 - memory
 * */
static unsigned long
phypGetLparMem(virConnectPtr conn, const char *managed_system, int lpar_id,
               int type)
1365
{
1366 1367 1368 1369 1370 1371
    ConnectionData *connection_data = conn->networkPrivateData;
    LIBSSH2_SESSION *session = connection_data->session;
    phyp_driverPtr phyp_driver = conn->privateData;
    int system_type = phyp_driver->system_type;
    int memory = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1372

1373 1374
    if (type != 1 && type != 0)
        return 0;
1375

1376 1377
    virBufferAddLit(&buf, "lshwres");
    if (system_type == HMC)
1378 1379
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1380 1381
                      " -r mem --level lpar -F %s --filter lpar_ids=%d",
                      type ? "curr_mem" : "curr_max_mem", lpar_id);
E
Eric Blake 已提交
1382
    phypExecInt(session, &buf, conn, &memory);
1383
    return memory;
1384 1385
}

1386 1387 1388
static unsigned long
phypGetLparCPUGeneric(virConnectPtr conn, const char *managed_system,
                      int lpar_id, int type)
1389
{
1390
    ConnectionData *connection_data = conn->networkPrivateData;
1391
    LIBSSH2_SESSION *session = connection_data->session;
1392
    phyp_driverPtr phyp_driver = conn->privateData;
E
Eduardo Otubo 已提交
1393
    int system_type = phyp_driver->system_type;
1394
    int vcpus = 0;
E
Eduardo Otubo 已提交
1395
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1396

1397
    virBufferAddLit(&buf, "lshwres");
E
Eduardo Otubo 已提交
1398
    if (system_type == HMC)
1399 1400
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1401 1402
                      " -r proc --level lpar -F %s --filter lpar_ids=%d",
                      type ? "curr_max_procs" : "curr_procs", lpar_id);
E
Eric Blake 已提交
1403
    phypExecInt(session, &buf, conn, &vcpus);
1404
    return vcpus;
1405
}
1406

1407 1408 1409 1410
static unsigned long
phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id)
{
    return phypGetLparCPUGeneric(conn, managed_system, lpar_id, 0);
1411 1412
}

1413
static int
1414
phypDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
1415 1416 1417
{
    phyp_driverPtr phyp_driver = dom->conn->privateData;
    char *managed_system = phyp_driver->managed_system;
1418

1419
    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) {
1420
        virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
1421 1422 1423
        return -1;
    }

1424 1425 1426
    return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1);
}

1427 1428 1429 1430 1431 1432 1433
static int
phypGetLparCPUMAX(virDomainPtr dom)
{
    return phypDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                         VIR_DOMAIN_VCPU_MAXIMUM));
}

1434 1435 1436
static int
phypGetRemoteSlot(virConnectPtr conn, const char *managed_system,
                  const char *lpar_name)
1437
{
1438 1439
    ConnectionData *connection_data = conn->networkPrivateData;
    LIBSSH2_SESSION *session = connection_data->session;
1440
    phyp_driverPtr phyp_driver = conn->privateData;
E
Eduardo Otubo 已提交
1441
    int system_type = phyp_driver->system_type;
1442
    int remote_slot = -1;
E
Eduardo Otubo 已提交
1443 1444
    virBuffer buf = VIR_BUFFER_INITIALIZER;

1445
    virBufferAddLit(&buf, "lshwres");
E
Eduardo Otubo 已提交
1446
    if (system_type == HMC)
1447 1448
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r virtualio --rsubtype scsi -F "
1449
                      "remote_slot_num --filter lpar_names=%s", lpar_name);
E
Eric Blake 已提交
1450
    phypExecInt(session, &buf, conn, &remote_slot);
1451
    return remote_slot;
1452 1453
}

1454 1455 1456 1457 1458 1459
/* XXX - is this needed? */
static char *phypGetBackingDevice(virConnectPtr, const char *, char *)
    ATTRIBUTE_UNUSED;
static char *
phypGetBackingDevice(virConnectPtr conn, const char *managed_system,
                     char *lpar_name)
1460
{
1461 1462
    ConnectionData *connection_data = conn->networkPrivateData;
    LIBSSH2_SESSION *session = connection_data->session;
1463
    phyp_driverPtr phyp_driver = conn->privateData;
1464 1465 1466 1467 1468 1469 1470
    int system_type = phyp_driver->system_type;
    char *ret = NULL;
    int remote_slot = 0;
    int exit_status = 0;
    char *char_ptr;
    char *backing_device = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1471

1472 1473 1474 1475 1476 1477
    if ((remote_slot =
         phypGetRemoteSlot(conn, managed_system, lpar_name)) == -1)
        return NULL;

    virBufferAddLit(&buf, "lshwres");
    if (system_type == HMC)
1478 1479
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r virtualio --rsubtype scsi -F "
1480
                      "backing_devices --filter slots=%d", remote_slot);
1481
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1482

1483
    if (exit_status < 0 || ret == NULL)
1484
        goto cleanup;
1485

1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
    /* here is a little trick to deal returns of this kind:
     *
     * 0x8100000000000000//lv01
     *
     * the information we really need is only lv01, so we
     * need to skip a lot of things on the string.
     * */
    char_ptr = strchr(ret, '/');

    if (char_ptr) {
        char_ptr++;
        if (char_ptr[0] == '/')
            char_ptr++;
        else
1500
            goto cleanup;
1501 1502 1503 1504 1505

        backing_device = strdup(char_ptr);

        if (backing_device == NULL) {
            virReportOOMError();
1506
            goto cleanup;
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
        }
    } else {
        backing_device = ret;
        ret = NULL;
    }

    char_ptr = strchr(backing_device, '\n');

    if (char_ptr)
        *char_ptr = '\0';

1518
cleanup:
1519
    VIR_FREE(ret);
1520

1521
    return backing_device;
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
}

static char *
phypGetLparProfile(virConnectPtr conn, int lpar_id)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&buf, "lssyscfg");
    if (system_type == HMC)
1538 1539
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1540 1541
                      " -r prof --filter lpar_ids=%d -F name|head -n 1",
                      lpar_id);
1542
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
1543

1544
    if (exit_status < 0)
1545 1546
        VIR_FREE(ret);
    return ret;
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558
}

static int
phypGetVIOSNextSlotNumber(virConnectPtr conn)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    char *profile = NULL;
1559
    int slot = -1;
1560 1561 1562
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (!(profile = phypGetLparProfile(conn, vios_id))) {
1563
        VIR_ERROR(_("Unable to get VIOS profile name."));
1564
        return -1;
1565 1566 1567 1568 1569
    }

    virBufferAddLit(&buf, "lssyscfg");

    if (system_type == HMC)
1570
        virBufferAsprintf(&buf, " -m %s", managed_system);
1571

1572
    virBufferAsprintf(&buf, " -r prof --filter "
1573 1574 1575 1576 1577
                      "profile_names=%s -F virtual_eth_adapters,"
                      "virtual_opti_pool_id,virtual_scsi_adapters,"
                      "virtual_serial_adapters|sed -e 's/\"//g' -e "
                      "'s/,/\\n/g'|sed -e 's/\\(^[0-9][0-9]\\*\\).*$/\\1/'"
                      "|sort|tail -n 1", profile);
E
Eric Blake 已提交
1578 1579 1580
    if (phypExecInt(session, &buf, conn, &slot) < 0)
        return -1;
    return slot + 1;
1581 1582 1583 1584 1585
}

static int
phypCreateServerSCSIAdapter(virConnectPtr conn)
{
1586
    int result = -1;
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    char *profile = NULL;
    int slot = 0;
    char *vios_name = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (!
        (vios_name =
         phypGetLparNAME(session, managed_system, vios_id, conn))) {
1603
        VIR_ERROR(_("Unable to get VIOS name"));
1604
        goto cleanup;
1605 1606 1607
    }

    if (!(profile = phypGetLparProfile(conn, vios_id))) {
1608
        VIR_ERROR(_("Unable to get VIOS profile name."));
1609
        goto cleanup;
1610 1611 1612
    }

    if ((slot = phypGetVIOSNextSlotNumber(conn)) == -1) {
1613
        VIR_ERROR(_("Unable to get free slot number"));
1614
        goto cleanup;
1615 1616 1617 1618 1619 1620 1621
    }

    /* Listing all the virtual_scsi_adapter interfaces, the new adapter must
     * be appended to this list
     * */
    virBufferAddLit(&buf, "lssyscfg");
    if (system_type == HMC)
1622 1623
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r prof --filter lpar_ids=%d,profile_names=%s"
1624 1625
                      " -F virtual_scsi_adapters|sed -e s/\\\"//g",
                      vios_id, profile);
1626
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1627 1628

    if (exit_status < 0 || ret == NULL)
1629
        goto cleanup;
1630 1631 1632 1633 1634 1635

    /* Here I change the VIOS configuration to append the new adapter
     * with the free slot I got with phypGetVIOSNextSlotNumber.
     * */
    virBufferAddLit(&buf, "chsyscfg");
    if (system_type == HMC)
1636 1637
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r prof -i 'name=%s,lpar_id=%d,"
1638 1639
                      "\"virtual_scsi_adapters=%s,%d/server/any/any/1\"'",
                      vios_name, vios_id, ret, slot);
1640
    VIR_FREE(ret);
1641
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1642 1643

    if (exit_status < 0 || ret == NULL)
1644
        goto cleanup;
1645 1646 1647 1648 1649 1650

    /* Finally I add the new scsi adapter to VIOS using the same slot
     * I used in the VIOS configuration.
     * */
    virBufferAddLit(&buf, "chhwres -r virtualio --rsubtype scsi");
    if (system_type == HMC)
1651 1652
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1653 1654
                      " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"",
                      vios_name, slot);
1655
    VIR_FREE(ret);
1656
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1657 1658

    if (exit_status < 0 || ret == NULL)
1659
        goto cleanup;
1660

1661
    result = 0;
1662

1663
cleanup:
1664 1665 1666
    VIR_FREE(profile);
    VIR_FREE(vios_name);
    VIR_FREE(ret);
1667 1668

    return result;
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684
}

static char *
phypGetVIOSFreeSCSIAdapter(virConnectPtr conn)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
1685
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
1686 1687
                          managed_system, vios_id);

1688
    virBufferAsprintf(&buf, "lsmap -all -field svsa backing -fmt , ");
1689 1690 1691 1692

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

1693
    virBufferAsprintf(&buf, "|sed '/,[^.*]/d; s/,//g; q'");
1694
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
1695

1696
    if (exit_status < 0)
1697 1698
        VIR_FREE(ret);
    return ret;
1699 1700 1701 1702 1703 1704
}


static int
phypAttachDevice(virDomainPtr domain, const char *xml)
{
1705
    int result = -1;
1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
    virConnectPtr conn = domain->conn;
    ConnectionData *connection_data = domain->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = domain->conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    char *scsi_adapter = NULL;
    int slot = 0;
    char *vios_name = NULL;
    char *profile = NULL;
    virDomainDeviceDefPtr dev = NULL;
    virDomainDefPtr def = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *domain_name = NULL;

E
Eric Blake 已提交
1724 1725 1726 1727 1728
    if (VIR_ALLOC(def) < 0) {
        virReportOOMError();
        goto cleanup;
    }

1729
    domain_name = escape_specialcharacters(domain->name);
1730

1731
    if (domain_name == NULL) {
1732
        goto cleanup;
1733 1734 1735 1736 1737 1738
    }

    def->os.type = strdup("aix");

    if (def->os.type == NULL) {
        virReportOOMError();
1739
        goto cleanup;
1740 1741
    }

1742 1743
    dev = virDomainDeviceDefParse(xml, def, phyp_driver->caps, NULL,
                                  VIR_DOMAIN_XML_INACTIVE);
1744
    if (!dev) {
1745
        goto cleanup;
1746 1747 1748 1749 1750
    }

    if (!
        (vios_name =
         phypGetLparNAME(session, managed_system, vios_id, conn))) {
1751
        VIR_ERROR(_("Unable to get VIOS name"));
1752
        goto cleanup;
1753 1754 1755 1756 1757 1758 1759 1760
    }

    /* First, let's look for a free SCSI Adapter
     * */
    if (!(scsi_adapter = phypGetVIOSFreeSCSIAdapter(conn))) {
        /* If not found, let's create one.
         * */
        if (phypCreateServerSCSIAdapter(conn) == -1) {
1761
            VIR_ERROR(_("Unable to create new virtual adapter"));
1762
            goto cleanup;
1763 1764
        } else {
            if (!(scsi_adapter = phypGetVIOSFreeSCSIAdapter(conn))) {
1765
                VIR_ERROR(_("Unable to create new virtual adapter"));
1766
                goto cleanup;
1767 1768 1769 1770 1771
            }
        }
    }

    if (system_type == HMC)
1772
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
1773 1774
                          managed_system, vios_id);

1775
    virBufferAsprintf(&buf, "mkvdev -vdev %s -vadapter %s",
1776 1777 1778 1779
                      dev->data.disk->src, scsi_adapter);

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');
1780
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1781 1782

    if (exit_status < 0 || ret == NULL)
1783
        goto cleanup;
1784 1785

    if (!(profile = phypGetLparProfile(conn, domain->id))) {
1786
        VIR_ERROR(_("Unable to get VIOS profile name."));
1787
        goto cleanup;
1788 1789 1790 1791 1792 1793
    }

    /* Let's get the slot number for the adapter we just created
     * */
    virBufferAddLit(&buf, "lshwres -r virtualio --rsubtype scsi");
    if (system_type == HMC)
1794 1795
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1796 1797
                      " slot_num,backing_device|grep %s|cut -d, -f1",
                      dev->data.disk->src);
E
Eric Blake 已提交
1798
    if (phypExecInt(session, &buf, conn, &slot) < 0)
1799
        goto cleanup;
1800 1801 1802 1803 1804 1805

    /* Listing all the virtual_scsi_adapter interfaces, the new adapter must
     * be appended to this list
     * */
    virBufferAddLit(&buf, "lssyscfg");
    if (system_type == HMC)
1806 1807
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1808 1809 1810
                      " -r prof --filter lpar_ids=%d,profile_names=%s"
                      " -F virtual_scsi_adapters|sed -e 's/\"//g'",
                      vios_id, profile);
1811
    VIR_FREE(ret);
1812
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1813 1814

    if (exit_status < 0 || ret == NULL)
1815
        goto cleanup;
1816 1817 1818 1819 1820 1821

    /* Here I change the LPAR configuration to append the new adapter
     * with the new slot we just created
     * */
    virBufferAddLit(&buf, "chsyscfg");
    if (system_type == HMC)
1822 1823
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1824 1825 1826 1827
                      " -r prof -i 'name=%s,lpar_id=%d,"
                      "\"virtual_scsi_adapters=%s,%d/client/%d/%s/0\"'",
                      domain_name, domain->id, ret, slot,
                      vios_id, vios_name);
E
Eric Blake 已提交
1828
    if (phypExecInt(session, &buf, conn, &slot) < 0)
1829
        goto cleanup;
1830 1831 1832 1833 1834 1835

    /* Finally I add the new scsi adapter to VIOS using the same slot
     * I used in the VIOS configuration.
     * */
    virBufferAddLit(&buf, "chhwres -r virtualio --rsubtype scsi");
    if (system_type == HMC)
1836 1837
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
1838 1839
                      " -p %s -o a -s %d -d 0 -a \"adapter_type=server\"",
                      domain_name, slot);
1840
    VIR_FREE(ret);
1841
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1842 1843

    if (exit_status < 0 || ret == NULL) {
1844
        VIR_ERROR(_
1845 1846
                   ("Possibly you don't have IBM Tools installed in your LPAR."
                    "Contact your support to enable this feature."));
1847
        goto cleanup;
1848 1849
    }

1850
    result = 0;
1851

1852
cleanup:
1853
    VIR_FREE(ret);
1854 1855
    virDomainDeviceDefFree(dev);
    virDomainDefFree(def);
1856 1857
    VIR_FREE(vios_name);
    VIR_FREE(scsi_adapter);
1858 1859 1860 1861
    VIR_FREE(profile);
    VIR_FREE(domain_name);

    return result;
1862 1863
}

1864 1865
static char *
phypVolumeGetKey(virConnectPtr conn, const char *name)
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
1878
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
1879 1880
                          managed_system, vios_id);

1881
    virBufferAsprintf(&buf, "lslv %s -field lvid", name);
1882 1883 1884 1885

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

1886
    virBufferAsprintf(&buf, "|sed -e 's/^LV IDENTIFIER://' -e 's/ //g'");
1887
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
1888

1889
    if (exit_status < 0)
1890 1891
        VIR_FREE(ret);
    return ret;
1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907
}

static char *
phypGetStoragePoolDevice(virConnectPtr conn, char *name)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
1908
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
1909 1910
                          managed_system, vios_id);

1911
    virBufferAsprintf(&buf, "lssp -detail -sp %s -field name", name);
1912 1913 1914 1915

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

1916
    virBufferAsprintf(&buf, "|sed '1d; s/ //g'");
1917
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
1918

1919
    if (exit_status < 0)
1920 1921
        VIR_FREE(ret);
    return ret;
1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
}

static unsigned long int
phypGetStoragePoolSize(virConnectPtr conn, char *name)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
1933
    int sp_size = -1;
1934 1935 1936
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
1937
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
1938 1939
                          managed_system, vios_id);

1940
    virBufferAsprintf(&buf, "lssp -detail -sp %s -field size", name);
1941 1942 1943 1944

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

1945
    virBufferAsprintf(&buf, "|sed '1d; s/ //g'");
E
Eric Blake 已提交
1946
    phypExecInt(session, &buf, conn, &sp_size);
1947
    return sp_size;
1948 1949
}

1950
static char *
1951
phypBuildVolume(virConnectPtr conn, const char *lvname, const char *spname,
1952
                unsigned int capacity)
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int vios_id = phyp_driver->vios_id;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    char *ret = NULL;
    int exit_status = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
1963
    char *key = NULL;
1964 1965

    if (system_type == HMC)
1966
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
1967 1968
                          managed_system, vios_id);

1969
    virBufferAsprintf(&buf, "mklv -lv %s %s %d", lvname, spname, capacity);
1970 1971 1972

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');
1973
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
1974 1975

    if (exit_status < 0) {
1976
        VIR_ERROR(_("Unable to create Volume: %s"), NULLSTR(ret));
1977
        goto cleanup;
1978 1979
    }

1980 1981
    key = phypVolumeGetKey(conn, lvname);

1982
cleanup:
1983 1984
    VIR_FREE(ret);

1985
    return key;
1986 1987 1988 1989 1990
}

static virStorageVolPtr
phypVolumeLookupByName(virStoragePoolPtr pool, const char *volname)
{
1991 1992
    char *key;
    virStorageVolPtr vol;
1993

1994
    key = phypVolumeGetKey(pool->conn, volname);
1995

1996
    if (key == NULL)
1997 1998
        return NULL;

1999
    vol = virGetStorageVol(pool->conn, pool->name, volname, key, NULL, NULL);
2000 2001 2002 2003

    VIR_FREE(key);

    return vol;
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
}

static virStorageVolPtr
phypStorageVolCreateXML(virStoragePoolPtr pool,
                        const char *xml, unsigned int flags)
{
    virCheckFlags(0, NULL);

    virStorageVolDefPtr voldef = NULL;
    virStoragePoolDefPtr spdef = NULL;
    virStorageVolPtr vol = NULL;
2015
    virStorageVolPtr dup_vol = NULL;
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
    char *key = NULL;

    if (VIR_ALLOC(spdef) < 0) {
        virReportOOMError();
        return NULL;
    }

    /* Filling spdef manually
     * */
    if (pool->name != NULL) {
        spdef->name = pool->name;
    } else {
2028
        VIR_ERROR(_("Unable to determine storage pool's name."));
2029 2030 2031 2032
        goto err;
    }

    if (memcpy(spdef->uuid, pool->uuid, VIR_UUID_BUFLEN) == NULL) {
2033
        VIR_ERROR(_("Unable to determine storage pool's uuid."));
2034 2035 2036 2037 2038
        goto err;
    }

    if ((spdef->capacity =
         phypGetStoragePoolSize(pool->conn, pool->name)) == -1) {
2039
        VIR_ERROR(_("Unable to determine storage pools's size."));
2040 2041 2042
        goto err;
    }

J
Ján Tomko 已提交
2043
    /* Information not available */
2044 2045 2046 2047 2048 2049
    spdef->allocation = 0;
    spdef->available = 0;

    spdef->source.ndevice = 1;

    /*XXX source adapter not working properly, should show hdiskX */
2050
    if ((spdef->source.adapter.data.name =
2051
         phypGetStoragePoolDevice(pool->conn, pool->name)) == NULL) {
2052
        VIR_ERROR(_("Unable to determine storage pools's source adapter."));
2053 2054 2055 2056
        goto err;
    }

    if ((voldef = virStorageVolDefParseString(spdef, xml)) == NULL) {
2057
        VIR_ERROR(_("Error parsing volume XML."));
2058 2059 2060 2061
        goto err;
    }

    /* checking if this name already exists on this system */
2062
    if ((dup_vol = phypVolumeLookupByName(pool, voldef->name)) != NULL) {
2063
        VIR_ERROR(_("StoragePool name already exists."));
2064
        virObjectUnref(dup_vol);
2065 2066 2067 2068 2069 2070 2071
        goto err;
    }

    /* The key must be NULL, the Power Hypervisor creates a key
     * in the moment you create the volume.
     * */
    if (voldef->key) {
2072
        VIR_ERROR(_("Key must be empty, Power Hypervisor will create one for you."));
2073 2074 2075 2076
        goto err;
    }

    if (voldef->capacity) {
2077
        VIR_ERROR(_("Capacity cannot be empty."));
2078 2079 2080
        goto err;
    }

2081 2082 2083 2084
    key = phypBuildVolume(pool->conn, voldef->name, spdef->name,
                          voldef->capacity);

    if (key == NULL)
2085 2086 2087 2088
        goto err;

    if ((vol =
         virGetStorageVol(pool->conn, pool->name, voldef->name,
2089
                          key, NULL, NULL)) == NULL)
2090 2091
        goto err;

2092 2093
    VIR_FREE(key);

2094 2095
    return vol;

2096
err:
2097
    VIR_FREE(key);
2098 2099
    virStorageVolDefFree(voldef);
    virStoragePoolDefFree(spdef);
2100
    virObjectUnref(vol);
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
    return NULL;
}

static char *
phypVolumeGetPhysicalVolumeByStoragePool(virStorageVolPtr vol, char *sp)
{
    virConnectPtr conn = vol->conn;
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2119
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2120 2121
                          managed_system, vios_id);

2122
    virBufferAsprintf(&buf, "lssp -detail -sp %s -field pvname", sp);
2123 2124 2125 2126

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

2127
    virBufferAsprintf(&buf, "|sed 1d");
2128
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
2129

2130
    if (exit_status < 0)
2131 2132
        VIR_FREE(ret);
    return ret;
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
}

static virStorageVolPtr
phypVolumeLookupByPath(virConnectPtr conn, const char *volname)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
2145
    char *ret = NULL;
2146 2147
    char *key = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
2148
    virStorageVolPtr vol = NULL;
2149 2150

    if (system_type == HMC)
2151
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2152 2153
                          managed_system, vios_id);

2154
    virBufferAsprintf(&buf, "lslv %s -field vgname", volname);
2155 2156 2157 2158

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

2159
    virBufferAsprintf(&buf, "|sed -e 's/^VOLUME GROUP://g' -e 's/ //g'");
2160
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
2161

2162
    if (exit_status < 0 || ret == NULL)
2163
        goto cleanup;
2164

2165
    key = phypVolumeGetKey(conn, volname);
2166

2167
    if (key == NULL)
2168
        goto cleanup;
2169

2170
    vol = virGetStorageVol(conn, ret, volname, key, NULL, NULL);
2171

2172
cleanup:
2173
    VIR_FREE(ret);
2174 2175 2176
    VIR_FREE(key);

    return vol;
2177 2178 2179 2180 2181 2182
}

static int
phypGetStoragePoolUUID(virConnectPtr conn, unsigned char *uuid,
                       const char *name)
{
2183
    int result = -1;
2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2195
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2196 2197
                          managed_system, vios_id);

2198
    virBufferAsprintf(&buf, "lsdev -dev %s -attr vgserial_id", name);
2199 2200 2201 2202

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

2203
    virBufferAsprintf(&buf, "|sed '1,2d'");
2204
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
2205 2206

    if (exit_status < 0 || ret == NULL)
2207
        goto cleanup;
2208

2209
    if (memcpy(uuid, ret, VIR_UUID_BUFLEN) == NULL)
2210
        goto cleanup;
2211

2212
    result = 0;
2213

2214
cleanup:
2215
    VIR_FREE(ret);
2216 2217

    return result;
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227
}

static virStoragePoolPtr
phypStoragePoolLookupByName(virConnectPtr conn, const char *name)
{
    unsigned char uuid[VIR_UUID_BUFLEN];

    if (phypGetStoragePoolUUID(conn, uuid, name) == -1)
        return NULL;

2228
    return virGetStoragePool(conn, name, uuid, NULL, NULL);
2229 2230 2231 2232 2233
}

static char *
phypVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
{
2234 2235 2236
    virStorageVolDef voldef;
    virStoragePoolDef pool;
    virStoragePoolPtr sp;
2237
    char *xml = NULL;
2238

2239 2240 2241
    virCheckFlags(0, NULL);

    memset(&voldef, 0, sizeof(virStorageVolDef));
2242
    memset(&pool, 0, sizeof(virStoragePoolDef));
2243

2244
    sp = phypStoragePoolLookupByName(vol->conn, vol->pool);
2245 2246

    if (!sp)
2247
        goto cleanup;
2248 2249 2250 2251

    if (sp->name != NULL) {
        pool.name = sp->name;
    } else {
2252
        VIR_ERROR(_("Unable to determine storage sp's name."));
2253
        goto cleanup;
2254 2255
    }

2256
    if (memcpy(pool.uuid, sp->uuid, VIR_UUID_BUFLEN) == NULL) {
2257
        VIR_ERROR(_("Unable to determine storage sp's uuid."));
2258
        goto cleanup;
2259 2260 2261
    }

    if ((pool.capacity = phypGetStoragePoolSize(sp->conn, sp->name)) == -1) {
2262
        VIR_ERROR(_("Unable to determine storage sps's size."));
2263
        goto cleanup;
2264 2265
    }

J
Ján Tomko 已提交
2266
    /* Information not available */
2267 2268 2269 2270 2271
    pool.allocation = 0;
    pool.available = 0;

    pool.source.ndevice = 1;

2272
    if ((pool.source.adapter.data.name =
2273
         phypGetStoragePoolDevice(sp->conn, sp->name)) == NULL) {
2274
        VIR_ERROR(_("Unable to determine storage sps's source adapter."));
2275
        goto cleanup;
2276 2277 2278 2279 2280
    }

    if (vol->name != NULL)
        voldef.name = vol->name;
    else {
2281
        VIR_ERROR(_("Unable to determine storage pool's name."));
2282
        goto cleanup;
2283 2284
    }

2285 2286 2287 2288
    voldef.key = strdup(vol->key);

    if (voldef.key == NULL) {
        virReportOOMError();
2289
        goto cleanup;
2290 2291 2292 2293
    }

    voldef.type = VIR_STORAGE_POOL_LOGICAL;

2294 2295 2296 2297
    xml = virStorageVolDefFormat(&pool, &voldef);

    VIR_FREE(voldef.key);

2298
cleanup:
2299
    virObjectUnref(sp);
2300
    return xml;
2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321
}

/* The Volume Group path here will be treated as suggested in the
 * email on the libvirt mailling list. As soon as I can't get the
 * path for every volume, the path will be a representation in
 * the form:
 *
 * /physical_volume/storage_pool/logical_volume
 *
 * */
static char *
phypVolumeGetPath(virStorageVolPtr vol)
{
    virConnectPtr conn = vol->conn;
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
2322
    char *ret = NULL;
2323 2324
    char *path = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
2325
    char *pv;
2326 2327

    if (system_type == HMC)
2328
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2329 2330
                          managed_system, vios_id);

2331
    virBufferAsprintf(&buf, "lslv %s -field vgname", vol->name);
2332 2333 2334 2335

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

2336
    virBufferAsprintf(&buf,
2337
                      "|sed -e 's/^VOLUME GROUP://g' -e 's/ //g'");
2338
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
2339

2340
    if (exit_status < 0 || ret == NULL)
2341
        goto cleanup;
2342

2343
    pv = phypVolumeGetPhysicalVolumeByStoragePool(vol, ret);
2344

2345 2346
    if (!pv)
        goto cleanup;
2347

2348
    if (virAsprintf(&path, "/%s/%s/%s", pv, ret, vol->name) < 0) {
2349 2350 2351
        virReportOOMError();
        goto cleanup;
    }
2352

2353
cleanup:
2354
    VIR_FREE(ret);
2355
    VIR_FREE(path);
2356 2357

    return path;
2358 2359 2360 2361 2362 2363
}

static int
phypStoragePoolListVolumes(virStoragePoolPtr pool, char **const volumes,
                           int nvolumes)
{
2364
    bool success = false;
2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376
    virConnectPtr conn = pool->conn;
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    int got = 0;
    int i;
    char *ret = NULL;
    char *volumes_list = NULL;
E
Eric Blake 已提交
2377
    char *char_ptr = NULL;
2378 2379 2380
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2381
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2382 2383
                          managed_system, vios_id);

2384
    virBufferAsprintf(&buf, "lsvg -lv %s -field lvname", pool->name);
2385 2386 2387 2388

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

2389
    virBufferAsprintf(&buf, "|sed '1,2d'");
2390
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
2391 2392 2393

    /* I need to parse the textual return in order to get the volumes */
    if (exit_status < 0 || ret == NULL)
2394
        goto cleanup;
2395 2396 2397 2398
    else {
        volumes_list = ret;

        while (got < nvolumes) {
E
Eric Blake 已提交
2399
            char_ptr = strchr(volumes_list, '\n');
2400

E
Eric Blake 已提交
2401 2402
            if (char_ptr) {
                *char_ptr = '\0';
2403 2404
                if ((volumes[got++] = strdup(volumes_list)) == NULL) {
                    virReportOOMError();
2405
                    goto cleanup;
2406
                }
E
Eric Blake 已提交
2407 2408
                char_ptr++;
                volumes_list = char_ptr;
2409 2410 2411 2412 2413
            } else
                break;
        }
    }

2414 2415
    success = true;

2416
cleanup:
2417 2418 2419 2420 2421 2422
    if (!success) {
        for (i = 0; i < got; i++)
            VIR_FREE(volumes[i]);

        got = -1;
    }
2423
    VIR_FREE(ret);
2424
    return got;
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434
}

static int
phypStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
    virConnectPtr conn = pool->conn;
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
2435
    int nvolumes = -1;
2436 2437 2438 2439 2440
    char *managed_system = phyp_driver->managed_system;
    int vios_id = phyp_driver->vios_id;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2441
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2442
                          managed_system, vios_id);
2443
    virBufferAsprintf(&buf, "lsvg -lv %s -field lvname", pool->name);
2444 2445
    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');
2446
    virBufferAsprintf(&buf, "|grep -c '^.*$'");
E
Eric Blake 已提交
2447 2448
    if (phypExecInt(session, &buf, conn, &nvolumes) < 0)
        return -1;
2449 2450

    /* We need to remove 2 line from the header text output */
E
Eric Blake 已提交
2451
    return nvolumes - 2;
2452 2453 2454 2455 2456
}

static int
phypDestroyStoragePool(virStoragePoolPtr pool)
{
2457
    int result = -1;
2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
    virConnectPtr conn = pool->conn;
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int vios_id = phyp_driver->vios_id;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    char *ret = NULL;
    int exit_status = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2470
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2471 2472
                          managed_system, vios_id);

2473
    virBufferAsprintf(&buf, "rmsp %s", pool->name);
2474 2475 2476

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');
2477
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
2478 2479

    if (exit_status < 0) {
2480
        VIR_ERROR(_("Unable to destroy Storage Pool: %s"), NULLSTR(ret));
2481
        goto cleanup;
2482 2483
    }

2484
    result = 0;
2485

2486
cleanup:
2487
    VIR_FREE(ret);
2488 2489

    return result;
2490 2491 2492 2493 2494
}

static int
phypBuildStoragePool(virConnectPtr conn, virStoragePoolDefPtr def)
{
2495
    int result = -1;
2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virStoragePoolSource source = def->source;
    int vios_id = phyp_driver->vios_id;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    char *ret = NULL;
    int exit_status = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

2507 2508 2509 2510 2511 2512 2513
    if (source.adapter.type !=
        VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_SCSI_HOST) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Only 'scsi_host' adapter is supported"));
        goto cleanup;
    }

2514
    if (system_type == HMC)
2515
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2516 2517
                          managed_system, vios_id);

2518
    virBufferAsprintf(&buf, "mksp -f %schild %s", def->name,
2519
                      source.adapter.data.name);
2520 2521 2522

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');
2523
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
2524 2525

    if (exit_status < 0) {
2526
        VIR_ERROR(_("Unable to create Storage Pool: %s"), NULLSTR(ret));
2527
        goto cleanup;
2528 2529
    }

2530
    result = 0;
2531

2532
cleanup:
2533
    VIR_FREE(ret);
2534 2535

    return result;
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545

}

static int
phypNumOfStoragePools(virConnectPtr conn)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
2546
    int nsp = -1;
2547 2548 2549 2550 2551
    char *managed_system = phyp_driver->managed_system;
    int vios_id = phyp_driver->vios_id;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2552
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2553 2554
                          managed_system, vios_id);

2555
    virBufferAsprintf(&buf, "lsvg");
2556 2557 2558 2559

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');

2560
    virBufferAsprintf(&buf, "|grep -c '^.*$'");
E
Eric Blake 已提交
2561
    phypExecInt(session, &buf, conn, &nsp);
2562
    return nsp;
2563 2564 2565 2566 2567
}

static int
phypListStoragePools(virConnectPtr conn, char **const pools, int npools)
{
2568
    bool success = false;
2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    int got = 0;
    int i;
    char *ret = NULL;
    char *storage_pools = NULL;
E
Eric Blake 已提交
2580
    char *char_ptr = NULL;
2581 2582 2583
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    if (system_type == HMC)
2584
        virBufferAsprintf(&buf, "viosvrcmd -m %s --id %d -c '",
2585 2586
                          managed_system, vios_id);

2587
    virBufferAsprintf(&buf, "lsvg");
2588 2589 2590

    if (system_type == HMC)
        virBufferAddChar(&buf, '\'');
2591
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
2592 2593 2594

    /* I need to parse the textual return in order to get the storage pools */
    if (exit_status < 0 || ret == NULL)
2595
        goto cleanup;
2596 2597 2598 2599
    else {
        storage_pools = ret;

        while (got < npools) {
E
Eric Blake 已提交
2600
            char_ptr = strchr(storage_pools, '\n');
2601

E
Eric Blake 已提交
2602 2603
            if (char_ptr) {
                *char_ptr = '\0';
2604 2605
                if ((pools[got++] = strdup(storage_pools)) == NULL) {
                    virReportOOMError();
2606
                    goto cleanup;
2607
                }
E
Eric Blake 已提交
2608 2609
                char_ptr++;
                storage_pools = char_ptr;
2610 2611 2612 2613 2614
            } else
                break;
        }
    }

2615 2616
    success = true;

2617
cleanup:
2618 2619 2620 2621 2622 2623
    if (!success) {
        for (i = 0; i < got; i++)
            VIR_FREE(pools[i]);

        got = -1;
    }
2624
    VIR_FREE(ret);
2625
    return got;
2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668
}

static virStoragePoolPtr
phypGetStoragePoolLookUpByUUID(virConnectPtr conn,
                               const unsigned char *uuid)
{
    virStoragePoolPtr sp = NULL;
    int npools = 0;
    int gotpools = 0;
    char **pools = NULL;
    unsigned int i = 0;
    unsigned char *local_uuid = NULL;

    if (VIR_ALLOC_N(local_uuid, VIR_UUID_BUFLEN) < 0) {
        virReportOOMError();
        goto err;
    }

    if ((npools = phypNumOfStoragePools(conn)) == -1) {
        virReportOOMError();
        goto err;
    }

    if (VIR_ALLOC_N(pools, npools) < 0) {
        virReportOOMError();
        goto err;
    }

    if ((gotpools = phypListStoragePools(conn, pools, npools)) == -1) {
        virReportOOMError();
        goto err;
    }

    if (gotpools != npools) {
        virReportOOMError();
        goto err;
    }

    for (i = 0; i < gotpools; i++) {
        if (phypGetStoragePoolUUID(conn, local_uuid, pools[i]) == -1)
            continue;

        if (!memcmp(local_uuid, uuid, VIR_UUID_BUFLEN)) {
2669
            sp = virGetStoragePool(conn, pools[i], uuid, NULL, NULL);
2670 2671 2672 2673 2674 2675 2676 2677 2678 2679
            VIR_FREE(local_uuid);
            VIR_FREE(pools);

            if (sp)
                return sp;
            else
                goto err;
        }
    }

2680
err:
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
    VIR_FREE(local_uuid);
    VIR_FREE(pools);
    return NULL;
}

static virStoragePoolPtr
phypStoragePoolCreateXML(virConnectPtr conn,
                         const char *xml, unsigned int flags)
{
    virCheckFlags(0, NULL);

    virStoragePoolDefPtr def = NULL;
2693
    virStoragePoolPtr dup_sp = NULL;
2694 2695 2696 2697 2698 2699
    virStoragePoolPtr sp = NULL;

    if (!(def = virStoragePoolDefParseString(xml)))
        goto err;

    /* checking if this name already exists on this system */
2700
    if ((dup_sp = phypStoragePoolLookupByName(conn, def->name)) != NULL) {
2701
        VIR_WARN("StoragePool name already exists.");
2702
        virObjectUnref(dup_sp);
2703 2704 2705 2706
        goto err;
    }

    /* checking if ID or UUID already exists on this system */
2707
    if ((dup_sp = phypGetStoragePoolLookUpByUUID(conn, def->uuid)) != NULL) {
2708
        VIR_WARN("StoragePool uuid already exists.");
2709
        virObjectUnref(dup_sp);
2710 2711
        goto err;
    }
2712

2713
    if ((sp = virGetStoragePool(conn, def->name, def->uuid, NULL, NULL)) == NULL)
2714 2715 2716 2717 2718 2719 2720
        goto err;

    if (phypBuildStoragePool(conn, def) == -1)
        goto err;

    return sp;

2721
err:
2722
    virStoragePoolDefFree(def);
2723
    virObjectUnref(sp);
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737
    return NULL;
}

static char *
phypGetStoragePoolXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
    virCheckFlags(0, NULL);

    virStoragePoolDef def;
    memset(&def, 0, sizeof(virStoragePoolDef));

    if (pool->name != NULL)
        def.name = pool->name;
    else {
2738
        VIR_ERROR(_("Unable to determine storage pool's name."));
2739 2740 2741
        goto err;
    }

2742
    if (memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN) == NULL) {
2743
        VIR_ERROR(_("Unable to determine storage pool's uuid."));
2744 2745 2746 2747 2748
        goto err;
    }

    if ((def.capacity =
         phypGetStoragePoolSize(pool->conn, pool->name)) == -1) {
2749
        VIR_ERROR(_("Unable to determine storage pools's size."));
2750 2751 2752
        goto err;
    }

J
Ján Tomko 已提交
2753
    /* Information not available */
2754 2755 2756 2757 2758 2759
    def.allocation = 0;
    def.available = 0;

    def.source.ndevice = 1;

    /*XXX source adapter not working properly, should show hdiskX */
2760
    if ((def.source.adapter.data.name =
2761
         phypGetStoragePoolDevice(pool->conn, pool->name)) == NULL) {
2762
        VIR_ERROR(_("Unable to determine storage pools's source adapter."));
2763 2764 2765 2766 2767
        goto err;
    }

    return virStoragePoolDefFormat(&def);

2768
err:
2769
    return NULL;
2770 2771
}

E
Eduardo Otubo 已提交
2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787
static int
phypInterfaceDestroy(virInterfacePtr iface,
                     unsigned int flags)
{
    virCheckFlags(0, -1);

    ConnectionData *connection_data = iface->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = iface->conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int exit_status = 0;
    int slot_num = 0;
    int lpar_id = 0;
    char *ret = NULL;
E
Eric Blake 已提交
2788
    int rv = -1;
E
Eduardo Otubo 已提交
2789 2790 2791 2792 2793

    /* Getting the remote slot number */

    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2794
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2795

2796
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2797 2798 2799
                      " -r virtualio --rsubtype eth --level lpar "
                      " -F mac_addr,slot_num|"
                      " sed -n '/%s/ s/^.*,//p'", iface->mac);
E
Eric Blake 已提交
2800
    if (phypExecInt(session, &buf, iface->conn, &slot_num) < 0)
E
Eric Blake 已提交
2801
        goto cleanup;
E
Eduardo Otubo 已提交
2802 2803 2804 2805

    /* Getting the remote slot number */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2806
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2807

2808
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2809 2810 2811
                      " -r virtualio --rsubtype eth --level lpar "
                      " -F mac_addr,lpar_id|"
                      " sed -n '/%s/ s/^.*,//p'", iface->mac);
E
Eric Blake 已提交
2812
    if (phypExecInt(session, &buf, iface->conn, &lpar_id) < 0)
E
Eric Blake 已提交
2813
        goto cleanup;
E
Eduardo Otubo 已提交
2814 2815 2816 2817

    /* excluding interface */
    virBufferAddLit(&buf, "chhwres ");
    if (system_type == HMC)
2818
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2819

2820
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2821 2822
                      " -r virtualio --rsubtype eth"
                      " --id %d -o r -s %d", lpar_id, slot_num);
2823 2824
    VIR_FREE(ret);
    ret = phypExecBuffer(session, &buf, &exit_status, iface->conn, false);
E
Eduardo Otubo 已提交
2825 2826

    if (exit_status < 0 || ret != NULL)
E
Eric Blake 已提交
2827
        goto cleanup;
E
Eduardo Otubo 已提交
2828

E
Eric Blake 已提交
2829
    rv = 0;
E
Eduardo Otubo 已提交
2830

E
Eric Blake 已提交
2831
cleanup:
E
Eduardo Otubo 已提交
2832
    VIR_FREE(ret);
E
Eric Blake 已提交
2833
    return rv;
E
Eduardo Otubo 已提交
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853
}

static virInterfacePtr
phypInterfaceDefineXML(virConnectPtr conn, const char *xml,
                       unsigned int flags)
{
    virCheckFlags(0, NULL);

    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int exit_status = 0;
    int slot = 0;
    char *ret = NULL;
    char name[PHYP_IFACENAME_SIZE];
    char mac[PHYP_MAC_SIZE];
    virInterfaceDefPtr def;
E
Eric Blake 已提交
2854
    virInterfacePtr result = NULL;
E
Eduardo Otubo 已提交
2855 2856

    if (!(def = virInterfaceDefParseString(xml)))
E
Eric Blake 已提交
2857
        goto cleanup;
E
Eduardo Otubo 已提交
2858 2859 2860 2861

    /* Now need to get the next free slot number */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2862
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2863

2864
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2865 2866 2867
                      " -r virtualio --rsubtype slot --level slot"
                      " -Fslot_num --filter lpar_names=%s"
                      " |sort|tail -n 1", def->name);
E
Eric Blake 已提交
2868
    if (phypExecInt(session, &buf, conn, &slot) < 0)
E
Eric Blake 已提交
2869
        goto cleanup;
E
Eduardo Otubo 已提交
2870 2871 2872 2873 2874 2875 2876

    /* The next free slot itself: */
    slot++;

    /* Now adding the new network interface */
    virBufferAddLit(&buf, "chhwres ");
    if (system_type == HMC)
2877
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2878

2879
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2880 2881 2882
                      " -r virtualio --rsubtype eth"
                      " -p %s -o a -s %d -a port_vlan_id=1,"
                      "ieee_virtual_eth=0", def->name, slot);
2883 2884
    VIR_FREE(ret);
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
E
Eduardo Otubo 已提交
2885 2886

    if (exit_status < 0 || ret != NULL)
E
Eric Blake 已提交
2887
        goto cleanup;
E
Eduardo Otubo 已提交
2888 2889 2890 2891 2892 2893 2894 2895 2896

    /* Need to sleep a little while to wait for the HMC to
     * complete the execution of the command.
     * */
    sleep(1);

    /* Getting the new interface name */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2897
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2898

2899
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2900 2901 2902
                      " -r virtualio --rsubtype slot --level slot"
                      " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; "
                      "s/^.*drc_name=//'", def->name, slot);
2903 2904
    VIR_FREE(ret);
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
E
Eduardo Otubo 已提交
2905 2906 2907 2908 2909

    if (exit_status < 0 || ret == NULL) {
        /* roll back and excluding interface if error*/
        virBufferAddLit(&buf, "chhwres ");
        if (system_type == HMC)
2910
            virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2911

2912
        virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2913 2914
                " -r virtualio --rsubtype eth"
                " -p %s -o r -s %d", def->name, slot);
2915 2916
        VIR_FREE(ret);
        ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
E
Eric Blake 已提交
2917
        goto cleanup;
E
Eduardo Otubo 已提交
2918 2919 2920 2921 2922 2923 2924
    }

    memcpy(name, ret, PHYP_IFACENAME_SIZE-1);

    /* Getting the new interface mac addr */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2925
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2926

2927
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2928 2929 2930
                      "-r virtualio --rsubtype eth --level lpar "
                      " |sed '/lpar_name=%s/!d; /slot_num=%d/!d; "
                      "s/^.*mac_addr=//'", def->name, slot);
2931 2932
    VIR_FREE(ret);
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
E
Eduardo Otubo 已提交
2933 2934

    if (exit_status < 0 || ret == NULL)
E
Eric Blake 已提交
2935
        goto cleanup;
E
Eduardo Otubo 已提交
2936 2937 2938

    memcpy(mac, ret, PHYP_MAC_SIZE-1);

E
Eric Blake 已提交
2939
    result = virGetInterface(conn, name, mac);
E
Eduardo Otubo 已提交
2940

E
Eric Blake 已提交
2941
cleanup:
E
Eduardo Otubo 已提交
2942 2943
    VIR_FREE(ret);
    virInterfaceDefFree(def);
E
Eric Blake 已提交
2944
    return result;
E
Eduardo Otubo 已提交
2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960
}

static virInterfacePtr
phypInterfaceLookupByName(virConnectPtr conn, const char *name)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int exit_status = 0;
    char *ret = NULL;
    int slot = 0;
    int lpar_id = 0;
    char mac[PHYP_MAC_SIZE];
2961
    virInterfacePtr result = NULL;
E
Eduardo Otubo 已提交
2962 2963 2964 2965

    /*Getting the slot number for the interface */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2966
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2967

2968
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2969 2970 2971
                      " -r virtualio --rsubtype slot --level slot "
                      " -F drc_name,slot_num |"
                      " sed -n '/%s/ s/^.*,//p'", name);
E
Eric Blake 已提交
2972
    if (phypExecInt(session, &buf, conn, &slot) < 0)
E
Eric Blake 已提交
2973
        goto cleanup;
E
Eduardo Otubo 已提交
2974 2975 2976 2977

    /*Getting the lpar_id for the interface */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2978
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2979

2980
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2981 2982 2983
                      " -r virtualio --rsubtype slot --level slot "
                      " -F drc_name,lpar_id |"
                      " sed -n '/%s/ s/^.*,//p'", name);
E
Eric Blake 已提交
2984
    if (phypExecInt(session, &buf, conn, &lpar_id) < 0)
E
Eric Blake 已提交
2985
        goto cleanup;
E
Eduardo Otubo 已提交
2986 2987 2988 2989

    /*Getting the interface mac */
    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
2990
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
2991

2992
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
2993 2994 2995
                      " -r virtualio --rsubtype eth --level lpar "
                      " -F lpar_id,slot_num,mac_addr|"
                      " sed -n '/%d,%d/ s/^.*,//p'", lpar_id, slot);
2996
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
E
Eduardo Otubo 已提交
2997 2998

    if (exit_status < 0 || ret == NULL)
E
Eric Blake 已提交
2999
        goto cleanup;
E
Eduardo Otubo 已提交
3000 3001 3002

    memcpy(mac, ret, PHYP_MAC_SIZE-1);

3003
    result = virGetInterface(conn, name, ret);
E
Eduardo Otubo 已提交
3004

E
Eric Blake 已提交
3005
cleanup:
E
Eduardo Otubo 已提交
3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018
    VIR_FREE(ret);
    return result;
}

static int
phypInterfaceIsActive(virInterfacePtr iface)
{
    ConnectionData *connection_data = iface->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = iface->conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
E
Eric Blake 已提交
3019
    int state = -1;
E
Eduardo Otubo 已提交
3020 3021 3022

    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
3023
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
3024

3025
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
3026 3027 3028
                      " -r virtualio --rsubtype eth --level lpar "
                      " -F mac_addr,state |"
                      " sed -n '/%s/ s/^.*,//p'", iface->mac);
E
Eric Blake 已提交
3029
    phypExecInt(session, &buf, iface->conn, &state);
E
Eduardo Otubo 已提交
3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
    return state;
}

static int
phypListInterfaces(virConnectPtr conn, char **const names, int nnames)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int vios_id = phyp_driver->vios_id;
    int exit_status = 0;
    int got = 0;
    int i;
    char *ret = NULL;
    char *networks = NULL;
E
Eric Blake 已提交
3047
    char *char_ptr = NULL;
E
Eduardo Otubo 已提交
3048
    virBuffer buf = VIR_BUFFER_INITIALIZER;
E
Eric Blake 已提交
3049
    bool success = false;
E
Eduardo Otubo 已提交
3050 3051 3052

    virBufferAddLit(&buf, "lshwres");
    if (system_type == HMC)
3053 3054
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r virtualio --rsubtype slot  --level slot|"
E
Eduardo Otubo 已提交
3055 3056
                      " sed '/eth/!d; /lpar_id=%d/d; s/^.*drc_name=//g'",
                      vios_id);
3057
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
E
Eduardo Otubo 已提交
3058

E
Eric Blake 已提交
3059 3060
    /* I need to parse the textual return in order to get the network
     * interfaces */
E
Eduardo Otubo 已提交
3061
    if (exit_status < 0 || ret == NULL)
E
Eric Blake 已提交
3062
        goto cleanup;
E
Eduardo Otubo 已提交
3063 3064 3065 3066

    networks = ret;

    while (got < nnames) {
E
Eric Blake 已提交
3067
        char_ptr = strchr(networks, '\n');
E
Eduardo Otubo 已提交
3068

E
Eric Blake 已提交
3069 3070
        if (char_ptr) {
            *char_ptr = '\0';
E
Eduardo Otubo 已提交
3071 3072
            if ((names[got++] = strdup(networks)) == NULL) {
                virReportOOMError();
E
Eric Blake 已提交
3073
                goto cleanup;
E
Eduardo Otubo 已提交
3074
            }
E
Eric Blake 已提交
3075 3076
            char_ptr++;
            networks = char_ptr;
E
Eduardo Otubo 已提交
3077 3078 3079 3080 3081
        } else {
            break;
        }
    }

E
Eric Blake 已提交
3082 3083 3084 3085 3086
cleanup:
    if (!success) {
        for (i = 0; i < got; i++)
            VIR_FREE(names[i]);
    }
E
Eduardo Otubo 已提交
3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099
    VIR_FREE(ret);
    return got;
}

static int
phypNumOfInterfaces(virConnectPtr conn)
{
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    char *managed_system = phyp_driver->managed_system;
    int system_type = phyp_driver->system_type;
    int vios_id = phyp_driver->vios_id;
E
Eric Blake 已提交
3100
    int nnets = -1;
E
Eduardo Otubo 已提交
3101 3102 3103 3104
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&buf, "lshwres ");
    if (system_type == HMC)
3105
        virBufferAsprintf(&buf, "-m %s ", managed_system);
E
Eduardo Otubo 已提交
3106

3107
    virBufferAsprintf(&buf,
E
Eduardo Otubo 已提交
3108 3109
                      "-r virtualio --rsubtype eth --level lpar|"
                      "grep -v lpar_id=%d|grep -c lpar_name", vios_id);
E
Eric Blake 已提交
3110
    phypExecInt(session, &buf, conn, &nnets);
E
Eduardo Otubo 已提交
3111 3112 3113
    return nnets;
}

3114 3115
static int
phypGetLparState(virConnectPtr conn, unsigned int lpar_id)
3116
{
3117
    ConnectionData *connection_data = conn->networkPrivateData;
3118
    phyp_driverPtr phyp_driver = conn->privateData;
3119 3120 3121 3122 3123 3124 3125
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *ret = NULL;
    int exit_status = 0;
    char *managed_system = phyp_driver->managed_system;
    int state = VIR_DOMAIN_NOSTATE;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3126

3127 3128
    virBufferAddLit(&buf, "lssyscfg -r lpar");
    if (system_type == HMC)
3129 3130
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -F state --filter lpar_ids=%d", lpar_id);
3131
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
3132

3133 3134
    if (exit_status < 0 || ret == NULL)
        goto cleanup;
3135

3136 3137 3138 3139 3140 3141
    if (STREQ(ret, "Running"))
        state = VIR_DOMAIN_RUNNING;
    else if (STREQ(ret, "Not Activated"))
        state = VIR_DOMAIN_SHUTOFF;
    else if (STREQ(ret, "Shutting Down"))
        state = VIR_DOMAIN_SHUTDOWN;
3142

3143
cleanup:
3144 3145
    VIR_FREE(ret);
    return state;
3146 3147
}

3148 3149 3150 3151
/* XXX - is this needed? */
static int phypDiskType(virConnectPtr, char *) ATTRIBUTE_UNUSED;
static int
phypDiskType(virConnectPtr conn, char *backing_device)
3152 3153
{
    phyp_driverPtr phyp_driver = conn->privateData;
3154 3155 3156 3157 3158 3159 3160 3161 3162
    ConnectionData *connection_data = conn->networkPrivateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *ret = NULL;
    int exit_status = 0;
    char *managed_system = phyp_driver->managed_system;
    int vios_id = phyp_driver->vios_id;
    int disk_type = -1;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3163

3164 3165
    virBufferAddLit(&buf, "viosvrcmd");
    if (system_type == HMC)
3166 3167
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -p %d -c \"lssp -field name type "
E
Eric Blake 已提交
3168
                      "-fmt , -all|sed -n '/%s/ {\n s/^.*,//\n p\n}'\"",
3169
                      vios_id, backing_device);
3170
    ret = phypExecBuffer(session, &buf, &exit_status, conn, true);
3171

3172 3173
    if (exit_status < 0 || ret == NULL)
        goto cleanup;
3174

3175 3176 3177 3178
    if (STREQ(ret, "LVPOOL"))
        disk_type = VIR_DOMAIN_DISK_TYPE_BLOCK;
    else if (STREQ(ret, "FBPOOL"))
        disk_type = VIR_DOMAIN_DISK_TYPE_FILE;
3179

3180
cleanup:
3181 3182 3183
    VIR_FREE(ret);
    return disk_type;
}
3184

3185 3186 3187 3188 3189
static int
phypNumDefinedDomains(virConnectPtr conn)
{
    return phypNumDomainsGeneric(conn, 1);
}
3190

3191 3192 3193 3194
static int
phypNumDomains(virConnectPtr conn)
{
    return phypNumDomainsGeneric(conn, 0);
3195 3196
}

3197 3198
static int
phypListDomains(virConnectPtr conn, int *ids, int nids)
3199
{
3200 3201
    return phypListDomainsGeneric(conn, ids, nids, 0);
}
3202

3203 3204 3205
static int
phypListDefinedDomains(virConnectPtr conn, char **const names, int nnames)
{
3206
    bool success = false;
3207 3208 3209 3210 3211 3212 3213 3214 3215 3216
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int exit_status = 0;
    int got = 0;
    int i;
    char *ret = NULL;
    char *domains = NULL;
E
Eric Blake 已提交
3217
    char *char_ptr = NULL;
3218
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3219

3220 3221
    virBufferAddLit(&buf, "lssyscfg -r lpar");
    if (system_type == HMC)
3222 3223
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -F name,state"
E
Eric Blake 已提交
3224
                      "|sed -n '/Not Activated/ {\n s/,.*$//\n p\n}'");
3225
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
3226

3227 3228
    /* I need to parse the textual return in order to get the domains */
    if (exit_status < 0 || ret == NULL)
3229
        goto cleanup;
3230 3231
    else {
        domains = ret;
3232

3233
        while (got < nnames) {
E
Eric Blake 已提交
3234
            char_ptr = strchr(domains, '\n');
3235

E
Eric Blake 已提交
3236 3237
            if (char_ptr) {
                *char_ptr = '\0';
3238
                if ((names[got++] = strdup(domains)) == NULL) {
3239
                    virReportOOMError();
3240
                    goto cleanup;
3241
                }
E
Eric Blake 已提交
3242 3243
                char_ptr++;
                domains = char_ptr;
3244 3245
            } else
                break;
3246
        }
3247 3248
    }

3249 3250
    success = true;

3251
cleanup:
3252 3253 3254 3255 3256 3257
    if (!success) {
        for (i = 0; i < got; i++)
            VIR_FREE(names[i]);

        got = -1;
    }
3258
    VIR_FREE(ret);
3259
    return got;
3260 3261
}

3262 3263
static virDomainPtr
phypDomainLookupByName(virConnectPtr conn, const char *lpar_name)
3264
{
3265 3266 3267 3268 3269 3270 3271
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virDomainPtr dom = NULL;
    int lpar_id = 0;
    char *managed_system = phyp_driver->managed_system;
    unsigned char lpar_uuid[VIR_UUID_BUFLEN];
3272

3273 3274 3275
    lpar_id = phypGetLparID(session, managed_system, lpar_name, conn);
    if (lpar_id == -1)
        return NULL;
3276

3277 3278
    if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
        return NULL;
3279

3280 3281 3282 3283 3284 3285
    dom = virGetDomain(conn, lpar_name, lpar_uuid);

    if (dom)
        dom->id = lpar_id;

    return dom;
3286 3287
}

3288 3289
static virDomainPtr
phypDomainLookupByID(virConnectPtr conn, int lpar_id)
3290 3291
{
    ConnectionData *connection_data = conn->networkPrivateData;
3292
    phyp_driverPtr phyp_driver = conn->privateData;
3293
    LIBSSH2_SESSION *session = connection_data->session;
3294 3295 3296
    virDomainPtr dom = NULL;
    char *managed_system = phyp_driver->managed_system;
    unsigned char lpar_uuid[VIR_UUID_BUFLEN];
E
Eduardo Otubo 已提交
3297

3298 3299
    char *lpar_name = phypGetLparNAME(session, managed_system, lpar_id,
                                      conn);
3300

3301
    if (phypGetLparUUID(lpar_uuid, lpar_id, conn) == -1)
3302
        goto cleanup;
3303

3304
    dom = virGetDomain(conn, lpar_name, lpar_uuid);
3305

3306 3307
    if (dom)
        dom->id = lpar_id;
3308

3309
cleanup:
3310
    VIR_FREE(lpar_name);
3311

3312
    return dom;
3313 3314
}

3315
static char *
3316
phypDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
3317
{
3318 3319
    ConnectionData *connection_data = dom->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = dom->conn->privateData;
3320
    LIBSSH2_SESSION *session = connection_data->session;
3321 3322
    virDomainDef def;
    char *managed_system = phyp_driver->managed_system;
E
Eduardo Otubo 已提交
3323

3324 3325
    /* Flags checked by virDomainDefFormat */

3326
    memset(&def, 0, sizeof(virDomainDef));
E
Eduardo Otubo 已提交
3327

3328 3329 3330 3331 3332 3333 3334
    def.virtType = VIR_DOMAIN_VIRT_PHYP;
    def.id = dom->id;

    char *lpar_name = phypGetLparNAME(session, managed_system, def.id,
                                      dom->conn);

    if (lpar_name == NULL) {
3335
        VIR_ERROR(_("Unable to determine domain's name."));
3336
        goto err;
E
Eduardo Otubo 已提交
3337 3338
    }

3339
    if (phypGetLparUUID(def.uuid, dom->id, dom->conn) == -1) {
3340
        VIR_ERROR(_("Unable to generate random uuid."));
E
Eduardo Otubo 已提交
3341 3342
        goto err;
    }
3343

3344
    if ((def.mem.max_balloon =
3345
         phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0) {
3346
        VIR_ERROR(_("Unable to determine domain's max memory."));
3347 3348
        goto err;
    }
3349

3350
    if ((def.mem.cur_balloon =
3351
         phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0) {
3352
        VIR_ERROR(_("Unable to determine domain's memory."));
3353 3354
        goto err;
    }
3355

E
Eric Blake 已提交
3356
    if ((def.maxvcpus = def.vcpus =
3357
         phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) {
3358
        VIR_ERROR(_("Unable to determine domain's CPU."));
3359
        goto err;
3360
    }
3361

3362
    return virDomainDefFormat(&def, flags);
3363

3364
err:
3365 3366
    return NULL;
}
3367

3368 3369 3370
static int
phypDomainResume(virDomainPtr dom)
{
3371
    int result = -1;
3372 3373 3374 3375 3376 3377 3378 3379
    ConnectionData *connection_data = dom->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = dom->conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3380

3381 3382
    virBufferAddLit(&buf, "chsysstate");
    if (system_type == HMC)
3383 3384
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r lpar -o on --id %d -f %s",
3385
                      dom->id, dom->name);
3386
    ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false);
3387

3388
    if (exit_status < 0)
3389
        goto cleanup;
3390

3391
    result = 0;
3392

3393
cleanup:
3394
    VIR_FREE(ret);
3395 3396

    return result;
3397 3398
}

3399
static int
E
Eric Blake 已提交
3400
phypDomainReboot(virDomainPtr dom, unsigned int flags)
3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412
{
    int result = -1;
    ConnectionData *connection_data = dom->conn->networkPrivateData;
    virConnectPtr conn = dom->conn;
    LIBSSH2_SESSION *session = connection_data->session;
    phyp_driverPtr phyp_driver = conn->privateData;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

E
Eric Blake 已提交
3413 3414
    virCheckFlags(0, -1);

3415 3416
    virBufferAddLit(&buf, "chsysstate");
    if (system_type == HMC)
3417 3418
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf,
3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433
                      " -r lpar -o shutdown --id %d --immed --restart",
                      dom->id);
    ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false);

    if (exit_status < 0)
        goto cleanup;

    result = 0;

  cleanup:
    VIR_FREE(ret);

    return result;
}

3434 3435
static int
phypDomainShutdown(virDomainPtr dom)
3436
{
3437
    int result = -1;
3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449
    ConnectionData *connection_data = dom->conn->networkPrivateData;
    virConnectPtr conn = dom->conn;
    LIBSSH2_SESSION *session = connection_data->session;
    phyp_driverPtr phyp_driver = conn->privateData;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virBufferAddLit(&buf, "chsysstate");
    if (system_type == HMC)
3450 3451
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r lpar -o shutdown --id %d", dom->id);
3452
    ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false);
3453 3454

    if (exit_status < 0)
3455
        goto cleanup;
3456

3457
    result = 0;
3458

3459
cleanup:
3460
    VIR_FREE(ret);
3461 3462

    return result;
3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474
}

static int
phypDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
    phyp_driverPtr phyp_driver = dom->conn->privateData;
    char *managed_system = phyp_driver->managed_system;

    info->state = phypGetLparState(dom->conn, dom->id);

    if ((info->maxMem =
         phypGetLparMem(dom->conn, managed_system, dom->id, 0)) == 0)
3475
        VIR_WARN("Unable to determine domain's max memory.");
3476 3477 3478

    if ((info->memory =
         phypGetLparMem(dom->conn, managed_system, dom->id, 1)) == 0)
3479
        VIR_WARN("Unable to determine domain's memory.");
3480 3481 3482

    if ((info->nrVirtCpu =
         phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
3483
        VIR_WARN("Unable to determine domain's CPU.");
3484 3485 3486 3487

    return 0;
}

3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502
static int
phypDomainGetState(virDomainPtr dom,
                   int *state,
                   int *reason,
                   unsigned int flags)
{
    virCheckFlags(0, -1);

    *state = phypGetLparState(dom->conn, dom->id);
    if (reason)
        *reason = 0;

    return 0;
}

3503
static int
3504 3505
phypDomainDestroyFlags(virDomainPtr dom,
                       unsigned int flags)
3506
{
3507
    int result = -1;
3508 3509 3510 3511 3512 3513 3514 3515 3516
    ConnectionData *connection_data = dom->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = dom->conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int exit_status = 0;
    char *ret = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

3517 3518
    virCheckFlags(0, -1);

3519 3520
    virBufferAddLit(&buf, "rmsyscfg");
    if (system_type == HMC)
3521 3522
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " -r lpar --id %d", dom->id);
3523
    ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false);
3524 3525

    if (exit_status < 0)
3526
        goto cleanup;
3527 3528

    if (phypUUIDTable_RemLpar(dom->conn, dom->id) == -1)
3529
        goto cleanup;
3530

3531
    dom->id = -1;
3532
    result = 0;
3533

3534
cleanup:
3535 3536
    VIR_FREE(ret);

3537
    return result;
3538
}
3539

3540 3541 3542 3543 3544 3545
static int
phypDomainDestroy(virDomainPtr dom)
{
    return phypDomainDestroyFlags(dom, 0);
}

3546 3547
static int
phypBuildLpar(virConnectPtr conn, virDomainDefPtr def)
3548
{
3549
    int result = -1;
3550 3551 3552 3553 3554 3555 3556 3557
    ConnectionData *connection_data = conn->networkPrivateData;
    phyp_driverPtr phyp_driver = conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    char *ret = NULL;
    int exit_status = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
3558

3559
    if (!def->mem.cur_balloon) {
3560 3561 3562
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Field <memory> on the domain XML file is missing or has "
                         "invalid value."));
3563
        goto cleanup;
3564 3565
    }

3566
    if (!def->mem.max_balloon) {
3567 3568 3569
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Field <currentMemory> on the domain XML file is missing or "
                         "has invalid value."));
3570
        goto cleanup;
3571 3572
    }

3573
    if (def->ndisks < 1) {
3574 3575
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Domain XML must contain at least one <disk> element."));
3576
        goto cleanup;
3577 3578 3579
    }

    if (!def->disks[0]->src) {
3580 3581 3582
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("Field <src> under <disk> on the domain XML file is "
                         "missing."));
3583
        goto cleanup;
3584 3585
    }

3586 3587
    virBufferAddLit(&buf, "mksyscfg");
    if (system_type == HMC)
3588
        virBufferAsprintf(&buf, " -m %s", managed_system);
3589 3590 3591 3592
    virBufferAsprintf(&buf, " -r lpar -p %s -i min_mem=%lld,desired_mem=%lld,"
                      "max_mem=%lld,desired_procs=%d,virtual_scsi_adapters=%s",
                      def->name, def->mem.cur_balloon,
                      def->mem.cur_balloon, def->mem.max_balloon,
3593
                      (int) def->vcpus, def->disks[0]->src);
3594
    ret = phypExecBuffer(session, &buf, &exit_status, conn, false);
3595

3596
    if (exit_status < 0) {
3597
        VIR_ERROR(_("Unable to create LPAR. Reason: '%s'"), NULLSTR(ret));
3598
        goto cleanup;
3599
    }
3600

3601
    if (phypUUIDTable_AddLpar(conn, def->uuid, def->id) == -1) {
3602
        VIR_ERROR(_("Unable to add LPAR to the table"));
3603
        goto cleanup;
3604
    }
3605

3606
    result = 0;
3607

3608
cleanup:
3609
    VIR_FREE(ret);
3610 3611

    return result;
3612
}
3613

3614 3615 3616 3617
static virDomainPtr
phypDomainCreateAndStart(virConnectPtr conn,
                         const char *xml, unsigned int flags)
{
E
Eduardo Otubo 已提交
3618
    virCheckFlags(0, NULL);
3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631

    ConnectionData *connection_data = conn->networkPrivateData;
    LIBSSH2_SESSION *session = connection_data->session;
    virDomainDefPtr def = NULL;
    virDomainPtr dom = NULL;
    phyp_driverPtr phyp_driver = conn->privateData;
    uuid_tablePtr uuid_table = phyp_driver->uuid_table;
    lparPtr *lpars = uuid_table->lpars;
    unsigned int i = 0;
    char *managed_system = phyp_driver->managed_system;

    virCheckFlags(0, NULL);

3632 3633 3634
    if (!(def = virDomainDefParseString(xml, phyp_driver->caps,
                                        phyp_driver->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_PHYP,
3635 3636 3637 3638
                                        VIR_DOMAIN_XML_SECURE)))
        goto err;

    /* checking if this name already exists on this system */
3639
    if (phypGetLparID(session, managed_system, def->name, conn) != -1) {
3640
        VIR_WARN("LPAR name already exists.");
3641 3642 3643 3644 3645 3646
        goto err;
    }

    /* checking if ID or UUID already exists on this system */
    for (i = 0; i < uuid_table->nlpars; i++) {
        if (lpars[i]->id == def->id || lpars[i]->uuid == def->uuid) {
3647
            VIR_WARN("LPAR ID or UUID already exists.");
3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
            goto err;
        }
    }

    if ((dom = virGetDomain(conn, def->name, def->uuid)) == NULL)
        goto err;

    if (phypBuildLpar(conn, def) == -1)
        goto err;

    if (phypDomainResume(dom) == -1)
        goto err;

    return dom;

3663
err:
3664
    virDomainDefFree(def);
3665
    virObjectUnref(dom);
3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681
    return NULL;
}

static char *
phypConnectGetCapabilities(virConnectPtr conn)
{
    phyp_driverPtr phyp_driver = conn->privateData;
    char *xml;

    if ((xml = virCapabilitiesFormatXML(phyp_driver->caps)) == NULL)
        virReportOOMError();

    return xml;
}

static int
3682 3683
phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                        unsigned int flags)
3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696
{
    ConnectionData *connection_data = dom->conn->networkPrivateData;
    phyp_driverPtr phyp_driver = dom->conn->privateData;
    LIBSSH2_SESSION *session = connection_data->session;
    int system_type = phyp_driver->system_type;
    char *managed_system = phyp_driver->managed_system;
    int exit_status = 0;
    char *ret = NULL;
    char operation;
    unsigned long ncpus = 0;
    unsigned int amount = 0;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

3697
    if (flags != VIR_DOMAIN_VCPU_LIVE) {
3698
        virReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags);
3699 3700 3701
        return -1;
    }

3702 3703 3704 3705
    if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0)
        return 0;

    if (nvcpus > phypGetLparCPUMAX(dom)) {
3706
        VIR_ERROR(_("You are trying to set a number of CPUs bigger than "
3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721
                     "the max possible."));
        return 0;
    }

    if (ncpus > nvcpus) {
        operation = 'r';
        amount = nvcpus - ncpus;
    } else if (ncpus < nvcpus) {
        operation = 'a';
        amount = nvcpus - ncpus;
    } else
        return 0;

    virBufferAddLit(&buf, "chhwres -r proc");
    if (system_type == HMC)
3722 3723
        virBufferAsprintf(&buf, " -m %s", managed_system);
    virBufferAsprintf(&buf, " --id %d -o %c --procunits %d 2>&1 |sed "
3724 3725
                      "-e 's/^.*\\([0-9][0-9]*.[0-9][0-9]*\\).*$/\\1/'",
                      dom->id, operation, amount);
3726
    ret = phypExecBuffer(session, &buf, &exit_status, dom->conn, false);
3727 3728

    if (exit_status < 0) {
3729
        VIR_ERROR(_
3730 3731 3732 3733 3734 3735
                   ("Possibly you don't have IBM Tools installed in your LPAR."
                    " Contact your support to enable this feature."));
    }

    VIR_FREE(ret);
    return 0;
3736 3737

}
3738

3739 3740 3741 3742 3743 3744
static int
phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus)
{
    return phypDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}

3745
static virDrvOpenStatus
3746 3747
phypVIOSDriverOpen(virConnectPtr conn,
                   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
3748
                   unsigned int flags)
3749
{
E
Eric Blake 已提交
3750 3751
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

3752 3753 3754
    if (conn->driver->no != VIR_DRV_PHYP)
        return VIR_DRV_OPEN_DECLINED;

3755 3756 3757 3758
    return VIR_DRV_OPEN_SUCCESS;
}

static int
3759
phypVIOSDriverClose(virConnectPtr conn ATTRIBUTE_UNUSED)
3760 3761 3762 3763
{
    return 0;
}

3764
static virDriver phypDriver = {
3765 3766
    .no = VIR_DRV_PHYP,
    .name = "PHYP",
3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778
    .open = phypOpen, /* 0.7.0 */
    .close = phypClose, /* 0.7.0 */
    .getCapabilities = phypConnectGetCapabilities, /* 0.7.3 */
    .listDomains = phypListDomains, /* 0.7.0 */
    .numOfDomains = phypNumDomains, /* 0.7.0 */
    .domainCreateXML = phypDomainCreateAndStart, /* 0.7.3 */
    .domainLookupByID = phypDomainLookupByID, /* 0.7.0 */
    .domainLookupByName = phypDomainLookupByName, /* 0.7.0 */
    .domainResume = phypDomainResume, /* 0.7.0 */
    .domainShutdown = phypDomainShutdown, /* 0.7.0 */
    .domainReboot = phypDomainReboot, /* 0.9.1 */
    .domainDestroy = phypDomainDestroy, /* 0.7.3 */
3779
    .domainDestroyFlags = phypDomainDestroyFlags, /* 0.9.4 */
3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792
    .domainGetInfo = phypDomainGetInfo, /* 0.7.0 */
    .domainGetState = phypDomainGetState, /* 0.9.2 */
    .domainSetVcpus = phypDomainSetCPU, /* 0.7.3 */
    .domainSetVcpusFlags = phypDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = phypDomainGetVcpusFlags, /* 0.8.5 */
    .domainGetMaxVcpus = phypGetLparCPUMAX, /* 0.7.3 */
    .domainGetXMLDesc = phypDomainGetXMLDesc, /* 0.7.0 */
    .listDefinedDomains = phypListDefinedDomains, /* 0.7.0 */
    .numOfDefinedDomains = phypNumDefinedDomains, /* 0.7.0 */
    .domainAttachDevice = phypAttachDevice, /* 0.8.2 */
    .isEncrypted = phypIsEncrypted, /* 0.7.3 */
    .isSecure = phypIsSecure, /* 0.7.3 */
    .domainIsUpdated = phypIsUpdated, /* 0.8.6 */
3793
    .isAlive = phypIsAlive, /* 0.9.8 */
3794 3795
};

3796 3797
static virStorageDriver phypStorageDriver = {
    .name = "PHYP",
3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815
    .open = phypVIOSDriverOpen, /* 0.8.2 */
    .close = phypVIOSDriverClose, /* 0.8.2 */

    .numOfPools = phypNumOfStoragePools, /* 0.8.2 */
    .listPools = phypListStoragePools, /* 0.8.2 */
    .poolLookupByName = phypStoragePoolLookupByName, /* 0.8.2 */
    .poolLookupByUUID = phypGetStoragePoolLookUpByUUID, /* 0.8.2 */
    .poolCreateXML = phypStoragePoolCreateXML, /* 0.8.2 */
    .poolDestroy = phypDestroyStoragePool, /* 0.8.2 */
    .poolGetXMLDesc = phypGetStoragePoolXMLDesc, /* 0.8.2 */
    .poolNumOfVolumes = phypStoragePoolNumOfVolumes, /* 0.8.2 */
    .poolListVolumes = phypStoragePoolListVolumes, /* 0.8.2 */

    .volLookupByName = phypVolumeLookupByName, /* 0.8.2 */
    .volLookupByPath = phypVolumeLookupByPath, /* 0.8.2 */
    .volCreateXML = phypStorageVolCreateXML, /* 0.8.2 */
    .volGetXMLDesc = phypVolumeGetXMLDesc, /* 0.8.2 */
    .volGetPath = phypVolumeGetPath, /* 0.8.2 */
3816 3817
};

E
Eduardo Otubo 已提交
3818
static virInterfaceDriver phypInterfaceDriver = {
3819
    .name = "PHYP",
3820 3821 3822 3823 3824 3825 3826 3827
    .open = phypVIOSDriverOpen, /* 0.9.1 */
    .close = phypVIOSDriverClose, /* 0.9.1 */
    .numOfInterfaces = phypNumOfInterfaces, /* 0.9.1 */
    .listInterfaces = phypListInterfaces, /* 0.9.1 */
    .interfaceLookupByName = phypInterfaceLookupByName, /* 0.9.1 */
    .interfaceDefineXML = phypInterfaceDefineXML, /* 0.9.1 */
    .interfaceDestroy = phypInterfaceDestroy, /* 0.9.1 */
    .interfaceIsActive = phypInterfaceIsActive /* 0.9.1 */
3828 3829
};

3830 3831 3832
int
phypRegister(void)
{
3833 3834 3835 3836
    if (virRegisterDriver(&phypDriver) < 0)
        return -1;
    if (virRegisterStorageDriver(&phypStorageDriver) < 0)
        return -1;
E
Eduardo Otubo 已提交
3837
    if (virRegisterInterfaceDriver(&phypInterfaceDriver) < 0)
3838
        return -1;
3839

3840 3841
    return 0;
}