dispatch.c 37.9 KB
Newer Older
D
Daniel P. Berrange 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * dispatch.c: (De-)marshall wire messages to driver functions.
 *
 * Copyright (C) 2006, 2007 Red Hat, Inc.
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

24 25
#include <config.h>

26
#include <unistd.h>
D
Daniel P. Berrange 已提交
27 28 29 30 31 32 33 34 35 36
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/utsname.h>
#include <libvirt/virterror.h>

#include "internal.h"
#include "driver.h"
#include "dispatch.h"
37 38
#include "conf.h"
#include "buf.h"
D
Daniel P. Berrange 已提交
39 40 41 42


static int qemudDispatchFailure(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
43 44 45 46
                                struct qemud_packet_server_data *out) {
    out->type = QEMUD_SERVER_PKT_FAILURE;
    out->qemud_packet_server_data_u.failureReply.code = server->errorCode;
    strcpy(out->qemud_packet_server_data_u.failureReply.message, server->errorMessage);
D
Daniel P. Berrange 已提交
47 48 49 50 51
    return 0;
}


static int qemudDispatchGetVersion(struct qemud_server *server, struct qemud_client *client,
52
                                   struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
53 54 55 56 57
    int version = qemudGetVersion(server);
    if (version < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
58 59
        out->type = QEMUD_SERVER_PKT_GET_VERSION;
        out->qemud_packet_server_data_u.getVersionReply.versionNum = version;
D
Daniel P. Berrange 已提交
60 61 62 63 64
    }
    return 0;
}

static int qemudDispatchGetNodeInfo(struct qemud_server *server, struct qemud_client *client,
65
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
66 67 68 69 70 71 72 73
    struct utsname info;

    if (uname(&info) < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
        return 0;
    }

74 75 76 77 78 79
    if (qemudGetCPUInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.cpus,
                        &out->qemud_packet_server_data_u.getNodeInfoReply.mhz,
                        &out->qemud_packet_server_data_u.getNodeInfoReply.nodes,
                        &out->qemud_packet_server_data_u.getNodeInfoReply.sockets,
                        &out->qemud_packet_server_data_u.getNodeInfoReply.cores,
                        &out->qemud_packet_server_data_u.getNodeInfoReply.threads) < 0) {
D
Daniel P. Berrange 已提交
80 81 82 83
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
        return 0;
    }
84
    if (qemudGetMemInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.memory) < 0) {
D
Daniel P. Berrange 已提交
85 86 87 88 89
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
        return 0;
    }

90 91 92
    out->type = QEMUD_SERVER_PKT_GET_NODEINFO;
    strncpy(out->qemud_packet_server_data_u.getNodeInfoReply.model, info.machine, sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model));
    out->qemud_packet_server_data_u.getNodeInfoReply.model[sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model)-1] = '\0';
D
Daniel P. Berrange 已提交
93 94 95 96

    return 0;
}

