1 /*
2  * libvirt-gconfig-domain.c: libvirt domain configuration
3  *
4  * Copyright (C) 2008 Daniel P. Berrange
5  * Copyright (C) 2010-2011 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  *
21  * Author: Daniel P. Berrange <berrange@redhat.com>
22  */
23 
24 #include <config.h>
25 
26 #include "libvirt-gconfig/libvirt-gconfig.h"
27 #include "libvirt-gconfig/libvirt-gconfig-private.h"
28 
29 #define GVIR_CONFIG_DOMAIN_GET_PRIVATE(obj)                         \
30         (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_CONFIG_TYPE_DOMAIN, GVirConfigDomainPrivate))
31 
32 struct _GVirConfigDomainPrivate
33 {
34     gboolean unused;
35 };
36 
37 G_DEFINE_TYPE_WITH_PRIVATE(GVirConfigDomain, gvir_config_domain, GVIR_CONFIG_TYPE_OBJECT);
38 
39 enum {
40     PROP_0,
41     PROP_NAME,
42     PROP_UUID,
43     PROP_TITLE,
44     PROP_DESCRIPTION,
45     PROP_MEMORY,
46     PROP_VCPU,
47     PROP_FEATURES,
48     PROP_CURRENT_MEMORY
49 };
50 
gvir_config_domain_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)51 static void gvir_config_domain_get_property(GObject *object,
52                                             guint prop_id,
53                                             GValue *value,
54                                             GParamSpec *pspec)
55 {
56     GVirConfigDomain *domain = GVIR_CONFIG_DOMAIN(object);
57 
58     switch (prop_id) {
59     case PROP_NAME:
60         g_value_set_string(value, gvir_config_domain_get_name(domain));
61         break;
62     case PROP_UUID:
63         g_value_set_string(value, gvir_config_domain_get_uuid(domain));
64         break;
65     case PROP_TITLE:
66         g_value_set_string(value, gvir_config_domain_get_title(domain));
67         break;
68     case PROP_DESCRIPTION:
69         g_value_set_string(value, gvir_config_domain_get_description(domain));
70         break;
71     case PROP_MEMORY:
72         g_value_set_uint64(value, gvir_config_domain_get_memory(domain));
73         break;
74     case PROP_CURRENT_MEMORY:
75         g_value_set_uint64(value, gvir_config_domain_get_current_memory(domain));
76         break;
77     case PROP_VCPU:
78         g_value_set_uint64(value, gvir_config_domain_get_vcpus(domain));
79         break;
80     case PROP_FEATURES:
81         g_value_take_boxed(value, gvir_config_domain_get_features(domain));
82         break;
83 
84     default:
85         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
86     }
87 }
88 
gvir_config_domain_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)89 static void gvir_config_domain_set_property(GObject *object,
90                                             guint prop_id,
91                                             const GValue *value,
92                                             GParamSpec *pspec)
93 {
94     GVirConfigDomain *domain = GVIR_CONFIG_DOMAIN(object);
95 
96     switch (prop_id) {
97     case PROP_NAME:
98         gvir_config_domain_set_name(domain, g_value_get_string(value));
99         break;
100     case PROP_UUID:
101         gvir_config_domain_set_uuid(domain, g_value_get_string(value));
102         break;
103     case PROP_TITLE:
104         gvir_config_domain_set_title(domain, g_value_get_string(value));
105         break;
106     case PROP_DESCRIPTION:
107         gvir_config_domain_set_description(domain, g_value_get_string(value));
108         break;
109     case PROP_MEMORY:
110         gvir_config_domain_set_memory(domain, g_value_get_uint64(value));
111         break;
112     case PROP_CURRENT_MEMORY:
113         gvir_config_domain_set_current_memory(domain, g_value_get_uint64(value));
114         break;
115     case PROP_VCPU:
116         gvir_config_domain_set_vcpus(domain, g_value_get_uint64(value));
117         break;
118     case PROP_FEATURES:
119         gvir_config_domain_set_features(domain, g_value_get_boxed(value));
120         break;
121     default:
122         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
123     }
124 }
125 
126 
gvir_config_domain_class_init(GVirConfigDomainClass * klass)127 static void gvir_config_domain_class_init(GVirConfigDomainClass *klass)
128 {
129     GObjectClass *object_class = G_OBJECT_CLASS(klass);
130 
131     object_class->get_property = gvir_config_domain_get_property;
132     object_class->set_property = gvir_config_domain_set_property;
133 
134     g_object_class_install_property(object_class,
135                                     PROP_NAME,
136                                     g_param_spec_string("name",
137                                                         "Name",
138                                                         "Domain Name",
139                                                         NULL,
140                                                         G_PARAM_READWRITE |
141                                                         G_PARAM_STATIC_STRINGS));
142     g_object_class_install_property(object_class,
143                                     PROP_UUID,
144                                     g_param_spec_string("uuid",
145                                                         "UUID",
146                                                         "Domain UUID",
147                                                         NULL,
148                                                         G_PARAM_READWRITE |
149                                                         G_PARAM_STATIC_STRINGS));
150     g_object_class_install_property(object_class,
151                                     PROP_TITLE,
152                                     g_param_spec_string("title",
153                                                         "Title",
154                                                         "A short description - title - of the domain",
155                                                         NULL,
156                                                         G_PARAM_READWRITE |
157                                                         G_PARAM_STATIC_STRINGS));
158     g_object_class_install_property(object_class,
159                                     PROP_DESCRIPTION,
160                                     g_param_spec_string("description",
161                                                         "Description",
162                                                         "Some human readable description (could be anything).",
163                                                         NULL,
164                                                         G_PARAM_READWRITE |
165                                                         G_PARAM_STATIC_STRINGS));
166     g_object_class_install_property(object_class,
167                                     PROP_MEMORY,
168                                     g_param_spec_uint64("memory",
169                                                         "Memory",
170                                                         "Maximum Guest Memory (in kilobytes)",
171                                                         0, G_MAXUINT64,
172                                                         0,
173                                                         G_PARAM_READWRITE |
174                                                         G_PARAM_STATIC_STRINGS));
175     g_object_class_install_property(object_class,
176                                     PROP_CURRENT_MEMORY,
177                                     g_param_spec_uint64("current-memory",
178                                                         "Current memory",
179                                                         "Current Guest Memory (in kilobytes)",
180                                                         0, G_MAXUINT64,
181                                                         0,
182                                                         G_PARAM_READWRITE |
183                                                         G_PARAM_STATIC_STRINGS));
184     g_object_class_install_property(object_class,
185                                     PROP_VCPU,
186                                     g_param_spec_uint64("vcpu",
187                                                         "Virtual CPUs",
188                                                         "Maximum Number of Guest Virtual CPUs",
189                                                         0, G_MAXUINT64,
190                                                         1,
191                                                         G_PARAM_READWRITE |
192                                                         G_PARAM_STATIC_STRINGS));
193     g_object_class_install_property(object_class,
194                                     PROP_FEATURES,
195                                     g_param_spec_boxed("features",
196                                                         "Features",
197                                                         "Hypervisor Features",
198                                                         G_TYPE_STRV,
199                                                         G_PARAM_READWRITE |
200                                                         G_PARAM_STATIC_STRINGS));
201 }
202 
203 
gvir_config_domain_init(GVirConfigDomain * domain)204 static void gvir_config_domain_init(GVirConfigDomain *domain)
205 {
206     domain->priv = GVIR_CONFIG_DOMAIN_GET_PRIVATE(domain);
207 }
208 
209 
gvir_config_domain_new_from_xml(const gchar * xml,GError ** error)210 GVirConfigDomain *gvir_config_domain_new_from_xml(const gchar *xml,
211                                                   GError **error)
212 {
213     GVirConfigObject *object;
214 
215     object = gvir_config_object_new_from_xml(GVIR_CONFIG_TYPE_DOMAIN,
216                                              "domain",
217                                              DATADIR "/libvirt/schemas/domain.rng",
218                                              xml, error);
219     return GVIR_CONFIG_DOMAIN(object);
220 }
221 
gvir_config_domain_new(void)222 GVirConfigDomain *gvir_config_domain_new(void)
223 {
224     GVirConfigObject *object;
225 
226     object = gvir_config_object_new(GVIR_CONFIG_TYPE_DOMAIN,
227                                     "domain",
228                                     DATADIR "/libvirt/schemas/domain.rng");
229     return GVIR_CONFIG_DOMAIN(object);
230 }
231 
gvir_config_domain_get_virt_type(GVirConfigDomain * domain)232 GVirConfigDomainVirtType gvir_config_domain_get_virt_type(GVirConfigDomain *domain)
233 {
234     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain),
235                          GVIR_CONFIG_DOMAIN_VIRT_QEMU);
236 
237     return gvir_config_object_get_attribute_genum
238                                 (GVIR_CONFIG_OBJECT(domain),
239                                  NULL,
240                                  "type",
241                                  GVIR_CONFIG_TYPE_DOMAIN_VIRT_TYPE,
242                                  GVIR_CONFIG_DOMAIN_VIRT_QEMU);
243 }
244 
gvir_config_domain_set_virt_type(GVirConfigDomain * domain,GVirConfigDomainVirtType type)245 void gvir_config_domain_set_virt_type(GVirConfigDomain *domain, GVirConfigDomainVirtType type)
246 {
247     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
248     gvir_config_object_set_attribute_with_type(GVIR_CONFIG_OBJECT(domain),
249                                                "type",
250                                                GVIR_CONFIG_TYPE_DOMAIN_VIRT_TYPE,
251                                                type, NULL);
252 }
253 
254 
gvir_config_domain_get_name(GVirConfigDomain * domain)255 const char *gvir_config_domain_get_name(GVirConfigDomain *domain)
256 {
257     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
258 
259     return gvir_config_object_get_node_content(GVIR_CONFIG_OBJECT(domain),
260                                                "name");
261 }
262 
gvir_config_domain_get_uuid(GVirConfigDomain * domain)263 const char *gvir_config_domain_get_uuid(GVirConfigDomain *domain)
264 {
265     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
266 
267     return gvir_config_object_get_node_content(GVIR_CONFIG_OBJECT(domain),
268                                                "uuid");
269 }
270 
gvir_config_domain_get_title(GVirConfigDomain * domain)271 const char *gvir_config_domain_get_title(GVirConfigDomain *domain)
272 {
273     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
274 
275     return gvir_config_object_get_node_content(GVIR_CONFIG_OBJECT(domain),
276                                                "title");
277 }
278 
279 /**
280  * gvir_config_domain_set_name:
281  * @domain: a #GVirConfigDomain
282  * @name: (allow-none):
283  */
gvir_config_domain_set_name(GVirConfigDomain * domain,const char * name)284 void gvir_config_domain_set_name(GVirConfigDomain *domain, const char *name)
285 {
286     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
287 
288     gvir_config_object_set_node_content(GVIR_CONFIG_OBJECT(domain),
289                                         "name", name);
290     g_object_notify(G_OBJECT(domain), "name");
291 }
292 
293 /**
294  * gvir_config_domain_set_uuid:
295  * @domain: a #GVirConfigDomain
296  * @uuid: (allow-none):
297  */
gvir_config_domain_set_uuid(GVirConfigDomain * domain,const char * uuid)298 void gvir_config_domain_set_uuid(GVirConfigDomain *domain, const char *uuid)
299 {
300     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
301 
302     gvir_config_object_set_node_content(GVIR_CONFIG_OBJECT(domain),
303                                         "uuid", uuid);
304     g_object_notify(G_OBJECT(domain), "uuid");
305 }
306 
307 /**
308  * gvir_config_domain_set_title:
309  * @domain: a #GVirConfigDomain
310  * @title: (allow-none): title of the domain
311  *
312  * Sets the title of the domain. This is an optional short textual description of the domain. Passing a NULL @title
313  * unsets the current domain title.
314  */
gvir_config_domain_set_title(GVirConfigDomain * domain,const char * title)315 void gvir_config_domain_set_title(GVirConfigDomain *domain, const char *title)
316 {
317     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
318 
319     gvir_config_object_set_node_content(GVIR_CONFIG_OBJECT(domain),
320                                         "title", title);
321     g_object_notify(G_OBJECT(domain), "title");
322 }
323 
gvir_config_domain_get_description(GVirConfigDomain * domain)324 const char *gvir_config_domain_get_description(GVirConfigDomain *domain)
325 {
326     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
327 
328     return gvir_config_object_get_node_content(GVIR_CONFIG_OBJECT(domain),
329                                                "description");
330 }
331 
332 /**
333  * gvir_config_domain_set_description:
334  * @domain: a #GVirConfigDomain
335  * @description: (allow-none):
336  */
gvir_config_domain_set_description(GVirConfigDomain * domain,const char * description)337 void gvir_config_domain_set_description(GVirConfigDomain *domain,
338                                         const char *description)
339 {
340     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
341 
342     gvir_config_object_set_node_content(GVIR_CONFIG_OBJECT(domain),
343                                         "description", description);
344     g_object_notify(G_OBJECT(domain), "description");
345 }
346 
insert_base(GHashTable * unit_bases,const char * unit,guint64 unit_base)347 static void insert_base(GHashTable *unit_bases,
348                         const char *unit,
349                         guint64 unit_base)
350 {
351     guint64 *base;
352     base = g_slice_alloc(sizeof(*base));
353     *base = unit_base;
354     g_hash_table_insert(unit_bases, (gpointer)unit, base);
355 }
356 
set_unit_bases(G_GNUC_UNUSED gpointer user_data)357 static gpointer set_unit_bases(G_GNUC_UNUSED gpointer user_data)
358 {
359     GHashTable *unit_bases;
360 
361     unit_bases = g_hash_table_new(g_str_hash, g_str_equal);
362 
363     insert_base(unit_bases, "b", 1);
364     insert_base(unit_bases, "bytes", 1);
365     insert_base(unit_bases, "KB", 1000);
366     insert_base(unit_bases, "k", 1024);
367     insert_base(unit_bases, "KiB", 1024);
368     insert_base(unit_bases, "MB", 1000*1000);
369     insert_base(unit_bases, "M", 1024*1024);
370     insert_base(unit_bases, "MiB", 1024*1024);
371     insert_base(unit_bases, "GB", 1000*1000*1000);
372     insert_base(unit_bases, "G", 1024*1024*1024);
373     insert_base(unit_bases, "GiB", 1024*1024*1024);
374     insert_base(unit_bases, "TB", (guint64)1000*1000*1000*1000);
375     insert_base(unit_bases, "T", (guint64)1024*1024*1024*1024);
376     insert_base(unit_bases, "TiB", (guint64)1024*1024*1024*1024);
377 
378     return unit_bases;
379 }
380 
get_unit_base(const char * unit,guint64 default_base)381 static guint64 get_unit_base(const char *unit, guint64 default_base)
382 {
383     static GOnce set_unit_bases_once = G_ONCE_INIT;
384     GHashTable *unit_bases;
385     guint64 *unit_base;
386 
387     if (unit == NULL) {
388         return default_base;
389     }
390 
391     unit_bases = g_once (&set_unit_bases_once, set_unit_bases, &unit_bases);
392     g_return_val_if_fail (unit_bases != NULL, default_base);
393 
394     unit_base = g_hash_table_lookup(unit_bases, unit);
395     if (unit_base == NULL) {
396         /* unknown unit, fall back to the default unit */
397         g_return_val_if_reached(default_base);
398     }
399 
400     return *unit_base;
401 }
402 
403 /**
404  * gvir_config_domain_get_memory:
405  * @domain: a #GVirConfigDomain
406  *
407  * Returns: maximum amount of RAM in kilobytes (i.e. blocks of 1024 bytes).
408  */
gvir_config_domain_get_memory(GVirConfigDomain * domain)409 guint64 gvir_config_domain_get_memory(GVirConfigDomain *domain)
410 {
411     const char *unit;
412     guint64 unit_base;
413     guint64 memory;
414 
415     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), 0);
416 
417     unit = gvir_config_object_get_attribute(GVIR_CONFIG_OBJECT(domain), "memory", "unit");
418     unit_base = get_unit_base(unit, 1024);
419 
420     memory = gvir_config_object_get_node_content_uint64(GVIR_CONFIG_OBJECT(domain),
421                                                         "memory");
422 
423     return memory * unit_base / 1024;
424 }
425 
426 /**
427  * gvir_config_domain_get_current_memory:
428  * @domain: a #GVirConfigDomain
429  *
430  * Returns: current amount of RAM in kilobytes (i.e. blocks of 1024 bytes).
431  */
gvir_config_domain_get_current_memory(GVirConfigDomain * domain)432 guint64 gvir_config_domain_get_current_memory(GVirConfigDomain *domain)
433 {
434     const char *unit;
435     guint64 unit_base;
436     guint64 memory;
437 
438     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), 0);
439 
440     unit = gvir_config_object_get_attribute(GVIR_CONFIG_OBJECT(domain), "currentMemory", "unit");
441     unit_base = get_unit_base(unit, 1024);
442 
443     memory = gvir_config_object_get_node_content_uint64(GVIR_CONFIG_OBJECT(domain),
444                                                         "currentMemory");
445 
446     return memory * unit_base / 1024;
447 }
448 
449 /**
450  * gvir_config_domain_set_memory:
451  * @domain: a #GVirConfigDomain
452  * @memory: The maximum amount of RAM in kilobytes.
453  *
454  * Sets the maximum amount of RAM allocated to @domain in kilobytes (i.e.
455  * blocks of 1024 bytes).
456  */
gvir_config_domain_set_memory(GVirConfigDomain * domain,guint64 memory)457 void gvir_config_domain_set_memory(GVirConfigDomain *domain, guint64 memory)
458 {
459     GVirConfigObject *node;
460 
461     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
462 
463     node = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(domain), "memory");
464     gvir_config_object_set_node_content_uint64(GVIR_CONFIG_OBJECT(node), NULL, memory);
465     gvir_config_object_set_attribute(GVIR_CONFIG_OBJECT(node),
466                                      "unit", "KiB",
467                                      NULL);
468     g_object_unref(G_OBJECT(node));
469     g_object_notify(G_OBJECT(domain), "memory");
470 }
471 
472 /**
473  * gvir_config_domain_set_current_memory:
474  * @domain: a #GVirConfigDomain
475  * @memory: The current amount of RAM in kilobytes.
476  *
477  * Sets the current amount of RAM allocated to @domain in kilobytes (i.e.
478  * blocks of 1024 bytes). This can be set to less than the maximum domain
479  * memory to allow to balloon the guest memory on the fly. Be aware that
480  * libvirt will set it automatically if it's not explictly set, which means
481  * you may need to set this value in addition to 'memory' if you want to
482  * change the available domain memory after creation.
483  */
gvir_config_domain_set_current_memory(GVirConfigDomain * domain,guint64 memory)484 void gvir_config_domain_set_current_memory(GVirConfigDomain *domain,
485                                            guint64 memory)
486 {
487     GVirConfigObject *node;
488 
489     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
490 
491     node = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(domain), "currentMemory");
492     gvir_config_object_set_node_content_uint64(GVIR_CONFIG_OBJECT(node), NULL, memory);
493     gvir_config_object_set_attribute(GVIR_CONFIG_OBJECT(node),
494                                      "unit", "KiB",
495                                      NULL);
496     g_object_unref(G_OBJECT(node));
497     g_object_notify(G_OBJECT(domain), "current-memory");
498 }
499 
gvir_config_domain_get_vcpus(GVirConfigDomain * domain)500 guint64 gvir_config_domain_get_vcpus(GVirConfigDomain *domain)
501 {
502     return gvir_config_object_get_node_content_uint64(GVIR_CONFIG_OBJECT(domain),
503                                                       "vcpu");
504 }
505 
gvir_config_domain_set_vcpus(GVirConfigDomain * domain,guint64 vcpu_count)506 void gvir_config_domain_set_vcpus(GVirConfigDomain *domain, guint64 vcpu_count)
507 {
508     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
509 
510     gvir_config_object_set_node_content_uint64(GVIR_CONFIG_OBJECT(domain),
511                                                "vcpu", vcpu_count);
512     g_object_notify(G_OBJECT(domain), "vcpu");
513 }
514 
add_feature(xmlNodePtr node,gpointer opaque)515 static gboolean add_feature(xmlNodePtr node, gpointer opaque)
516 {
517     GPtrArray *features;
518     g_return_val_if_fail(opaque != NULL, FALSE);
519 
520     features = (GPtrArray *)opaque;
521 
522     g_ptr_array_add(features, g_strdup((char *)node->name));
523 
524     return TRUE;
525 }
526 
527 /**
528  * gvir_config_domain_get_features:
529  * @domain: a #GVirConfigDomain
530  *
531  * Returns: (transfer full): The returned list should be freed with
532  * g_strfreev() when no longer needed.
533 
534  */
gvir_config_domain_get_features(GVirConfigDomain * domain)535 GStrv gvir_config_domain_get_features(GVirConfigDomain *domain)
536 {
537     GPtrArray *features;
538 
539     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
540 
541     features = g_ptr_array_new();
542     gvir_config_object_foreach_child(GVIR_CONFIG_OBJECT(domain), "features",
543                                      add_feature, features);
544     g_ptr_array_add(features, NULL);
545 
546     return (GStrv)g_ptr_array_free(features, FALSE);
547 }
548 
gvir_config_domain_set_features(GVirConfigDomain * domain,const GStrv features)549 void gvir_config_domain_set_features(GVirConfigDomain *domain,
550                                      const GStrv features)
551 {
552     GVirConfigObject *features_node;
553     GStrv it;
554 
555     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
556 
557     features_node = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(domain),
558                                                      "features");
559     g_return_if_fail(GVIR_CONFIG_IS_OBJECT(features_node));
560     for (it = features; *it != NULL; it++) {
561         GVirConfigObject *feature;
562         feature = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(features_node),
563                                                    *it);
564         g_object_unref(G_OBJECT(feature));
565     }
566     g_object_unref(G_OBJECT(features_node));
567     g_object_notify(G_OBJECT(domain), "features");
568 }
569 
570 
571 /**
572  * gvir_config_domain_get_clock:
573  * @domain: a #GVirConfigDomain
574  *
575  * Gets the clock configuration of @domain
576  *
577  * Returns: (transfer full): A #GVirConfigDomainClock. The returned
578  * object should be unreffed with g_object_unref() when no longer needed.
579  */
gvir_config_domain_get_clock(GVirConfigDomain * domain)580 GVirConfigDomainClock *gvir_config_domain_get_clock(GVirConfigDomain *domain)
581 {
582     GVirConfigObject *object;
583 
584     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
585 
586     object = gvir_config_object_get_child_with_type(GVIR_CONFIG_OBJECT(domain),
587                                                     "clock",
588                                                     GVIR_CONFIG_TYPE_DOMAIN_CLOCK);
589 
590     return GVIR_CONFIG_DOMAIN_CLOCK(object);
591 }
592 
593 
594 /**
595  * gvir_config_domain_set_clock:
596  * @domain: a #GVirConfigDomain
597  * @klock: (allow-none):
598  */
gvir_config_domain_set_clock(GVirConfigDomain * domain,GVirConfigDomainClock * klock)599 void gvir_config_domain_set_clock(GVirConfigDomain *domain,
600                                   GVirConfigDomainClock *klock)
601 {
602     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
603     g_return_if_fail(klock == NULL || GVIR_CONFIG_IS_DOMAIN_CLOCK(klock));
604 
605     gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
606                                       "clock",
607                                       GVIR_CONFIG_OBJECT(klock));
608 }
609 
610 /**
611  * gvir_config_domain_get_os:
612  * @domain: a #GVirConfigDomain
613  *
614  * Gets the operating system configuration of @domain
615  *
616  * Returns: (transfer full): A #GVirConfigDomainOs. The returned
617  * object should be unreffed with g_object_unref() when no longer needed.
618  */
gvir_config_domain_get_os(GVirConfigDomain * domain)619 GVirConfigDomainOs *gvir_config_domain_get_os(GVirConfigDomain *domain)
620 {
621     GVirConfigObject *object;
622 
623     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
624 
625     object = gvir_config_object_get_child_with_type(GVIR_CONFIG_OBJECT(domain),
626                                                     "os",
627                                                     GVIR_CONFIG_TYPE_DOMAIN_OS);
628 
629     return GVIR_CONFIG_DOMAIN_OS(object);
630 }
631 
632 /**
633  * gvir_config_domain_set_os:
634  * @domain: a #GVirConfigDomain
635  * @os: (allow-none): the os configuration to set
636  */
gvir_config_domain_set_os(GVirConfigDomain * domain,GVirConfigDomainOs * os)637 void gvir_config_domain_set_os(GVirConfigDomain *domain,
638                                GVirConfigDomainOs *os)
639 {
640     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
641     g_return_if_fail(os == NULL || GVIR_CONFIG_IS_DOMAIN_OS(os));
642 
643     gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
644                                       "os",
645                                       GVIR_CONFIG_OBJECT(os));
646 }
647 
648 /**
649  * gvir_config_domain_set_seclabel:
650  * @domain: a #GVirConfigDomain
651  * @seclabel: (allow-none): the security label configuration to set
652  */
gvir_config_domain_set_seclabel(GVirConfigDomain * domain,GVirConfigDomainSeclabel * seclabel)653 void gvir_config_domain_set_seclabel(GVirConfigDomain *domain,
654                                      GVirConfigDomainSeclabel *seclabel)
655 {
656     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
657     g_return_if_fail(seclabel == NULL ||
658                      GVIR_CONFIG_IS_DOMAIN_SECLABEL(seclabel));
659 
660     gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
661                                       "seclabel",
662                                       GVIR_CONFIG_OBJECT(seclabel));
663 }
664 
gvir_config_domain_set_lifecycle(GVirConfigDomain * domain,GVirConfigDomainLifecycleEvent event,GVirConfigDomainLifecycleAction action)665 void gvir_config_domain_set_lifecycle(GVirConfigDomain *domain,
666                                       GVirConfigDomainLifecycleEvent event,
667                                       GVirConfigDomainLifecycleAction action)
668 {
669     const char *event_str;
670     const char *action_str;
671 
672     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
673     g_return_if_fail((event == GVIR_CONFIG_DOMAIN_LIFECYCLE_ON_CRASH) ||
674                      ((action != GVIR_CONFIG_DOMAIN_LIFECYCLE_COREDUMP_DESTROY) &&
675                       (action != GVIR_CONFIG_DOMAIN_LIFECYCLE_COREDUMP_RESTART)));
676 
677     event_str = gvir_config_genum_get_nick(GVIR_CONFIG_TYPE_DOMAIN_LIFECYCLE_EVENT, event);
678     g_return_if_fail(event_str != NULL);
679     action_str = gvir_config_genum_get_nick(GVIR_CONFIG_TYPE_DOMAIN_LIFECYCLE_ACTION, action);
680     g_return_if_fail(action_str != NULL);
681 
682     gvir_config_object_set_node_content(GVIR_CONFIG_OBJECT(domain),
683                                         event_str, action_str);
684 }
685 
686 /**
687  * gvir_config_domain_set_devices:
688  * @domain: a #GVirConfigDomain
689  * @devices: (in) (element-type LibvirtGConfig.DomainDevice):
690  */
gvir_config_domain_set_devices(GVirConfigDomain * domain,GList * devices)691 void gvir_config_domain_set_devices(GVirConfigDomain *domain,
692                                     GList *devices)
693 {
694     GVirConfigObject *devices_node;
695     GList *it;
696 
697     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
698 
699     if (devices == NULL) {
700         gvir_config_object_delete_children(GVIR_CONFIG_OBJECT(domain),
701                                            "devices",
702                                            NULL);
703         return;
704     }
705     devices_node = gvir_config_object_new(GVIR_CONFIG_TYPE_OBJECT,
706                                           "devices", NULL);
707 
708     for (it = devices; it != NULL; it = it->next) {
709         if (!GVIR_CONFIG_IS_DOMAIN_DEVICE(it->data)) {
710             g_warn_if_reached();
711             continue;
712         }
713         gvir_config_object_attach_add(devices_node,
714                                       GVIR_CONFIG_OBJECT(it->data));
715     }
716 
717     gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
718                                       "devices",
719                                       devices_node);
720     g_object_unref(G_OBJECT(devices_node));
721 }
722 
gvir_config_domain_add_device(GVirConfigDomain * domain,GVirConfigDomainDevice * device)723 void gvir_config_domain_add_device(GVirConfigDomain *domain,
724                                    GVirConfigDomainDevice *device)
725 {
726     GVirConfigObject *devices_node;
727 
728     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
729     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_DEVICE(device));
730 
731     devices_node = gvir_config_object_add_child(GVIR_CONFIG_OBJECT(domain),
732                                                 "devices");
733 
734     gvir_config_object_attach_add(devices_node, GVIR_CONFIG_OBJECT(device));
735     g_object_unref(G_OBJECT(devices_node));
736 }
737 
738 struct GetDeviceData {
739     GVirConfigXmlDoc *doc;
740     GList *devices;
741 };
742 
add_device(xmlNodePtr node,gpointer opaque)743 static gboolean add_device(xmlNodePtr node, gpointer opaque)
744 {
745     struct GetDeviceData* data = (struct GetDeviceData*)opaque;
746     GVirConfigDomainDevice *device;
747 
748     device = gvir_config_domain_device_new_from_tree(data->doc, node);
749     if (device != NULL)
750         data->devices = g_list_append(data->devices, device);
751     else
752         g_debug("Failed to parse %s node", node->name);
753 
754     return TRUE;
755 }
756 
757 /**
758  * gvir_config_domain_get_devices:
759  * @domain: a #GVirConfigDomain
760  *
761  * Gets the list of devices attached to @domain.  The returned list should
762  * be freed with g_list_free(), after its elements have been unreffed with
763  * g_object_unref().
764  *
765  * Returns: (element-type LibvirtGConfig.DomainDevice) (transfer full):
766  * a newly allocated #GList of #GVirConfigDomainDevice.
767  */
gvir_config_domain_get_devices(GVirConfigDomain * domain)768 GList *gvir_config_domain_get_devices(GVirConfigDomain *domain)
769 {
770     struct GetDeviceData data;
771 
772     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
773 
774     g_object_get(G_OBJECT(domain), "doc", &data.doc, NULL);
775     data.devices = NULL;
776     gvir_config_object_foreach_child(GVIR_CONFIG_OBJECT(domain), "devices",
777                                      add_device, &data);
778     if (data.doc != NULL) {
779         g_object_unref(G_OBJECT(data.doc));
780     }
781 
782     return data.devices;
783 }
784 
gvir_config_domain_set_custom_xml_helper(GVirConfigDomain * domain,const gchar * xml,const gchar * ns,const gchar * ns_uri,gboolean ns_children,GError ** error)785 static gboolean gvir_config_domain_set_custom_xml_helper(GVirConfigDomain *domain,
786                                                          const gchar *xml,
787                                                          const gchar *ns,
788                                                          const gchar *ns_uri,
789                                                          gboolean ns_children,
790                                                          GError **error)
791 {
792     GVirConfigObject *metadata;
793     GVirConfigObject *custom_xml;
794 
795     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), FALSE);
796     g_return_val_if_fail(xml != NULL, FALSE);
797     g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
798 
799     metadata = gvir_config_object_add_child(GVIR_CONFIG_OBJECT(domain),
800                                             "metadata");
801 
802     custom_xml = gvir_config_object_new_from_xml(GVIR_CONFIG_TYPE_OBJECT,
803                                                  NULL, NULL, xml, error);
804     if (custom_xml == NULL) {
805         g_assert_not_reached();
806         g_object_unref(G_OBJECT(metadata));
807         return FALSE;
808     }
809 
810     gvir_config_object_set_namespace(custom_xml, ns, ns_uri, ns_children);
811 
812     gvir_config_object_delete_children(metadata, NULL, ns_uri);
813     gvir_config_object_attach_add(metadata, custom_xml);
814     g_object_unref(G_OBJECT(metadata));
815     g_object_unref(G_OBJECT(custom_xml));
816 
817     return TRUE;
818 }
819 
gvir_config_domain_set_custom_xml(GVirConfigDomain * domain,const gchar * xml,const gchar * ns,const gchar * ns_uri,GError ** error)820 gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain,
821                                            const gchar *xml,
822                                            const gchar *ns,
823                                            const gchar *ns_uri,
824                                            GError **error)
825 {
826     return gvir_config_domain_set_custom_xml_helper(domain,
827                                                     xml,
828                                                     ns,
829                                                     ns_uri,
830                                                     FALSE,
831                                                     error);
832 }
833 
gvir_config_domain_set_custom_xml_ns_children(GVirConfigDomain * domain,const gchar * xml,const gchar * ns,const gchar * ns_uri,GError ** error)834 gboolean gvir_config_domain_set_custom_xml_ns_children(GVirConfigDomain *domain,
835                                                        const gchar *xml,
836                                                        const gchar *ns,
837                                                        const gchar *ns_uri,
838                                                        GError **error)
839 {
840     return gvir_config_domain_set_custom_xml_helper(domain,
841                                                     xml,
842                                                     ns,
843                                                     ns_uri,
844                                                     TRUE,
845                                                     error);
846 }
847 
848 struct LookupNamespacedNodeData {
849     const char *ns_uri;
850     xmlNodePtr node;
851 };
852 
lookup_namespaced_node(xmlNodePtr node,gpointer opaque)853 static gboolean lookup_namespaced_node(xmlNodePtr node, gpointer opaque)
854 {
855     struct LookupNamespacedNodeData* data = opaque;
856 
857     if (node->ns == NULL)
858         return TRUE;
859 
860     if (g_strcmp0((char *)node->ns->href, data->ns_uri) == 0) {
861         data->node = node;
862         return FALSE;
863     }
864 
865     return TRUE;
866 }
867 
gvir_config_domain_get_custom_xml(GVirConfigDomain * domain,const gchar * ns_uri)868 gchar *gvir_config_domain_get_custom_xml(GVirConfigDomain *domain,
869                                          const gchar *ns_uri)
870 {
871     struct LookupNamespacedNodeData data = { NULL, NULL };
872 
873     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
874     g_return_val_if_fail(ns_uri != NULL, NULL);
875 
876     data.ns_uri = ns_uri;
877     gvir_config_object_foreach_child(GVIR_CONFIG_OBJECT(domain), "metadata",
878                                      lookup_namespaced_node, &data);
879     return gvir_config_xml_node_to_string(data.node);
880 }
881 
882 /**
883  * gvir_config_domain_get_cpu:
884  * @domain: a #GVirConfigDomain
885  *
886  * Gets the CPU configuration of @domain
887  *
888  * Returns: (transfer full): A #GVirConfigDomainCpu. The returned object
889  * should be unreffed with g_object_unref() when no longer needed.
890  */
gvir_config_domain_get_cpu(GVirConfigDomain * domain)891 GVirConfigDomainCpu *gvir_config_domain_get_cpu(GVirConfigDomain *domain)
892 {
893     GVirConfigObject *object;
894 
895     g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL);
896 
897     object = gvir_config_object_get_child_with_type(GVIR_CONFIG_OBJECT(domain),
898                                                     "cpu",
899                                                     GVIR_CONFIG_TYPE_DOMAIN_CPU);
900 
901     return GVIR_CONFIG_DOMAIN_CPU(object);
902 }
903 
904 /**
905  * gvir_config_domain_set_cpu:
906  * @domain: a #GVirConfigDomain
907  * @cpu: (allow-none):
908  */
gvir_config_domain_set_cpu(GVirConfigDomain * domain,GVirConfigDomainCpu * cpu)909 void gvir_config_domain_set_cpu(GVirConfigDomain *domain,
910                                 GVirConfigDomainCpu *cpu)
911 {
912     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
913     g_return_if_fail(cpu == NULL || GVIR_CONFIG_IS_DOMAIN_CPU(cpu));
914 
915     gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
916                                       "cpu",
917                                       GVIR_CONFIG_OBJECT(cpu));
918 }
919 
920 /**
921  * gvir_config_domain_set_power_management:
922  * @domain: a #GVirConfigDomain
923  * @pm: (allow-none): a #GVirPowerManagement instance
924  */
gvir_config_domain_set_power_management(GVirConfigDomain * domain,GVirConfigDomainPowerManagement * pm)925 void gvir_config_domain_set_power_management(GVirConfigDomain *domain,
926                                              GVirConfigDomainPowerManagement *pm)
927 {
928     g_return_if_fail(GVIR_CONFIG_IS_DOMAIN(domain));
929     g_return_if_fail(pm != NULL || GVIR_CONFIG_IS_DOMAIN_POWER_MANAGEMENT(pm));
930 
931     gvir_config_object_attach_replace(GVIR_CONFIG_OBJECT(domain),
932                                       "pm",
933                                       GVIR_CONFIG_OBJECT(pm));
934 }
935