xref: /qemu/qom/object_interfaces.c (revision 6134d752)
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 
113650b2deSMarc-André Lureau void user_creatable_complete(UserCreatable *uc, Error **errp)
12269e09f3SIgor Mammedov {
133650b2deSMarc-André Lureau     UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
14269e09f3SIgor Mammedov 
15269e09f3SIgor Mammedov     if (ucc->complete) {
16269e09f3SIgor Mammedov         ucc->complete(uc, errp);
17269e09f3SIgor Mammedov     }
18269e09f3SIgor Mammedov }
19269e09f3SIgor Mammedov 
203beacfb9SEduardo Habkost bool user_creatable_can_be_deleted(UserCreatable *uc)
21d6edb155SLin Ma {
22d6edb155SLin Ma 
23d6edb155SLin Ma     UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
24d6edb155SLin Ma 
25d6edb155SLin Ma     if (ucc->can_be_deleted) {
263beacfb9SEduardo Habkost         return ucc->can_be_deleted(uc);
27d6edb155SLin Ma     } else {
28d6edb155SLin Ma         return true;
29d6edb155SLin Ma     }
30d6edb155SLin Ma }
31d6edb155SLin Ma 
3290998d58SDaniel P. Berrange Object *user_creatable_add_type(const char *type, const char *id,
3390998d58SDaniel P. Berrange                                 const QDict *qdict,
3490998d58SDaniel P. Berrange                                 Visitor *v, Error **errp)
3590998d58SDaniel P. Berrange {
3690998d58SDaniel P. Berrange     Object *obj;
3790998d58SDaniel P. Berrange     ObjectClass *klass;
3890998d58SDaniel P. Berrange     const QDictEntry *e;
3990998d58SDaniel P. Berrange     Error *local_err = NULL;
4090998d58SDaniel P. Berrange 
4190998d58SDaniel P. Berrange     klass = object_class_by_name(type);
4290998d58SDaniel P. Berrange     if (!klass) {
4390998d58SDaniel P. Berrange         error_setg(errp, "invalid object type: %s", type);
4490998d58SDaniel P. Berrange         return NULL;
4590998d58SDaniel P. Berrange     }
4690998d58SDaniel P. Berrange 
4790998d58SDaniel P. Berrange     if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
4890998d58SDaniel P. Berrange         error_setg(errp, "object type '%s' isn't supported by object-add",
4990998d58SDaniel P. Berrange                    type);
5090998d58SDaniel P. Berrange         return NULL;
5190998d58SDaniel P. Berrange     }
5290998d58SDaniel P. Berrange 
5390998d58SDaniel P. Berrange     if (object_class_is_abstract(klass)) {
5490998d58SDaniel P. Berrange         error_setg(errp, "object type '%s' is abstract", type);
5590998d58SDaniel P. Berrange         return NULL;
5690998d58SDaniel P. Berrange     }
5790998d58SDaniel P. Berrange 
58ad739706SEric Blake     assert(qdict);
5990998d58SDaniel P. Berrange     obj = object_new(type);
60ad739706SEric Blake     visit_start_struct(v, NULL, NULL, 0, &local_err);
6190998d58SDaniel P. Berrange     if (local_err) {
6290998d58SDaniel P. Berrange         goto out;
6390998d58SDaniel P. Berrange     }
64ad739706SEric Blake     for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
65ad739706SEric Blake         object_property_set(obj, v, e->key, &local_err);
66ad739706SEric Blake         if (local_err) {
67ad739706SEric Blake             break;
6890998d58SDaniel P. Berrange         }
6990998d58SDaniel P. Berrange     }
7015c2f669SEric Blake     if (!local_err) {
7115c2f669SEric Blake         visit_check_struct(v, &local_err);
7215c2f669SEric Blake     }
731158bb2aSEric Blake     visit_end_struct(v, NULL);
74ad739706SEric Blake     if (local_err) {
75ad739706SEric Blake         goto out;
76ad739706SEric Blake     }
7790998d58SDaniel P. Berrange 
78*6134d752SDaniel P. Berrangé     if (id != NULL) {
7990998d58SDaniel P. Berrange         object_property_add_child(object_get_objects_root(),
8090998d58SDaniel P. Berrange                                   id, obj, &local_err);
8190998d58SDaniel P. Berrange         if (local_err) {
8290998d58SDaniel P. Berrange             goto out;
8390998d58SDaniel P. Berrange         }
84*6134d752SDaniel P. Berrangé     }
8590998d58SDaniel P. Berrange 
863650b2deSMarc-André Lureau     user_creatable_complete(USER_CREATABLE(obj), &local_err);
8790998d58SDaniel P. Berrange     if (local_err) {
88*6134d752SDaniel P. Berrangé         if (id != NULL) {
8990998d58SDaniel P. Berrange             object_property_del(object_get_objects_root(),
9090998d58SDaniel P. Berrange                                 id, &error_abort);
91*6134d752SDaniel P. Berrangé         }
9290998d58SDaniel P. Berrange         goto out;
9390998d58SDaniel P. Berrange     }
9490998d58SDaniel P. Berrange out:
9590998d58SDaniel P. Berrange     if (local_err) {
9690998d58SDaniel P. Berrange         error_propagate(errp, local_err);
9790998d58SDaniel P. Berrange         object_unref(obj);
9890998d58SDaniel P. Berrange         return NULL;
9990998d58SDaniel P. Berrange     }
10090998d58SDaniel P. Berrange     return obj;
10190998d58SDaniel P. Berrange }
10290998d58SDaniel P. Berrange 
10390998d58SDaniel P. Berrange 
10490998d58SDaniel P. Berrange Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
10590998d58SDaniel P. Berrange {
10609204eacSEric Blake     Visitor *v;
10790998d58SDaniel P. Berrange     QDict *pdict;
1083a464105SIgor Mammedov     Object *obj;
1093a464105SIgor Mammedov     const char *id = qemu_opts_id(opts);
1109a6d1acbSEric Blake     char *type = qemu_opt_get_del(opts, "qom-type");
1113a464105SIgor Mammedov 
1123a464105SIgor Mammedov     if (!type) {
1133a464105SIgor Mammedov         error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
1143a464105SIgor Mammedov         return NULL;
1153a464105SIgor Mammedov     }
1163a464105SIgor Mammedov     if (!id) {
1173a464105SIgor Mammedov         error_setg(errp, QERR_MISSING_PARAMETER, "id");
11808329701SEric Blake         qemu_opt_set(opts, "qom-type", type, &error_abort);
1199a6d1acbSEric Blake         g_free(type);
1203a464105SIgor Mammedov         return NULL;
1213a464105SIgor Mammedov     }
1223a464105SIgor Mammedov 
1239a6d1acbSEric Blake     qemu_opts_set_id(opts, NULL);
1243a464105SIgor Mammedov     pdict = qemu_opts_to_qdict(opts, NULL);
12590998d58SDaniel P. Berrange 
12609204eacSEric Blake     v = opts_visitor_new(opts);
1273a464105SIgor Mammedov     obj = user_creatable_add_type(type, id, pdict, v, errp);
12809204eacSEric Blake     visit_free(v);
1293a464105SIgor Mammedov 
1309a6d1acbSEric Blake     qemu_opts_set_id(opts, (char *) id);
13108329701SEric Blake     qemu_opt_set(opts, "qom-type", type, &error_abort);
1329a6d1acbSEric Blake     g_free(type);
133cb3e7f08SMarc-André Lureau     qobject_unref(pdict);
13490998d58SDaniel P. Berrange     return obj;
13590998d58SDaniel P. Berrange }
13690998d58SDaniel P. Berrange 
13790998d58SDaniel P. Berrange 
13890998d58SDaniel P. Berrange int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
13990998d58SDaniel P. Berrange {
1401195fa2bSMarc-André Lureau     bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque;
14190998d58SDaniel P. Berrange     Object *obj = NULL;
14290998d58SDaniel P. Berrange     const char *type;
14390998d58SDaniel P. Berrange 
14490998d58SDaniel P. Berrange     type = qemu_opt_get(opts, "qom-type");
1451195fa2bSMarc-André Lureau     if (type && type_opt_predicate &&
1461195fa2bSMarc-André Lureau         !type_opt_predicate(type, opts)) {
14790998d58SDaniel P. Berrange         return 0;
14890998d58SDaniel P. Berrange     }
14990998d58SDaniel P. Berrange 
1507e1e0c11SMarkus Armbruster     obj = user_creatable_add_opts(opts, errp);
15190998d58SDaniel P. Berrange     if (!obj) {
15290998d58SDaniel P. Berrange         return -1;
15390998d58SDaniel P. Berrange     }
15490998d58SDaniel P. Berrange     object_unref(obj);
15590998d58SDaniel P. Berrange     return 0;
15690998d58SDaniel P. Berrange }
15790998d58SDaniel P. Berrange 
15890998d58SDaniel P. Berrange 
15990998d58SDaniel P. Berrange void user_creatable_del(const char *id, Error **errp)
16090998d58SDaniel P. Berrange {
16190998d58SDaniel P. Berrange     Object *container;
16290998d58SDaniel P. Berrange     Object *obj;
16390998d58SDaniel P. Berrange 
16490998d58SDaniel P. Berrange     container = object_get_objects_root();
16590998d58SDaniel P. Berrange     obj = object_resolve_path_component(container, id);
16690998d58SDaniel P. Berrange     if (!obj) {
16790998d58SDaniel P. Berrange         error_setg(errp, "object '%s' not found", id);
16890998d58SDaniel P. Berrange         return;
16990998d58SDaniel P. Berrange     }
17090998d58SDaniel P. Berrange 
1713beacfb9SEduardo Habkost     if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) {
17290998d58SDaniel P. Berrange         error_setg(errp, "object '%s' is in use, can not be deleted", id);
17390998d58SDaniel P. Berrange         return;
17490998d58SDaniel P. Berrange     }
175c645d5acSMichael Roth 
176c645d5acSMichael Roth     /*
177c645d5acSMichael Roth      * if object was defined on the command-line, remove its corresponding
178c645d5acSMichael Roth      * option group entry
179c645d5acSMichael Roth      */
180c645d5acSMichael Roth     qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort),
181c645d5acSMichael Roth                                  id));
182c645d5acSMichael Roth 
18390998d58SDaniel P. Berrange     object_unparent(obj);
18490998d58SDaniel P. Berrange }
18590998d58SDaniel P. Berrange 
1869d5139e5SEduardo Habkost void user_creatable_cleanup(void)
1879d5139e5SEduardo Habkost {
1889d5139e5SEduardo Habkost     object_unparent(object_get_objects_root());
1899d5139e5SEduardo Habkost }
1909d5139e5SEduardo Habkost 
191269e09f3SIgor Mammedov static void register_types(void)
192269e09f3SIgor Mammedov {
193269e09f3SIgor Mammedov     static const TypeInfo uc_interface_info = {
194269e09f3SIgor Mammedov         .name          = TYPE_USER_CREATABLE,
195269e09f3SIgor Mammedov         .parent        = TYPE_INTERFACE,
196269e09f3SIgor Mammedov         .class_size = sizeof(UserCreatableClass),
197269e09f3SIgor Mammedov     };
198269e09f3SIgor Mammedov 
199269e09f3SIgor Mammedov     type_register_static(&uc_interface_info);
200269e09f3SIgor Mammedov }
201269e09f3SIgor Mammedov 
202269e09f3SIgor Mammedov type_init(register_types)
203