97 98 99
static int
qemudDispatchGetCapabilities (struct qemud_server *server,
                              struct qemud_client *client,
100 101
                              struct qemud_packet_client_data *in ATTRIBUTE_UNUSED,
                              struct qemud_packet_server_data *out)
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 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 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
{
    struct utsname utsname;
    int i, j, r;
    int have_kqemu = 0;
    int have_kvm = 0;
    bufferPtr xml;
    int len;

    /* Really, this never fails - look at the man-page. */
    uname (&utsname);

    have_kqemu = access ("/dev/kqemu", F_OK) == 0;
    have_kvm = access ("/dev/kvm", F_OK) == 0;

    /* Construct the XML. */
    xml = bufferNew (1024);
    if (!xml) {
        qemudReportError (server, VIR_ERR_NO_MEMORY, NULL);
        qemudDispatchFailure (server, client, out);
        return 0;
    }

    r = bufferVSprintf (xml,
                        "\
<capabilities>\n\
  <host>\n\
    <cpu>\n\
      <arch>%s</arch>\n\
    </cpu>\n\
  </host>\n",
                        utsname.machine);
    if (r == -1) {
    vir_buffer_failed:
        bufferFree (xml);
        qemudReportError (server, VIR_ERR_NO_MEMORY, NULL);
        qemudDispatchFailure (server, client, out);
        return 0;
    }

    i = -1;
    if (strcmp (utsname.machine, "i686") == 0) i = 0;
    else if (strcmp (utsname.machine, "x86_64") == 0) i = 1;
    if (i >= 0) {
        /* For the default (PC-like) guest, qemudArchs[0] or [1]. */
        r = bufferVSprintf (xml,
                            "\
\n\
  <guest>\n\
    <os_type>hvm</os_type>\n\
    <arch name=\"%s\">\n\
      <wordsize>%d</wordsize>\n\
      <emulator>/usr/bin/%s</emulator>\n\
      <domain type=\"qemu\"/>\n",
                            qemudArchs[i].arch,
                            qemudArchs[i].wordsize,
                            qemudArchs[i].binary);
        if (r == -1) goto vir_buffer_failed;

        for (j = 0; qemudArchs[i].machines[j]; ++j) {
            r = bufferVSprintf (xml,
                                "\
      <machine>%s</machine>\n",
                                qemudArchs[i].machines[j]);
            if (r == -1) goto vir_buffer_failed;
        }

        if (have_kqemu) {
            r = bufferAdd (xml,
                           "\
      <domain type=\"kqemu\"/>\n", -1);
            if (r == -1) goto vir_buffer_failed;
        }
        if (have_kvm) {
            r = bufferAdd (xml,
                           "\
      <domain type=\"kvm\">\n\
        <emulator>/usr/bin/qemu-kvm</emulator>\n\
      </domain>\n", -1);
            if (r == -1) goto vir_buffer_failed;
        }
        r = bufferAdd (xml,
                       "\
    </arch>\n\
  </guest>\n", -1);
        if (r == -1) goto vir_buffer_failed;

        /* The "other" PC architecture needs emulation. */
        i = i ^ 1;
        r = bufferVSprintf (xml,
                            "\
\n\
  <guest>\n\
    <os_type>hvm</os_type>\n\
    <arch name=\"%s\">\n\
      <wordsize>%d</wordsize>\n\
      <emulator>/usr/bin/%s</emulator>\n\
      <domain type=\"qemu\"/>\n",
                            qemudArchs[i].arch,
                            qemudArchs[i].wordsize,
                            qemudArchs[i].binary);
        if (r == -1) goto vir_buffer_failed;
        for (j = 0; qemudArchs[i].machines[j]; ++j) {
            r = bufferVSprintf (xml,
                                "\
      <machine>%s</machine>\n",
                                qemudArchs[i].machines[j]);
            if (r == -1) goto vir_buffer_failed;
        }
        r = bufferAdd (xml,
                       "\
    </arch>\n\
  </guest>\n", -1);
        if (r == -1) goto vir_buffer_failed;
    }

    /* The non-PC architectures, qemudArchs[>=2]. */
    for (i = 2; qemudArchs[i].arch; ++i) {
        r = bufferVSprintf (xml,
                            "\
\n\
  <guest>\n\
    <os_type>hvm</os_type>\n\
    <arch name=\"%s\">\n\
      <wordsize>%d</wordsize>\n\
      <emulator>/usr/bin/%s</emulator>\n\
      <domain type=\"qemu\"/>\n",
                            qemudArchs[i].arch,
                            qemudArchs[i].wordsize,
                            qemudArchs[i].binary);
        if (r == -1) goto vir_buffer_failed;
        for (j = 0; qemudArchs[i].machines[j]; ++j) {
            r = bufferVSprintf (xml,
                                "\
      <machine>%s</machine>\n",
                                qemudArchs[i].machines[j]);
            if (r == -1) goto vir_buffer_failed;
        }
        r = bufferAdd (xml,
                       "\
    </arch>\n\
  </guest>\n", -1);
        if (r == -1) goto vir_buffer_failed;
    }

    /* Finish off. */
    r = bufferAdd (xml,
                      "\
</capabilities>\n", -1);
    if (r == -1) goto vir_buffer_failed;

    /* Copy the XML into the outgoing packet, assuming it's not too large. */
    len = strlen (xml->content);
    if (len > QEMUD_MAX_XML_LEN) {
        bufferFree (xml);
        qemudReportError (server, VIR_ERR_XML_ERROR, NULL);
        qemudDispatchFailure (server, client, out);
        return 0;
    }
260 261
    out->type = QEMUD_SERVER_PKT_GET_CAPABILITIES;
    strcpy (out->qemud_packet_server_data_u.getCapabilitiesReply.xml, xml->content);
262 263 264 265
    bufferFree (xml);
    return 0;
}

