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; 45*15c2f669SEric 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 } 66*15c2f669SEric 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 71*15c2f669SEric Blake obj = user_creatable_add_type(type, id, pdict, v, &local_err); 72*15c2f669SEric Blake 7390998d58SDaniel P. Berrange out_visit: 74*15c2f669SEric Blake visit_end_struct(v); 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 } 127*15c2f669SEric Blake if (!local_err) { 128*15c2f669SEric Blake visit_check_struct(v, &local_err); 129*15c2f669SEric Blake } 130*15c2f669SEric Blake visit_end_struct(v); 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 { 15990998d58SDaniel P. Berrange OptsVisitor *ov; 16090998d58SDaniel P. Berrange QDict *pdict; 16190998d58SDaniel P. Berrange Object *obj = NULL; 16290998d58SDaniel P. Berrange 16390998d58SDaniel P. Berrange ov = opts_visitor_new(opts); 16490998d58SDaniel P. Berrange pdict = qemu_opts_to_qdict(opts, NULL); 16590998d58SDaniel P. Berrange 16690998d58SDaniel P. Berrange obj = user_creatable_add(pdict, opts_get_visitor(ov), errp); 16790998d58SDaniel P. Berrange opts_visitor_cleanup(ov); 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