1 /*
2  * esx_vi_types.c: client for the VMware VI API 2.5 to manage ESX hosts
3  *
4  * Copyright (C) 2010, 2014 Red Hat, Inc.
5  * Copyright (C) 2009-2011 Matthias Bolte <matthias.bolte@googlemail.com>
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  */
22 
23 #include <config.h>
24 
25 #include <libxml/parser.h>
26 #include <libxml/xpathInternals.h>
27 
28 #include "virbuffer.h"
29 #include "datatypes.h"
30 #include "viralloc.h"
31 #include "virlog.h"
32 #include "esx_vi.h"
33 #include "esx_vi_types.h"
34 #include "virstring.h"
35 #include "virxml.h"
36 
37 #define VIR_FROM_THIS VIR_FROM_ESX
38 
39 VIR_LOG_INIT("esx.esx_vi_types");
40 
41 #define ESX_VI__TEMPLATE__ALLOC(__type) \
42     int \
43     esxVI_##__type##_Alloc(esxVI_##__type **ptrptr) \
44     { \
45         ESX_VI_CHECK_ARG_LIST(ptrptr); \
46  \
47         *ptrptr = g_new0(esxVI_##__type, 1); \
48  \
49         (*ptrptr)->_type = esxVI_Type_##__type; \
50  \
51         return 0; \
52     }
53 
54 
55 
56 #define ESX_VI__TEMPLATE__FREE(_type, _body) \
57     void \
58     esxVI_##_type##_Free(esxVI_##_type **ptrptr) \
59     { \
60         esxVI_##_type *item G_GNUC_UNUSED; \
61  \
62         if (!ptrptr || !(*ptrptr)) { \
63             return; \
64         } \
65  \
66         item = *ptrptr; \
67  \
68         _body \
69  \
70         g_clear_pointer(ptrptr, g_free); \
71     }
72 
73 
74 
75 #define ESX_VI__TEMPLATE__VALIDATE(__type, _require) \
76     int \
77     esxVI_##__type##_Validate(esxVI_##__type *item) \
78     { \
79         const char *typeName = esxVI_Type_ToString(esxVI_Type_##__type); \
80  \
81         if (item->_type <= esxVI_Type_Undefined || \
82             item->_type >= esxVI_Type_Other) { \
83             virReportError(VIR_ERR_INTERNAL_ERROR, \
84                            _("%s object has invalid dynamic type"), typeName);\
85             return -1; \
86         } \
87  \
88         _require \
89  \
90         return 0; \
91     }
92 
93 
94 
95 #define ESX_VI__TEMPLATE__DEEP_COPY(_type, _deep_copy) \
96     int \
97     esxVI_##_type##_DeepCopy(esxVI_##_type **dest, esxVI_##_type *src) \
98     { \
99         ESX_VI_CHECK_ARG_LIST(dest); \
100  \
101         if (!src) { \
102             return 0; \
103         } \
104  \
105         if (esxVI_##_type##_Alloc(dest) < 0) { \
106             goto failure; \
107         } \
108  \
109         _deep_copy \
110  \
111         return 0; \
112  \
113       failure: \
114         esxVI_##_type##_Free(dest); \
115  \
116         return -1; \
117     }
118 
119 
120 
121 #define ESX_VI__TEMPLATE__LIST__APPEND(_type) \
122     int \
123     esxVI_##_type##_AppendToList(esxVI_##_type **list,  esxVI_##_type *item) \
124     { \
125         return esxVI_List_Append((esxVI_List **)list, (esxVI_List *)item); \
126     }
127 
128 
129 
130 #define ESX_VI__TEMPLATE__LIST__DEEP_COPY(_type) \
131     int \
132     esxVI_##_type##_DeepCopyList(esxVI_##_type **destList, \
133                                  esxVI_##_type *srcList) \
134     { \
135         return esxVI_List_DeepCopy \
136                  ((esxVI_List **)destList, (esxVI_List *)srcList, \
137                   (esxVI_List_DeepCopyFunc)esxVI_##_type##_DeepCopy, \
138                   (esxVI_List_FreeFunc)esxVI_##_type##_Free); \
139     }
140 
141 
142 
143 #define ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(_type) \
144     int \
145     esxVI_##_type##_CastListFromAnyType(esxVI_AnyType *anyType, \
146                                         esxVI_##_type **list) \
147     { \
148         return esxVI_List_CastFromAnyType \
149                  (anyType, (esxVI_List **)list, \
150                   (esxVI_List_CastFromAnyTypeFunc) \
151                     esxVI_##_type##_CastFromAnyType, \
152                   (esxVI_List_FreeFunc)esxVI_##_type##_Free); \
153     }
154 
155 
156 
157 #define ESX_VI__TEMPLATE__LIST__SERIALIZE(_type) \
158     int \
159     esxVI_##_type##_SerializeList(esxVI_##_type *list, const char *element, \
160                                   virBuffer *output) \
161     { \
162         return esxVI_List_Serialize((esxVI_List *)list, element, output, \
163                                     (esxVI_List_SerializeFunc) \
164                                       esxVI_##_type##_Serialize); \
165     }
166 
167 
168 
169 #define ESX_VI__TEMPLATE__LIST__DESERIALIZE(_type) \
170     int \
171     esxVI_##_type##_DeserializeList(xmlNodePtr node, esxVI_##_type **list) \
172     { \
173         return esxVI_List_Deserialize \
174                  (node, (esxVI_List **)list, \
175                   (esxVI_List_DeserializeFunc)esxVI_##_type##_Deserialize, \
176                   (esxVI_List_FreeFunc)esxVI_##_type##_Free); \
177     }
178 
179 
180 
181 #define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(_type, _dest_type, _extra, \
182                                                    _dest_extra) \
183     int \
184     esxVI_##_type##_Cast##_dest_extra##FromAnyType(esxVI_AnyType *anyType, \
185                                                    _dest_type **ptrptr) \
186     { \
187         _dest_type *item G_GNUC_UNUSED; \
188  \
189         if (!anyType || !ptrptr || *ptrptr) { \
190             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
191                            _("Invalid argument")); \
192             return -1; \
193         } \
194  \
195         item = *ptrptr; \
196  \
197         _extra \
198  \
199         return esxVI_##_type##_Deserialize##_dest_extra(anyType->node, \
200                                                         ptrptr); \
201     }
202 
203 
204 
205 #define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type) \
206     ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(_type, esxVI_##_type, \
207     { \
208         if (anyType->type != esxVI_Type_##_type) { \
209             virReportError(VIR_ERR_INTERNAL_ERROR, \
210                            _("Call to %s for unexpected type '%s', " \
211                              "expected '%s'"), \
212                            __FUNCTION__, anyType->other, \
213                            esxVI_Type_ToString(esxVI_Type_##_type)); \
214             return -1; \
215         } \
216     }, /* nothing */)
217 
218 
219 
220 #define ESX_VI__TEMPLATE__CAST_VALUE_FROM_ANY_TYPE(_type, _value_type) \
221     ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(_type, _value_type, \
222     { \
223         if (anyType->type != esxVI_Type_##_type) { \
224             virReportError(VIR_ERR_INTERNAL_ERROR, \
225                            _("Call to %s for unexpected type '%s', " \
226                              "expected '%s'"), \
227                            __FUNCTION__, anyType->other, \
228                            esxVI_Type_ToString(esxVI_Type_##_type)); \
229             return -1; \
230         } \
231     }, Value)
232 
233 
234 
235 #define ESX_VI__TEMPLATE__SERIALIZE_EXTRA(_type, _extra, _serialize) \
236     int \
237     esxVI_##_type##_Serialize(esxVI_##_type *item, \
238                               const char *element, virBuffer *output) \
239     { \
240         if (!element || !output) { \
241             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
242                            _("Invalid argument")); \
243             return -1; \
244         } \
245  \
246         if (!item) { \
247             return 0; \
248         } \
249  \
250         _extra \
251  \
252         if (esxVI_##_type##_Validate(item) < 0) { \
253             return -1; \
254         } \
255  \
256         ESV_VI__XML_TAG__OPEN(output, element, \
257                               esxVI_Type_ToString(esxVI_Type_##_type)); \
258  \
259         _serialize \
260  \
261         ESV_VI__XML_TAG__CLOSE(output, element); \
262  \
263         return 0; \
264     }
265 
266 
267 
268 #define ESX_VI__TEMPLATE__SERIALIZE(_type, _serialize) \
269     ESX_VI__TEMPLATE__SERIALIZE_EXTRA(_type, /* nothing */, _serialize)
270 
271 
272 
273 #define ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(_type, _extra1, _extra2, \
274                                             _deserialize) \
275     int \
276     esxVI_##_type##_Deserialize(xmlNodePtr node, esxVI_##_type **ptrptr) \
277     { \
278         xmlNodePtr childNode = NULL; \
279  \
280         _extra1 \
281  \
282         if (!ptrptr || *ptrptr) { \
283             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
284                            _("Invalid argument")); \
285             return -1; \
286         } \
287  \
288         if (esxVI_##_type##_Alloc(ptrptr) < 0) { \
289             return -1; \
290         } \
291  \
292         _extra2 \
293  \
294         for (childNode = node->children; childNode; \
295              childNode = childNode->next) { \
296             if (childNode->type != XML_ELEMENT_NODE) { \
297                 virReportError(VIR_ERR_INTERNAL_ERROR, \
298                                _("Wrong XML element type %d"), \
299                                childNode->type); \
300                 goto failure; \
301             } \
302  \
303             _deserialize \
304  \
305             VIR_WARN("Unexpected '%s' property", childNode->name); \
306         } \
307  \
308         if (esxVI_##_type##_Validate(*ptrptr) < 0) { \
309             goto failure; \
310         } \
311  \
312         return 0; \
313  \
314       failure: \
315         esxVI_##_type##_Free(ptrptr); \
316  \
317         return -1; \
318     }
319 
320 
321 
322 #define ESX_VI__TEMPLATE__DESERIALIZE(_type, _deserialize) \
323     ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(_type, /* nothing */, /* nothing */, \
324                                         _deserialize)
325 
326 
327 
328 #define ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(_type, _xsdType, _min, _max) \
329     int \
330     esxVI_##_type##_Deserialize(xmlNodePtr node, esxVI_##_type **number) \
331     { \
332         int result = -1; \
333         g_autofree char *string = NULL; \
334         long long value; \
335  \
336         if (!number || *number) { \
337             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
338                            _("Invalid argument")); \
339             return -1; \
340         } \
341  \
342         if (esxVI_##_type##_Alloc(number) < 0) { \
343             return -1; \
344         } \
345  \
346         string = (char *)xmlNodeListGetString(node->doc, node->children, 1); \
347  \
348         if (!string) { \
349             virReportError(VIR_ERR_INTERNAL_ERROR, \
350                            _("XML node doesn't contain text, expecting an %s "\
351                              "value"), _xsdType); \
352             goto cleanup; \
353         } \
354  \
355         if (virStrToLong_ll(string, NULL, 10, &value) < 0) { \
356             virReportError(VIR_ERR_INTERNAL_ERROR, \
357                            _("Unknown value '%s' for %s"), string, _xsdType); \
358             goto cleanup; \
359         } \
360  \
361         if (((_min) != INT64_MIN && value < (_min)) \
362             || ((_max) != INT64_MAX && value > (_max))) { \
363             virReportError(VIR_ERR_INTERNAL_ERROR, \
364                            _("Value '%s' is not representable as %s"), \
365                            string, _xsdType); \
366             goto cleanup; \
367         } \
368  \
369         (*number)->value = value; \
370  \
371         result = 0; \
372  \
373       cleanup: \
374         if (result < 0) { \
375             esxVI_##_type##_Free(number); \
376         } \
377  \
378         return result; \
379     }
380 
381 
382 
383 /*
384  * Macros for property handling to be used as part of other macros
385  */
386 
387 #define ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY(_type, _name) \
388     if (esxVI_##_type##_DeepCopy(&(*dest)->_name, src->_name) < 0) { \
389         goto failure; \
390     }
391 
392 
393 
394 #define ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_LIST(_type, _name) \
395     if (esxVI_##_type##_DeepCopyList(&(*dest)->_name, src->_name) < 0) { \
396         goto failure; \
397     }
398 
399 
400 
401 #define ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(_type, _name) \
402     if (esxVI_##_type##_DeepCopyValue(&(*dest)->_name, src->_name) < 0) { \
403         goto failure; \
404     }
405 
406 
407 
408 #define ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(_type, _name) \
409     if (esxVI_##_type##_Serialize(item->_name, #_name, output) < 0) { \
410         return -1; \
411     }
412 
413 
414 
415 #define ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(_type, _name) \
416     if (esxVI_##_type##_SerializeValue(item->_name, #_name, output) < 0) { \
417         return -1; \
418     }
419 
420 
421 
422 #define ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(_type, _name) \
423     if (esxVI_##_type##_SerializeList(item->_name, #_name, output) < 0) { \
424         return -1; \
425     }
426 
427 
428 
429 #define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(_type, _name) \
430     if (virXMLNodeNameEqual(childNode, #_name)) { \
431         if (esxVI_##_type##_Deserialize(childNode, &(*ptrptr)->_name) < 0) { \
432             goto failure; \
433         } \
434  \
435         continue; \
436     }
437 
438 
439 
440 #define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(_name) \
441     if (virXMLNodeNameEqual(childNode, #_name)) { \
442         continue; \
443     }
444 
445 
446 
447 #define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(_type, _name) \
448     if (virXMLNodeNameEqual(childNode, #_name)) { \
449         if (esxVI_##_type##_DeserializeValue(childNode, \
450                                              &(*ptrptr)->_name) < 0) { \
451             goto failure; \
452         } \
453  \
454         continue; \
455     }
456 
457 
458 
459 #define ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(_type, _name) \
460     if (virXMLNodeNameEqual(childNode, #_name)) { \
461         esxVI_##_type *_name##Item = NULL; \
462  \
463         if (esxVI_##_type##_Deserialize(childNode, &_name##Item) < 0) { \
464             goto failure; \
465         } \
466  \
467         if (esxVI_##_type##_AppendToList(&(*ptrptr)->_name, \
468                                          _name##Item) < 0) { \
469             esxVI_##_type##_Free(&_name##Item); \
470             goto failure; \
471         } \
472  \
473         continue; \
474     }
475 
476 
477 
478 /*
479  * A required property must be != 0 (NULL for pointers, "undefined" == 0 for
480  * enumeration values).
481  *
482  * To be used as part of ESX_VI__TEMPLATE__VALIDATE.
483  */
484 #define ESX_VI__TEMPLATE__PROPERTY__REQUIRE(_name) \
485     if (item->_name == 0) { \
486         virReportError(VIR_ERR_INTERNAL_ERROR, \
487                        _("%s object is missing the required '%s' property"), \
488                        typeName, #_name); \
489         return -1; \
490     }
491 
492 
493 
494 /*
495  * Macros to implement enumerations
496  */
497 
498 #define ESX_VI__TEMPLATE__ENUMERATION__CAST_FROM_ANY_TYPE(_type) \
499     int \
500     esxVI_##_type##_CastFromAnyType(esxVI_AnyType *anyType, \
501                                     esxVI_##_type *value) \
502     { \
503         return esxVI_Enumeration_CastFromAnyType \
504                  (&_esxVI_##_type##_Enumeration, anyType, (int *)value); \
505     }
506 
507 
508 
509 #define ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(_type) \
510     int \
511     esxVI_##_type##_Serialize(esxVI_##_type value, const char *element, \
512                               virBuffer *output) \
513     { \
514         return esxVI_Enumeration_Serialize(&_esxVI_##_type##_Enumeration, \
515                                            value, element, output); \
516     }
517 
518 
519 
520 #define ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(_type) \
521     int \
522     esxVI_##_type##_Deserialize(xmlNodePtr node, esxVI_##_type *value) \
523     { \
524         return esxVI_Enumeration_Deserialize(&_esxVI_##_type##_Enumeration, \
525                                              node, (int *)value); \
526     }
527 
528 
529 
530 /*
531  * Macros to implement dynamic dispatched functions
532  */
533 
534 #define ESX_VI__TEMPLATE__DISPATCH(_actual_type, _actual_type_name, __type, \
535                                    _dispatch,  _error_return) \
536     switch ((int)_actual_type) { \
537       _dispatch \
538  \
539       case esxVI_Type_##__type: \
540         break; \
541  \
542       default: \
543         virReportError(VIR_ERR_INTERNAL_ERROR, \
544                        _("Call to %s for unexpected type '%s'"), \
545                        __FUNCTION__, _actual_type_name); \
546         return _error_return; \
547     }
548 
549 
550 
551 #define ESX_VI__TEMPLATE__DISPATCH__FREE(_type) \
552     case esxVI_Type_##_type: \
553       esxVI_##_type##_Free((esxVI_##_type **)ptrptr); \
554       return;
555 
556 
557 
558 #define ESX_VI__TEMPLATE__DISPATCH__DEEP_COPY(_type) \
559     case esxVI_Type_##_type: \
560       return esxVI_##_type##_DeepCopy((esxVI_##_type **)dest, \
561                                       (esxVI_##_type *)src);
562 
563 
564 
565 #define ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(_type) \
566     case esxVI_Type_##_type: \
567       return esxVI_##_type##_Deserialize(anyType->node, \
568                                          (esxVI_##_type **)ptrptr);
569 
570 
571 
572 #define ESX_VI__TEMPLATE__DISPATCH__SERIALIZE(_type) \
573     case esxVI_Type_##_type: \
574       return esxVI_##_type##_Serialize((esxVI_##_type *)item, element, \
575                                        output);
576 
577 
578 
579 #define ESX_VI__TEMPLATE__DISPATCH__DESERIALIZE(_type) \
580     case esxVI_Type_##_type: \
581       return esxVI_##_type##_Deserialize(node, (esxVI_##_type **)ptrptr);
582 
583 
584 
585 #define ESX_VI__TEMPLATE__DYNAMIC_FREE(__type, _dispatch, _body) \
586     ESX_VI__TEMPLATE__FREE(__type, \
587       ESX_VI__TEMPLATE__DISPATCH(item->_type, \
588                                  esxVI_Type_ToString(item->_type), \
589                                  __type, _dispatch, \
590                                  /* nothing */) \
591       _body)
592 
593 
594 
595 #define ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
596     if (((esxVI_Object *)item)->_type == esxVI_Type_##__type) { \
597         return item; \
598     }
599 
600 
601 
602 #define ESX_VI__TEMPLATE__DYNAMIC_CAST(__type, _accept) \
603     esxVI_##__type * \
604     esxVI_##__type##_DynamicCast(void *item) \
605     { \
606         if (!item) { \
607             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
608                            _("Invalid argument")); \
609             return NULL; \
610         } \
611  \
612         ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
613  \
614         _accept \
615  \
616         return NULL; \
617     }
618 
619 
620 
621 #define ESX_VI__TEMPLATE__DYNAMIC_DEEP_COPY(__type, _dispatch, _deep_copy) \
622     int \
623     esxVI_##__type##_DeepCopy(esxVI_##__type **dest, esxVI_##__type *src) \
624     { \
625         if (!dest || *dest) { \
626             virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
627                            _("Invalid argument")); \
628             return -1; \
629         } \
630  \
631         if (!src) { \
632             return 0; \
633         } \
634  \
635         ESX_VI__TEMPLATE__DISPATCH(src->_type, \
636                                    esxVI_Type_ToString(src->_type), \
637                                    __type, _dispatch, -1) \
638  \
639         if (esxVI_##__type##_Alloc(dest) < 0) { \
640             goto failure; \
641         } \
642  \
643         _deep_copy \
644  \
645         return 0; \
646  \
647       failure: \
648         esxVI_##__type##_Free(dest); \
649  \
650         return -1; \
651     }
652 
653 
654 
655 #define ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(__type, _dispatch) \
656     ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE_EXTRA(__type, esxVI_##__type, \
657       ESX_VI__TEMPLATE__DISPATCH(anyType->type, \
658                                  esxVI_AnyType_TypeToString(anyType), \
659                                 __type, _dispatch, -1), \
660       /* nothing */)
661 
662 
663 
664 #define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) \
665     ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, \
666       ESX_VI__TEMPLATE__DISPATCH(item->_type, \
667                                  esxVI_Type_ToString(item->_type), \
668                                  __type, _dispatch, -1), \
669       _serialize)
670 
671 
672 
673 #define ESX_VI__TEMPLATE__DYNAMIC_DESERIALIZE(__type, _dispatch, \
674                                               _deserialize) \
675     ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(__type, \
676       esxVI_Type type = esxVI_Type_Undefined; \
677  \
678       if (esxVI_GetActualObjectType(node, esxVI_Type_##__type, &type) < 0) { \
679           return -1; \
680       } \
681  \
682       switch ((int)type) { \
683         _dispatch \
684  \
685         case esxVI_Type_##__type: \
686           break; \
687  \
688         default: \
689           virReportError(VIR_ERR_INTERNAL_ERROR, \
690                          _("Call to %s for unexpected type '%s'"), \
691                          __FUNCTION__, esxVI_Type_ToString(type)); \
692           return -1; \
693       }, \
694       /* nothing */, \
695       _deserialize)
696 
697 
698 
699 static int
esxVI_GetActualObjectType(xmlNodePtr node,esxVI_Type baseType,esxVI_Type * actualType)700 esxVI_GetActualObjectType(xmlNodePtr node, esxVI_Type baseType,
701                           esxVI_Type *actualType)
702 {
703     g_autofree char *type = NULL;
704 
705     if (!actualType || *actualType != esxVI_Type_Undefined) {
706         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
707         return -1;
708     }
709 
710     type = (char *)xmlGetNsProp
711                      (node, BAD_CAST "type",
712                       BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
713 
714     if (!type) {
715         /* no actual type specified, use base type instead */
716         *actualType = baseType;
717         return 0;
718     }
719 
720     *actualType = esxVI_Type_FromString(type);
721 
722     if (*actualType == esxVI_Type_Undefined || *actualType == esxVI_Type_Other) {
723         virReportError(VIR_ERR_INTERNAL_ERROR,
724                        _("Unknown value '%s' for %s 'type' property"),
725                        type, esxVI_Type_ToString(baseType));
726         return -1;
727     }
728 
729     return 0;
730 }
731 
732 
733 
734 /*
735  * Macros to implement managed objects
736  */
737 
738 #define ESX_VI__TEMPLATE__PROPERTY__MANAGED_REQUIRE(_name) \
739     /* FIXME: This results in O(n^2) runtime in case of missing required, but \
740      * unselected properties. */ \
741     if (item->_name == 0 && \
742         esxVI_String_ListContainsValue(selectedPropertyNameList, #_name)) { \
743         virReportError(VIR_ERR_INTERNAL_ERROR, \
744                        _("%s object is missing the required '%s' property"), \
745                        typeName, #_name); \
746         return -1; \
747     }
748 
749 
750 
751 #define ESX_VI__TEMPLATE__MANAGED_VALIDATE(__type, _require) \
752     int \
753     esxVI_##__type##_Validate(esxVI_##__type *item, \
754                               esxVI_String *selectedPropertyNameList) \
755     { \
756         const char *typeName = esxVI_Type_ToString(esxVI_Type_##__type); \
757  \
758         if (item->_type <= esxVI_Type_Undefined || \
759             item->_type >= esxVI_Type_Other) { \
760             virReportError(VIR_ERR_INTERNAL_ERROR, \
761                            _("%s object has invalid dynamic type"), typeName);\
762             return -1; \
763         } \
764  \
765         _require \
766  \
767         return 0; \
768     }
769 
770 
771 
772 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
773  * XSI: Type
774  */
775 
776 const char *
esxVI_Type_ToString(esxVI_Type type)777 esxVI_Type_ToString(esxVI_Type type)
778 {
779     switch (type) {
780       default:
781       case esxVI_Type_Undefined:
782         return "<undefined>";
783 
784       case esxVI_Type_Boolean:
785         return "xsd:boolean";
786 
787       case esxVI_Type_AnyType:
788         return "xsd:anyType";
789 
790       case esxVI_Type_String:
791         return "xsd:string";
792 
793       case esxVI_Type_Byte:
794         return "xsd:byte";
795 
796       case esxVI_Type_Short:
797         return "xsd:short";
798 
799       case esxVI_Type_Int:
800         return "xsd:int";
801 
802       case esxVI_Type_Long:
803         return "xsd:long";
804 
805       case esxVI_Type_DateTime:
806         return "xsd:dateTime";
807 
808       case esxVI_Type_Fault:
809         return "Fault";
810 
811       case esxVI_Type_MethodFault:
812         return "MethodFault";
813 
814       case esxVI_Type_ManagedObjectReference:
815         return "ManagedObjectReference";
816 
817       case esxVI_Type_Event:
818         return "Event";
819 
820 #include "esx_vi_types.generated.typetostring"
821 
822       case esxVI_Type_Other:
823         return "<other>";
824     }
825 }
826 
827 esxVI_Type
esxVI_Type_FromString(const char * type)828 esxVI_Type_FromString(const char *type)
829 {
830     if (!type || STREQ(type, "<undefined>")) {
831         return esxVI_Type_Undefined;
832     } else if (STREQ(type, "xsd:boolean")) {
833         return esxVI_Type_Boolean;
834     } else if (STREQ(type, "xsd:anyType")) {
835         return esxVI_Type_AnyType;
836     } else if (STREQ(type, "xsd:string")) {
837         return esxVI_Type_String;
838     } else if (STREQ(type, "xsd:byte")) {
839         return esxVI_Type_Byte;
840     } else if (STREQ(type, "xsd:short")) {
841         return esxVI_Type_Short;
842     } else if (STREQ(type, "xsd:int")) {
843         return esxVI_Type_Int;
844     } else if (STREQ(type, "xsd:long")) {
845         return esxVI_Type_Long;
846     } else if (STREQ(type, "xsd:dateTime")) {
847         return esxVI_Type_DateTime;
848     } else if (STREQ(type, "Fault")) {
849         return esxVI_Type_Fault;
850     } else if (STREQ(type, "MethodFault")) {
851         return esxVI_Type_MethodFault;
852     } else if (STREQ(type, "ManagedObjectReference")) {
853         return esxVI_Type_ManagedObjectReference;
854     } else if (STREQ(type, "Event")) {
855         return esxVI_Type_Event;
856     }
857 
858 #include "esx_vi_types.generated.typefromstring"
859 
860     return esxVI_Type_Other;
861 }
862 
863 
864 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
865  * XSD: Boolean
866  */
867 
868 static const esxVI_Enumeration _esxVI_Boolean_Enumeration = {
869     esxVI_Type_Boolean, {
870         { "true", esxVI_Boolean_True },
871         { "false", esxVI_Boolean_False },
872         { NULL, -1 },
873     },
874 };
875 
876 /* esxVI_Boolean_Serialize */
877 ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(Boolean)
878 
879 /* esxVI_Boolean_Deserialize */
ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(Boolean)880 ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(Boolean)
881 
882 
883 
884 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
885  * XSD: AnyType
886  */
887 
888 /* esxVI_AnyType_Alloc */
889 ESX_VI__TEMPLATE__ALLOC(AnyType)
890 
891 /* esxVI_AnyType_Free */
892 ESX_VI__TEMPLATE__FREE(AnyType,
893 {
894     xmlFreeNode(item->node);
895     g_free(item->other);
896     g_free(item->value);
897 })
898 
899 const char *
900 esxVI_AnyType_TypeToString(esxVI_AnyType *anyType)
901 {
902     if (anyType->type == esxVI_Type_Other) {
903         return anyType->other;
904     } else {
905         return esxVI_Type_ToString(anyType->type);
906     }
907 }
908 
909 int
esxVI_AnyType_ExpectType(esxVI_AnyType * anyType,esxVI_Type type)910 esxVI_AnyType_ExpectType(esxVI_AnyType *anyType, esxVI_Type type)
911 {
912     if (anyType->type != type) {
913         virReportError(VIR_ERR_INTERNAL_ERROR,
914                        _("Expecting type '%s' but found '%s'"),
915                        esxVI_Type_ToString(type),
916                        esxVI_AnyType_TypeToString(anyType));
917         return -1;
918     }
919 
920     return 0;
921 }
922 
923 int
esxVI_AnyType_DeepCopy(esxVI_AnyType ** dest,esxVI_AnyType * src)924 esxVI_AnyType_DeepCopy(esxVI_AnyType **dest, esxVI_AnyType *src)
925 {
926     ESX_VI_CHECK_ARG_LIST(dest);
927 
928     if (!src)
929         return 0;
930 
931     if (esxVI_AnyType_Alloc(dest) < 0)
932         goto failure;
933 
934     (*dest)->_type = src->_type;
935     (*dest)->node = xmlCopyNode(src->node, 1);
936 
937     if (!(*dest)->node) {
938         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
939                        _("Could not copy an XML node"));
940         goto failure;
941     }
942 
943     (*dest)->type = src->type;
944 
945     (*dest)->other = g_strdup(src->other);
946     (*dest)->value = g_strdup(src->value);
947 
948     switch ((int)src->type) {
949       case esxVI_Type_Boolean:
950         (*dest)->boolean = src->boolean;
951         break;
952 
953       case esxVI_Type_String:
954         (*dest)->string = (*dest)->value;
955         break;
956 
957       case esxVI_Type_Byte:
958         (*dest)->int8 = src->int8;
959         break;
960 
961       case esxVI_Type_Short:
962         (*dest)->int16 = src->int16;
963         break;
964 
965       case esxVI_Type_Int:
966         (*dest)->int32 = src->int32;
967         break;
968 
969       case esxVI_Type_Long:
970         (*dest)->int64 = src->int64;
971         break;
972 
973       default:
974         break;
975     }
976 
977     return 0;
978 
979  failure:
980     esxVI_AnyType_Free(dest);
981 
982     return -1;
983 }
984 
985 int
esxVI_AnyType_Deserialize(xmlNodePtr node,esxVI_AnyType ** anyType)986 esxVI_AnyType_Deserialize(xmlNodePtr node, esxVI_AnyType **anyType)
987 {
988     long long int number;
989 
990     ESX_VI_CHECK_ARG_LIST(anyType);
991 
992     if (esxVI_AnyType_Alloc(anyType) < 0)
993         return -1;
994 
995     (*anyType)->node = xmlCopyNode(node, 1);
996 
997     if (!(*anyType)->node) {
998         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
999                        _("Could not copy an XML node"));
1000         goto failure;
1001     }
1002 
1003     (*anyType)->other =
1004       (char *)xmlGetNsProp
1005                 (node, BAD_CAST "type",
1006                  BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
1007 
1008     if (!(*anyType)->other) {
1009         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1010                        _("AnyType is missing 'type' property"));
1011         goto failure;
1012     }
1013 
1014     (*anyType)->type = esxVI_Type_FromString((*anyType)->other);
1015 
1016     if ((*anyType)->type == esxVI_Type_Undefined) {
1017         virReportError(VIR_ERR_INTERNAL_ERROR,
1018                        _("Unknown value '%s' for AnyType 'type' property"),
1019                        (*anyType)->other);
1020         goto failure;
1021     }
1022 
1023     (*anyType)->value =
1024       (char *)xmlNodeListGetString(node->doc, node->children, 1);
1025 
1026     if (!(*anyType)->value)
1027         (*anyType)->value = g_strdup("");
1028 
1029 #define _DESERIALIZE_NUMBER(_type, _xsdType, _name, _min, _max) \
1030         do { \
1031             if (virStrToLong_ll((*anyType)->value, NULL, 10, &number) < 0) { \
1032                 virReportError(VIR_ERR_INTERNAL_ERROR, \
1033                                _("Unknown value '%s' for %s"), \
1034                                (*anyType)->value, _xsdType); \
1035                 goto failure; \
1036             } \
1037  \
1038             if (((_min) != INT64_MIN && number < (_min)) \
1039                 || ((_max) != INT64_MAX && number > (_max))) { \
1040                 virReportError(VIR_ERR_INTERNAL_ERROR, \
1041                                _("Value '%s' is out of %s range"), \
1042                                (*anyType)->value, _xsdType); \
1043                 goto failure; \
1044             } \
1045  \
1046             (*anyType)->_name = number; \
1047         } while (0)
1048 
1049     switch ((int)(*anyType)->type) {
1050       case esxVI_Type_Boolean:
1051         if (STREQ((*anyType)->value, "true")) {
1052             (*anyType)->boolean = esxVI_Boolean_True;
1053         } else if (STREQ((*anyType)->value, "false")) {
1054             (*anyType)->boolean = esxVI_Boolean_False;
1055         } else {
1056             virReportError(VIR_ERR_INTERNAL_ERROR,
1057                            _("Unknown value '%s' for xsd:boolean"),
1058                            (*anyType)->value);
1059             goto failure;
1060         }
1061 
1062         break;
1063 
1064       case esxVI_Type_String:
1065         (*anyType)->string = (*anyType)->value;
1066         break;
1067 
1068       case esxVI_Type_Byte:
1069         _DESERIALIZE_NUMBER(Byte, "xsd:byte", int8, INT8_MIN, INT8_MAX);
1070         break;
1071 
1072       case esxVI_Type_Short:
1073         _DESERIALIZE_NUMBER(Short, "xsd:short", int16, INT16_MIN, INT16_MAX);
1074         break;
1075 
1076       case esxVI_Type_Int:
1077         _DESERIALIZE_NUMBER(Int, "xsd:int", int32, INT32_MIN, INT32_MAX);
1078         break;
1079 
1080       case esxVI_Type_Long:
1081         _DESERIALIZE_NUMBER(Long, "xsd:long", int64, INT64_MIN, INT64_MAX);
1082         break;
1083 
1084       default:
1085         break;
1086     }
1087 
1088 #undef _DESERIALIZE_NUMBER
1089 
1090     return 0;
1091 
1092  failure:
1093     esxVI_AnyType_Free(anyType);
1094 
1095     return -1;
1096 }
1097 
1098 
1099 
1100 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1101  * XSD: String
1102  */
1103 
1104 /* esxVI_String_Alloc */
1105 ESX_VI__TEMPLATE__ALLOC(String)
1106 
1107 /* esxVI_String_Free */
1108 ESX_VI__TEMPLATE__FREE(String,
1109 {
1110     esxVI_String_Free(&item->_next);
1111 
1112     g_free(item->value);
1113 })
1114 
1115 /* esxVI_String_Validate */
1116 ESX_VI__TEMPLATE__VALIDATE(String,
1117 {
1118     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(value)
1119 })
1120 
1121 bool
esxVI_String_ListContainsValue(esxVI_String * stringList,const char * value)1122 esxVI_String_ListContainsValue(esxVI_String *stringList, const char *value)
1123 {
1124     esxVI_String *string;
1125 
1126     for (string = stringList; string; string = string->_next) {
1127         if (STREQ(string->value, value))
1128             return true;
1129     }
1130 
1131     return false;
1132 }
1133 
1134 /* esxVI_String_AppendToList */
ESX_VI__TEMPLATE__LIST__APPEND(String)1135 ESX_VI__TEMPLATE__LIST__APPEND(String)
1136 
1137 int
1138 esxVI_String_AppendValueToList(esxVI_String **stringList, const char *value)
1139 {
1140     esxVI_String *string = NULL;
1141 
1142     if (esxVI_String_Alloc(&string) < 0)
1143         return -1;
1144 
1145     string->value = g_strdup(value);
1146 
1147     if (esxVI_String_AppendToList(stringList, string) < 0)
1148         goto failure;
1149 
1150     return 0;
1151 
1152  failure:
1153     esxVI_String_Free(&string);
1154 
1155     return -1;
1156 }
1157 
1158 int
esxVI_String_AppendValueListToList(esxVI_String ** stringList,const char * valueList)1159 esxVI_String_AppendValueListToList(esxVI_String **stringList,
1160                                    const char *valueList)
1161 {
1162     esxVI_String *stringListToAppend = NULL;
1163     const char *value = valueList;
1164 
1165     while (value && *value != '\0') {
1166         if (esxVI_String_AppendValueToList(&stringListToAppend, value) < 0)
1167             goto failure;
1168 
1169         value += strlen(value) + 1;
1170     }
1171 
1172     if (esxVI_String_AppendToList(stringList, stringListToAppend) < 0)
1173         goto failure;
1174 
1175     return 0;
1176 
1177  failure:
1178     esxVI_String_Free(&stringListToAppend);
1179 
1180     return -1;
1181 }
1182 
1183 /* esxVI_String_DeepCopy */
1184 ESX_VI__TEMPLATE__DEEP_COPY(String,
1185 {
1186     ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, value)
1187 })
1188 
1189 /* esxVI_String_DeepCopyList */
ESX_VI__TEMPLATE__LIST__DEEP_COPY(String)1190 ESX_VI__TEMPLATE__LIST__DEEP_COPY(String)
1191 
1192 int
1193 esxVI_String_DeepCopyValue(char **dest, const char *src)
1194 {
1195     ESX_VI_CHECK_ARG_LIST(dest);
1196 
1197     *dest = g_strdup(src);
1198     return 0;
1199 }
1200 
1201 /* esxVI_String_CastFromAnyType */
1202 ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(String)
1203 
1204 /* esxVI_String_CastValueFromAnyType */
ESX_VI__TEMPLATE__CAST_VALUE_FROM_ANY_TYPE(String,char)1205 ESX_VI__TEMPLATE__CAST_VALUE_FROM_ANY_TYPE(String, char)
1206 
1207 int
1208 esxVI_String_Serialize(esxVI_String *string, const char *element,
1209                        virBuffer *output)
1210 {
1211     return esxVI_String_SerializeValue(string ? string->value : NULL,
1212                                        element, output);
1213 }
1214 
1215 /* esxVI_String_SerializeList */
ESX_VI__TEMPLATE__LIST__SERIALIZE(String)1216 ESX_VI__TEMPLATE__LIST__SERIALIZE(String)
1217 
1218 int
1219 esxVI_String_SerializeValue(const char *value, const char *element,
1220                             virBuffer *output)
1221 {
1222     if (!element || !output) {
1223         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
1224         return -1;
1225     }
1226 
1227     if (!value)
1228         return 0;
1229 
1230     ESV_VI__XML_TAG__OPEN(output, element, "xsd:string");
1231 
1232     virBufferAdd(output, value, -1);
1233 
1234     ESV_VI__XML_TAG__CLOSE(output, element);
1235 
1236     return 0;
1237 }
1238 
1239 int
esxVI_String_Deserialize(xmlNodePtr node,esxVI_String ** string)1240 esxVI_String_Deserialize(xmlNodePtr node, esxVI_String **string)
1241 {
1242     ESX_VI_CHECK_ARG_LIST(string);
1243 
1244     if (esxVI_String_Alloc(string) < 0 ||
1245         esxVI_String_DeserializeValue(node, &(*string)->value) < 0) {
1246         goto failure;
1247     }
1248 
1249     return 0;
1250 
1251  failure:
1252     esxVI_String_Free(string);
1253 
1254     return -1;
1255 }
1256 
1257 /* esxVI_String_DeserializeList */
ESX_VI__TEMPLATE__LIST__DESERIALIZE(String)1258 ESX_VI__TEMPLATE__LIST__DESERIALIZE(String)
1259 
1260 int
1261 esxVI_String_DeserializeValue(xmlNodePtr node, char **value)
1262 {
1263     ESX_VI_CHECK_ARG_LIST(value);
1264 
1265     *value = (char *)xmlNodeListGetString(node->doc, node->children, 1);
1266     if (!*value)
1267         *value = g_strdup("");
1268 
1269     return 0;
1270 }
1271 
1272 
1273 
1274 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1275  * XSD: Byte
1276  */
1277 
1278 /* esxVI_Byte_Alloc */
1279 ESX_VI__TEMPLATE__ALLOC(Byte)
1280 
1281 /* esxVI_Byte_Free */
1282 ESX_VI__TEMPLATE__FREE(Byte,
1283 {
1284     esxVI_Byte_Free(&item->_next);
1285 })
1286 
1287 /* esxVI_Byte_Validate */
1288 ESX_VI__TEMPLATE__VALIDATE(Byte,
1289 {
1290 })
1291 
1292 /* esxVI_Byte_AppendToList */
1293 ESX_VI__TEMPLATE__LIST__APPEND(Byte)
1294 
1295 /* esxVI_Byte_DeepCopy */
1296 ESX_VI__TEMPLATE__DEEP_COPY(Byte,
1297 {
1298     (*dest)->value = src->value;
1299 })
1300 
1301 /* esxVI_Byte_DeepCopyList */
1302 ESX_VI__TEMPLATE__LIST__DEEP_COPY(Byte)
1303 
1304 /* esxVI_Byte_Serialize */
1305 ESX_VI__TEMPLATE__SERIALIZE(Byte,
1306 {
1307     virBufferAsprintf(output, "%d", (int)item->value);
1308 })
1309 
1310 /* esxVI_Byte_SerializeList */
1311 ESX_VI__TEMPLATE__LIST__SERIALIZE(Byte)
1312 
1313 /* esxVI_Byte_Deserialize */
1314 ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(Byte, "xsd:byte", INT8_MIN, INT8_MAX);
1315 
1316 
1317 
1318 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1319  * XSD: Int
1320  */
1321 
1322 /* esxVI_Int_Alloc */
1323 ESX_VI__TEMPLATE__ALLOC(Int)
1324 
1325 /* esxVI_Int_Free */
1326 ESX_VI__TEMPLATE__FREE(Int,
1327 {
1328     esxVI_Int_Free(&item->_next);
1329 })
1330 
1331 /* esxVI_Int_Validate */
1332 ESX_VI__TEMPLATE__VALIDATE(Int,
1333 {
1334 })
1335 
1336 /* esxVI_Int_AppendToList */
ESX_VI__TEMPLATE__LIST__APPEND(Int)1337 ESX_VI__TEMPLATE__LIST__APPEND(Int)
1338 
1339 /* esxVI_Int_DeepCopy */
1340 ESX_VI__TEMPLATE__DEEP_COPY(Int,
1341 {
1342     (*dest)->value = src->value;
1343 })
1344 
1345 /* esxVI_Int_CastFromAnyType */
1346 ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(Int)
1347 
1348 /* esxVI_Int_Serialize */
1349 ESX_VI__TEMPLATE__SERIALIZE(Int,
1350 {
1351     virBufferAsprintf(output, "%d", (int)item->value);
1352 })
1353 
1354 /* esxVI_Int_SerializeList */
1355 ESX_VI__TEMPLATE__LIST__SERIALIZE(Int)
1356 
1357 /* esxVI_Int_Deserialize */
1358 ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(Int, "xsd:int", INT32_MIN, INT32_MAX)
1359 
1360 
1361 
1362 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1363  * XSD: Long
1364  */
1365 
1366 /* esxVI_Long_Alloc */
1367 ESX_VI__TEMPLATE__ALLOC(Long)
1368 
1369 /* esxVI_Long_Free */
1370 ESX_VI__TEMPLATE__FREE(Long,
1371 {
1372     esxVI_Long_Free(&item->_next);
1373 })
1374 
1375 /* esxVI_Long_Validate */
1376 ESX_VI__TEMPLATE__VALIDATE(Long,
1377 {
1378 })
1379 
1380 /* esxVI_Long_AppendToList */
1381 ESX_VI__TEMPLATE__LIST__APPEND(Long)
1382 
1383 /* esxVI_Long_DeepCopy */
1384 ESX_VI__TEMPLATE__DEEP_COPY(Long,
1385 {
1386     (*dest)->value = src->value;
1387 })
1388 
1389 /* esxVI_Long_CastFromAnyType */
1390 ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(Long)
1391 
1392 /* esxVI_Long_Serialize */
1393 ESX_VI__TEMPLATE__SERIALIZE(Long,
1394 {
1395     virBufferAsprintf(output, "%lld", (long long int)item->value);
1396 })
1397 
1398 /* esxVI_Long_SerializeList */
1399 ESX_VI__TEMPLATE__LIST__SERIALIZE(Long)
1400 
1401 /* esxVI_Long_Deserialize */
1402 ESX_VI__TEMPLATE__DESERIALIZE_NUMBER(Long, "xsd:long", INT64_MIN, INT64_MAX)
1403 
1404 
1405 
1406 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1407  * XSD: DateTime
1408  */
1409 
1410 /* esxVI_DateTime_Alloc */
1411 ESX_VI__TEMPLATE__ALLOC(DateTime)
1412 
1413 /* esxVI_DateTime_Free */
1414 ESX_VI__TEMPLATE__FREE(DateTime,
1415 {
1416     g_free(item->value);
1417 })
1418 
1419 /* esxVI_DateTime_Validate */
1420 ESX_VI__TEMPLATE__VALIDATE(DateTime,
1421 {
1422     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(value);
1423 })
1424 
1425 /* esxVI_DateTime_DeepCopy */
1426 ESX_VI__TEMPLATE__DEEP_COPY(DateTime,
1427 {
1428     ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, value)
1429 })
1430 
1431 /* esxVI_DateTime_Serialize */
1432 ESX_VI__TEMPLATE__SERIALIZE(DateTime,
1433 {
1434     virBufferAdd(output, item->value, -1);
1435 })
1436 
1437 int
1438 esxVI_DateTime_Deserialize(xmlNodePtr node, esxVI_DateTime **dateTime)
1439 {
1440     ESX_VI_CHECK_ARG_LIST(dateTime);
1441 
1442     if (esxVI_DateTime_Alloc(dateTime) < 0)
1443         return -1;
1444 
1445     (*dateTime)->value =
1446       (char *)xmlNodeListGetString(node->doc, node->children, 1);
1447 
1448     if (!(*dateTime)->value) {
1449         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1450                        _("XML node doesn't contain text, expecting an "
1451                          "xsd:dateTime value"));
1452         goto failure;
1453     }
1454 
1455     return 0;
1456 
1457  failure:
1458     esxVI_DateTime_Free(dateTime);
1459 
1460     return -1;
1461 }
1462 
1463 int
esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime * dateTime,long long * secondsSinceEpoch)1464 esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime,
1465                                      long long *secondsSinceEpoch)
1466 {
1467     char *tmp;
1468     g_autoptr(GDateTime) then = NULL;
1469     g_autoptr(GTimeZone) tz = NULL;
1470     int year, mon, mday, hour, min, sec, milliseconds;
1471 
1472     if (!dateTime || !secondsSinceEpoch) {
1473         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
1474         return -1;
1475     }
1476 
1477     /*
1478      * expected format: [-]CCYY-MM-DDTHH:MM:SS[.ssssss][((+|-)HH:MM|Z)]
1479      * typical example: 2010-04-05T12:13:55.316789+02:00
1480      *
1481      * see http://www.w3.org/TR/xmlschema-2/#dateTime
1482      *
1483      * map negative years to 0, since the base for time_t is the year 1970.
1484      */
1485     if (dateTime->value[0] == '-') {
1486         *secondsSinceEpoch = 0;
1487         return 0;
1488     }
1489 
1490     if (/* year */
1491         virStrToLong_i(dateTime->value, &tmp, 10, &year) < 0 || *tmp != '-' ||
1492         /* month */
1493         virStrToLong_i(tmp+1, &tmp, 10, &mon) < 0 || *tmp != '-' ||
1494         /* day */
1495         virStrToLong_i(tmp+1, &tmp, 10, &mday) < 0 || *tmp != 'T' ||
1496         /* hour */
1497         virStrToLong_i(tmp+1, &tmp, 10, &hour) < 0 || *tmp != ':' ||
1498         /* minute */
1499         virStrToLong_i(tmp+1, &tmp, 10, &min) < 0 || *tmp != ':' ||
1500         /* second */
1501         virStrToLong_i(tmp+1, &tmp, 10, &sec) < 0) {
1502         virReportError(VIR_ERR_INTERNAL_ERROR,
1503                        _("xsd:dateTime value '%s' has unexpected format"),
1504                        dateTime->value);
1505         return -1;
1506     }
1507 
1508     if (*tmp != '\0') {
1509         /* skip .ssssss part if present */
1510         if (*tmp == '.' &&
1511             virStrToLong_i(tmp + 1, &tmp, 10, &milliseconds) < 0) {
1512             virReportError(VIR_ERR_INTERNAL_ERROR,
1513                            _("xsd:dateTime value '%s' has unexpected format"),
1514                            dateTime->value);
1515             return -1;
1516         }
1517 
1518         /* parse timezone offset if present. if missing assume UTC */
1519         if (*tmp == '+' || *tmp == '-') {
1520             tz = g_time_zone_new(tmp);
1521         } else if (STREQ(tmp, "Z")) {
1522             tz = g_time_zone_new_utc();
1523         } else {
1524             virReportError(VIR_ERR_INTERNAL_ERROR,
1525                            _("xsd:dateTime value '%s' has unexpected format"),
1526                            dateTime->value);
1527             return -1;
1528         }
1529     } else {
1530         tz = g_time_zone_new_utc();
1531     }
1532 
1533     /*
1534      * xsd:dateTime represents local time relative to the optional timezone
1535      * given as offset. pretend the local time is in UTC and use timegm in
1536      * order to avoid interference with the timezone to this computer.
1537      * apply timezone correction afterwards, because it's simpler than
1538      * handling all the possible over- and underflows when trying to apply
1539      * it to the tm struct.
1540      */
1541     then = g_date_time_new(tz, year, mon, mday, hour, min, sec);
1542     *secondsSinceEpoch = (long long)g_date_time_to_unix(then);
1543 
1544     return 0;
1545 }
1546 
1547 
1548 
1549 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1550  * SOAP: Fault
1551  */
1552 
1553 /* esxVI_Fault_Alloc */
1554 ESX_VI__TEMPLATE__ALLOC(Fault);
1555 
1556 /* esxVI_Fault_Free */
1557 ESX_VI__TEMPLATE__FREE(Fault,
1558 {
1559     g_free(item->faultcode);
1560     g_free(item->faultstring);
1561 })
1562 
1563 /* esxVI_Fault_Validate */
1564 ESX_VI__TEMPLATE__VALIDATE(Fault,
1565 {
1566     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(faultcode);
1567     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(faultstring);
1568 })
1569 
1570 /* esxVI_Fault_Deserialize */
1571 ESX_VI__TEMPLATE__DESERIALIZE(Fault,
1572 {
1573     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, faultcode);
1574     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, faultstring);
1575     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(detail); /* FIXME */
1576 })
1577 
1578 
1579 
1580 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1581  * VI Object: MethodFault
1582  */
1583 
1584 /* esxVI_MethodFault_Alloc */
1585 ESX_VI__TEMPLATE__ALLOC(MethodFault);
1586 
1587 /* esxVI_MethodFault_Free */
1588 ESX_VI__TEMPLATE__FREE(MethodFault,
1589 {
1590     g_free(item->_actualType);
1591 })
1592 
1593 int
esxVI_MethodFault_Deserialize(xmlNodePtr node,esxVI_MethodFault ** methodFault)1594 esxVI_MethodFault_Deserialize(xmlNodePtr node, esxVI_MethodFault **methodFault)
1595 {
1596     ESX_VI_CHECK_ARG_LIST(methodFault);
1597 
1598     if (esxVI_MethodFault_Alloc(methodFault) < 0)
1599         return -1;
1600 
1601     (*methodFault)->_actualType =
1602       (char *)xmlGetNsProp(node, BAD_CAST "type",
1603                            BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
1604 
1605     if (!(*methodFault)->_actualType) {
1606         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1607                        _("MethodFault is missing 'type' property"));
1608         goto failure;
1609     }
1610 
1611     return 0;
1612 
1613  failure:
1614     esxVI_MethodFault_Free(methodFault);
1615 
1616     return -1;
1617 }
1618 
1619 
1620 
1621 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1622  * VI Object: ManagedObjectReference
1623  */
1624 
1625 /* esxVI_ManagedObjectReference_Alloc */
1626 ESX_VI__TEMPLATE__ALLOC(ManagedObjectReference)
1627 
1628 /* esxVI_ManagedObjectReference_Free */
1629 ESX_VI__TEMPLATE__FREE(ManagedObjectReference,
1630 {
1631     esxVI_ManagedObjectReference_Free(&item->_next);
1632 
1633     g_free(item->type);
1634     g_free(item->value);
1635 })
1636 
1637 /* esxVI_ManagedObjectReference_DeepCopy */
1638 ESX_VI__TEMPLATE__DEEP_COPY(ManagedObjectReference,
1639 {
1640     ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, type)
1641     ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, value)
1642 })
1643 
1644 /* esxVI_ManagedObjectReference_AppendToList */
ESX_VI__TEMPLATE__LIST__APPEND(ManagedObjectReference)1645 ESX_VI__TEMPLATE__LIST__APPEND(ManagedObjectReference)
1646 
1647 /* esxVI_ManagedObjectReference_CastFromAnyType */
1648 ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference)
1649 
1650 /* esxVI_ManagedObjectReference_CastListFromAnyType */
1651 ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(ManagedObjectReference)
1652 
1653 int
1654 esxVI_ManagedObjectReference_Serialize
1655   (esxVI_ManagedObjectReference *managedObjectReference,
1656    const char *element, virBuffer *output)
1657 {
1658     if (!element || !output) {
1659         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
1660         return -1;
1661     }
1662 
1663     if (!managedObjectReference)
1664         return 0;
1665 
1666     virBufferAddLit(output, "<");
1667     virBufferAdd(output, element, -1);
1668     virBufferAsprintf(output,
1669                       " xmlns=\"urn:vim25\" "
1670                       "xsi:type=\"ManagedObjectReference\" type=\"%s\">",
1671                       managedObjectReference->type);
1672 
1673     virBufferAdd(output, managedObjectReference->value, -1);
1674 
1675     ESV_VI__XML_TAG__CLOSE(output, element);
1676 
1677     return 0;
1678 }
1679 
1680 /* esxVI_ManagedObjectReference_SerializeList */
ESX_VI__TEMPLATE__LIST__SERIALIZE(ManagedObjectReference)1681 ESX_VI__TEMPLATE__LIST__SERIALIZE(ManagedObjectReference)
1682 
1683 int
1684 esxVI_ManagedObjectReference_Deserialize
1685   (xmlNodePtr node, esxVI_ManagedObjectReference **managedObjectReference)
1686 {
1687     ESX_VI_CHECK_ARG_LIST(managedObjectReference);
1688 
1689     if (esxVI_ManagedObjectReference_Alloc(managedObjectReference) < 0)
1690         return -1;
1691 
1692     (*managedObjectReference)->type =
1693       (char *)xmlGetNoNsProp(node, BAD_CAST "type");
1694 
1695     if (!(*managedObjectReference)->type) {
1696         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1697                        _("ManagedObjectReference is missing 'type' property"));
1698         goto failure;
1699     }
1700 
1701     if (esxVI_String_DeserializeValue(node,
1702                                       &(*managedObjectReference)->value) < 0) {
1703         goto failure;
1704     }
1705 
1706     return 0;
1707 
1708  failure:
1709     esxVI_ManagedObjectReference_Free(managedObjectReference);
1710 
1711     return -1;
1712 }
1713 
1714 
1715 
1716 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1717  * VI Type: Event
1718  */
1719 
1720 /* esxVI_Event_Alloc */
1721 ESX_VI__TEMPLATE__ALLOC(Event)
1722 
1723 /* esxVI_Event_Free */
1724 ESX_VI__TEMPLATE__FREE(Event,
1725 {
1726     esxVI_Event_Free(&item->_next);
1727     g_free(item->_actualType);
1728 
1729     esxVI_Int_Free(&item->key);
1730     esxVI_Int_Free(&item->chainId);
1731     esxVI_DateTime_Free(&item->createdTime);
1732     g_free(item->userName);
1733     /* FIXME: datacenter is currently ignored */
1734     /* FIXME: computeResource is currently ignored */
1735     /* FIXME: host is currently ignored */
1736     esxVI_VmEventArgument_Free(&item->vm);
1737     g_free(item->fullFormattedMessage);
1738 })
1739 
1740 /* esxVI_Event_Validate */
1741 ESX_VI__TEMPLATE__VALIDATE(Event,
1742 {
1743     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(key)
1744     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(chainId)
1745     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(createdTime)
1746     ESX_VI__TEMPLATE__PROPERTY__REQUIRE(userName)
1747     /* FIXME: datacenter is currently ignored */
1748     /* FIXME: computeResource is currently ignored */
1749     /* FIXME: host is currently ignored */
1750 })
1751 
1752 /* esxVI_Event_AppendToList */
ESX_VI__TEMPLATE__LIST__APPEND(Event)1753 ESX_VI__TEMPLATE__LIST__APPEND(Event)
1754 
1755 /* esxVI_Event_CastFromAnyType */
1756 ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(Event,
1757 {
1758     case esxVI_Type_Other:
1759         /* Just accept everything here */
1760         break;
1761 })
1762 
1763 /* esxVI_Event_CastListFromAnyType */
1764 ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(Event)
1765 
1766 /* esxVI_Event_Deserialize */
1767 ESX_VI__TEMPLATE__DESERIALIZE_EXTRA(Event, /* nothing */,
1768 {
1769     (*ptrptr)->_actualType =
1770       (char *)xmlGetNsProp(node, BAD_CAST "type",
1771                            BAD_CAST "http://www.w3.org/2001/XMLSchema-instance");
1772 
1773     if (!(*ptrptr)->_actualType) {
1774         virReportError(VIR_ERR_INTERNAL_ERROR,
1775                        _("%s is missing 'type' property"),
1776                        esxVI_Type_ToString((*ptrptr)->_type));
1777         goto failure;
1778     }
1779 },
1780 {
1781     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, key)
1782     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, chainId)
1783     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(DateTime, createdTime)
1784     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, userName)
1785     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(datacenter) /* FIXME */
1786     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(computeResource) /* FIXME */
1787     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(host) /* FIXME */
1788     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(VmEventArgument, vm)
1789     ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, fullFormattedMessage)
1790 
1791     /* Don't warn about unexpected properties */
1792     continue;
1793 })
1794 
1795 /* esxVI_Event_DeserializeList */
1796 ESX_VI__TEMPLATE__LIST__DESERIALIZE(Event)
1797 
1798 
1799 
1800 #include "esx_vi_types.generated.c"
1801 
1802 
1803 
1804 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1805  * VI Enum: VirtualMachinePowerState (Additions)
1806  */
1807 
1808 int
1809 esxVI_VirtualMachinePowerState_ConvertToLibvirt
1810   (esxVI_VirtualMachinePowerState powerState)
1811 {
1812     switch (powerState) {
1813       case esxVI_VirtualMachinePowerState_PoweredOff:
1814         return VIR_DOMAIN_SHUTOFF;
1815 
1816       case esxVI_VirtualMachinePowerState_PoweredOn:
1817         return VIR_DOMAIN_RUNNING;
1818 
1819       case esxVI_VirtualMachinePowerState_Suspended:
1820         return VIR_DOMAIN_PAUSED;
1821 
1822       case esxVI_VirtualMachinePowerState_Undefined:
1823       default:
1824         return VIR_DOMAIN_NOSTATE;
1825     }
1826 }
1827