object_interfaces.c 4.9 KB

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