D
Daniel P. Berrange 已提交
266
static int qemudDispatchListDomains(struct qemud_server *server, struct qemud_client *client,
267
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
268 269 270 271 272 273 274 275 276
    int i, ndomains, domains[QEMUD_MAX_NUM_DOMAINS];

    ndomains = qemudListDomains(server,
                                domains,
                                QEMUD_MAX_NUM_DOMAINS);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
277
        out->type = QEMUD_SERVER_PKT_LIST_DOMAINS;
D
Daniel P. Berrange 已提交
278
        for (i = 0 ; i < ndomains ; i++) {
279
            out->qemud_packet_server_data_u.listDomainsReply.domains[i] = domains[i];
D
Daniel P. Berrange 已提交
280
        }
281
        out->qemud_packet_server_data_u.listDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
282 283 284 285 286
    }
    return 0;
}

static int qemudDispatchNumDomains(struct qemud_server *server, struct qemud_client *client,
287
                                   struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
288 289 290 291 292
    int ndomains = qemudNumDomains(server);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
293 294
        out->type = QEMUD_SERVER_PKT_NUM_DOMAINS;
        out->qemud_packet_server_data_u.numDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
295 296 297 298 299
    }
    return 0;
}

static int qemudDispatchDomainCreate(struct qemud_server *server, struct qemud_client *client,
300 301
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    in->qemud_packet_client_data_u.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
D
Daniel P. Berrange 已提交
302

303
    struct qemud_vm *vm = qemudDomainCreate(server, in->qemud_packet_client_data_u.domainCreateRequest.xml);
D
Daniel P. Berrange 已提交
304 305 306 307
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
308 309 310 311 312
        out->type = QEMUD_SERVER_PKT_DOMAIN_CREATE;
        out->qemud_packet_server_data_u.domainCreateReply.id = vm->id;
        memcpy(out->qemud_packet_server_data_u.domainCreateReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.domainCreateReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
D
Daniel P. Berrange 已提交
313 314 315 316 317
    }
    return 0;
}

static int qemudDispatchDomainLookupByID(struct qemud_server *server, struct qemud_client *client,
318 319
                                         struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    struct qemud_vm *vm = qemudFindVMByID(server, in->qemud_packet_client_data_u.domainLookupByIDRequest.id);
D
Daniel P. Berrange 已提交
320 321 322 323
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
324 325 326 327
        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID;
        memcpy(out->qemud_packet_server_data_u.domainLookupByIDReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.domainLookupByIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
D
Daniel P. Berrange 已提交
328 329 330 331 332
    }
    return 0;
}

static int qemudDispatchDomainLookupByUUID(struct qemud_server *server, struct qemud_client *client,
333 334
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    struct qemud_vm *vm = qemudFindVMByUUID(server, in->qemud_packet_client_data_u.domainLookupByUUIDRequest.uuid);
D
Daniel P. Berrange 已提交
335 336 337 338
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
339 340 341 342
        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID;
        out->qemud_packet_server_data_u.domainLookupByUUIDReply.id = vm->id;
        strncpy(out->qemud_packet_server_data_u.domainLookupByUUIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
D
Daniel P. Berrange 已提交
343 344 345 346 347
    }
    return 0;
}

static int qemudDispatchDomainLookupByName(struct qemud_server *server, struct qemud_client *client,
348
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
349
    /* Paranoia NULL termination */
350 351
    in->qemud_packet_client_data_u.domainLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
    struct qemud_vm *vm = qemudFindVMByName(server, in->qemud_packet_client_data_u.domainLookupByNameRequest.name);
D
Daniel P. Berrange 已提交
352 353 354 355
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
356 357 358
        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME;
        out->qemud_packet_server_data_u.domainLookupByNameReply.id = vm->id;
        memcpy(out->qemud_packet_server_data_u.domainLookupByNameReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
D
Daniel P. Berrange 已提交
359 360 361 362 363
    }
    return 0;
}

