github.com/vmware/govmomi@v0.37.1/vapi/vcenter/vcenter_ovf.go (about) 1 /* 2 Copyright (c) 2018 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vcenter 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 24 "github.com/vmware/govmomi/vapi/internal" 25 "github.com/vmware/govmomi/vapi/rest" 26 "github.com/vmware/govmomi/vim25/types" 27 ) 28 29 // AdditionalParams are additional OVF parameters which can be specified for a deployment target. 30 // This structure is a union where based on Type, only one of each commented section will be set. 31 type AdditionalParams struct { 32 Class string `json:"@class"` 33 Type string `json:"type"` 34 35 // DeploymentOptionParams 36 SelectedKey string `json:"selected_key,omitempty"` 37 DeploymentOptions []DeploymentOption `json:"deployment_options,omitempty"` 38 39 // ExtraConfigs 40 ExtraConfig []ExtraConfig `json:"extra_configs,omitempty"` 41 42 // PropertyParams 43 Properties []Property `json:"properties,omitempty"` 44 45 // SizeParams 46 ApproximateSparseDeploymentSize int64 `json:"approximate_sparse_deployment_size,omitempty"` 47 VariableDiskSize bool `json:"variable_disk_size,omitempty"` 48 ApproximateDownloadSize int64 `json:"approximate_download_size,omitempty"` 49 ApproximateFlatDeploymentSize int64 `json:"approximate_flat_deployment_size,omitempty"` 50 51 // IpAllocationParams 52 SupportedAllocationScheme []string `json:"supported_allocation_scheme,omitempty"` 53 SupportedIPProtocol []string `json:"supported_ip_protocol,omitempty"` 54 SupportedIPAllocationPolicy []string `json:"supported_ip_allocation_policy,omitempty"` 55 IPAllocationPolicy string `json:"ip_allocation_policy,omitempty"` 56 IPProtocol string `json:"ip_protocol,omitempty"` 57 58 // UnknownSections 59 UnknownSections []UnknownSection `json:"unknown_sections,omitempty"` 60 } 61 62 const ( 63 ClassDeploymentOptionParams = "com.vmware.vcenter.ovf.deployment_option_params" 64 ClassPropertyParams = "com.vmware.vcenter.ovf.property_params" 65 TypeDeploymentOptionParams = "DeploymentOptionParams" 66 TypeExtraConfigParams = "ExtraConfigParams" 67 TypeIPAllocationParams = "IpAllocationParams" 68 TypePropertyParams = "PropertyParams" 69 TypeSizeParams = "SizeParams" 70 ) 71 72 // DeploymentOption contains the information about a deployment option as defined in the OVF specification 73 type DeploymentOption struct { 74 Key string `json:"key,omitempty"` 75 Label string `json:"label,omitempty"` 76 Description string `json:"description,omitempty"` 77 DefaultChoice bool `json:"default_choice,omitempty"` 78 } 79 80 // ExtraConfig contains information about a vmw:ExtraConfig OVF element 81 type ExtraConfig struct { 82 Key string `json:"key,omitempty"` 83 Value string `json:"value,omitempty"` 84 VirtualSystemID string `json:"virtual_system_id,omitempty"` 85 } 86 87 // Property contains information about a property in an OVF package 88 type Property struct { 89 Category string `json:"category,omitempty"` 90 ClassID string `json:"class_id,omitempty"` 91 Description string `json:"description,omitempty"` 92 ID string `json:"id,omitempty"` 93 InstanceID string `json:"instance_id,omitempty"` 94 Label string `json:"label,omitempty"` 95 Type string `json:"type,omitempty"` 96 UIOptional bool `json:"ui_optional,omitempty"` 97 Value string `json:"value,omitempty"` 98 } 99 100 // UnknownSection contains information about an unknown section in an OVF package 101 type UnknownSection struct { 102 Tag string `json:"tag,omitempty"` 103 Info string `json:"info,omitempty"` 104 } 105 106 // NetworkMapping specifies the target network to use for sections of type ovf:NetworkSection in the OVF descriptor 107 type NetworkMapping struct { 108 Key string `json:"key"` 109 Value string `json:"value"` 110 } 111 112 // StorageGroupMapping defines the storage deployment target and storage provisioning type for a section of type vmw:StorageGroupSection in the OVF descriptor 113 type StorageGroupMapping struct { 114 Type string `json:"type"` 115 StorageProfileID string `json:"storage_profile_id,omitempty"` 116 DatastoreID string `json:"datastore_id,omitempty"` 117 Provisioning string `json:"provisioning,omitempty"` 118 } 119 120 // StorageMapping specifies the target storage to use for sections of type vmw:StorageGroupSection in the OVF descriptor 121 type StorageMapping struct { 122 Key string `json:"key"` 123 Value StorageGroupMapping `json:"value"` 124 } 125 126 // VmConfigSpec defines the optional virtual machine configuration settings used when deploying an OVF template 127 type VmConfigSpec struct { 128 Provider string `json:"provider"` 129 XML string `json:"xml"` 130 } 131 132 // DeploymentSpec is the deployment specification for the deployment 133 type DeploymentSpec struct { 134 Name string `json:"name,omitempty"` 135 Annotation string `json:"annotation,omitempty"` 136 AcceptAllEULA bool `json:"accept_all_EULA,omitempty"` 137 NetworkMappings []NetworkMapping `json:"network_mappings,omitempty"` 138 StorageMappings []StorageMapping `json:"storage_mappings,omitempty"` 139 StorageProvisioning string `json:"storage_provisioning,omitempty"` 140 StorageProfileID string `json:"storage_profile_id,omitempty"` 141 Locale string `json:"locale,omitempty"` 142 Flags []string `json:"flags,omitempty"` 143 AdditionalParams []AdditionalParams `json:"additional_parameters,omitempty"` 144 DefaultDatastoreID string `json:"default_datastore_id,omitempty"` 145 VmConfigSpec *VmConfigSpec `json:"vm_config_spec,omitempty"` 146 } 147 148 // Target is the target for the deployment 149 type Target struct { 150 ResourcePoolID string `json:"resource_pool_id,omitempty"` 151 HostID string `json:"host_id,omitempty"` 152 FolderID string `json:"folder_id,omitempty"` 153 } 154 155 // Deploy contains the information to start the deployment of a library OVF 156 type Deploy struct { 157 DeploymentSpec `json:"deployment_spec,omitempty"` 158 Target `json:"target,omitempty"` 159 } 160 161 // Error is a SERVER error 162 type Error struct { 163 Class string `json:"@class,omitempty"` 164 Messages []rest.LocalizableMessage `json:"messages,omitempty"` 165 } 166 167 // ParseIssue is a parse issue struct 168 type ParseIssue struct { 169 Category string `json:"@classcategory,omitempty"` 170 File string `json:"file,omitempty"` 171 LineNumber int64 `json:"line_number,omitempty"` 172 ColumnNumber int64 `json:"column_number,omitempty"` 173 Message rest.LocalizableMessage `json:"message,omitempty"` 174 } 175 176 // OVFError is a list of errors from create or deploy 177 type OVFError struct { 178 Category string `json:"category,omitempty"` 179 Error *Error `json:"error,omitempty"` 180 Issues []ParseIssue `json:"issues,omitempty"` 181 Message *rest.LocalizableMessage `json:"message,omitempty"` 182 } 183 184 // ResourceID is a managed object reference for a deployed resource. 185 type ResourceID struct { 186 Type string `json:"type,omitempty"` 187 Value string `json:"id,omitempty"` 188 } 189 190 // DeploymentError is an error that occurs when deploying and OVF from 191 // a library item. 192 type DeploymentError struct { 193 Errors []OVFError `json:"errors,omitempty"` 194 } 195 196 // Error implements the error interface 197 func (e *DeploymentError) Error() string { 198 msg := "" 199 if len(e.Errors) != 0 { 200 err := e.Errors[0] 201 if err.Message != nil { 202 msg = err.Message.DefaultMessage 203 } else if err.Error != nil && len(err.Error.Messages) != 0 { 204 msg = err.Error.Messages[0].DefaultMessage 205 } 206 } 207 if msg == "" { 208 msg = fmt.Sprintf("%#v", e) 209 } 210 return "deploy error: " + msg 211 } 212 213 // LibraryTarget specifies a Library or Library item 214 type LibraryTarget struct { 215 LibraryID string `json:"library_id,omitempty"` 216 LibraryItemID string `json:"library_item_id,omitempty"` 217 } 218 219 // CreateSpec info used to create an OVF package from a VM 220 type CreateSpec struct { 221 Description string `json:"description,omitempty"` 222 Name string `json:"name,omitempty"` 223 Flags []string `json:"flags,omitempty"` 224 } 225 226 // OVF data used by CreateOVF 227 type OVF struct { 228 Spec CreateSpec `json:"create_spec"` 229 Source ResourceID `json:"source"` 230 Target LibraryTarget `json:"target"` 231 } 232 233 // CreateResult used for decoded a CreateOVF response 234 type CreateResult struct { 235 Succeeded bool `json:"succeeded,omitempty"` 236 ID string `json:"ovf_library_item_id,omitempty"` 237 Error *DeploymentError `json:"error,omitempty"` 238 } 239 240 // Deployment is the results from issuing a library OVF deployment 241 type Deployment struct { 242 Succeeded bool `json:"succeeded,omitempty"` 243 ResourceID *ResourceID `json:"resource_id,omitempty"` 244 Error *DeploymentError `json:"error,omitempty"` 245 } 246 247 // FilterRequest contains the information to start a vcenter filter call 248 type FilterRequest struct { 249 Target `json:"target,omitempty"` 250 } 251 252 // FilterResponse returns information from the vcenter filter call 253 type FilterResponse struct { 254 EULAs []string `json:"EULAs,omitempty"` 255 AdditionalParams []AdditionalParams `json:"additional_params,omitempty"` 256 Annotation string `json:"Annotation,omitempty"` 257 Name string `json:"name,omitempty"` 258 Networks []string `json:"Networks,omitempty"` 259 StorageGroups []string `json:"storage_groups,omitempty"` 260 } 261 262 // Manager extends rest.Client, adding content library related methods. 263 type Manager struct { 264 *rest.Client 265 } 266 267 // NewManager creates a new Manager instance with the given client. 268 func NewManager(client *rest.Client) *Manager { 269 return &Manager{ 270 Client: client, 271 } 272 } 273 274 // CreateOVF creates a library OVF item in content library from an existing VM 275 func (c *Manager) CreateOVF(ctx context.Context, ovf OVF) (string, error) { 276 if ovf.Source.Type == "" { 277 ovf.Source.Type = "VirtualMachine" 278 } 279 url := c.Resource(internal.VCenterOVFLibraryItem) 280 var res CreateResult 281 err := c.Do(ctx, url.Request(http.MethodPost, ovf), &res) 282 if err != nil { 283 return "", err 284 } 285 if res.Succeeded { 286 return res.ID, nil 287 } 288 return "", res.Error 289 } 290 291 // DeployLibraryItem deploys a library OVF 292 func (c *Manager) DeployLibraryItem(ctx context.Context, libraryItemID string, deploy Deploy) (*types.ManagedObjectReference, error) { 293 url := c.Resource(internal.VCenterOVFLibraryItem).WithID(libraryItemID).WithAction("deploy") 294 var res Deployment 295 err := c.Do(ctx, url.Request(http.MethodPost, deploy), &res) 296 if err != nil { 297 return nil, err 298 } 299 if res.Succeeded { 300 return &types.ManagedObjectReference{ 301 Type: res.ResourceID.Type, 302 Value: res.ResourceID.Value, 303 }, nil 304 } 305 return nil, res.Error 306 } 307 308 // FilterLibraryItem deploys a library OVF 309 func (c *Manager) FilterLibraryItem(ctx context.Context, libraryItemID string, filter FilterRequest) (FilterResponse, error) { 310 url := c.Resource(internal.VCenterOVFLibraryItem).WithID(libraryItemID).WithAction("filter") 311 var res FilterResponse 312 return res, c.Do(ctx, url.Request(http.MethodPost, filter), &res) 313 }