1 /*
2  * libosinfo:
3  *
4  * Copyright (C) 2009-2020 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <osinfo/osinfo.h>
22 #include <glib/gi18n-lib.h>
23 
24 /**
25  * SECTION:osinfo_deployment
26  * @short_description: An virtualization deployment
27  * @see_also: #OsinfoOs, #OsinfoDeployment
28  *
29  * #OsinfoDeployment is an entity representing an virtualization
30  * deployment. Deployments have a list of supported devices
31  */
32 
33 struct _OsinfoDeploymentPrivate
34 {
35     // Value: List of device_link structs
36     GList *deviceLinks;
37 
38     OsinfoOs *os;
39     OsinfoPlatform *platform;
40 };
41 
42 G_DEFINE_TYPE_WITH_PRIVATE(OsinfoDeployment, osinfo_deployment, OSINFO_TYPE_ENTITY);
43 
44 enum {
45     PROP_0,
46 
47     PROP_OS,
48     PROP_PLATFORM,
49 
50     LAST_PROP
51 };
52 static GParamSpec *properties[LAST_PROP];
53 
54 static void
osinfo_deployment_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)55 osinfo_deployment_set_property(GObject *object,
56                                guint property_id,
57                                const GValue *value,
58                                GParamSpec *pspec)
59 {
60     OsinfoDeployment *deployment = OSINFO_DEPLOYMENT(object);
61 
62     switch (property_id)
63         {
64         case PROP_OS:
65             if (deployment->priv->os)
66                 g_object_unref(deployment->priv->os);
67             deployment->priv->os = g_value_get_object(value);
68             if (deployment->priv->os)
69                 g_object_ref(deployment->priv->os);
70             break;
71         case PROP_PLATFORM:
72             if (deployment->priv->platform)
73                 g_object_unref(deployment->priv->platform);
74             deployment->priv->platform = g_value_get_object(value);
75             if (deployment->priv->platform)
76                 g_object_ref(deployment->priv->platform);
77             break;
78         default:
79             /* We don't have any other property... */
80             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
81             break;
82         }
83 }
84 
85 static void
osinfo_deployment_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)86 osinfo_deployment_get_property(GObject *object,
87                                guint property_id,
88                                GValue *value,
89                                GParamSpec *pspec)
90 {
91     OsinfoDeployment *deployment = OSINFO_DEPLOYMENT(object);
92 
93     switch (property_id)
94         {
95         case PROP_OS:
96             g_value_set_object(value, deployment->priv->os);
97             break;
98         case PROP_PLATFORM:
99             g_value_set_object(value, deployment->priv->platform);
100             break;
101         default:
102             /* We don't have any other property... */
103             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
104             break;
105         }
106 }
107 
108 
109 
110 static void
osinfo_deployment_finalize(GObject * object)111 osinfo_deployment_finalize(GObject *object)
112 {
113     OsinfoDeployment *deployment = OSINFO_DEPLOYMENT(object);
114 
115     g_list_free_full(deployment->priv->deviceLinks, g_object_unref);
116 
117     g_object_unref(deployment->priv->os);
118     g_object_unref(deployment->priv->platform);
119 
120     /* Chain up to the parent class */
121     G_OBJECT_CLASS(osinfo_deployment_parent_class)->finalize(object);
122 }
123 
124 /* Init functions */
125 static void
osinfo_deployment_class_init(OsinfoDeploymentClass * klass)126 osinfo_deployment_class_init(OsinfoDeploymentClass *klass)
127 {
128     GObjectClass *g_klass = G_OBJECT_CLASS(klass);
129 
130     g_klass->set_property = osinfo_deployment_set_property;
131     g_klass->get_property = osinfo_deployment_get_property;
132     g_klass->finalize = osinfo_deployment_finalize;
133 
134     /**
135      * OsinfoDeployment:os:
136      *
137      * The operating system to be deployed
138      */
139     properties[PROP_OS] = g_param_spec_object("os",
140                                               "Os",
141                                               _("Operating system"),
142                                               OSINFO_TYPE_OS,
143                                               G_PARAM_CONSTRUCT_ONLY |
144                                               G_PARAM_READWRITE |
145                                               G_PARAM_STATIC_STRINGS);
146     /**
147      * OsinfoDeployment:platform:
148      *
149      * The platform to deploy on
150      */
151     properties[PROP_PLATFORM] = g_param_spec_object("platform",
152                                                     "Platform",
153                                                     _("Virtualization platform"),
154                                                     OSINFO_TYPE_PLATFORM,
155                                                     G_PARAM_CONSTRUCT_ONLY |
156                                                     G_PARAM_READWRITE |
157                                                     G_PARAM_STATIC_STRINGS);
158 
159     g_object_class_install_properties(g_klass, LAST_PROP, properties);
160 }
161 
162 static void
osinfo_deployment_init(OsinfoDeployment * deployment)163 osinfo_deployment_init(OsinfoDeployment *deployment)
164 {
165     deployment->priv = osinfo_deployment_get_instance_private(deployment);
166     deployment->priv->deviceLinks = NULL;
167 }
168 
169 
170 /**
171  * osinfo_deployment_new:
172  * @id: the unique identifier
173  * @os: the operating system to deploy
174  * @platform: the platform to deploy on
175  *
176  * Create a new deployment entity
177  *
178  * Returns: (transfer full): A deployment entity
179  */
osinfo_deployment_new(const gchar * id,OsinfoOs * os,OsinfoPlatform * platform)180 OsinfoDeployment *osinfo_deployment_new(const gchar *id,
181                                         OsinfoOs *os,
182                                         OsinfoPlatform *platform)
183 {
184     return g_object_new(OSINFO_TYPE_DEPLOYMENT,
185                         "id", id,
186                         "os", os,
187                         "platform", platform,
188                         NULL);
189 }
190 
191 
192 /**
193  * osinfo_deployment_get_os:
194  * @deployment: the deployment entity
195  *
196  * Get the operating system for the deployment
197  *
198  * Returns: (transfer none): an OS, or NULL
199  */
osinfo_deployment_get_os(OsinfoDeployment * deployment)200 OsinfoOs *osinfo_deployment_get_os(OsinfoDeployment *deployment)
201 {
202     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
203 
204     return deployment->priv->os;
205 }
206 
207 
208 /**
209  * osinfo_deployment_get_platform:
210  * @deployment: the deployment entity
211  *
212  * Get the platform for the deployment
213  *
214  * Returns: (transfer none): a platform, or NULL
215  */
osinfo_deployment_get_platform(OsinfoDeployment * deployment)216 OsinfoPlatform *osinfo_deployment_get_platform(OsinfoDeployment *deployment)
217 {
218     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
219 
220     return deployment->priv->platform;
221 }
222 
223 
224 /**
225  * osinfo_deployment_get_preferred_device:
226  * @deployment: the deployment entity
227  * @filter: (transfer none)(allow-none): a device metadata filter
228  *
229  * Get the preferred device matching a given filter
230  *
231  * Returns: (transfer none): a device, or NULL
232  */
osinfo_deployment_get_preferred_device(OsinfoDeployment * deployment,OsinfoFilter * filter)233 OsinfoDevice *osinfo_deployment_get_preferred_device(OsinfoDeployment *deployment, OsinfoFilter *filter)
234 {
235     OsinfoDeviceLinkFilter *linkfilter;
236     OsinfoDeviceLink *devlink;
237 
238     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
239     g_return_val_if_fail(OSINFO_IS_FILTER(filter), NULL);
240 
241     linkfilter = osinfo_devicelinkfilter_new(filter);
242     devlink = osinfo_deployment_get_preferred_device_link(deployment, OSINFO_FILTER(linkfilter));
243     if (devlink)
244         return osinfo_devicelink_get_target(devlink);
245     return NULL;
246 }
247 
248 
249 /**
250  * osinfo_deployment_get_preferred_device_link:
251  * @deployment: the deployment entity
252  * @filter: (transfer none)(allow-none): a device metadata filter
253  *
254  * Get the preferred device link matching a given filter and platform.
255  * The filter matches against attributes on the link, not the device.
256  *
257  * Returns: (transfer none): a device, or NULL
258  */
osinfo_deployment_get_preferred_device_link(OsinfoDeployment * deployment,OsinfoFilter * filter)259 OsinfoDeviceLink *osinfo_deployment_get_preferred_device_link(OsinfoDeployment *deployment, OsinfoFilter *filter)
260 {
261     GList *tmp;
262 
263     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
264     g_return_val_if_fail(OSINFO_IS_FILTER(filter), NULL);
265 
266     tmp = deployment->priv->deviceLinks;
267 
268     // For each device in section list, apply filter. If filter passes, return device.
269     while (tmp) {
270         OsinfoDeviceLink *devlink = OSINFO_DEVICELINK(tmp->data);
271 
272         if (!filter || osinfo_filter_matches(filter, OSINFO_ENTITY(devlink))) {
273            return devlink;
274         }
275 
276        tmp = tmp->next;
277     }
278 
279     // If no devices pass filter, return NULL.
280     return NULL;
281 }
282 
283 
284 /**
285  * osinfo_deployment_get_devices:
286  * @deployment: a deployment entity
287  * @filter: (transfer none)(allow-none): an optional filter
288  *
289  * Retrieve all the associated devices matching the filter.
290  * The filter matches against the device, not the link.
291  *
292  * Returns: (transfer full): a list of #OsinfoDevice entities
293  */
osinfo_deployment_get_devices(OsinfoDeployment * deployment,OsinfoFilter * filter)294 OsinfoDeviceList *osinfo_deployment_get_devices(OsinfoDeployment *deployment, OsinfoFilter *filter)
295 {
296     OsinfoDeviceList *newList;
297     GList *tmp;
298 
299     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
300     g_return_val_if_fail(!filter || OSINFO_IS_FILTER(filter), NULL);
301 
302     newList = osinfo_devicelist_new();
303     tmp = deployment->priv->deviceLinks;
304 
305     while (tmp) {
306         OsinfoDeviceLink *devlink = OSINFO_DEVICELINK(tmp->data);
307         OsinfoDevice *dev = osinfo_devicelink_get_target(devlink);
308         if (!filter || osinfo_filter_matches(filter, OSINFO_ENTITY(dev)))
309             osinfo_list_add(OSINFO_LIST(newList), OSINFO_ENTITY(dev));
310 
311         tmp = tmp->next;
312     }
313 
314     return newList;
315 }
316 
317 
318 /**
319  * osinfo_deployment_get_device_links:
320  * @deployment: a deployment entity
321  * @filter: (transfer none)(allow-none): an optional filter
322  *
323  * Retrieve all the associated devices matching the filter.
324  * The filter matches against the link, not the device.
325  *
326  * Returns: (transfer full): a list of #OsinfoDevice entities
327  */
osinfo_deployment_get_device_links(OsinfoDeployment * deployment,OsinfoFilter * filter)328 OsinfoDeviceLinkList *osinfo_deployment_get_device_links(OsinfoDeployment *deployment, OsinfoFilter *filter)
329 {
330     OsinfoDeviceLinkList *newList;
331     GList *tmp;
332 
333     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
334     g_return_val_if_fail(!filter || OSINFO_IS_FILTER(filter), NULL);
335 
336     newList = osinfo_devicelinklist_new();
337     tmp = deployment->priv->deviceLinks;
338 
339     while (tmp) {
340         OsinfoDeviceLink *devlink = OSINFO_DEVICELINK(tmp->data);
341 
342         if (!filter || osinfo_filter_matches(filter, OSINFO_ENTITY(devlink)))
343             osinfo_list_add(OSINFO_LIST(newList), OSINFO_ENTITY(devlink));
344 
345         tmp = tmp->next;
346     }
347 
348     return newList;
349 }
350 
351 
352 /**
353  * osinfo_deployment_add_device:
354  * @deployment: a deployment entity
355  * @dev: (transfer none): the device to associate
356  *
357  * Associate a device with a deployment. The returned #OsinfoDeviceLink
358  * can be used to record extra metadata against the link
359  *
360  * Returns: (transfer none): the device association
361  */
osinfo_deployment_add_device(OsinfoDeployment * deployment,OsinfoDevice * dev)362 OsinfoDeviceLink *osinfo_deployment_add_device(OsinfoDeployment *deployment, OsinfoDevice *dev)
363 {
364     OsinfoDeviceLink *devlink;
365 
366     g_return_val_if_fail(OSINFO_IS_DEPLOYMENT(deployment), NULL);
367     g_return_val_if_fail(OSINFO_IS_DEVICE(dev), NULL);
368 
369     devlink = osinfo_devicelink_new(dev);
370 
371     deployment->priv->deviceLinks = g_list_prepend(deployment->priv->deviceLinks, devlink);
372 
373     return devlink;
374 }
375