static int qemudDispatchDomainSuspend(struct qemud_server *server, struct qemud_client *client,
364 365
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudDomainSuspend(server, in->qemud_packet_client_data_u.domainSuspendRequest.id);
D
Daniel P. Berrange 已提交
366 367 368 369
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
370
        out->type = QEMUD_SERVER_PKT_DOMAIN_SUSPEND;
D
Daniel P. Berrange 已提交
371 372 373 374 375
    }
    return 0;
}

static int qemudDispatchDomainResume(struct qemud_server *server, struct qemud_client *client,
376 377
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudDomainResume(server, in->qemud_packet_client_data_u.domainResumeRequest.id);
D
Daniel P. Berrange 已提交
378 379 380 381
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
382
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESUME;
D
Daniel P. Berrange 已提交
383 384 385 386 387
    }
    return 0;
}

static int qemudDispatchDomainDestroy(struct qemud_server *server, struct qemud_client *client,
388 389
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    if (qemudDomainDestroy(server, in->qemud_packet_client_data_u.domainDestroyRequest.id) < 0) {
D
Daniel P. Berrange 已提交
390 391 392
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
393
        out->type = QEMUD_SERVER_PKT_DOMAIN_DESTROY;
D
Daniel P. Berrange 已提交
394 395 396 397 398
    }
    return 0;
}

static int qemudDispatchDomainGetInfo(struct qemud_server *server, struct qemud_client *client,
399
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
400 401 402 403 404 405
    int runstate;
    unsigned long long cpuTime;
    unsigned long memory;
    unsigned long maxmem;
    unsigned int nrVirtCpu;

406
    int ret = qemudDomainGetInfo(server, in->qemud_packet_client_data_u.domainGetInfoRequest.uuid,
D
Daniel P. Berrange 已提交
407 408 409 410 411 412 413 414 415
                                 &runstate,
                                 &cpuTime,
                                 &maxmem,
                                 &memory,
                                 &nrVirtCpu);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
416 417 418 419 420 421
        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_INFO;
        out->qemud_packet_server_data_u.domainGetInfoReply.runstate = runstate;
        out->qemud_packet_server_data_u.domainGetInfoReply.cpuTime = cpuTime;
        out->qemud_packet_server_data_u.domainGetInfoReply.maxmem = maxmem;
        out->qemud_packet_server_data_u.domainGetInfoReply.memory = memory;
        out->qemud_packet_server_data_u.domainGetInfoReply.nrVirtCpu = nrVirtCpu;
D
Daniel P. Berrange 已提交
422 423 424 425 426
    }
    return 0;
}

static int qemudDispatchDomainSave(struct qemud_server *server, struct qemud_client *client,
427
                                   struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
428
    /* Paranoia NULL termination */
429
    in->qemud_packet_client_data_u.domainSaveRequest.file[PATH_MAX-1] ='\0';
D
Daniel P. Berrange 已提交
430 431

    int ret = qemudDomainSave(server,
432 433
                              in->qemud_packet_client_data_u.domainSaveRequest.id,
                              in->qemud_packet_client_data_u.domainSaveRequest.file);
D
Daniel P. Berrange 已提交
434 435 436 437
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
438
        out->type = QEMUD_SERVER_PKT_DOMAIN_SAVE;
D
Daniel P. Berrange 已提交
439 440 441 442 443
    }
    return 0;
}

static int qemudDispatchDomainRestore(struct qemud_server *server, struct qemud_client *client,
444
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
445 446 447
    int id;

    /* Paranoia null termination */
448
    in->qemud_packet_client_data_u.domainRestoreRequest.file[PATH_MAX-1] ='\0';
D
Daniel P. Berrange 已提交
449

450
    id = qemudDomainRestore(server, in->qemud_packet_client_data_u.domainRestoreRequest.file);
D
Daniel P. Berrange 已提交
451 452 453 454
    if (id < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
455 456
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESTORE;
        out->qemud_packet_server_data_u.domainRestoreReply.id = id;
D
Daniel P. Berrange 已提交
457 458 459 460 461
    }
    return 0;
}

