Annotation of qemu/qmp.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * QEMU Management Protocol
                      3:  *
                      4:  * Copyright IBM, Corp. 2011
                      5:  *
                      6:  * Authors:
                      7:  *  Anthony Liguori   <aliguori@us.ibm.com>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU GPL, version 2.  See
                     10:  * the COPYING file in the top-level directory.
                     11:  *
1.1.1.2 ! root       12:  * Contributions after 2012-01-13 are licensed under the terms of the
        !            13:  * GNU GPL, version 2 or (at your option) any later version.
1.1       root       14:  */
                     15: 
                     16: #include "qemu-common.h"
                     17: #include "sysemu.h"
                     18: #include "qmp-commands.h"
1.1.1.2 ! root       19: #include "ui/qemu-spice.h"
        !            20: #include "ui/vnc.h"
1.1       root       21: #include "kvm.h"
                     22: #include "arch_init.h"
1.1.1.2 ! root       23: #include "hw/qdev.h"
        !            24: #include "blockdev.h"
        !            25: #include "qemu/qom-qobject.h"
1.1       root       26: 
                     27: NameInfo *qmp_query_name(Error **errp)
                     28: {
                     29:     NameInfo *info = g_malloc0(sizeof(*info));
                     30: 
                     31:     if (qemu_name) {
                     32:         info->has_name = true;
                     33:         info->name = g_strdup(qemu_name);
                     34:     }
                     35: 
                     36:     return info;
                     37: }
                     38: 
                     39: VersionInfo *qmp_query_version(Error **err)
                     40: {
                     41:     VersionInfo *info = g_malloc0(sizeof(*info));
                     42:     const char *version = QEMU_VERSION;
                     43:     char *tmp;
                     44: 
                     45:     info->qemu.major = strtol(version, &tmp, 10);
                     46:     tmp++;
                     47:     info->qemu.minor = strtol(tmp, &tmp, 10);
                     48:     tmp++;
                     49:     info->qemu.micro = strtol(tmp, &tmp, 10);
                     50:     info->package = g_strdup(QEMU_PKGVERSION);
                     51: 
                     52:     return info;
                     53: }
                     54: 
                     55: KvmInfo *qmp_query_kvm(Error **errp)
                     56: {
                     57:     KvmInfo *info = g_malloc0(sizeof(*info));
                     58: 
                     59:     info->enabled = kvm_enabled();
                     60:     info->present = kvm_available();
                     61: 
                     62:     return info;
                     63: }
                     64: 
                     65: UuidInfo *qmp_query_uuid(Error **errp)
                     66: {
                     67:     UuidInfo *info = g_malloc0(sizeof(*info));
                     68:     char uuid[64];
                     69: 
                     70:     snprintf(uuid, sizeof(uuid), UUID_FMT, qemu_uuid[0], qemu_uuid[1],
                     71:                    qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], qemu_uuid[5],
                     72:                    qemu_uuid[6], qemu_uuid[7], qemu_uuid[8], qemu_uuid[9],
                     73:                    qemu_uuid[10], qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
                     74:                    qemu_uuid[14], qemu_uuid[15]);
                     75: 
                     76:     info->UUID = g_strdup(uuid);
                     77:     return info;
                     78: }
                     79: 
                     80: void qmp_quit(Error **err)
                     81: {
                     82:     no_shutdown = 0;
                     83:     qemu_system_shutdown_request();
                     84: }
                     85: 
                     86: void qmp_stop(Error **errp)
                     87: {
                     88:     vm_stop(RUN_STATE_PAUSED);
                     89: }
                     90: 
                     91: void qmp_system_reset(Error **errp)
                     92: {
                     93:     qemu_system_reset_request();
                     94: }
                     95: 
                     96: void qmp_system_powerdown(Error **erp)
                     97: {
                     98:     qemu_system_powerdown_request();
                     99: }
                    100: 
                    101: void qmp_cpu(int64_t index, Error **errp)
                    102: {
                    103:     /* Just do nothing */
                    104: }
                    105: 
                    106: #ifndef CONFIG_VNC
                    107: /* If VNC support is enabled, the "true" query-vnc command is
                    108:    defined in the VNC subsystem */
                    109: VncInfo *qmp_query_vnc(Error **errp)
                    110: {
                    111:     error_set(errp, QERR_FEATURE_DISABLED, "vnc");
                    112:     return NULL;
                    113: };
                    114: #endif
                    115: 
                    116: #ifndef CONFIG_SPICE
                    117: /* If SPICE support is enabled, the "true" query-spice command is
                    118:    defined in the SPICE subsystem. Also note that we use a small
                    119:    trick to maintain query-spice's original behavior, which is not
                    120:    to be available in the namespace if SPICE is not compiled in */
                    121: SpiceInfo *qmp_query_spice(Error **errp)
                    122: {
                    123:     error_set(errp, QERR_COMMAND_NOT_FOUND, "query-spice");
                    124:     return NULL;
                    125: };
                    126: #endif
