xref: /qemu/qom/object_interfaces.c (revision 1195fa2b)
19bbc853bSPeter Maydell #include "qemu/osdep.h"
2da34e65cSMarkus Armbruster #include "qapi/error.h"
3452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h"
40dd13589SMarkus Armbruster #include "qapi/qmp/qerror.h"
5269e09f3SIgor Mammedov #include "qom/object_interfaces.h"
6269e09f3SIgor Mammedov #include "qemu/module.h"
7922a01a0SMarkus Armbruster #include "qemu/option.h"
890998d58SDaniel P. Berrange #include "qapi/opts-visitor.h"
9c645d5acSMichael Roth #include "qemu/config-file.h"
10269e09f3SIgor Mammedov 
11269e09f3SIgor Mammedov void user_creatable_complete(Object *obj, Error **errp)
12269e09f3SIgor Mammedov {
13269e09f3SIgor Mammedov 
14269e09f3SIgor Mammedov     UserCreatableClass *ucc;
15269e09f3SIgor Mammedov     UserCreatable *uc =
16269e09f3SIgor Mammedov         (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
17269e09f3SIgor Mammedov 
18269e09f3SIgor Mammedov     if (!uc) {
19269e09f3SIgor Mammedov         return;
20269e09f3SIgor Mammedov     }
21269e09f3SIgor Mammedov 
22269e09f3SIgor Mammedov     ucc = USER_CREATABLE_GET_CLASS(uc);
23269e09f3SIgor Mammedov     if (ucc->complete) {
24269e09f3SIgor Mammedov         ucc->complete(uc, errp);
25269e09f3SIgor Mammedov     }
26269e09f3SIgor Mammedov }
27269e09f3SIgor Mammedov 
283beacfb9SEduardo Habkost bool user_creatable_can_be_deleted(UserCreatable *uc)
29d6edb155SLin Ma {
30d6edb155SLin Ma 
31d6edb155SLin Ma     UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
32d6edb155SLin Ma 
33d6edb155SLin Ma     if (ucc->can_be_deleted) {
343beacfb9SEduardo Habkost         return ucc->can_be_deleted(uc);
35d6edb155SLin Ma     } else {
36d6edb155SLin Ma         return true;
37d6edb155SLin Ma     }
38d6edb155SLin Ma }
39d6edb155SLin Ma 
4090998d58SDaniel P. Berrange Object *user_creatable_add_type(const char *type, const char *id,
4190998d58SDaniel P. Berrange                                 const QDict *qdict,
4290998d58SDaniel P. Berrange                                 Visitor *v, Error **errp)
4390998d58SDaniel P. Berrange {
4490998d58SDaniel P. Berrange     Object *obj;
4590998d58SDaniel P. Berrange     ObjectClass *klass;
4690998d58SDaniel P. Berrange     const QDictEntry *e;
4790998d58SDaniel P. Berrange     Error *local_err = NULL;
4890998d58SDaniel P. Berrange 
4990998d58SDaniel P. Berrange     klass = object_class_by_name(type);
5090998d58SDaniel P. Berrange     if (!klass) {
5190998d58SDaniel P. Berrange         error_setg(errp, "invalid object type: %s", type);
5290998d58SDaniel P. Berrange         return NULL;
5390998d58SDaniel P. Berrange     }
5490998d58SDaniel P. Berrange 
5590998d58SDaniel P. Berrange     if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
5690998d58SDaniel P. Berrange         error_setg(errp, "object type '%s' isn't supported by object-add",
5790998d58SDaniel P. Berrange                    type);
5890998d58SDaniel P. Berrange         return NULL;
5990998d58SDaniel P. Berrange     }
6090998d58SDaniel P. Berrange 
6190998d58SDaniel P. Berrange     if (object_class_is_abstract(klass)) {
6290998d58SDaniel P. Berrange         error_setg(errp, "object type '%s' is abstract", type);
6390998d58SDaniel P. Berrange         return NULL;
6490998d58SDaniel P. Berrange     }
6590998d58SDaniel P. Berrange 
66ad739706SEric Blake     assert(qdict);
6790998d58SDaniel P. Berrange     obj = object_new(type);
68ad739706SEric Blake     visit_start_struct(v, NULL, NULL, 0, &local_err);
6990998d58SDaniel P. Berrange     if (local_err) {
7090998d58SDaniel P. Berrange         goto out;
7190998d58SDaniel P. Berrange     }
72ad739706SEric Blake     for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
73ad739706SEric Blake         object_property_set(obj, v, e->key, &local_err);
74ad739706SEric Blake         if (local_err) {
75ad739706SEric Blake             break;
7690998d58SDaniel P. Berrange         }
7790998d58SDaniel P. Berrange     }
7815c2f669SEric Blake     if (!local_err) {
7915c2f669SEric Blake         visit_check_struct(v, &local_err);
8015c2f669SEric Blake     }
811158bb2aSEric Blake     visit_end_struct(v, NULL);
82ad739706SEric Blake     if (local_err) {
83ad739706SEric Blake         goto out;
84ad739706SEric Blake     }
8590998d58SDaniel P. Berrange 
8690998d58SDaniel P. Berrange     object_property_add_child(object_get_objects_root(),
8790998d58SDaniel P. Berrange                               id, obj, &local_err);
8890998d58SDaniel P. Berrange     if (local_err) {
8990998d58SDaniel P. Berrange         goto out;
9090998d58SDaniel P. Berrange     }
9190998d58SDaniel P. Berrange 
9290998d58SDaniel P. Berrange     user_creatable_complete(obj, &local_err);
9390998d58SDaniel P. Berrange     if (local_err) {
9490998d58SDaniel P. Berrange         object_property_del(object_get_objects_root(),
9590998d58SDaniel P. Berrange                             id, &error_abort);
9690998d58SDaniel P. Berrange         goto out;
9790998d58SDaniel P. Berrange     }
9890998d58SDaniel P. Berrange out:
9990998d58SDaniel P. Berrange     if (local_err) {
10090998d58SDaniel P. Berrange         error_propagate(errp, local_err);
10190998d58SDaniel P. Berrange         object_unref(obj);
10290998d58SDaniel P. Berrange         return NULL;
10390998d58SDaniel P. Berrange     }
10490998d58SDaniel P. Berrange     return obj;
10590998d58SDaniel P. Berrange }
10690998d58SDaniel P. Berrange 
10790998d58SDaniel P. Berrange 
10890998d58SDaniel P. Berrange Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
10990998d58SDaniel P. Berrange {
11009204eacSEric Blake     Visitor *v;
11190998d58SDaniel P. Berrange     QDict *pdict;
1123a464105SIgor Mammedov     Object *obj;
1133a464105SIgor Mammedov     const char *id = qemu_opts_id(opts);
1149a6d1acbSEric Blake     char *type = qemu_opt_get_del(opts, "qom-type");
1153a464105SIgor Mammedov 
1163a464105SIgor Mammedov     if (!type) {
1173a464105SIgor Mammedov         error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
1183a464105SIgor Mammedov         return NULL;
1193a464105SIgor Mammedov     }
1203a464105SIgor Mammedov     if (!id) {
1213a464105SIgor Mammedov         error_setg(errp, QERR_MISSING_PARAMETER, "id");
12208329701SEric Blake         qemu_opt_set(opts, "qom-type", type, &error_abort);
1239a6d1acbSEric Blake         g_free(type);
1243a464105SIgor Mammedov         return NULL;
1253a464105SIgor Mammedov     }
1263a464105SIgor Mammedov 
1279a6d1acbSEric Blake     qemu_opts_set_id(opts, NULL);
1283a464105SIgor Mammedov     pdict = qemu_opts_to_qdict(opts, NULL);
12990998d58SDaniel P. Berrange 
13009204eacSEric Blake     v = opts_visitor_new(opts);
1313a464105SIgor Mammedov     obj = user_creatable_add_type(type, id, pdict, v, errp);
13209204eacSEric Blake     visit_free(v);
1333a464105SIgor Mammedov 
1349a6d1acbSEric Blake     qemu_opts_set_id(opts, (char *) id);
13508329701SEric Blake     qemu_opt_set(opts, "qom-type", type, &error_abort);
1369a6d1acbSEric Blake     g_free(type);
137cb3e7f08SMarc-André Lureau     qobject_unref(pdict);
13890998d58SDaniel P. Berrange     return obj;
13990998d58SDaniel P. Berrange }
14090998d58SDaniel P. Berrange 
14190998d58SDaniel P. Berrange 
14290998d58SDaniel P. Berrange int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
14390998d58SDaniel P. Berrange {
144*1195fa2bSMarc-André Lureau     bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque;
14590998d58SDaniel P. Berrange     Object *obj = NULL;
14651b9b478SMarkus Armbruster     Error *err = NULL;
14790998d58SDaniel P. Berrange     const char *type;
14890998d58SDaniel P. Berrange 
14990998d58SDaniel P. Berrange     type = qemu_opt_get(opts, "qom-type");
150*1195fa2bSMarc-André Lureau     if (type && type_opt_predicate &&
151*1195fa2bSMarc-André Lureau         !type_opt_predicate(type, opts)) {
15290998d58SDaniel P. Berrange         return 0;
15390998d58SDaniel P. Berrange     }
15490998d58SDaniel P. Berrange 
15551b9b478SMarkus Armbruster     obj = user_creatable_add_opts(opts, &err);
15690998d58SDaniel P. Berrange     if (!obj) {
15751b9b478SMarkus Armbruster         error_report_err(err);
15890998d58SDaniel P. Berrange         return -1;
15990998d58SDaniel P. Berrange     }
16090998d58SDaniel P. Berrange     object_unref(obj);
16190998d58SDaniel P. Berrange     return 0;
16290998d58SDaniel P. Berrange }
16390998d58SDaniel P. Berrange 
16490998d58SDaniel P. Berrange 
16590998d58SDaniel P. Berrange void user_creatable_del(const char *id, Error **errp)
16690998d58SDaniel P. Berrange {
16790998d58SDaniel P. Berrange     Object *container;
16890998d58SDaniel P. Berrange     Object *obj;
16990998d58SDaniel P. Berrange 
17090998d58SDaniel P. Berrange     container = object_get_objects_root();
17190998d58SDaniel P. Berrange     obj = object_resolve_path_component(container, id);
17290998d58SDaniel P. Berrange     if (!obj) {
17390998d58SDaniel P. Berrange         error_setg(errp, "object '%s' not found", id);
17490998d58SDaniel P. Berrange         return;
17590998d58SDaniel P. Berrange     }
17690998d58SDaniel P. Berrange 
1773beacfb9SEduardo Habkost     if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) {
17890998d58SDaniel P. Berrange         error_setg(errp, "object '%s' is in use, can not be deleted", id);
17990998d58SDaniel P. Berrange         return;
18090998d58SDaniel P. Berrange     }
181c645d5acSMichael Roth 
182c645d5acSMichael Roth     /*
183c645d5acSMichael Roth      * if object was defined on the command-line, remove its corresponding
184c645d5acSMichael Roth      * option group entry
185c645d5acSMichael Roth      */
186c645d5acSMichael Roth     qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort),
187c645d5acSMichael Roth                                  id));
188c645d5acSMichael Roth 
18990998d58SDaniel P. Berrange     object_unparent(obj);
19090998d58SDaniel P. Berrange }
19190998d58SDaniel P. Berrange 
1929d5139e5SEduardo Habkost void user_creatable_cleanup(void)
1939d5139e5SEduardo Habkost {
1949d5139e5SEduardo Habkost     object_unparent(object_get_objects_root());
1959d5139e5SEduardo Habkost }
1969d5139e5SEduardo Habkost 
197269e09f3SIgor Mammedov static void register_types(void)
198269e09f3SIgor Mammedov {
199269e09f3SIgor Mammedov     static const TypeInfo uc_interface_info = {
200269e09f3SIgor Mammedov         .name          = TYPE_USER_CREATABLE,
201269e09f3SIgor Mammedov         .parent        = TYPE_INTERFACE,
202269e09f3SIgor Mammedov         .class_size = sizeof(UserCreatableClass),
203269e09f3SIgor Mammedov     };
204269e09f3SIgor Mammedov 
205269e09f3SIgor Mammedov     type_register_static(&uc_interface_info);
206269e09f3SIgor Mammedov }
207269e09f3SIgor Mammedov 
208269e09f3SIgor Mammedov type_init(register_types)
209