static int qemudDispatchDumpXML(struct qemud_server *server, struct qemud_client *client,
462
                                struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
463 464
    int ret;
    ret = qemudDomainDumpXML(server,
465 466
                             in->qemud_packet_client_data_u.domainDumpXMLRequest.uuid,
                             out->qemud_packet_server_data_u.domainDumpXMLReply.xml,
D
Daniel P. Berrange 已提交
467 468 469 470 471
                             QEMUD_MAX_XML_LEN);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
472
        out->type = QEMUD_SERVER_PKT_DUMP_XML;
D
Daniel P. Berrange 已提交
473 474 475 476 477
    }
    return 0;
}

static int qemudDispatchListDefinedDomains(struct qemud_server *server, struct qemud_client *client,
478
                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
479 480 481 482 483 484 485
    char **names;
    int i, ndomains;

    if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_DOMAINS)))
        return -1;

    for (i = 0 ; i < QEMUD_MAX_NUM_DOMAINS ; i++) {
486
        names[i] = &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN];
D
Daniel P. Berrange 已提交
487 488 489 490 491 492 493 494 495 496
    }

    ndomains = qemudListDefinedDomains(server,
                                       names,
                                       QEMUD_MAX_NUM_DOMAINS);
    free(names);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
497 498 499 500 501 502
        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS;
        out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains = ndomains;
    }
    printf("%d %d\n", out->type, out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains);
    for (i = 0 ; i < ndomains;i++) {
        printf("[%s]\n", &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN]);
D
Daniel P. Berrange 已提交
503 504 505 506 507
    }
    return 0;
}

static int qemudDispatchNumDefinedDomains(struct qemud_server *server, struct qemud_client *client,
508
                                          struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
509 510 511 512 513
    int ndomains = qemudNumDefinedDomains(server);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
514 515
        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS;
        out->qemud_packet_server_data_u.numDefinedDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
516 517 518 519 520
    }
    return 0;
}

static int qemudDispatchDomainStart(struct qemud_server *server, struct qemud_client *client,
521
                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
522 523
    struct qemud_vm *vm;

524
    if (!(vm = qemudDomainStart(server, in->qemud_packet_client_data_u.domainStartRequest.uuid))) {
D
Daniel P. Berrange 已提交
525 526 527
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
528 529
        out->type = QEMUD_SERVER_PKT_DOMAIN_START;
        out->qemud_packet_server_data_u.domainStartReply.id = vm->id;
D
Daniel P. Berrange 已提交
530 531 532 533 534
    }
    return 0;
}

static int qemudDispatchDomainDefine(struct qemud_server *server, struct qemud_client *client,
535 536
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    in->qemud_packet_client_data_u.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
D
Daniel P. Berrange 已提交
537

538
    struct qemud_vm *vm = qemudDomainDefine(server, in->qemud_packet_client_data_u.domainDefineRequest.xml);
D
Daniel P. Berrange 已提交
539 540 541 542
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
543 544 545 546
        out->type = QEMUD_SERVER_PKT_DOMAIN_DEFINE;
        memcpy(out->qemud_packet_server_data_u.domainDefineReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.domainDefineReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
D
Daniel P. Berrange 已提交
547 548 549 550 551
    }
    return 0;
}

static int qemudDispatchDomainUndefine(struct qemud_server *server, struct qemud_client *client,
552 553
                                       struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudDomainUndefine(server, in->qemud_packet_client_data_u.domainUndefineRequest.uuid);
D
Daniel P. Berrange 已提交
554 555 556 557
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
558
        out->type = QEMUD_SERVER_PKT_DOMAIN_UNDEFINE;
D
Daniel P. Berrange 已提交
559 560 561 562
    }
    return 0;
}

563
static int qemudDispatchNumNetworks(struct qemud_server *server, struct qemud_client *client,
564
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
565 566 567 568 569
    int nnetworks = qemudNumNetworks(server);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
570 571
        out->type = QEMUD_SERVER_PKT_NUM_NETWORKS;
        out->qemud_packet_server_data_u.numNetworksReply.numNetworks = nnetworks;
572 573 574 575 576
    }
    return 0;
}

static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_client *client,
577
                                     struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
578 579 580 581 582 583 584
    char **names;
    int i;

    if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
        return -1;

    for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
585
        names[i] = &out->qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
586 587 588 589 590 591 592 593 594 595
    }

    int nnetworks = qemudListNetworks(server,
                                      names,
                                      QEMUD_MAX_NUM_NETWORKS);
    free(names);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