1.1.1.2 ! root      127: 
        !           128: static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
        !           129: {
        !           130:     bdrv_iostatus_reset(bs);
        !           131: }
        !           132: 
        !           133: static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
        !           134: {
        !           135:     Error **err = opaque;
        !           136: 
        !           137:     if (!error_is_set(err) && bdrv_key_required(bs)) {
        !           138:         error_set(err, QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs),
        !           139:                   bdrv_get_encrypted_filename(bs));
        !           140:     }
        !           141: }
        !           142: 
        !           143: void qmp_cont(Error **errp)
        !           144: {
        !           145:     Error *local_err = NULL;
        !           146: 
        !           147:     if (runstate_check(RUN_STATE_INMIGRATE)) {
        !           148:         error_set(errp, QERR_MIGRATION_EXPECTED);
        !           149:         return;
        !           150:     } else if (runstate_check(RUN_STATE_INTERNAL_ERROR) ||
        !           151:                runstate_check(RUN_STATE_SHUTDOWN)) {
        !           152:         error_set(errp, QERR_RESET_REQUIRED);
        !           153:         return;
        !           154:     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
        !           155:         return;
        !           156:     }
        !           157: 
        !           158:     bdrv_iterate(iostatus_bdrv_it, NULL);
        !           159:     bdrv_iterate(encrypted_bdrv_it, &local_err);
        !           160:     if (local_err) {
        !           161:         error_propagate(errp, local_err);
        !           162:         return;
        !           163:     }
        !           164: 
        !           165:     vm_start();
        !           166: }
        !           167: 
        !           168: void qmp_system_wakeup(Error **errp)
        !           169: {
        !           170:     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
        !           171: }
        !           172: 
        !           173: ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
        !           174: {
        !           175:     Object *obj;
        !           176:     bool ambiguous = false;
        !           177:     ObjectPropertyInfoList *props = NULL;
        !           178:     ObjectProperty *prop;
        !           179: 
        !           180:     obj = object_resolve_path(path, &ambiguous);
        !           181:     if (obj == NULL) {
        !           182:         error_set(errp, QERR_DEVICE_NOT_FOUND, path);
        !           183:         return NULL;
        !           184:     }
        !           185: 
        !           186:     QTAILQ_FOREACH(prop, &obj->properties, node) {
        !           187:         ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
        !           188: 
        !           189:         entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
        !           190:         entry->next = props;
        !           191:         props = entry;
        !           192: 
        !           193:         entry->value->name = g_strdup(prop->name);
        !           194:         entry->value->type = g_strdup(prop->type);
        !           195:     }
        !           196: 
        !           197:     return props;
        !           198: }
        !           199: 
        !           200: /* FIXME: teach qapi about how to pass through Visitors */
        !           201: int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret)
        !           202: {
        !           203:     const char *path = qdict_get_str(qdict, "path");
        !           204:     const char *property = qdict_get_str(qdict, "property");
        !           205:     QObject *value = qdict_get(qdict, "value");
        !           206:     Error *local_err = NULL;
        !           207:     Object *obj;
        !           208: 
        !           209:     obj = object_resolve_path(path, NULL);
        !           210:     if (!obj) {
        !           211:         error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
        !           212:         goto out;
        !           213:     }
        !           214: 
        !           215:     object_property_set_qobject(obj, value, property, &local_err);
        !           216: 
        !           217: out:
        !           218:     if (local_err) {
        !           219:         qerror_report_err(local_err);
        !           220:         error_free(local_err);
        !           221:         return -1;
        !           222:     }
        !           223: 
        !           224:     return 0;
        !           225: }
        !           226: 
        !           227: int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret)
        !           228: {
        !           229:     const char *path = qdict_get_str(qdict, "path");
        !           230:     const char *property = qdict_get_str(qdict, "property");
        !           231:     Error *local_err = NULL;
        !           232:     Object *obj;
        !           233: 
        !           234:     obj = object_resolve_path(path, NULL);
        !           235:     if (!obj) {
        !           236:         error_set(&local_err, QERR_DEVICE_NOT_FOUND, path);
        !           237:         goto out;
        !           238:     }
        !           239: 
        !           240:     *ret = object_property_get_qobject(obj, property, &local_err);
        !           241: 
        !           242: out:
        !           243:     if (local_err) {
        !           244:         qerror_report_err(local_err);
        !           245:         error_free(local_err);
        !           246:         return -1;
        !           247:     }
        !           248: 
        !           249:     return 0;
        !           250: }
        !           251: 
        !           252: void qmp_set_password(const char *protocol, const char *password,
        !           253:                       bool has_connected, const char *connected, Error **errp)
        !           254: {
        !           255:     int disconnect_if_connected = 0;
        !           256:     int fail_if_connected = 0;
        !           257:     int rc;
        !           258: 
        !           259:     if (has_connected) {
        !           260:         if (strcmp(connected, "fail") == 0) {
        !           261:             fail_if_connected = 1;
        !           262:         } else if (strcmp(connected, "disconnect") == 0) {
        !           263:             disconnect_if_connected = 1;
        !           264:         } else if (strcmp(connected, "keep") == 0) {
        !           265:             /* nothing */
        !           266:         } else {
        !           267:             error_set(errp, QERR_INVALID_PARAMETER, "connected");
        !           268:             return;
        !           269:         }
        !           270:     }
        !           271: 
        !           272:     if (strcmp(protocol, "spice") == 0) {
        !           273:         if (!using_spice) {
        !           274:             /* correct one? spice isn't a device ,,, */
        !           275:             error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
        !           276:             return;
        !           277:         }
        !           278:         rc = qemu_spice_set_passwd(password, fail_if_connected,
        !           279:                                    disconnect_if_connected);
        !           280:         if (rc != 0) {
        !           281:             error_set(errp, QERR_SET_PASSWD_FAILED);
        !           282:         }
        !           283:         return;
        !           284:     }
        !           285: 
        !           286:     if (strcmp(protocol, "vnc") == 0) {
        !           287:         if (fail_if_connected || disconnect_if_connected) {
        !           288:             /* vnc supports "connected=keep" only */
        !           289:             error_set(errp, QERR_INVALID_PARAMETER, "connected");
        !           290:             return;
        !           291:         }
        !           292:         /* Note that setting an empty password will not disable login through
        !           293:          * this interface. */
        !           294:         rc = vnc_display_password(NULL, password);
        !           295:         if (rc < 0) {
        !           296:             error_set(errp, QERR_SET_PASSWD_FAILED);
        !           297:         }
        !           298:         return;
        !           299:     }
        !           300: 
        !           301:     error_set(errp, QERR_INVALID_PARAMETER, "protocol");
        !           302: }
        !           303: 
        !           304: void qmp_expire_password(const char *protocol, const char *whenstr,
        !           305:                          Error **errp)
        !           306: {
        !           307:     time_t when;
        !           308:     int rc;
        !           309: 
        !           310:     if (strcmp(whenstr, "now") == 0) {
        !           311:         when = 0;
        !           312:     } else if (strcmp(whenstr, "never") == 0) {
        !           313:         when = TIME_MAX;
        !           314:     } else if (whenstr[0] == '+') {
        !           315:         when = time(NULL) + strtoull(whenstr+1, NULL, 10);
        !           316:     } else {
        !           317:         when = strtoull(whenstr, NULL, 10);
        !           318:     }
        !           319: 
        !           320:     if (strcmp(protocol, "spice") == 0) {
        !           321:         if (!using_spice) {
        !           322:             /* correct one? spice isn't a device ,,, */
        !           323:             error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice");
        !           324:             return;
        !           325:         }
        !           326:         rc = qemu_spice_set_pw_expire(when);
        !           327:         if (rc != 0) {
        !           328:             error_set(errp, QERR_SET_PASSWD_FAILED);
        !           329:         }
        !           330:         return;
        !           331:     }
        !           332: 
        !           333:     if (strcmp(protocol, "vnc") == 0) {
        !           334:         rc = vnc_display_pw_expire(NULL, when);
        !           335:         if (rc != 0) {
        !           336:             error_set(errp, QERR_SET_PASSWD_FAILED);
        !           337:         }
        !           338:         return;
        !           339:     }
        !           340: 
        !           341:     error_set(errp, QERR_INVALID_PARAMETER, "protocol");
        !           342: }
        !           343: 
        !           344: #ifdef CONFIG_VNC
        !           345: void qmp_change_vnc_password(const char *password, Error **errp)
        !           346: {
        !           347:     if (vnc_display_password(NULL, password) < 0) {
        !           348:         error_set(errp, QERR_SET_PASSWD_FAILED);
        !           349:     }
        !           350: }
        !           351: 
        !           352: static void qmp_change_vnc_listen(const char *target, Error **err)
        !           353: {
        !           354:     if (vnc_display_open(NULL, target) < 0) {
        !           355:         error_set(err, QERR_VNC_SERVER_FAILED, target);
        !           356:     }
        !           357: }
        !           358: 
        !           359: static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
        !           360:                            Error **errp)
        !           361: {
        !           362:     if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
        !           363:         if (!has_arg) {
        !           364:             error_set(errp, QERR_MISSING_PARAMETER, "password");
        !           365:         } else {
        !           366:             qmp_change_vnc_password(arg, errp);
        !           367:         }
        !           368:     } else {
        !           369:         qmp_change_vnc_listen(target, errp);
        !           370:     }
        !           371: }
        !           372: #else
        !           373: void qmp_change_vnc_password(const char *password, Error **errp)
        !           374: {
        !           375:     error_set(errp, QERR_FEATURE_DISABLED, "vnc");
        !           376: }
        !           377: static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
        !           378:                            Error **errp)
        !           379: {
        !           380:     error_set(errp, QERR_FEATURE_DISABLED, "vnc");
        !           381: }
        !           382: #endif /* !CONFIG_VNC */
        !           383: 
        !           384: void qmp_change(const char *device, const char *target,
        !           385:                 bool has_arg, const char *arg, Error **err)
        !           386: {
        !           387:     if (strcmp(device, "vnc") == 0) {
        !           388:         qmp_change_vnc(target, has_arg, arg, err);
        !           389:     } else {
        !           390:         qmp_change_blockdev(device, target, has_arg, arg, err);
        !           391:     }
        !           392: }
        !           393: 
        !           394: static void qom_list_types_tramp(ObjectClass *klass, void *data)
        !           395: {
        !           396:     ObjectTypeInfoList *e, **pret = data;
        !           397:     ObjectTypeInfo *info;
        !           398: 
        !           399:     info = g_malloc0(sizeof(*info));
        !           400:     info->name = g_strdup(object_class_get_name(klass));
        !           401: 
        !           402:     e = g_malloc0(sizeof(*e));
        !           403:     e->value = info;
        !           404:     e->next = *pret;
        !           405:     *pret = e;
        !           406: }
        !           407: 
        !           408: ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
        !           409:                                        const char *implements,
        !           410:                                        bool has_abstract,
        !           411:                                        bool abstract,
        !           412:                                        Error **errp)
        !           413: {
        !           414:     ObjectTypeInfoList *ret = NULL;
        !           415: 
        !           416:     object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
        !           417: 
        !           418:     return ret;
        !           419: }

unix.superglobalmegacorp.com