qemu/qom/object_interfaces.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "qapi/error.h"
   3#include "qapi/qmp/qdict.h"
   4#include "qapi/qmp/qerror.h"
   5#include "qom/object_interfaces.h"
   6#include "qemu/module.h"
   7#include "qemu/option.h"
   8#include "qapi/opts-visitor.h"
   9#include "qemu/config-file.h"
  10
  11void user_creatable_complete(UserCreatable *uc, Error **errp)
  12{
  13    UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
  14
  15    if (ucc->complete) {
  16        ucc->complete(uc, errp);
  17    }
  18}
  19
  20bool user_creatable_can_be_deleted(UserCreatable *uc)
  21{
  22
  23    UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
  24
  25    if (ucc->can_be_deleted) {
  26        return ucc->can_be_deleted(uc);
  27    } else {
  28        return true;
  29    }
  30}
  31
  32Object *user_creatable_add_type(const char *type, const char *id,
  33                                const QDict *qdict,
  34                                Visitor *v, Error **errp)
  35{
  36    Object *obj;
  37    ObjectClass *klass;
  38    const QDictEntry *e;
  39    Error *local_err = NULL;
  40
  41    klass = object_class_by_name(type);
  42    if (!klass) {
  43        error_setg(errp, "invalid object type: %s", type);
  44        return NULL;
  45    }
  46
  47    if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
  48        error_setg(errp, "object type '%s' isn't supported by object-add",
  49                   type);
  50        return NULL;
  51    }
  52
  53    if (object_class_is_abstract(klass)) {
  54        error_setg(errp, "object type '%s' is abstract", type);
  55        return NULL;
  56    }
  57
  58    assert(qdict);
  59    obj = object_new(type);
  60    visit_start_struct(v, NULL, NULL, 0, &local_err);
  61    if (local_err) {
  62        goto out;
  63    }
  64    for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
  65        object_property_set(obj, v, e->key, &local_err);
  66        if (local_err) {
  67            break;
  68        }
  69    }
  70    if (!local_err) {
  71        visit_check_struct(v, &local_err);
  72    }
  73    visit_end_struct(v, NULL);
  74    if (local_err) {
  75        goto out;
  76    }
  77
  78    if (id != NULL) {
  79        object_property_add_child(object_get_objects_root(),
  80                                  id, obj, &local_err);
  81        if (local_err) {
  82            goto out;
  83        }
  84    }
  85
  86    user_creatable_complete(USER_CREATABLE(obj), &local_err);
  87    if (local_err) {
  88        if (id != NULL) {
  89            object_property_del(object_get_objects_root(),
  90                                id, &error_abort);
  91        }
  92        goto out;
  93    }
  94out:
  95    if (local_err) {
  96        error_propagate(errp, local_err);
  97        object_unref(obj);
  98        return NULL;
  99    }
 100    return obj;
 101}
 102
 103
 104Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
 105{
 106    Visitor *v;
 107    QDict *pdict;
 108    Object *obj;
 109    const char *id = qemu_opts_id(opts);
 110    char *type = qemu_opt_get_del(opts, "qom-type");
 111
 112    if (!type) {
 113        error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
 114        return NULL;
 115    }
 116    if (!id) {
 117        error_setg(errp, QERR_MISSING_PARAMETER, "id");
 118        qemu_opt_set(opts, "qom-type", type, &error_abort);
 119        g_free(type);
 120        return NULL;
 121    }
 122
 123    qemu_opts_set_id(opts, NULL);
 124    pdict = qemu_opts_to_qdict(opts, NULL);
 125
 126    v = opts_visitor_new(opts);
 127    obj = user_creatable_add_type(type, id, pdict, v, errp);
 128    visit_free(v);
 129
 130    qemu_opts_set_id(opts, (char *) id);
 131    qemu_opt_set(opts, "qom-type", type, &error_abort);
 132    g_free(type);
 133    qobject_unref(pdict);
 134    return obj;
 135}
 136
 137
 138int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
 139{
 140    bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque;
 141    Object *obj = NULL;
 142    const char *type;
 143
 144    type = qemu_opt_get(opts, "qom-type");
 145    if (type && type_opt_predicate &&
 146        !type_opt_predicate(type, opts)) {
 147        return 0;
 148    }
 149
 150    obj = user_creatable_add_opts(opts, errp);
 151    if (!obj) {
 152        return -1;
 153    }
 154    object_unref(obj);
 155    return 0;
 156}
 157
 158
 159void user_creatable_del(const char *id, Error **errp)
 160{
 161    Object *container;
 162    Object *obj;
 163
 164    container = object_get_objects_root();
 165    obj = object_resolve_path_component(container, id);
 166    if (!obj) {
 167        error_setg(errp, "object '%s' not found", id);
 168        return;
 169    }
 170
 171    if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) {
 172        error_setg(errp, "object '%s' is in use, can not be deleted", id);
 173        return;
 174    }
 175
 176    /*
 177     * if object was defined on the command-line, remove its corresponding
 178     * option group entry
 179     */
 180    qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort),
 181                                 id));
 182
 183    object_unparent(obj);
 184}
 185
 186void user_creatable_cleanup(void)
 187{
 188    object_unparent(object_get_objects_root());
 189}
 190
 191static void register_types(void)
 192{
 193    static const TypeInfo uc_interface_info = {
 194        .name          = TYPE_USER_CREATABLE,
 195        .parent        = TYPE_INTERFACE,
 196        .class_size = sizeof(UserCreatableClass),
 197    };
 198
 199    type_register_static(&uc_interface_info);
 200}
 201
 202type_init(register_types)
 203