596 597
        out->type = QEMUD_SERVER_PKT_LIST_NETWORKS;
        out->qemud_packet_server_data_u.listNetworksReply.numNetworks = nnetworks;
598 599 600 601 602
    }
    return 0;
}

static int qemudDispatchNumDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
603
                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
604 605 606 607 608
    int nnetworks = qemudNumDefinedNetworks(server);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
609 610
        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.numDefinedNetworksReply.numNetworks = nnetworks;
611 612 613 614 615
    }
    return 0;
}

static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
616
                                            struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
617 618 619 620 621 622 623
    char **names;
    int i;

    if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
        return -1;

    for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
624
        names[i] = &out->qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
625 626 627 628 629 630 631 632 633 634
    }

    int nnetworks = qemudListDefinedNetworks(server,
                                             names,
                                             QEMUD_MAX_NUM_NETWORKS);
    free(names);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
635 636
        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks = nnetworks;
637 638 639 640 641
    }
    return 0;
}

static int qemudDispatchNetworkLookupByName(struct qemud_server *server, struct qemud_client *client,
642
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
643
    /* Paranoia NULL termination */
644 645
    in->qemud_packet_client_data_u.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
    struct qemud_network *network = qemudFindNetworkByName(server, in->qemud_packet_client_data_u.networkLookupByNameRequest.name);
646 647 648 649
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
650 651
        out->type = QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME;
        memcpy(out->qemud_packet_server_data_u.networkLookupByNameReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
652 653 654 655 656
    }
    return 0;
}

static int qemudDispatchNetworkLookupByUUID(struct qemud_server *server, struct qemud_client *client,
657 658
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    struct qemud_network *network = qemudFindNetworkByUUID(server, in->qemud_packet_client_data_u.networkLookupByUUIDRequest.uuid);
659 660 661 662
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
663 664 665
        out->type = QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID;
        strncpy(out->qemud_packet_server_data_u.networkLookupByUUIDReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
666 667 668 669 670
    }
    return 0;
}

static int qemudDispatchNetworkCreate(struct qemud_server *server, struct qemud_client *client,
671 672
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    in->qemud_packet_client_data_u.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
673

674
    struct qemud_network *network = qemudNetworkCreate(server, in->qemud_packet_client_data_u.networkCreateRequest.xml);
675 676 677 678
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
679 680 681 682
        out->type = QEMUD_SERVER_PKT_NETWORK_CREATE;
        memcpy(out->qemud_packet_server_data_u.networkCreateReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.networkCreateReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
683 684 685 686 687
    }
    return 0;
}

static int qemudDispatchNetworkDefine(struct qemud_server *server, struct qemud_client *client,
688 689
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    in->qemud_packet_client_data_u.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
690

691
    struct qemud_network *network = qemudNetworkDefine(server, in->qemud_packet_client_data_u.networkDefineRequest.xml);
692 693 694 695
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
696 697 698 699
        out->type = QEMUD_SERVER_PKT_NETWORK_DEFINE;
        memcpy(out->qemud_packet_server_data_u.networkDefineReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.networkDefineReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
        out->qemud_packet_server_data_u.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
700 701 702 703 704
    }
    return 0;
}

static int qemudDispatchNetworkUndefine(struct qemud_server *server, struct qemud_client *client,
705 706
                                        struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudNetworkUndefine(server, in->qemud_packet_client_data_u.networkUndefineRequest.uuid);
707 708 709 710
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
711
        out->type = QEMUD_SERVER_PKT_NETWORK_UNDEFINE;
712 713 714 715 716
    }
    return 0;
}

static int qemudDispatchNetworkStart(struct qemud_server *server, struct qemud_client *client,
717
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
718 719
    struct qemud_network *network;

720
    if (!(network = qemudNetworkStart(server, in->qemud_packet_client_data_u.networkStartRequest.uuid))) {
721 722 723
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
724
        out->type = QEMUD_SERVER_PKT_NETWORK_START;
725 726 727 728 729
    }
    return 0;
}

