xref: /qemu/qom/object_interfaces.c (revision 09204eac)
19bbc853bSPeter Maydell #include "qemu/osdep.h"
2da34e65cSMarkus Armbruster #include "qapi/error.h"
3269e09f3SIgor Mammedov #include "qom/object_interfaces.h"
4269e09f3SIgor Mammedov #include "qemu/module.h"
590998d58SDaniel P. Berrange #include "qapi-visit.h"
690998d58SDaniel P. Berrange #include "qapi/qmp-output-visitor.h"
790998d58SDaniel P. Berrange #include "qapi/opts-visitor.h"
8269e09f3SIgor Mammedov 
9269e09f3SIgor Mammedov void user_creatable_complete(Object *obj, Error **errp)
10269e09f3SIgor Mammedov {
11269e09f3SIgor Mammedov 
12269e09f3SIgor Mammedov     UserCreatableClass *ucc;
13269e09f3SIgor Mammedov     UserCreatable *uc =
14269e09f3SIgor Mammedov         (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
15269e09f3SIgor Mammedov 
16269e09f3SIgor Mammedov     if (!uc) {
17269e09f3SIgor Mammedov         return;
18269e09f3SIgor Mammedov     }
19269e09f3SIgor Mammedov 
20269e09f3SIgor Mammedov     ucc = USER_CREATABLE_GET_CLASS(uc);
21269e09f3SIgor Mammedov     if (ucc->complete) {
22269e09f3SIgor Mammedov         ucc->complete(uc, errp);
23269e09f3SIgor Mammedov     }
24269e09f3SIgor Mammedov }
25269e09f3SIgor Mammedov 
26d6edb155SLin Ma bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp)
27d6edb155SLin Ma {
28d6edb155SLin Ma 
29d6edb155SLin Ma     UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
30d6edb155SLin Ma 
31d6edb155SLin Ma     if (ucc->can_be_deleted) {
32d6edb155SLin Ma         return ucc->can_be_deleted(uc, errp);
33d6edb155SLin Ma     } else {
34d6edb155SLin Ma         return true;
35d6edb155SLin Ma     }
36d6edb155SLin Ma }
37d6edb155SLin Ma 
3890998d58SDaniel P. Berrange 
3990998d58SDaniel P. Berrange Object *user_creatable_add(const QDict *qdict,
4090998d58SDaniel P. Berrange                            Visitor *v, Error **errp)
4190998d58SDaniel P. Berrange {
4290998d58SDaniel P. Berrange     char *type = NULL;
4390998d58SDaniel P. Berrange     char *id = NULL;
4490998d58SDaniel P. Berrange     Object *obj = NULL;
4515c2f669SEric Blake     Error *local_err = NULL;
4690998d58SDaniel P. Berrange     QDict *pdict;
4790998d58SDaniel P. Berrange 
4890998d58SDaniel P. Berrange     pdict = qdict_clone_shallow(qdict);
4990998d58SDaniel P. Berrange 
5090998d58SDaniel P. Berrange     visit_start_struct(v, NULL, NULL, 0, &local_err);
5190998d58SDaniel P. Berrange     if (local_err) {
5290998d58SDaniel P. Berrange         goto out;
5390998d58SDaniel P. Berrange     }
5490998d58SDaniel P. Berrange 
5590998d58SDaniel P. Berrange     qdict_del(pdict, "qom-type");
5690998d58SDaniel P. Berrange     visit_type_str(v, "qom-type", &type, &local_err);
5790998d58SDaniel P. Berrange     if (local_err) {
5890998d58SDaniel P. Berrange         goto out_visit;
5990998d58SDaniel P. Berrange     }
6090998d58SDaniel P. Berrange 
6190998d58SDaniel P. Berrange     qdict_del(pdict, "id");
6290998d58SDaniel P. Berrange     visit_type_str(v, "id", &id, &local_err);
6390998d58SDaniel P. Berrange     if (local_err) {
6490998d58SDaniel P. Berrange         goto out_visit;
6590998d58SDaniel P. Berrange     }
6615c2f669SEric Blake     visit_check_struct(v, &local_err);
6790998d58SDaniel P. Berrange     if (local_err) {
6890998d58SDaniel P. Berrange         goto out_visit;
6990998d58SDaniel P. Berrange     }
7090998d58SDaniel P. Berrange 
7115c2f669SEric Blake     obj = user_creatable_add_type(type, id, pdict, v, &local_err);
7215c2f669SEric Blake 
7390998d58SDaniel P. Berrange out_visit:
741158bb2aSEric Blake     visit_end_struct(v, NULL);
7590998d58SDaniel P. Berrange 
7690998d58SDaniel P. Berrange out:
7790998d58SDaniel P. Berrange     QDECREF(pdict);
7890998d58SDaniel P. Berrange     g_free(id);
7990998d58SDaniel P. Berrange     g_free(type);
8090998d58SDaniel P. Berrange     if (local_err) {
8190998d58SDaniel P. Berrange         error_propagate(errp, local_err);
8290998d58SDaniel P. Berrange         object_unref(obj);
8390998d58SDaniel P. Berrange         return NULL;
8490998d58SDaniel P. Berrange     }
8590998d58SDaniel P. Berrange     return obj;
8690998d58SDaniel P. Berrange }
8790998d58SDaniel P. Berrange 
8890998d58SDaniel P. Berrange 
8990998d58SDaniel P. Berrange Object *user_creatable_add_type(const char *type, const char *id,
9090998d58SDaniel P. Berrange                                 const QDict *qdict,
9190998d58SDaniel P. Berrange                                 Visitor *v, Error **errp)
9290998d58SDaniel P. Berrange {
9390998d58SDaniel P. Berrange     Object *obj;
9490998d58SDaniel P. Berrange     ObjectClass *klass;
9590998d58SDaniel P. Berrange     const QDictEntry *e;
9690998d58SDaniel P. Berrange     Error *local_err = NULL;
9790998d58SDaniel P. Berrange 
9890998d58SDaniel P. Berrange     klass = object_class_by_name(type);
9990998d58SDaniel P. Berrange     if (!klass) {
10090998d58SDaniel P. Berrange         error_setg(errp, "invalid object type: %s", type);
10190998d58SDaniel P. Berrange         return NULL;
10290998d58SDaniel P. Berrange     }
10390998d58SDaniel P. Berrange 
10490998d58SDaniel P. Berrange     if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
10590998d58SDaniel P. Berrange         error_setg(errp, "object type '%s' isn't supported by object-add",
10690998d58SDaniel P. Berrange                    type);
10790998d58SDaniel P. Berrange         return NULL;
10890998d58SDaniel P. Berrange     }
10990998d58SDaniel P. Berrange 
11090998d58SDaniel P. Berrange     if (object_class_is_abstract(klass)) {
11190998d58SDaniel P. Berrange         error_setg(errp, "object type '%s' is abstract", type);
11290998d58SDaniel P. Berrange         return NULL;
11390998d58SDaniel P. Berrange     }
11490998d58SDaniel P. Berrange 
115ad739706SEric Blake     assert(qdict);
11690998d58SDaniel P. Berrange     obj = object_new(type);
117ad739706SEric Blake     visit_start_struct(v, NULL, NULL, 0, &local_err);
11890998d58SDaniel P. Berrange     if (local_err) {
11990998d58SDaniel P. Berrange         goto out;
12090998d58SDaniel P. Berrange     }
121ad739706SEric Blake     for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
122ad739706SEric Blake         object_property_set(obj, v, e->key, &local_err);
123ad739706SEric Blake         if (local_err) {
124ad739706SEric Blake             break;
12590998d58SDaniel P. Berrange         }
12690998d58SDaniel P. Berrange     }
12715c2f669SEric Blake     if (!local_err) {
12815c2f669SEric Blake         visit_check_struct(v, &local_err);
12915c2f669SEric Blake     }
1301158bb2aSEric Blake     visit_end_struct(v, NULL);
131ad739706SEric Blake     if (local_err) {
132ad739706SEric Blake         goto out;
133ad739706SEric Blake     }
13490998d58SDaniel P. Berrange 
13590998d58SDaniel P. Berrange     object_property_add_child(object_get_objects_root(),
13690998d58SDaniel P. Berrange                               id, obj, &local_err);
13790998d58SDaniel P. Berrange     if (local_err) {
13890998d58SDaniel P. Berrange         goto out;
13990998d58SDaniel P. Berrange     }
14090998d58SDaniel P. Berrange 
14190998d58SDaniel P. Berrange     user_creatable_complete(obj, &local_err);
14290998d58SDaniel P. Berrange     if (local_err) {
14390998d58SDaniel P. Berrange         object_property_del(object_get_objects_root(),
14490998d58SDaniel P. Berrange                             id, &error_abort);
14590998d58SDaniel P. Berrange         goto out;
14690998d58SDaniel P. Berrange     }
14790998d58SDaniel P. Berrange out:
14890998d58SDaniel P. Berrange     if (local_err) {
14990998d58SDaniel P. Berrange         error_propagate(errp, local_err);
15090998d58SDaniel P. Berrange         object_unref(obj);
15190998d58SDaniel P. Berrange         return NULL;
15290998d58SDaniel P. Berrange     }
15390998d58SDaniel P. Berrange     return obj;
15490998d58SDaniel P. Berrange }
15590998d58SDaniel P. Berrange 
15690998d58SDaniel P. Berrange 
15790998d58SDaniel P. Berrange Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
15890998d58SDaniel P. Berrange {
159*09204eacSEric Blake     Visitor *v;
16090998d58SDaniel P. Berrange     QDict *pdict;
16190998d58SDaniel P. Berrange     Object *obj = NULL;
16290998d58SDaniel P. Berrange 
163*09204eacSEric Blake     v = opts_visitor_new(opts);
16490998d58SDaniel P. Berrange     pdict = qemu_opts_to_qdict(opts, NULL);
16590998d58SDaniel P. Berrange 
166*09204eacSEric Blake     obj = user_creatable_add(pdict, v, errp);
167*09204eacSEric Blake     visit_free(v);
16890998d58SDaniel P. Berrange     QDECREF(pdict);
16990998d58SDaniel P. Berrange     return obj;
17090998d58SDaniel P. Berrange }
17190998d58SDaniel P. Berrange 
17290998d58SDaniel P. Berrange 
17390998d58SDaniel P. Berrange int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
17490998d58SDaniel P. Berrange {
17590998d58SDaniel P. Berrange     bool (*type_predicate)(const char *) = opaque;
17690998d58SDaniel P. Berrange     Object *obj = NULL;
17751b9b478SMarkus Armbruster     Error *err = NULL;
17890998d58SDaniel P. Berrange     const char *type;
17990998d58SDaniel P. Berrange 
18090998d58SDaniel P. Berrange     type = qemu_opt_get(opts, "qom-type");
18190998d58SDaniel P. Berrange     if (type && type_predicate &&
18290998d58SDaniel P. Berrange         !type_predicate(type)) {
18390998d58SDaniel P. Berrange         return 0;
18490998d58SDaniel P. Berrange     }
18590998d58SDaniel P. Berrange 
18651b9b478SMarkus Armbruster     obj = user_creatable_add_opts(opts, &err);
18790998d58SDaniel P. Berrange     if (!obj) {
18851b9b478SMarkus Armbruster         error_report_err(err);
18990998d58SDaniel P. Berrange         return -1;
19090998d58SDaniel P. Berrange     }
19190998d58SDaniel P. Berrange     object_unref(obj);
19290998d58SDaniel P. Berrange     return 0;
19390998d58SDaniel P. Berrange }
19490998d58SDaniel P. Berrange 
19590998d58SDaniel P. Berrange 
19690998d58SDaniel P. Berrange void user_creatable_del(const char *id, Error **errp)
19790998d58SDaniel P. Berrange {
19890998d58SDaniel P. Berrange     Object *container;
19990998d58SDaniel P. Berrange     Object *obj;
20090998d58SDaniel P. Berrange 
20190998d58SDaniel P. Berrange     container = object_get_objects_root();
20290998d58SDaniel P. Berrange     obj = object_resolve_path_component(container, id);
20390998d58SDaniel P. Berrange     if (!obj) {
20490998d58SDaniel P. Berrange         error_setg(errp, "object '%s' not found", id);
20590998d58SDaniel P. Berrange         return;
20690998d58SDaniel P. Berrange     }
20790998d58SDaniel P. Berrange 
20890998d58SDaniel P. Berrange     if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) {
20990998d58SDaniel P. Berrange         error_setg(errp, "object '%s' is in use, can not be deleted", id);
21090998d58SDaniel P. Berrange         return;
21190998d58SDaniel P. Berrange     }
21290998d58SDaniel P. Berrange     object_unparent(obj);
21390998d58SDaniel P. Berrange }
21490998d58SDaniel P. Berrange 
215269e09f3SIgor Mammedov static void register_types(void)
216269e09f3SIgor Mammedov {
217269e09f3SIgor Mammedov     static const TypeInfo uc_interface_info = {
218269e09f3SIgor Mammedov         .name          = TYPE_USER_CREATABLE,
219269e09f3SIgor Mammedov         .parent        = TYPE_INTERFACE,
220269e09f3SIgor Mammedov         .class_size = sizeof(UserCreatableClass),
221269e09f3SIgor Mammedov     };
222269e09f3SIgor Mammedov 
223269e09f3SIgor Mammedov     type_register_static(&uc_interface_info);
224269e09f3SIgor Mammedov }
225269e09f3SIgor Mammedov 
226269e09f3SIgor Mammedov type_init(register_types)
227