GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/virtualization.c
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 18 208 8.7%
Functions: 3 27 11.1%
Branches: 6 86 7.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/tech/virtualization.h"
30
31 #include "gate/results.h"
32
33
34 static gate_string_t const virtprov_name_lxc = GATE_STRING_INIT_STATIC("lxc");
35 static gate_string_t const virtprov_descr_lxc = GATE_STRING_INIT_STATIC("Linux-Containers");
36
37 static gate_string_t const virtprov_name_docker = GATE_STRING_INIT_STATIC("docker");
38 static gate_string_t const virtprov_descr_docker = GATE_STRING_INIT_STATIC("Docker");
39
40
41 #if defined(GATE_SYS_LINUX)
42 # define GATE_TECH_VIRTUALIZATION_LXC 1
43 #endif
44
45 #if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
46 # define GATE_TECH_VIRTUALIZATION_HYPERV2 1
47 #endif
48
49 #define GATE_TECH_VIRTUALIZATION_DOCKER 1
50
51
52
53
54 #if defined(GATE_TECH_VIRTUALIZATION_LXC)
55
56 #include <stdlib.h>
57
58 #include "gate/tech/platform/gate_lxc.h"
59 #include "gate/utilities.h"
60 #include "gate/debugging.h"
61
62 static gate_lxc_functions_t lxc_code;
63 static gate_bool_t lxc_code_init;
64
65 1 static gate_result_t gate_lxc_init()
66 {
67 1 gate_result_t ret = GATE_RESULT_OK;
68
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!lxc_code_init)
69 {
70 1 ret = gate_load_lxc_functions(&lxc_code);
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
72 {
73 lxc_code_init = true;
74 }
75 }
76 1 return ret;
77 }
78
79 static void free_lxc_array(void** array, int count)
80 {
81 while(count-- > 0)
82 {
83 free(*array);
84 ++array;
85 }
86 }
87
88 /* LXC sandbox interface methods */
89
90 typedef struct lxcsbox_class
91 {
92 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const* vtbl;
93
94 gate_atomic_int_t ref_counter;
95 gate_string_t name;
96 gate_property_t settings;
97 } lxcsbox_t;
98
99 static void lxcsbox_destroy(lxcsbox_t* self)
100 {
101 gate_string_release(&self->name);
102 gate_property_destroy(&self->settings);
103 gate_mem_dealloc(self);
104 }
105
106 static char const* lxcsbox_get_interface_name(void* thisptr)
107 {
108 GATE_UNUSED_ARG(thisptr);
109 return GATE_INTERFACE_NAME_VIRTUALIZATION_SANDBOX;
110 }
111
112 static void lxcsbox_release(void* thisptr)
113 {
114 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
115 if (gate_atomic_int_dec(&self->ref_counter) == 0)
116 {
117 lxcsbox_destroy(self);
118 }
119 }
120
121 static int lxcsbox_retain(void* thisptr)
122 {
123 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
124 return gate_atomic_int_inc(&self->ref_counter);
125 }
126
127 static gate_result_t get_lxc_container_from_sandbox(lxcsbox_t* self, struct lxc_container** ptr_container)
128 {
129 gate_result_t ret;
130 gate_cstrbuffer_t buffer = GATE_INIT_EMPTY;
131 struct lxc_container* container = NULL;
132 do
133 {
134 if (NULL == gate_cstrbuffer_create_string(&buffer, &self->name, false))
135 {
136 GATE_DEBUG_TRACE("gate_cstrbuffer_create_string() failed");
137 ret = GATE_RESULT_OUTOFMEMORY;
138 break;
139 }
140 container = lxc_code.lxc_container_new(gate_cstrbuffer_get(&buffer), NULL);
141 if (NULL == container)
142 {
143 GATE_DEBUG_TRACE("lxc_container_new() failed");
144 ret = GATE_RESULT_FAILED;
145 break;
146 }
147 ret = GATE_RESULT_OK;
148 } while (0);
149 gate_cstrbuffer_destroy(&buffer);
150 *ptr_container = container;
151 return ret;
152 }
153
154 static void release_container(struct lxc_container** ptr_container)
155 {
156 GATE_DEBUG_ASSERT(ptr_container != NULL);
157 if (NULL != *ptr_container)
158 {
159 lxc_code.lxc_container_put(*ptr_container);
160 *ptr_container = NULL;
161 }
162 }
163
164 static gate_result_t lxcsbox_start(void* thisptr)
165 {
166 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
167 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
168 struct lxc_container* ptr_container = NULL;
169 do
170 {
171 ret = get_lxc_container_from_sandbox(self, &ptr_container);
172 GATE_BREAK_IF_FAILED(ret);
173
174 if (!ptr_container->is_defined(ptr_container))
175 {
176 /* container not defined/existing */
177 ret = GATE_RESULT_NOTAVAILABLE;
178 break;
179 }
180
181 if (ptr_container->is_running(ptr_container))
182 {
183 /* container is already started -> start not supported */
184 ret = GATE_RESULT_INVALIDSTATE;
185 break;
186 }
187
188 if (!ptr_container->start(ptr_container, 0, NULL))
189 {
190 /* failed to start container */
191 ret = GATE_RESULT_FAILED;
192 break;
193 }
194
195 /* success case */
196 ret = GATE_RESULT_OK;
197 } while (0);
198
199 release_container(&ptr_container);
200 return ret;
201 }
202
203 static gate_result_t lxcsbox_stop(void* thisptr)
204 {
205 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
206 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
207 struct lxc_container* ptr_container = NULL;
208 do
209 {
210 ret = get_lxc_container_from_sandbox(self, &ptr_container);
211 GATE_BREAK_IF_FAILED(ret);
212
213 if (!ptr_container->is_defined(ptr_container))
214 {
215 /* container not defined/existing */
216 ret = GATE_RESULT_NOTAVAILABLE;
217 break;
218 }
219
220 if (!ptr_container->is_running(ptr_container))
221 {
222 /* conainter is not running, stop not supported */
223 ret = GATE_RESULT_INVALIDSTATE;
224 break;
225 }
226
227 if (!ptr_container->stop(ptr_container))
228 {
229 /* failed to stop container */
230 ret = GATE_RESULT_FAILED;
231 break;
232 }
233
234 /* success case */
235 ret = GATE_RESULT_OK;
236 } while (0);
237
238 release_container(&ptr_container);
239 return ret;
240 }
241
242 static gate_enumint_t lxcsbox_get_status(void* thisptr)
243 {
244 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
245 gate_enumint_t ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
246 struct lxc_container* ptr_container = NULL;
247 do
248 {
249 gate_result_t result = get_lxc_container_from_sandbox(self, &ptr_container);
250 GATE_BREAK_IF_FAILED(result);
251
252 if (!ptr_container->is_defined(ptr_container))
253 {
254 /* container not defined/existing */
255 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
256 }
257 else
258 {
259 /* evaluate running state */
260 ret = ptr_container->is_running(ptr_container)
261 ? GATE_VIRTUALIZATION_SANDBOX_STATUS_ONLINE
262 : GATE_VIRTUALIZATION_SANDBOX_STATUS_OFFLINE
263 ;
264 }
265 } while (0);
266 release_container(&ptr_container);
267 return ret;
268 }
269
270 static gate_result_t lxcsbox_get_id(void* thisptr, gate_string_t* id)
271 {
272 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
273 if (id)
274 {
275 gate_string_clone(id, &self->name);
276 }
277 return GATE_RESULT_OK;
278 }
279
280 static gate_result_t lxcsbox_get_name(void* thisptr, gate_string_t* name)
281 {
282 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
283 if (name)
284 {
285 gate_string_clone(name, &self->name);
286 }
287 return GATE_RESULT_OK;
288 }
289
290 static gate_result_t lxcsbox_get_settings(void* thisptr, gate_property_t* settings)
291 {
292 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
293 if (settings)
294 {
295 if (NULL == gate_property_copy(settings, &self->settings))
296 {
297 return GATE_RESULT_OUTOFMEMORY;
298 }
299 }
300 return GATE_RESULT_OK;
301 }
302
303 static gate_result_t lxcsbox_update_settings(void* thisptr, gate_property_t const* settings)
304 {
305 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
306 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
307 /* TODO */
308 return ret;
309 }
310
311 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const* lxcsbox_vtbl_init()
312 {
313 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox) lxcsbox_vtbl;
314 if (lxcsbox_vtbl.get_interface_name == NULL)
315 {
316 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const vtbl = {
317 &lxcsbox_get_interface_name,
318 &lxcsbox_release,
319 &lxcsbox_retain,
320
321 &lxcsbox_start,
322 &lxcsbox_stop,
323 &lxcsbox_get_status,
324
325 &lxcsbox_get_id,
326 &lxcsbox_get_name,
327 &lxcsbox_get_settings,
328 &lxcsbox_update_settings
329 };
330 lxcsbox_vtbl = vtbl;
331 }
332 return &lxcsbox_vtbl;
333 }
334
335 static gate_result_t lxcsbox_create(gate_string_t const* name, lxcsbox_t** ptr_lxcsbox)
336 {
337 lxcsbox_t* ptr = (lxcsbox_t*)gate_mem_alloc(sizeof(lxcsbox_t));
338 if (NULL == ptr)
339 {
340 return GATE_RESULT_OUTOFMEMORY;
341 }
342 gate_mem_clear(ptr, sizeof(lxcsbox_t));
343 ptr->vtbl = lxcsbox_vtbl_init();
344 gate_atomic_int_init(&ptr->ref_counter, 1);
345 gate_string_clone(&ptr->name, name);
346 gate_property_create_object(&ptr->settings);
347 *ptr_lxcsbox = ptr;
348 return GATE_RESULT_OK;
349 }
350
351
352
353 /* LXC provider interface methods */
354
355 static char const* lxcprov_get_interface_name(void* obj)
356 {
357 GATE_UNUSED_ARG(obj);
358 return GATE_INTERFACE_NAME_VIRTUALIZATION_PROVIDER;
359 }
360 static void lxcprov_release(void* obj)
361 {
362 GATE_UNUSED_ARG(obj);
363 }
364 static int lxcprov_retain(void* obj)
365 {
366 GATE_UNUSED_ARG(obj);
367 return 1;
368 }
369 static gate_result_t lxcprov_get_name(void* obj, gate_string_t* name)
370 {
371 GATE_UNUSED_ARG(obj);
372 gate_string_create_static_len(name, "LXC", 3);
373 return GATE_RESULT_OK;
374 }
375 static gate_result_t lxcprov_get_settings(void* obj, gate_property_t* settings)
376 {
377 GATE_UNUSED_ARG(obj);
378 gate_property_create_object(settings);
379 return GATE_RESULT_OK;
380 }
381 static gate_result_t lxcprov_list_sandbox_ids(void* obj, gate_array_t* sandbox_ids)
382 {
383 GATE_UNUSED_ARG(obj);
384 gate_result_t ret = GATE_RESULT_FAILED;
385 char** names = NULL;
386 int found_containers;
387 gate_arraylist_t arr = NULL;
388
389 do
390 {
391 gate_size_t ndx;
392 char const* const lxcpath = NULL;
393 found_containers = lxc_code.list_all_containers(lxcpath, &names, NULL);
394 if (found_containers < 0)
395 {
396 ret = GATE_RESULT_FAILED;
397 break;
398 }
399
400 arr = gate_util_stringarray_create();
401 if (arr == NULL)
402 {
403 ret = GATE_RESULT_OUTOFMEMORY;
404 break;
405 }
406
407 for (ndx = 0; ndx < found_containers; ++ndx)
408 {
409 char const* name = names[ndx];
410 gate_util_stringarray_add_str(arr, name);
411 }
412
413 ret = GATE_RESULT_OK;
414 if (sandbox_ids)
415 {
416 if (NULL == gate_array_create(sandbox_ids, arr))
417 {
418 ret = GATE_RESULT_OUTOFMEMORY;
419 }
420 }
421 } while (0);
422
423 if (arr)
424 {
425 gate_arraylist_release(arr);
426 }
427 if (names)
428 {
429 free_lxc_array((void**)names, found_containers);
430 }
431
432 return ret;
433 }
434
435 static gate_result_t lxcprov_get_sandbox(void* obj, gate_string_t const* sandbox_id, gate_virtualization_sandbox_t** ptr_sandbox)
436 {
437 lxcsbox_t* ptr = NULL;
438 gate_result_t result = lxcsbox_create(sandbox_id, &ptr);
439 if (GATE_SUCCEEDED(result))
440 {
441 if (ptr_sandbox)
442 {
443 *ptr_sandbox = (gate_virtualization_sandbox_t*)ptr;
444 }
445 else
446 {
447 gate_object_release(ptr);
448 }
449 }
450 return result;
451 }
452
453
454 static gate_virtualization_provider_t* init_global_lxc_provider()
455 {
456 static gate_virtualization_provider_t lxc_prov;
457 static GATE_INTERFACE_VTBL(gate_virtualization_provider) lxc_prov_vtbl;
458
459 if (lxc_prov.vtbl == NULL)
460 {
461 GATE_INTERFACE_VTBL(gate_virtualization_provider) const vtbl = {
462 &lxcprov_get_interface_name,
463 &lxcprov_release,
464 &lxcprov_retain,
465
466 &lxcprov_get_name,
467 &lxcprov_get_settings,
468
469 &lxcprov_list_sandbox_ids,
470 &lxcprov_get_sandbox
471 };
472 lxc_prov_vtbl = vtbl;
473 lxc_prov.vtbl = &lxc_prov_vtbl;
474 }
475 return &lxc_prov;
476 }
477
478 #endif /* GATE_TECH_VIRTUALIZATION_LXC */
479
480
481
482 #if defined(GATE_TECH_VIRTUALIZATION_HYPERV2)
483
484 #include "gate/system/management.h"
485 #include "gate/utilities.h"
486
487 static gate_string_t const virtprov_name_hyperv2 = GATE_STRING_INIT_STATIC("mshyperv2");
488 static gate_string_t const virtprov_descr_hyperv2 = GATE_STRING_INIT_STATIC("Microsoft Hyper-V v2");
489
490 static gate_string_t const wmi_default_host = GATE_STRING_INIT_STATIC(".");
491 static gate_string_t const wmi_default_namespace = GATE_STRING_INIT_STATIC("ROOT\\virtualization\\v2");
492 static gate_string_t const wmi_search_path = GATE_STRING_INIT_STATIC("\\\\.\\ROOT\\virtualization\\v2");
493
494
495 typedef struct mshv2sbox_class
496 {
497 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const* vtbl;
498
499 gate_atomic_int_t ref_counter;
500 gate_management_t mgmt;
501 gate_string_t vm_path;
502 } mshv2sbox_t;
503
504 static void mshv2sbox_destroy(mshv2sbox_t* self)
505 {
506 if (self->mgmt)
507 {
508 gate_management_close(self->mgmt);
509 }
510 gate_string_release(&self->vm_path);
511
512 gate_mem_clear(self, sizeof(mshv2sbox_t));
513 gate_mem_dealloc(self);
514 }
515
516 static char const* mshv2sbox_get_interface_name(void* thisptr)
517 {
518 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
519 return GATE_INTERFACE_NAME_VIRTUALIZATION_SANDBOX;
520 }
521 static void mshv2sbox_release(void* thisptr)
522 {
523 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
524 if (gate_atomic_int_dec(&self->ref_counter) == 0)
525 {
526 mshv2sbox_destroy(self);
527 }
528 }
529 static int mshv2sbox_retain(void* thisptr)
530 {
531 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
532 return gate_atomic_int_inc(&self->ref_counter);
533 }
534
535
536 static gate_result_t mshv2sbox_change_state(mshv2sbox_t* self, gate_int32_t new_state)
537 {
538 gate_result_t ret;
539 gate_map_t input_args = GATE_INIT_EMPTY;
540 gate_map_t output_args = GATE_INIT_EMPTY;
541 do
542 {
543 static gate_string_t const methodname = GATE_STRING_INIT_STATIC("RequestStateChange");
544 static gate_string_t const param_requestedstate = GATE_STRING_INIT_STATIC("RequestedState");
545 static gate_string_t const param_returnvalue = GATE_STRING_INIT_STATIC("ReturnValue");
546 gate_value_t const* ptr_retval = NULL;
547
548 if (NULL == gate_util_stringvaluemap_create_ex(&input_args, true, true))
549 {
550 ret = GATE_RESULT_OUTOFMEMORY;
551 break;
552 }
553 gate_util_stringvaluemap_add_string(&input_args, &param_requestedstate, GATE_TYPE_I32, &new_state);
554
555 ret = gate_management_invoke(self->mgmt, &self->vm_path, &methodname, &input_args, &output_args);
556 GATE_BREAK_IF_FAILED(ret);
557
558 ptr_retval = gate_util_stringvaluemap_get_string(&output_args, &param_returnvalue);
559 if (ptr_retval)
560 {
561 /* evaluate WMI return value */
562 gate_int32_t const* ptr_intretval = (gate_int32_t const*)gate_value_get_ptr(ptr_retval);
563 if (ptr_intretval)
564 {
565 gate_int32_t const rv = *ptr_intretval;
566 if ((rv == 0) || (rv == 4096))
567 {
568 ret = GATE_RESULT_OK;
569 }
570 else
571 {
572 ret = GATE_RESULT_EXECUTIONFAILED;
573 }
574 }
575 }
576 } while (0);
577
578 gate_map_destroy(&input_args);
579 gate_map_destroy(&output_args);
580 return ret;
581 }
582
583 static gate_result_t mshv2sbox_start(void* thisptr)
584 {
585 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
586 static int const state_enabled = 2;
587 return mshv2sbox_change_state(self, state_enabled);
588 }
589 static gate_result_t mshv2sbox_stop(void* thisptr)
590 {
591 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
592 static int const state_disabled = 3;
593 return mshv2sbox_change_state(self, state_disabled);
594 }
595
596 #define MSHV2SBOX_STATE_UNKNOWN 0
597 #define MSHV2SBOX_STATE_OTHER 1
598 #define MSHV2SBOX_STATE_ENABLED 2
599 #define MSHV2SBOX_STATE_DISABLED 3
600 #define MSHV2SBOX_STATE_SHUTDOWN 4
601 #define MSHV2SBOX_STATE_NOTAPPLICABLE 5
602 #define MSHV2SBOX_STATE_OFFLINE 6
603 #define MSHV2SBOX_STATE_TEST 7
604 #define MSHV2SBOX_STATE_DEFERRED 8
605 #define MSHV2SBOX_STATE_QUIESCE 9
606 #define MSHV2SBOX_STATE_STARTING 10
607
608 static gate_enumint_t mshv2sbox_get_status(void* thisptr)
609 {
610 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
611 gate_management_object_t obj = GATE_INIT_EMPTY;
612 gate_enumint_t ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
613
614 do
615 {
616 static gate_string_t const keyEnabledState = GATE_STRING_INIT_STATIC("EnabledState");
617 gate_map_iterator_t iter;
618 gate_result_t result = gate_management_get_object(self->mgmt, &self->vm_path, &obj);
619 GATE_BREAK_IF_FAILED(result);
620
621 iter = gate_map_get(&obj.properties, &keyEnabledState);
622 if (!gate_map_iterator_valid(iter))
623 {
624 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
625 break;
626 }
627 else
628 {
629 gate_value_t const* ptr_value = (gate_value_t const*)gate_map_iterator_value(iter);
630 gate_int32_t const* ptr_state;
631 if (gate_value_type(ptr_value) != GATE_TYPE_I32)
632 {
633 break;
634 }
635 ptr_state = (gate_int32_t const*)gate_value_get_ptr(ptr_value);
636 switch (*ptr_state)
637 {
638 case MSHV2SBOX_STATE_UNKNOWN:
639 case MSHV2SBOX_STATE_OTHER:
640 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
641 break;
642 case MSHV2SBOX_STATE_ENABLED:
643 case MSHV2SBOX_STATE_QUIESCE:
644 case MSHV2SBOX_STATE_OFFLINE:
645 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_ONLINE;
646 break;
647 case MSHV2SBOX_STATE_DISABLED:
648 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_OFFLINE;
649 break;
650 case MSHV2SBOX_STATE_SHUTDOWN:
651 case MSHV2SBOX_STATE_NOTAPPLICABLE:
652 case MSHV2SBOX_STATE_TEST:
653 case MSHV2SBOX_STATE_DEFERRED:
654 case MSHV2SBOX_STATE_STARTING:
655 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_BUSY;
656 break;
657 }
658 }
659 } while (0);
660
661 gate_management_object_release(&obj);
662 return ret;
663 }
664
665 static gate_result_t mshv2sbox_get_id(void* thisptr, gate_string_t* id)
666 {
667 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
668 gate_result_t ret;
669 gate_management_object_t obj = GATE_INIT_EMPTY;
670
671 do
672 {
673 static gate_string_t const keyName = GATE_STRING_INIT_STATIC("Name");
674 gate_map_iterator_t iter;
675 gate_value_t const* value;
676 gate_string_t const* strvalue;
677
678 ret = gate_management_get_object(self->mgmt, &self->vm_path, &obj);
679 GATE_BREAK_IF_FAILED(ret);
680
681 iter = gate_map_get(&obj.properties, &keyName);
682 if (!gate_map_iterator_valid(iter))
683 {
684 ret = GATE_RESULT_NOTAVAILABLE;
685 break;
686 }
687 value = (gate_value_t const*)gate_map_iterator_value(iter);
688 if (gate_value_type(value) != GATE_TYPE_STRING)
689 {
690 ret = GATE_RESULT_INCORRECTTYPE;
691 break;
692 }
693 strvalue = (gate_string_t const*)gate_value_get_ptr(value);
694 if (NULL == gate_string_clone(id, strvalue))
695 {
696 ret = GATE_RESULT_OUTOFMEMORY;
697 break;
698 }
699 ret = GATE_RESULT_OK;
700 } while (0);
701 gate_management_object_release(&obj);
702 return ret;
703 }
704 static gate_result_t mshv2sbox_get_name(void* thisptr, gate_string_t* name)
705 {
706 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
707 gate_result_t ret;
708 gate_management_object_t obj = GATE_INIT_EMPTY;
709
710 do
711 {
712 static gate_string_t const keyName = GATE_STRING_INIT_STATIC("ElementName");
713 gate_map_iterator_t iter;
714 gate_value_t const* value;
715 gate_string_t const* strvalue;
716
717 ret = gate_management_get_object(self->mgmt, &self->vm_path, &obj);
718 GATE_BREAK_IF_FAILED(ret);
719
720 iter = gate_map_get(&obj.properties, &keyName);
721 if (!gate_map_iterator_valid(iter))
722 {
723 ret = GATE_RESULT_NOTAVAILABLE;
724 break;
725 }
726 value = (gate_value_t const*)gate_map_iterator_value(iter);
727 if (gate_value_type(value) != GATE_TYPE_STRING)
728 {
729 ret = GATE_RESULT_INCORRECTTYPE;
730 break;
731 }
732 strvalue = (gate_string_t const*)gate_value_get_ptr(value);
733 if (NULL == gate_string_clone(name, strvalue))
734 {
735 ret = GATE_RESULT_OUTOFMEMORY;
736 break;
737 }
738 ret = GATE_RESULT_OK;
739 } while (0);
740 gate_management_object_release(&obj);
741 return ret;
742 }
743 static gate_result_t mshv2sbox_get_settings(void* thisptr, gate_property_t* settings)
744 {
745 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
746 gate_result_t ret;
747 do
748 {
749 if (NULL == gate_property_create_object(settings))
750 {
751 ret = GATE_RESULT_OUTOFMEMORY;
752 break;
753 }
754 /* TODO */
755 ret = GATE_RESULT_OK;
756 } while (0);
757 return ret;
758 }
759 static gate_result_t mshv2sbox_update_settings(void* thisptr, gate_property_t const* settings)
760 {
761 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
762 gate_result_t ret;
763 do
764 {
765 /* TODO */
766 ret = GATE_RESULT_NOTSUPPORTED;
767 } while (0);
768 return ret;
769 }
770
771 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox)* mshv2sbox_vtbl_init()
772 {
773 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox) vtbl;
774 if (vtbl.get_interface_name == NULL)
775 {
776 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) v =
777 {
778 &mshv2sbox_get_interface_name,
779 &mshv2sbox_release,
780 &mshv2sbox_retain,
781
782 &mshv2sbox_start,
783 &mshv2sbox_stop,
784 &mshv2sbox_get_status,
785
786 &mshv2sbox_get_id,
787 &mshv2sbox_get_name,
788 &mshv2sbox_get_settings,
789 &mshv2sbox_update_settings
790 };
791 vtbl = v;
792 }
793 return &vtbl;
794 }
795
796
797 static gate_result_t mshv2sbox_create(gate_string_t const* path, mshv2sbox_t** ptr_obj)
798 {
799 gate_result_t ret;
800 gate_management_t mgmt;
801 mshv2sbox_t* sbox = NULL;
802
803 do
804 {
805 sbox = (mshv2sbox_t*)gate_mem_alloc(sizeof(mshv2sbox_t));
806 if (sbox == NULL)
807 {
808 ret = GATE_RESULT_OUTOFMEMORY;
809 break;
810 }
811
812 gate_mem_clear(sbox, sizeof(mshv2sbox_t));
813 sbox->vtbl = mshv2sbox_vtbl_init();
814 gate_atomic_int_init(&sbox->ref_counter, 1);
815
816 gate_string_clone(&sbox->vm_path, path);
817 ret = gate_management_open(&wmi_default_host, NULL, &wmi_default_namespace, 0, &sbox->mgmt);
818 GATE_BREAK_IF_FAILED(ret);
819
820 *ptr_obj = sbox;
821 sbox = NULL;
822 ret = GATE_RESULT_OK;
823 } while (0);
824
825 if (sbox != NULL)
826 {
827 mshv2sbox_destroy(sbox);
828 }
829
830 return ret;
831 }
832
833
834 typedef struct mshv2prov_class
835 {
836 GATE_INTERFACE_VTBL(gate_virtualization_provider) const* vtbl;
837
838 gate_atomic_int_t ref_counter;
839 gate_management_t mgmt;
840 } mshv2prov_t;
841
842 static void mshv2prov_destroy(mshv2prov_t* self)
843 {
844 if (NULL != self->mgmt)
845 {
846 gate_management_close(self->mgmt);
847 }
848 gate_mem_clear(self, sizeof(mshv2prov_t));
849 gate_mem_dealloc(self);
850 }
851
852 static char const* mshv2prov_get_interface_name(void* thisptr)
853 {
854 mshv2prov_t* self = (mshv2prov_t*)thisptr;
855 return GATE_INTERFACE_NAME_VIRTUALIZATION_PROVIDER;
856 }
857
858 static void mshv2prov_release(void* thisptr)
859 {
860 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
861 if (0 == gate_atomic_int_dec(&self->ref_counter))
862 {
863 mshv2prov_destroy(self);
864 }
865 }
866
867 static int mshv2prov_retain(void* thisptr)
868 {
869 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
870 return gate_atomic_int_inc(&self->ref_counter);
871 }
872
873 static gate_result_t mshv2prov_get_name(void* thisptr, gate_string_t* name)
874 {
875 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
876 gate_string_duplicate(name, &virtprov_name_hyperv2);
877 return GATE_RESULT_OK;
878 }
879
880 static gate_result_t mshv2prov_get_settings(void* thisptr, gate_property_t* settings)
881 {
882 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
883 if (NULL == gate_property_create_object(settings))
884 {
885 return GATE_RESULT_OUTOFMEMORY;
886 }
887 return GATE_RESULT_OK;
888 }
889
890 static gate_bool_t GATE_CALL mshv2prov_list_callback(gate_management_object_t const* mgmt_obj, void* user_param)
891 {
892 gate_arraylist_t lst = (gate_arraylist_t)user_param;
893 static gate_string_t const keyInstallDate = GATE_STRING_INIT_STATIC("InstallDate");
894 static gate_string_t const keyName = GATE_STRING_INIT_STATIC("Name");
895 gate_map_iterator_t iterDate = gate_map_get(&mgmt_obj->properties, &keyInstallDate);
896 gate_map_iterator_t iterName = gate_map_get(&mgmt_obj->properties, &keyName);
897 if (gate_map_iterator_valid(iterDate) && gate_map_iterator_valid(iterName))
898 {
899 gate_value_t const* val_name = gate_map_iterator_value(iterName);
900 if (val_name && (gate_value_type(val_name) == GATE_TYPE_STRING))
901 {
902 gate_string_t const* name = (gate_string_t const*)gate_value_get_ptr(val_name);
903 gate_arraylist_add(lst, name);
904 }
905 }
906 return true;
907 }
908
909 static gate_string_t const search_query = GATE_STRING_INIT_STATIC("SELECT * FROM Msvm_ComputerSystem");
910
911 static gate_result_t mshv2prov_list_sandbox_ids(void* thisptr, gate_array_t* sandbox_ids)
912 {
913 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
914 gate_result_t ret;
915 gate_arraylist_t lst = gate_util_stringarray_create();
916
917 do
918 {
919 if (NULL == lst)
920 {
921 ret = GATE_RESULT_OUTOFMEMORY;
922 break;
923 }
924
925 ret = gate_management_query(self->mgmt, &wmi_search_path, &search_query, &mshv2prov_list_callback, lst);
926 GATE_BREAK_IF_FAILED(ret);
927
928 if (NULL == gate_array_create(sandbox_ids, lst))
929 {
930 ret = GATE_RESULT_OUTOFMEMORY;
931 break;
932 }
933
934 ret = GATE_RESULT_OK;
935 } while (0);
936
937 if (NULL != lst)
938 {
939 gate_arraylist_release(lst);
940 }
941
942 return ret;
943 }
944
945 static gate_bool_t GATE_CALL mshv2prov_sandbox_callback(gate_management_object_t const* mgmt_obj, void* user_param)
946 {
947 gate_string_t* path = (gate_string_t*)user_param;
948 gate_string_clone(path, &mgmt_obj->path);
949 return false;
950 }
951
952 static gate_result_t mshv2prov_get_sandbox(void* thisptr, gate_string_t const* sandbox_id, gate_virtualization_sandbox_t** ptr_sandbox)
953 {
954 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
955 mshv2sbox_t* mshv2sbox = NULL;
956 gate_result_t result;
957 gate_strbuilder_t builder;
958 gate_string_t query = GATE_STRING_INIT_EMPTY;
959 gate_string_t found_path = GATE_STRING_INIT_EMPTY;
960 char buffer[1024];
961
962 do
963 {
964 gate_strbuilder_create_static(&builder, buffer, sizeof(buffer), 0);
965
966 gate_strbuilder_append_string(&builder, &search_query);
967 gate_strbuilder_append_cstr(&builder, " WHERE Name=\"");
968 gate_strbuilder_append_string(&builder, sandbox_id);
969 gate_strbuilder_append_cstr(&builder, "\"");
970
971 if (NULL == gate_strbuilder_to_string(&builder, &query))
972 {
973 result = GATE_RESULT_OUTOFMEMORY;
974 break;
975 }
976
977 result = gate_management_query(self->mgmt, &wmi_search_path, &query, &mshv2prov_sandbox_callback, &found_path);
978 GATE_BREAK_IF_FAILED(result);
979
980 if (gate_string_is_empty(&found_path))
981 {
982 result = GATE_RESULT_NOMATCH;
983 break;
984 }
985
986 result = mshv2sbox_create(&found_path, &mshv2sbox);
987 if (GATE_SUCCEEDED(result))
988 {
989 if (ptr_sandbox)
990 {
991 *ptr_sandbox = (gate_virtualization_sandbox_t*)mshv2sbox;
992 }
993 else
994 {
995 gate_object_release(mshv2sbox);
996 }
997 }
998 } while (0);
999
1000 gate_string_release(&found_path);
1001 gate_string_release(&query);
1002 gate_strbuilder_release(&builder);
1003
1004 return result;
1005 }
1006
1007 static GATE_INTERFACE_VTBL(gate_virtualization_provider) const* init_virutalization_provider_vtbl()
1008 {
1009 static GATE_INTERFACE_VTBL(gate_virtualization_provider) vtbl;
1010 if (vtbl.get_interface_name == NULL)
1011 {
1012 GATE_INTERFACE_VTBL(gate_virtualization_provider) v =
1013 {
1014 &mshv2prov_get_interface_name,
1015 &mshv2prov_release,
1016 &mshv2prov_retain,
1017
1018 &mshv2prov_get_name,
1019 &mshv2prov_get_settings,
1020
1021 &mshv2prov_list_sandbox_ids,
1022 &mshv2prov_get_sandbox
1023 };
1024 vtbl = v;
1025 }
1026 return &vtbl;
1027 }
1028
1029 static gate_result_t mshv2prov_create(gate_string_t const* host, gate_virtualization_provider_t** ptr)
1030 {
1031 gate_result_t ret;
1032 mshv2prov_t* mshv2prov = NULL;
1033
1034 do
1035 {
1036 mshv2prov = (mshv2prov_t*)gate_mem_alloc(sizeof(mshv2prov_t));
1037 if (NULL == mshv2prov)
1038 {
1039 ret = GATE_RESULT_OUTOFMEMORY;
1040 break;
1041 }
1042 gate_mem_clear(mshv2prov, sizeof(mshv2prov_t));
1043 mshv2prov->vtbl = init_virutalization_provider_vtbl();
1044 gate_atomic_int_init(&mshv2prov->ref_counter, 1);
1045
1046 if (gate_string_is_empty(host))
1047 {
1048 host = &wmi_default_host;
1049 }
1050
1051 ret = gate_management_open(host, NULL, &wmi_default_namespace, 0, &mshv2prov->mgmt);
1052 GATE_BREAK_IF_FAILED(ret);
1053
1054 if (ptr != NULL)
1055 {
1056 *ptr = (gate_virtualization_provider_t*)mshv2prov;
1057 mshv2prov = NULL;
1058 }
1059 ret = GATE_RESULT_OK;
1060 } while (0);
1061
1062 if (NULL != mshv2prov)
1063 {
1064 gate_mem_dealloc(mshv2prov);
1065 }
1066 return ret;
1067 }
1068
1069 #endif /* GATE_TECH_VIRTUALIZATION_HYPERV2 */
1070
1071
1072
1073 1 gate_result_t gate_tech_virtualization_providers_enum(gate_tech_virtualization_providers_callback_t callback, void* param)
1074 {
1075 1 gate_result_t ret = GATE_RESULT_OK;
1076
1077 do
1078 {
1079 #if defined(GATE_TECH_VIRTUALIZATION_LXC)
1080 /* lxc support */
1081
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (GATE_SUCCEEDED(gate_lxc_init()))
1082 {
1083 if (!callback(&virtprov_name_lxc, &virtprov_descr_lxc, param))
1084 {
1085 break;
1086 }
1087 }
1088 #endif
1089
1090 #if defined(GATE_TECH_VIRTUALIZATION_HYPERV2)
1091 /* MS hyper-v wmi access */
1092 if (!callback(&virtprov_name_hyperv2, &virtprov_descr_hyperv2, param))
1093 {
1094 break;
1095 }
1096 #endif
1097
1098 #if defined(GATE_TECH_VIRTUALIZATION_DOCKER)
1099 /* docker support */
1100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!callback(&virtprov_name_docker, &virtprov_descr_docker, param))
1101 {
1102 break;
1103 }
1104 #endif /* GATE_TECH_VIRTUALIZATION_DOCKER */
1105
1106 } while (0);
1107
1108 1 return ret;
1109 }
1110
1111
1112 1 gate_result_t gate_tech_virtualization_provider_create(gate_string_t const* name, gate_virtualization_provider_t** ptr_provider)
1113 {
1114 1 gate_result_t ret = GATE_RESULT_NOMATCH;
1115
1116 do
1117 {
1118 #if defined(GATE_TECH_VIRTUALIZATION_LXC)
1119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_string_equals(name, &virtprov_name_lxc))
1120 {
1121 ret = gate_lxc_init();
1122 GATE_BREAK_IF_FAILED(ret);
1123
1124 if (ptr_provider)
1125 {
1126 gate_virtualization_provider_t* prov = init_global_lxc_provider();
1127 if (!prov)
1128 {
1129 ret = GATE_RESULT_FAILED;
1130 break;
1131 }
1132 *ptr_provider = prov;
1133 }
1134 ret = GATE_RESULT_OK;
1135 break;
1136 }
1137 #endif
1138
1139 #if defined(GATE_TECH_VIRTUALIZATION_HYPERV2)
1140 if (gate_string_equals(name, &virtprov_name_hyperv2))
1141 {
1142 ret = mshv2prov_create(NULL, ptr_provider);
1143 return ret;
1144 }
1145 #endif
1146
1147 #if defined(GATE_TECH_VIRTUALIZATION_DOCKER)
1148
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_equals(name, &virtprov_name_docker))
1149 {
1150 /* TODO */
1151 1 ret = GATE_RESULT_FAILED;
1152 1 break;
1153 }
1154 #endif
1155
1156 ret = GATE_RESULT_NOMATCH;
1157 } while (0);
1158
1159 1 return ret;
1160 }
1161