static int qemudDispatchNetworkDestroy(struct qemud_server *server, struct qemud_client *client,
730 731
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    if (qemudNetworkDestroy(server, in->qemud_packet_client_data_u.networkDestroyRequest.uuid) < 0) {
732 733 734
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
735
        out->type = QEMUD_SERVER_PKT_NETWORK_DESTROY;
736 737 738 739 740
    }
    return 0;
}

static int qemudDispatchNetworkDumpXML(struct qemud_server *server, struct qemud_client *client,
741
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
742
    int ret = qemudNetworkDumpXML(server,
743 744
                                  in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
                                  out->qemud_packet_server_data_u.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN);
745 746 747 748
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
749
        out->type = QEMUD_SERVER_PKT_NETWORK_DUMP_XML;
750 751 752 753
    }
    return 0;
}

754
static int qemudDispatchNetworkGetBridgeName(struct qemud_server *server, struct qemud_client *client,
755
                                             struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
756
    int ret = qemudNetworkGetBridgeName(server,
757 758
                                        in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
                                        out->qemud_packet_server_data_u.networkGetBridgeNameReply.ifname, QEMUD_MAX_IFNAME_LEN);
759 760 761 762
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
763
        out->type = QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME;
764 765 766 767
    }
    return 0;
}

768
static int qemudDispatchDomainGetAutostart(struct qemud_server *server, struct qemud_client *client,
769
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
770 771 772 773 774 775 776
{
    int ret;
    int autostart;

    autostart = 0;

    ret = qemudDomainGetAutostart(server,
777
                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
778 779 780 781 782
                                  &autostart);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
783 784
        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART;
        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
785 786 787 788 789
    }
    return 0;
}

static int qemudDispatchDomainSetAutostart(struct qemud_server *server, struct qemud_client *client,
790
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
791 792 793 794
{
    int ret;

    ret = qemudDomainSetAutostart(server,
795 796
                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
                                  in->qemud_packet_client_data_u.domainSetAutostartRequest.autostart);
797 798 799 800
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
801
        out->type = QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART;
802 803 804 805 806
    }
    return 0;
}

static int qemudDispatchNetworkGetAutostart(struct qemud_server *server, struct qemud_client *client,
807
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
808 809 810 811 812 813 814
{
    int ret;
    int autostart;

    autostart = 0;

    ret = qemudNetworkGetAutostart(server,
815
                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
816 817 818 819 820
                                   &autostart);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
821 822
        out->type = QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART;
        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
823 824 825 826 827
    }
    return 0;
}

static int qemudDispatchNetworkSetAutostart(struct qemud_server *server, struct qemud_client *client,
828
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
829 830 831 832
{
    int ret;

    ret = qemudNetworkSetAutostart(server,
833 834
                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
                                   in->qemud_packet_client_data_u.networkSetAutostartRequest.autostart);
835 836 837 838
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
839
        out->type = QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART;
840 841 842
    }
    return 0;
}
D
Daniel P. Berrange 已提交
843 844

