1/*
2Copyright (c) 2017 VMware, Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package object
18
19import (
20	"context"
21	"reflect"
22
23	"github.com/vmware/govmomi/vim25/soap"
24	"github.com/vmware/govmomi/vim25/types"
25)
26
27func init() {
28	types.Add("ArrayOfVirtualDiskInfo", reflect.TypeOf((*arrayOfVirtualDiskInfo)(nil)).Elem())
29
30	types.Add("VirtualDiskInfo", reflect.TypeOf((*VirtualDiskInfo)(nil)).Elem())
31}
32
33type arrayOfVirtualDiskInfo struct {
34	VirtualDiskInfo []VirtualDiskInfo `xml:"VirtualDiskInfo,omitempty"`
35}
36
37type queryVirtualDiskInfoTaskRequest struct {
38	This           types.ManagedObjectReference  `xml:"_this"`
39	Name           string                        `xml:"name"`
40	Datacenter     *types.ManagedObjectReference `xml:"datacenter,omitempty"`
41	IncludeParents bool                          `xml:"includeParents"`
42}
43
44type queryVirtualDiskInfoTaskResponse struct {
45	Returnval types.ManagedObjectReference `xml:"returnval"`
46}
47
48type queryVirtualDiskInfoTaskBody struct {
49	Req         *queryVirtualDiskInfoTaskRequest  `xml:"urn:internalvim25 QueryVirtualDiskInfo_Task,omitempty"`
50	Res         *queryVirtualDiskInfoTaskResponse `xml:"urn:vim25 QueryVirtualDiskInfo_TaskResponse,omitempty"`
51	InternalRes *queryVirtualDiskInfoTaskResponse `xml:"urn:internalvim25 QueryVirtualDiskInfo_TaskResponse,omitempty"`
52	Err         *soap.Fault                       `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
53}
54
55func (b *queryVirtualDiskInfoTaskBody) Fault() *soap.Fault { return b.Err }
56
57func queryVirtualDiskInfoTask(ctx context.Context, r soap.RoundTripper, req *queryVirtualDiskInfoTaskRequest) (*queryVirtualDiskInfoTaskResponse, error) {
58	var reqBody, resBody queryVirtualDiskInfoTaskBody
59
60	reqBody.Req = req
61
62	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
63		return nil, err
64	}
65
66	if resBody.Res != nil {
67		return resBody.Res, nil
68	}
69
70	return resBody.InternalRes, nil
71}
72
73type VirtualDiskInfo struct {
74	Name     string `xml:"unit>name"`
75	DiskType string `xml:"diskType"`
76	Parent   string `xml:"parent,omitempty"`
77}
78
79func (m VirtualDiskManager) QueryVirtualDiskInfo(ctx context.Context, name string, dc *Datacenter, includeParents bool) ([]VirtualDiskInfo, error) {
80	req := queryVirtualDiskInfoTaskRequest{
81		This:           m.Reference(),
82		Name:           name,
83		IncludeParents: includeParents,
84	}
85
86	if dc != nil {
87		ref := dc.Reference()
88		req.Datacenter = &ref
89	}
90
91	res, err := queryVirtualDiskInfoTask(ctx, m.Client(), &req)
92	if err != nil {
93		return nil, err
94	}
95
96	info, err := NewTask(m.Client(), res.Returnval).WaitForResult(ctx, nil)
97	if err != nil {
98		return nil, err
99	}
100
101	return info.Result.(arrayOfVirtualDiskInfo).VirtualDiskInfo, nil
102}
103
104type createChildDiskTaskRequest struct {
105	This             types.ManagedObjectReference  `xml:"_this"`
106	ChildName        string                        `xml:"childName"`
107	ChildDatacenter  *types.ManagedObjectReference `xml:"childDatacenter,omitempty"`
108	ParentName       string                        `xml:"parentName"`
109	ParentDatacenter *types.ManagedObjectReference `xml:"parentDatacenter,omitempty"`
110	IsLinkedClone    bool                          `xml:"isLinkedClone"`
111}
112
113type createChildDiskTaskResponse struct {
114	Returnval types.ManagedObjectReference `xml:"returnval"`
115}
116
117type createChildDiskTaskBody struct {
118	Req         *createChildDiskTaskRequest  `xml:"urn:internalvim25 CreateChildDisk_Task,omitempty"`
119	Res         *createChildDiskTaskResponse `xml:"urn:vim25 CreateChildDisk_TaskResponse,omitempty"`
120	InternalRes *createChildDiskTaskResponse `xml:"urn:internalvim25 CreateChildDisk_TaskResponse,omitempty"`
121	Err         *soap.Fault                  `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
122}
123
124func (b *createChildDiskTaskBody) Fault() *soap.Fault { return b.Err }
125
126func createChildDiskTask(ctx context.Context, r soap.RoundTripper, req *createChildDiskTaskRequest) (*createChildDiskTaskResponse, error) {
127	var reqBody, resBody createChildDiskTaskBody
128
129	reqBody.Req = req
130
131	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
132		return nil, err
133	}
134
135	if resBody.Res != nil {
136		return resBody.Res, nil // vim-version <= 6.5
137	}
138
139	return resBody.InternalRes, nil // vim-version >= 6.7
140}
141
142func (m VirtualDiskManager) CreateChildDisk(ctx context.Context, parent string, pdc *Datacenter, name string, dc *Datacenter, linked bool) (*Task, error) {
143	req := createChildDiskTaskRequest{
144		This:          m.Reference(),
145		ChildName:     name,
146		ParentName:    parent,
147		IsLinkedClone: linked,
148	}
149
150	if dc != nil {
151		ref := dc.Reference()
152		req.ChildDatacenter = &ref
153	}
154
155	if pdc != nil {
156		ref := pdc.Reference()
157		req.ParentDatacenter = &ref
158	}
159
160	res, err := createChildDiskTask(ctx, m.Client(), &req)
161	if err != nil {
162		return nil, err
163	}
164
165	return NewTask(m.Client(), res.Returnval), nil
166}
167