github.com/vmware/govmomi@v0.43.0/govc/library/deploy.go (about) 1 /* 2 Copyright (c) 2019-2024 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 library 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 24 "github.com/vmware/govmomi/govc/cli" 25 "github.com/vmware/govmomi/govc/flags" 26 "github.com/vmware/govmomi/govc/importx" 27 "github.com/vmware/govmomi/object" 28 "github.com/vmware/govmomi/vapi/library" 29 "github.com/vmware/govmomi/vapi/vcenter" 30 "github.com/vmware/govmomi/vim25/types" 31 ) 32 33 type deploy struct { 34 *flags.DatastoreFlag 35 *flags.ResourcePoolFlag 36 *flags.HostSystemFlag 37 *flags.FolderFlag 38 *flags.StorageProfileFlag 39 *importx.OptionsFlag 40 41 config string 42 } 43 44 func init() { 45 cli.Register("library.deploy", &deploy{}) 46 } 47 48 func (cmd *deploy) Register(ctx context.Context, f *flag.FlagSet) { 49 cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx) 50 cmd.DatastoreFlag.Register(ctx, f) 51 52 cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx) 53 cmd.ResourcePoolFlag.Register(ctx, f) 54 55 cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx) 56 cmd.HostSystemFlag.Register(ctx, f) 57 58 cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx) 59 cmd.FolderFlag.Register(ctx, f) 60 61 cmd.StorageProfileFlag, ctx = flags.NewStorageProfileFlag(ctx) 62 cmd.StorageProfileFlag.Register(ctx, f) 63 64 cmd.OptionsFlag = new(importx.OptionsFlag) 65 cmd.OptionsFlag.Register(ctx, f) 66 67 if cli.ShowUnreleased() { 68 f.StringVar(&cmd.config, "config", "", "VM config spec") 69 } 70 } 71 72 func (cmd *deploy) Process(ctx context.Context) error { 73 if err := cmd.DatastoreFlag.Process(ctx); err != nil { 74 return err 75 } 76 if err := cmd.ResourcePoolFlag.Process(ctx); err != nil { 77 return err 78 } 79 if err := cmd.HostSystemFlag.Process(ctx); err != nil { 80 return err 81 } 82 if err := cmd.FolderFlag.Process(ctx); err != nil { 83 return err 84 } 85 if err := cmd.StorageProfileFlag.Process(ctx); err != nil { 86 return err 87 } 88 return cmd.OptionsFlag.Process(ctx) 89 } 90 91 func (cmd *deploy) Usage() string { 92 return "TEMPLATE [NAME]" 93 } 94 95 func (cmd *deploy) Description() string { 96 return `Deploy library OVF template. 97 98 Examples: 99 govc library.deploy /library_name/ovf_template vm_name 100 govc library.export /library_name/ovf_template/*.ovf # save local copy of .ovf 101 govc import.spec *.ovf > deploy.json # generate options from .ovf 102 # edit deploy.json as needed 103 govc library.deploy -options deploy.json /library_name/ovf_template` 104 } 105 106 func (cmd *deploy) Run(ctx context.Context, f *flag.FlagSet) error { 107 if f.NArg() > 2 { 108 return flag.ErrHelp 109 } 110 path := f.Arg(0) 111 name := f.Arg(1) 112 113 if name == "" && cmd.Options.Name != nil { 114 name = *cmd.Options.Name 115 } 116 117 vc, err := cmd.DatastoreFlag.Client() 118 if err != nil { 119 return err 120 } 121 cmd.FolderFlag.KeepAlive(vc) 122 123 c, err := cmd.DatastoreFlag.RestClient() 124 if err != nil { 125 return err 126 } 127 cmd.FolderFlag.KeepAlive(c) 128 129 m := vcenter.NewManager(c) 130 131 item, err := flags.ContentLibraryItem(ctx, c, path) 132 if err != nil { 133 return err 134 } 135 136 ds, err := cmd.DatastoreIfSpecified() 137 if err != nil { 138 return err 139 } 140 rp, err := cmd.ResourcePoolIfSpecified() 141 if err != nil { 142 return err 143 } 144 host, err := cmd.HostSystemIfSpecified() 145 if err != nil { 146 return err 147 } 148 hostID := "" 149 if rp == nil { 150 if host == nil { 151 rp, err = cmd.ResourcePoolFlag.ResourcePool() 152 } else { 153 rp, err = host.ResourcePool(ctx) 154 hostID = host.Reference().Value 155 } 156 if err != nil { 157 return err 158 } 159 } 160 folder, err := cmd.Folder() 161 if err != nil { 162 return err 163 } 164 finder, err := cmd.FolderFlag.Finder(false) 165 if err != nil { 166 return err 167 } 168 169 var networks []vcenter.NetworkMapping 170 for _, net := range cmd.Options.NetworkMapping { 171 if net.Network == "" { 172 continue 173 } 174 obj, err := finder.Network(ctx, net.Network) 175 if err != nil { 176 return err 177 } 178 networks = append(networks, vcenter.NetworkMapping{ 179 Key: net.Name, 180 Value: obj.Reference().Value, 181 }) 182 } 183 184 var properties []vcenter.Property 185 for _, prop := range cmd.Options.PropertyMapping { 186 properties = append(properties, vcenter.Property{ 187 ID: prop.Key, 188 Value: prop.Value, 189 }) 190 } 191 192 dsID := "" 193 if ds != nil { 194 dsID = ds.Reference().Value 195 } 196 197 cmd.FolderFlag.Log("Deploying library item...\n") 198 199 var ref *types.ManagedObjectReference 200 201 profile, err := cmd.StorageProfile(ctx) 202 if err != nil { 203 return err 204 } 205 206 switch item.Type { 207 case library.ItemTypeOVF: 208 deploy := vcenter.Deploy{ 209 DeploymentSpec: vcenter.DeploymentSpec{ 210 Name: name, 211 DefaultDatastoreID: dsID, 212 AcceptAllEULA: true, 213 Annotation: cmd.Options.Annotation, 214 AdditionalParams: []vcenter.AdditionalParams{ 215 { 216 Class: vcenter.ClassDeploymentOptionParams, 217 Type: vcenter.TypeDeploymentOptionParams, 218 SelectedKey: cmd.Options.Deployment, 219 }, 220 { 221 Class: vcenter.ClassPropertyParams, 222 Type: vcenter.TypePropertyParams, 223 SelectedKey: cmd.Options.Deployment, 224 Properties: properties, 225 }, 226 }, 227 NetworkMappings: networks, 228 StorageProvisioning: cmd.Options.DiskProvisioning, 229 StorageProfileID: profile, 230 }, 231 Target: vcenter.Target{ 232 ResourcePoolID: rp.Reference().Value, 233 HostID: hostID, 234 FolderID: folder.Reference().Value, 235 }, 236 } 237 238 if cmd.config != "" { 239 deploy.VmConfigSpec = &vcenter.VmConfigSpec{ 240 Provider: "XML", 241 XML: cmd.config, 242 } 243 } 244 245 ref, err = m.DeployLibraryItem(ctx, item.ID, deploy) 246 if err != nil { 247 return err 248 } 249 case library.ItemTypeVMTX: 250 storage := &vcenter.DiskStorage{ 251 Datastore: dsID, 252 StoragePolicy: &vcenter.StoragePolicy{ 253 Policy: profile, 254 Type: "USE_SOURCE_POLICY", 255 }, 256 } 257 if profile != "" { 258 storage.StoragePolicy.Type = "USE_SPECIFIED_POLICY" 259 } 260 261 deploy := vcenter.DeployTemplate{ 262 Name: name, 263 Description: cmd.Options.Annotation, 264 DiskStorage: storage, 265 VMHomeStorage: storage, 266 Placement: &vcenter.Placement{ 267 ResourcePool: rp.Reference().Value, 268 Host: hostID, 269 Folder: folder.Reference().Value, 270 }, 271 } 272 ref, err = m.DeployTemplateLibraryItem(ctx, item.ID, deploy) 273 if err != nil { 274 return err 275 } 276 default: 277 return fmt.Errorf("unsupported library item type: %s", item.Type) 278 } 279 280 obj, err := finder.ObjectReference(ctx, *ref) 281 if err != nil { 282 return err 283 } 284 285 vm := obj.(*object.VirtualMachine) 286 287 return cmd.Deploy(vm, cmd.FolderFlag.OutputFlag) 288 }