typedef int (*clientFunc)(struct qemud_server *server, struct qemud_client *client,
845
                          struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
D
Daniel P. Berrange 已提交
846 847 848 849


/* One per message type recorded in qemud_packet_type enum */

850
clientFunc funcsTransmitRW[QEMUD_CLIENT_PKT_MAX] = {
D
Daniel P. Berrange 已提交
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
    qemudDispatchGetVersion,
    qemudDispatchGetNodeInfo,
    qemudDispatchListDomains,
    qemudDispatchNumDomains,
    qemudDispatchDomainCreate,
    qemudDispatchDomainLookupByID,
    qemudDispatchDomainLookupByUUID,
    qemudDispatchDomainLookupByName,
    qemudDispatchDomainSuspend,
    qemudDispatchDomainResume,
    qemudDispatchDomainDestroy,
    qemudDispatchDomainGetInfo,
    qemudDispatchDomainSave,
    qemudDispatchDomainRestore,
    qemudDispatchDumpXML,
    qemudDispatchListDefinedDomains,
    qemudDispatchNumDefinedDomains,
    qemudDispatchDomainStart,
    qemudDispatchDomainDefine,
870 871 872 873 874 875 876 877 878 879 880 881 882
    qemudDispatchDomainUndefine,
    qemudDispatchNumNetworks,
    qemudDispatchListNetworks,
    qemudDispatchNumDefinedNetworks,
    qemudDispatchListDefinedNetworks,
    qemudDispatchNetworkLookupByUUID,
    qemudDispatchNetworkLookupByName,
    qemudDispatchNetworkCreate,
    qemudDispatchNetworkDefine,
    qemudDispatchNetworkUndefine,
    qemudDispatchNetworkStart,
    qemudDispatchNetworkDestroy,
    qemudDispatchNetworkDumpXML,
883
    qemudDispatchNetworkGetBridgeName,
884 885 886 887
    qemudDispatchDomainGetAutostart,
    qemudDispatchDomainSetAutostart,
    qemudDispatchNetworkGetAutostart,
    qemudDispatchNetworkSetAutostart,
888
    qemudDispatchGetCapabilities,
D
Daniel P. Berrange 已提交
889 890
};

891
clientFunc funcsTransmitRO[QEMUD_CLIENT_PKT_MAX] = {
D
Daniel P. Berrange 已提交
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
    qemudDispatchGetVersion,
    qemudDispatchGetNodeInfo,
    qemudDispatchListDomains,
    qemudDispatchNumDomains,
    NULL,
    qemudDispatchDomainLookupByID,
    qemudDispatchDomainLookupByUUID,
    qemudDispatchDomainLookupByName,
    NULL,
    NULL,
    NULL,
    qemudDispatchDomainGetInfo,
    NULL,
    NULL,
    qemudDispatchDumpXML,
    qemudDispatchListDefinedDomains,
    qemudDispatchNumDefinedDomains,
    NULL,
    NULL,
    NULL,
912 913 914 915 916 917 918 919 920 921 922 923
    qemudDispatchNumNetworks,
    qemudDispatchListNetworks,
    qemudDispatchNumDefinedNetworks,
    qemudDispatchListDefinedNetworks,
    qemudDispatchNetworkLookupByUUID,
    qemudDispatchNetworkLookupByName,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    qemudDispatchNetworkDumpXML,
924
    qemudDispatchNetworkGetBridgeName,
925 926 927 928
    qemudDispatchDomainGetAutostart,
    NULL,
    qemudDispatchNetworkGetAutostart,
    NULL,
D
Daniel P. Berrange 已提交
929 930 931 932 933 934 935 936 937 938 939 940 941
};

/*
 * Returns -1 if message processing failed - eg, illegal header sizes,
 * a memory error dealing with stuff, or any other bad stuff which
 * should trigger immediate client disconnect
 *
 * Return 0 if message processing succeeded. NB, this does not mean
 * the operation itself succeeded - success/failure of the operation
 * is recorded by the return message type - either it matches the
 * incoming type, or is QEMUD_PKT_FAILURE
 */
int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
942
                  qemud_packet_client_data *in, qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
943
    clientFunc *funcs;
944 945 946
    unsigned int type = in->type;
    qemudDebug("> Dispatching request type %d, readonly ? %d",
               in->type, client->readonly);
D
Daniel P. Berrange 已提交
947 948 949 950

    server->errorCode = 0;
    server->errorMessage[0] = '\0';

951
    memset(out, 0, sizeof(*out));
D
Daniel P. Berrange 已提交
952

953
    if (type >= QEMUD_CLIENT_PKT_MAX) {
954
        qemudDebug("Illegal request type");
D
Daniel P. Berrange 已提交
955 956 957 958 959 960 961 962 963
        return -1;
    }

    if (client->readonly)
        funcs = funcsTransmitRO;
    else
        funcs = funcsTransmitRW;

    if (!funcs[type]) {
964
        qemudDebug("Illegal operation requested");
D
Daniel P. Berrange 已提交
965 966 967 968
        qemudReportError(server, VIR_ERR_OPERATION_DENIED, NULL);
        qemudDispatchFailure(server, client, out);
    } else {
        if ((funcs[type])(server, client, in, out) < 0) {
969
            qemudDebug("Dispatch failed");
D
Daniel P. Berrange 已提交
970 971 972 973
            return -1;
        }
    }

974
    qemudDebug("< Returning reply %d", out->type);
D
Daniel P. Berrange 已提交
975 976 977 978 979 980 981 982 983 984 985 986

    return 0;
}

/*
 * Local variables:
 *  indent-tabs-mode: nil
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 * End:
 */