github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/vsphere/vsphereclient/client.go (about) 1 package vsphereclient 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/url" 7 "path/filepath" 8 "strings" 9 10 "github.com/sirupsen/logrus" 11 "github.com/emc-advanced-dev/pkg/errors" 12 "github.com/solo-io/unik/pkg/types" 13 unikutil "github.com/solo-io/unik/pkg/util" 14 "github.com/vmware/govmomi" 15 "github.com/vmware/govmomi/find" 16 "golang.org/x/net/context" 17 ) 18 19 type VsphereClient struct { 20 u *url.URL 21 ds string 22 dc string 23 } 24 25 func NewVsphereClient(u *url.URL, datastore, datacenter string) *VsphereClient { 26 return &VsphereClient{ 27 u: u, 28 ds: datastore, 29 dc: datacenter, 30 } 31 } 32 33 func (vc *VsphereClient) newGovmomiClient() (*govmomi.Client, error) { 34 c, err := govmomi.NewClient(context.TODO(), vc.u, true) 35 if err != nil { 36 return nil, errors.New("creating new govmovi client", err) 37 } 38 return c, nil 39 } 40 41 func (vc *VsphereClient) newGovmomiFinder() (*find.Finder, error) { 42 c, err := vc.newGovmomiClient() 43 if err != nil { 44 return nil, err 45 } 46 f := find.NewFinder(c.Client, true) 47 48 // Find one and only datacenter 49 dc, err := f.DefaultDatacenter(context.TODO()) 50 if err != nil { 51 return nil, errors.New("finding default datacenter", err) 52 } 53 54 // Make future calls local to this datacenter 55 f.SetDatacenter(dc) 56 return f, nil 57 } 58 59 func (vc *VsphereClient) GetVmByUuid(uuid string) (*VirtualMachine, error) { 60 61 container := unikutil.NewContainer("vsphere-client") 62 args := []string{ 63 "govc", 64 "vm.info", 65 "-k", 66 "-u", formatUrl(vc.u), 67 "--json", 68 "--vm.uuid=" + uuid, 69 } 70 logrus.WithField("command", args).Debugf("running command") 71 out, err := container.CombinedOutput(args...) 72 if err != nil { 73 return nil, errors.New("failed running govc vm.info "+uuid, err) 74 } 75 var vm VmInfo 76 if err := json.Unmarshal(out, &vm); err != nil { 77 return nil, errors.New("unmarshalling json: "+string(out), err) 78 } 79 if len(vm.VirtualMachines) < 1 { 80 return nil, errors.New("returned virtualmachines had len 0; does vm exist? "+string(out), nil) 81 } 82 return &vm.VirtualMachines[0], nil 83 } 84 85 func (vc *VsphereClient) GetVm(name string) (*VirtualMachine, error) { 86 87 container := unikutil.NewContainer("vsphere-client") 88 args := []string{ 89 "govc", 90 "vm.info", 91 "-k", 92 "-u", formatUrl(vc.u), 93 "--json", 94 name, 95 } 96 logrus.WithField("command", args).Debugf("running command") 97 out, err := container.CombinedOutput(args...) 98 if err != nil { 99 return nil, errors.New("failed running govc vm.info "+name, err) 100 } 101 var vm VmInfo 102 if err := json.Unmarshal(out, &vm); err != nil { 103 return nil, errors.New("unmarshalling json: "+string(out), err) 104 } 105 if len(vm.VirtualMachines) < 1 { 106 return nil, errors.New("returned virtualmachines had len 0; does vm exist? "+string(out), nil) 107 } 108 return &vm.VirtualMachines[0], nil 109 } 110 111 func (vc *VsphereClient) GetVmIp(vmName string) (string, error) { 112 vm, err := vc.GetVm(vmName) 113 if err != nil { 114 return "", errors.New("getting vsphere vm", err) 115 } 116 return vm.Guest.IPAddress, nil 117 } 118 119 func (vc *VsphereClient) CreateVm(vmName string, memoryMb int, networkType types.VsphereNetworkType, networkLabel string) error { 120 121 container := unikutil.NewContainer("vsphere-client") 122 args := []string{ 123 "govc", 124 "vm.create", 125 "-k", 126 "-u", formatUrl(vc.u), 127 "--force=true", 128 fmt.Sprintf("--m=%v", memoryMb), 129 "--on=false", 130 "-ds", vc.ds, 131 fmt.Sprintf("-net.adapter=%s", networkType), 132 } 133 if networkLabel != "" { 134 args = append(args, fmt.Sprintf("-net=%s", networkLabel)) 135 } 136 args = append(args, vmName) 137 138 if err := container.Run(args...); err != nil { 139 return errors.New("failed running govc vm.create "+vmName, err) 140 } 141 return nil 142 } 143 144 func (vc *VsphereClient) DestroyVm(vmName string) error { 145 146 container := unikutil.NewContainer("vsphere-client") 147 args := []string{ 148 "govc", 149 "vm.destroy", 150 "-k", 151 "-u", formatUrl(vc.u), 152 vmName, 153 } 154 if err := container.Run(args...); err != nil { 155 return errors.New("failed running govc vm.destroy "+vmName, err) 156 } 157 return nil 158 } 159 160 func (vc *VsphereClient) Mkdir(folder string) error { 161 162 container := unikutil.NewContainer("vsphere-client") 163 args := []string{ 164 "govc", 165 "datastore.mkdir", 166 "-ds", vc.ds, 167 "-k", 168 "-u", formatUrl(vc.u), 169 folder, 170 } 171 if err := container.Run(args...); err != nil { 172 logrus.WithError(err).Warnf("failed running govc datastore.mkdir " + folder) 173 } 174 return nil 175 } 176 177 func (vc *VsphereClient) Rmdir(folder string) error { 178 179 container := unikutil.NewContainer("vsphere-client") 180 args := []string{ 181 "govc", 182 "datastore.rm", 183 "-ds", vc.ds, 184 "-k", 185 "-u", formatUrl(vc.u), 186 folder, 187 } 188 if err := container.Run(args...); err != nil { 189 return errors.New("failed running govc datastore.rm "+folder, err) 190 } 191 return nil 192 } 193 194 func (vc *VsphereClient) ImportVmdk(vmdkPath, remoteFolder string) error { 195 vmdkFolder, err := filepath.Abs(filepath.Dir(vmdkPath)) 196 if err != nil { 197 return errors.New("getting aboslute path for "+vmdkFolder, err) 198 } 199 200 container := unikutil.NewContainer("vsphere-client").WithVolume(vmdkFolder, vmdkFolder) 201 args := []string{ 202 "govc", 203 "import.vmdk", 204 "-ds", vc.ds, 205 "-k", 206 "-u", formatUrl(vc.u), 207 vmdkPath, 208 remoteFolder, 209 } 210 if err := container.Run(args...); err != nil { 211 return errors.New("failed running govc import.vmdk "+remoteFolder, err) 212 } 213 return nil 214 } 215 216 func (vc *VsphereClient) UploadFile(srcFile, dest string) error { 217 srcDir := filepath.Dir(srcFile) 218 219 container := unikutil.NewContainer("vsphere-client").WithVolume(srcDir, srcDir) 220 args := []string{ 221 "govc", 222 "datastore.upload", 223 "-ds", vc.ds, 224 "-k", 225 "-u", formatUrl(vc.u), 226 srcFile, 227 dest, 228 } 229 if err := container.Run(args...); err != nil { 230 return errors.New("failed running govc datastore.upload", err) 231 } 232 return nil 233 } 234 235 func (vc *VsphereClient) DownloadFile(remoteFile, localFile string) error { 236 localDir := filepath.Dir(localFile) 237 238 container := unikutil.NewContainer("vsphere-client").WithVolume(localDir, localDir) 239 args := []string{ 240 "govc", 241 "datastore.download", 242 "-ds", vc.ds, 243 "-k", 244 "-u", formatUrl(vc.u), 245 remoteFile, 246 localFile, 247 } 248 if err := container.Run(args...); err != nil { 249 return errors.New("failed running govc datastore.upload", err) 250 } 251 return nil 252 } 253 254 func (vc *VsphereClient) CopyVmdk(src, dest string) error { 255 password, _ := vc.u.User.Password() 256 257 container := unikutil.NewContainer("vsphere-client") 258 args := []string{ 259 "java", 260 "-jar", 261 "/vsphere-client.jar", 262 "CopyVirtualDisk", 263 vc.u.String(), 264 vc.u.User.Username(), 265 password, 266 vc.dc, 267 "[" + vc.ds + "] " + src, 268 "[" + vc.ds + "] " + dest, 269 } 270 if err := container.Run(args...); err != nil { 271 return errors.New("failed running vsphere-client.jar CopyVirtualDisk "+src+" "+dest, err) 272 } 273 return nil 274 } 275 276 func (vc *VsphereClient) CopyFile(src, dest string) error { 277 password, _ := vc.u.User.Password() 278 container := unikutil.NewContainer("vsphere-client") 279 args := []string{ 280 "java", 281 "-jar", 282 "/vsphere-client.jar", 283 "CopyFile", 284 vc.u.String(), 285 vc.u.User.Username(), 286 password, 287 vc.dc, 288 "[" + vc.ds + "] " + src, 289 "[" + vc.ds + "] " + dest, 290 } 291 if err := container.Run(args...); err != nil { 292 lastSlash := strings.LastIndex(dest, "/") 293 directory := "/" 294 file := dest[lastSlash+1:] 295 if lastSlash != -1 { 296 directory += dest[0:lastSlash] 297 file = dest[lastSlash+1:] 298 } 299 files, err := vc.Ls(directory) 300 if err != nil { 301 return errors.New("failed running vsphere-client.jar CopyFile "+src+" "+dest, err) 302 } 303 if !unikutil.StringInSlice(file, files) { 304 return errors.New("failed running vsphere-client.jar CopyFile "+src+" "+dest, err) 305 } 306 } 307 return nil 308 } 309 310 func (vc *VsphereClient) Ls(dir string) ([]string, error) { 311 312 container := unikutil.NewContainer("vsphere-client") 313 args := []string{ 314 "govc", 315 "datastore.ls", 316 "-ds", vc.ds, 317 "-k", 318 "-u", formatUrl(vc.u), 319 dir, 320 } 321 out, err := container.Output(args...) 322 if err != nil { 323 return nil, errors.New("failed running govc datastore.ls "+dir, err) 324 } 325 split := strings.Split(string(out), "\n") 326 contents := []string{} 327 for _, content := range split { 328 if content != "" { 329 contents = append(contents, content) 330 } 331 } 332 return contents, nil 333 } 334 335 func (vc *VsphereClient) PowerOnVm(vmName string) error { 336 337 container := unikutil.NewContainer("vsphere-client") 338 args := []string{ 339 "govc", 340 "vm.power", 341 "--on=true", 342 "-k", 343 "-u", formatUrl(vc.u), 344 vmName, 345 } 346 if err := container.Run(args...); err != nil { 347 return errors.New("failed running govc vm.power (on)", err) 348 } 349 return nil 350 } 351 352 func (vc *VsphereClient) PowerOffVm(vmName string) error { 353 354 container := unikutil.NewContainer("vsphere-client") 355 args := []string{ 356 "govc", 357 "vm.power", 358 "--off=true", 359 "-k", 360 "-u", formatUrl(vc.u), 361 vmName, 362 } 363 if err := container.Run(args...); err != nil { 364 return errors.New("failed running govc vm.power (off)", err) 365 } 366 return nil 367 } 368 369 func (vc *VsphereClient) AttachDisk(vmName, vmdkPath string, controllerKey int, deviceType types.StorageDriver) error { 370 password, _ := vc.u.User.Password() 371 372 container := unikutil.NewContainer("vsphere-client") 373 args := []string{ 374 "java", 375 "-jar", 376 "/vsphere-client.jar", 377 "VmAttachDisk", 378 vc.u.String(), 379 vc.u.User.Username(), 380 password, 381 vmName, 382 "[" + vc.ds + "] " + vmdkPath, 383 string(deviceType), 384 fmt.Sprintf("%v", controllerKey), 385 } 386 if err := container.Run(args...); err != nil { 387 return errors.New("failed running vsphere-client.jar AttachVmdk", err) 388 } 389 return nil 390 } 391 392 func (vc *VsphereClient) DetachDisk(vmName string, controllerKey int, deviceType types.StorageDriver) error { 393 password, _ := vc.u.User.Password() 394 395 container := unikutil.NewContainer("vsphere-client") 396 args := []string{ 397 "java", 398 "-jar", 399 "/vsphere-client.jar", 400 "VmDetachDisk", 401 vc.u.String(), 402 vc.u.User.Username(), 403 password, 404 vmName, 405 string(deviceType), 406 fmt.Sprintf("%v", controllerKey), 407 } 408 if err := container.Run(args...); err != nil { 409 return errors.New("failed running vsphere-client.jar DetachVmdk", err) 410 } 411 return nil 412 } 413 414 func formatUrl(u *url.URL) string { 415 return "https://" + strings.TrimPrefix(strings.TrimPrefix(u.String(), "http://"), "https://") 416 }