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