github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/virtualbox/run_instance.go (about) 1 package virtualbox 2 3 import ( 4 "os" 5 "time" 6 7 "path/filepath" 8 9 "github.com/sirupsen/logrus" 10 "github.com/emc-advanced-dev/pkg/errors" 11 unikos "github.com/solo-io/unik/pkg/os" 12 "github.com/solo-io/unik/pkg/providers/common" 13 "github.com/solo-io/unik/pkg/providers/virtualbox/virtualboxclient" 14 "github.com/solo-io/unik/pkg/types" 15 "github.com/layer-x/layerx-commons/lxhttpclient" 16 ) 17 18 func (p *VirtualboxProvider) RunInstance(params types.RunInstanceParams) (_ *types.Instance, err error) { 19 logrus.WithFields(logrus.Fields{ 20 "image-id": params.ImageId, 21 "mounts": params.MntPointsToVolumeIds, 22 "env": params.Env, 23 }).Infof("running instance %s", params.Name) 24 25 if _, err := p.GetInstance(params.Name); err == nil { 26 return nil, errors.New("instance with name "+params.Name+" already exists. virtualbox provider requires unique names for instances", nil) 27 } 28 29 image, err := p.GetImage(params.ImageId) 30 if err != nil { 31 return nil, errors.New("getting image", err) 32 } 33 34 if err := common.VerifyMntsInput(p, image, params.MntPointsToVolumeIds); err != nil { 35 return nil, errors.New("invalid mapping for volume", err) 36 } 37 38 instanceDir := getInstanceDir(params.Name) 39 40 portsUsed := []int{} 41 42 logrus.Debugf("using storage controller %s", image.RunSpec.StorageDriver) 43 44 defer func() { 45 if err != nil { 46 if params.NoCleanup { 47 logrus.Warnf("because --no-cleanup flag was provided, not cleaning up failed instance %s.2", params.Name) 48 return 49 } 50 logrus.WithError(err).Errorf("error encountered, ensuring vm and disks are destroyed") 51 virtualboxclient.PowerOffVm(params.Name) 52 for _, portUsed := range portsUsed { 53 virtualboxclient.DetachDisk(params.Name, portUsed, image.RunSpec.StorageDriver) 54 } 55 virtualboxclient.DestroyVm(params.Name) 56 os.RemoveAll(instanceDir) 57 } 58 }() 59 60 //if not set, use default 61 if params.InstanceMemory <= 0 { 62 params.InstanceMemory = image.RunSpec.DefaultInstanceMemory 63 } 64 65 logrus.Debugf("creating virtualbox vm") 66 67 if err := virtualboxclient.CreateVm(params.Name, virtualboxInstancesDirectory(), params.InstanceMemory, p.config.AdapterName, p.config.VirtualboxAdapterType, image.RunSpec.StorageDriver); err != nil { 68 return nil, errors.New("creating vm", err) 69 } 70 71 logrus.Debugf("copying source boot vmdk") 72 instanceBootImage := filepath.Join(instanceDir, "boot.vmdk") 73 if err := unikos.CopyFile(getImagePath(image.Name), instanceBootImage); err != nil { 74 return nil, errors.New("copying base boot image", err) 75 } 76 if err := virtualboxclient.RefreshDiskUUID(instanceBootImage); err != nil { 77 return nil, errors.New("refreshing disk uuid", err) 78 } 79 if err := virtualboxclient.AttachDisk(params.Name, instanceBootImage, 0, image.RunSpec.StorageDriver); err != nil { 80 return nil, errors.New("attaching boot vol to instance", err) 81 } 82 83 for mntPoint, volumeId := range params.MntPointsToVolumeIds { 84 volume, err := p.GetVolume(volumeId) 85 if err != nil { 86 return nil, errors.New("getting volume", err) 87 } 88 controllerPort, err := common.GetControllerPortForMnt(image, mntPoint) 89 if err != nil { 90 return nil, errors.New("getting controller port for mnt point", err) 91 } 92 if err := virtualboxclient.RefreshDiskUUID(getVolumePath(volume.Name)); err != nil { 93 return nil, errors.New("refreshing disk uuid", err) 94 } 95 if err := virtualboxclient.AttachDisk(params.Name, getVolumePath(volume.Name), controllerPort, image.RunSpec.StorageDriver); err != nil { 96 return nil, errors.New("attaching to vm", err) 97 } 98 portsUsed = append(portsUsed, controllerPort) 99 } 100 101 logrus.Debugf("setting instance id from mac address") 102 vm, err := virtualboxclient.GetVm(params.Name) 103 if err != nil { 104 return nil, errors.New("retrieving created vm from vbox", err) 105 } 106 macAddr := vm.MACAddr 107 instanceId := vm.UUID 108 109 instanceListenerIp, err := common.GetInstanceListenerIp(instanceListenerPrefix, timeout) 110 if err != nil { 111 return nil, errors.New("failed to retrieve instance listener ip. is unik instance listener running?", err) 112 } 113 114 logrus.Debugf("sending env to listener") 115 if _, _, err := lxhttpclient.Post(instanceListenerIp+":3000", "/set_instance_env?mac_address="+macAddr, nil, params.Env); err != nil { 116 return nil, errors.New("sending instance env to listener", err) 117 } 118 119 logrus.Debugf("powering on vm") 120 if err := virtualboxclient.PowerOnVm(params.Name); err != nil { 121 return nil, errors.New("powering on vm", err) 122 } 123 124 instance := &types.Instance{ 125 Id: instanceId, 126 Name: params.Name, 127 State: types.InstanceState_Pending, 128 IpAddress: "", 129 Infrastructure: types.Infrastructure_VIRTUALBOX, 130 ImageId: image.Id, 131 Created: time.Now(), 132 } 133 134 if err := p.state.ModifyInstances(func(instances map[string]*types.Instance) error { 135 instances[instance.Id] = instance 136 return nil 137 }); err != nil { 138 return nil, errors.New("modifying instance map in state", err) 139 } 140 141 logrus.WithField("instance", instance).Infof("instance created successfully") 142 143 return instance, nil 144 }