github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/provider/vmware/client.go (about) 1 package vmware 2 3 import ( 4 "strings" 5 6 "github.com/juju/errors" 7 "github.com/vmware/govmomi" 8 "github.com/vmware/govmomi/find" 9 "github.com/vmware/govmomi/vim25/mo" 10 11 "github.com/juju/juju/instance" 12 ) 13 14 const ( 15 metadataKeyIsState = "juju-is-state" 16 ) 17 18 type client struct { 19 connection *govmomi.Client 20 datacenter *govmomi.Datacenter 21 datastore *govmomi.Datastore 22 resourcePool *govmomi.ResourcePool 23 finder *find.Finder 24 } 25 26 func newClient(ecfg *environConfig) (*client, error) { 27 url, err := ecfg.url() 28 if err != nil { 29 return nil, err 30 } 31 connection, err := govmomi.NewClient(*url, true) 32 if err != nil { 33 return nil, errors.Trace(err) 34 } 35 36 finder := find.NewFinder(connection, true) 37 datacenter, err := finder.Datacenter(ecfg.datacenter()) 38 if err != nil { 39 return nil, errors.Trace(err) 40 } 41 finder.SetDatacenter(datacenter) 42 datastore, err := finder.Datastore(ecfg.datastore()) 43 if err != nil { 44 return nil, errors.Trace(err) 45 } 46 resourcePool, err := finder.ResourcePool(ecfg.resourcePool()) 47 if err != nil { 48 return nil, errors.Trace(err) 49 } 50 return &client{ 51 connection: connection, 52 datacenter: datacenter, 53 datastore: datastore, 54 resourcePool: resourcePool, 55 finder: finder, 56 }, nil 57 } 58 59 func (c *client) CreateInstance(machineID string, hwc *instance.HardwareCharacteristics, img *OvfFileMetadata, userData []byte, sshKey string, isState bool) (*mo.VirtualMachine, error) { 60 61 manager := &ovfImportManager{client: c} 62 vm, err := manager.importOvf(machineID, hwc, img, userData, sshKey, isState) 63 if err != nil { 64 return nil, errors.Annotatef(err, "Failed to import ovf file") 65 } 66 task, err := vm.PowerOn() 67 if err != nil { 68 return nil, errors.Trace(err) 69 } 70 taskInfo, err := task.WaitForResult(nil) 71 if err != nil { 72 return nil, errors.Trace(err) 73 } 74 var res mo.VirtualMachine 75 err = c.connection.Properties(*taskInfo.Entity, nil, &res) 76 if err != nil { 77 return nil, errors.Trace(err) 78 } 79 return &res, nil 80 } 81 82 func (c *client) RemoveInstances(ids ...string) error { 83 var firstError error 84 tasks := make([]*govmomi.Task, len(ids)) 85 for _, id := range ids { 86 vm, err := c.finder.VirtualMachine(id) 87 if err != nil && firstError == nil { 88 firstError = err 89 continue 90 } 91 task, err := vm.Destroy() 92 if err != nil && firstError == nil { 93 firstError = err 94 continue 95 } 96 //We don't wait for task completeon here. Instead we want to run all tasks as soon as posible 97 //and then wait for them all. such aproach will run all tasks in parallel 98 tasks = append(tasks, task) 99 } 100 101 for _, task := range tasks { 102 _, err := task.WaitForResult(nil) 103 if err != nil && firstError == nil { 104 firstError = err 105 continue 106 } 107 } 108 return errors.Annotatef(firstError, "Failed while remowing instances") 109 } 110 111 func (c *client) Instances(prefix string) ([]*mo.VirtualMachine, error) { 112 items, err := c.finder.VirtualMachineList("*") 113 if err != nil { 114 return nil, errors.Trace(err) 115 } 116 117 var vms []*mo.VirtualMachine 118 vms = make([]*mo.VirtualMachine, len(vms)) 119 for _, item := range items { 120 var vm mo.VirtualMachine 121 err = c.connection.Properties(item.Reference(), nil, &vm) 122 if err != nil { 123 return nil, errors.Trace(err) 124 } 125 if vm.Config != nil && strings.HasPrefix(vm.Config.Name, prefix) { 126 vms = append(vms, &vm) 127 } 128 } 129 130 return vms, nil 131 } 132 133 func (c *client) Refresh(v *mo.VirtualMachine) error { 134 item, err := c.finder.VirtualMachine(v.Config.Name) 135 if err != nil { 136 return errors.Trace(err) 137 } 138 var vm mo.VirtualMachine 139 err = c.connection.Properties(item.Reference(), nil, &vm) 140 if err != nil { 141 return errors.Trace(err) 142 } 143 *v = vm 144 return nil 145 }