github.com/solo-io/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/xen/run_instance.go (about) 1 package xen 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "os" 9 10 "github.com/sirupsen/logrus" 11 "github.com/emc-advanced-dev/pkg/errors" 12 "github.com/solo-io/unik/pkg/providers/common" 13 "github.com/solo-io/unik/pkg/providers/xen/xenclient" 14 "github.com/solo-io/unik/pkg/types" 15 ) 16 17 func (p *XenProvider) RunInstance(params types.RunInstanceParams) (_ *types.Instance, err error) { 18 logrus.WithFields(logrus.Fields{ 19 "image-id": params.ImageId, 20 "mounts": params.MntPointsToVolumeIds, 21 "env": params.Env, 22 }).Infof("running instance %s", params.Name) 23 24 if _, err := p.GetInstance(params.Name); err == nil { 25 return nil, errors.New("instance with name "+params.Name+" already exists. xen provider requires unique names for instances", nil) 26 } 27 28 image, err := p.GetImage(params.ImageId) 29 if err != nil { 30 return nil, errors.New("getting image", err) 31 } 32 33 if err := common.VerifyMntsInput(p, image, params.MntPointsToVolumeIds); err != nil { 34 return nil, errors.New("invalid mapping for volume", err) 35 } 36 37 volumeIdToDevice := make(map[string]string) 38 39 // till we support pv without boot device, we need a boot device.. 40 bootmapping := "sda1" 41 for _, mapping := range image.RunSpec.DeviceMappings { 42 if mapping.MountPoint == "/" { 43 bootmapping = removeDevFromDeviceName(mapping.DeviceName) 44 break 45 } 46 } 47 48 for mntPoint, volumeId := range params.MntPointsToVolumeIds { 49 for _, mapping := range image.RunSpec.DeviceMappings { 50 if mntPoint == mapping.MountPoint { 51 volumeIdToDevice[volumeId] = mapping.DeviceName 52 break 53 } 54 } 55 } 56 57 logrus.Debugf("creating xen vm") 58 59 // TODO add support for boot drive mapping. 60 61 var dataVolumes []xenclient.VolumeConfig 62 for volid, deviceName := range volumeIdToDevice { 63 volPath, err := p.getVolPath(volid) 64 if err != nil { 65 return nil, errors.New("failed to get volume path", err) 66 } 67 dataVolumes = append(dataVolumes, xenclient.VolumeConfig{ 68 ImagePath: volPath, 69 DeviceName: removeDevFromDeviceName(deviceName), 70 }) 71 } 72 73 if err := os.MkdirAll(getInstanceDir(params.Name), 0755); err != nil { 74 return nil, errors.New("failed to create instance dir", err) 75 } 76 77 //if not set, use default 78 if params.InstanceMemory <= 0 { 79 params.InstanceMemory = image.RunSpec.DefaultInstanceMemory 80 } 81 82 xenParams := xenclient.CreateVmParams{ 83 Name: params.Name, 84 Memory: params.InstanceMemory, 85 BootImage: getImagePath(image.Name), 86 BootDeviceName: bootmapping, 87 VmDir: getInstanceDir(params.Name), 88 DataVolumes: dataVolumes, 89 } 90 91 if err := p.client.CreateVm(xenParams); err != nil { 92 return nil, errors.New("creating xen domain", err) 93 } 94 95 instanceId := params.Name 96 if doms, err := p.client.ListVms(); err == nil { 97 for _, d := range doms { 98 if d.Config.CInfo.Name == params.Name { 99 instanceId = fmt.Sprintf("%d", d.Domid) 100 break 101 } 102 } 103 } 104 105 var instanceIp string 106 107 instance := &types.Instance{ 108 Id: instanceId, 109 Name: params.Name, 110 State: types.InstanceState_Running, 111 IpAddress: instanceIp, 112 Infrastructure: types.Infrastructure_XEN, 113 ImageId: image.Id, 114 Created: time.Now(), 115 } 116 117 if err := p.state.ModifyInstances(func(instances map[string]*types.Instance) error { 118 instances[instance.Id] = instance 119 return nil 120 }); err != nil { 121 return nil, errors.New("modifying instance map in state", err) 122 } 123 124 logrus.WithField("instance", instance).Infof("instance created successfully") 125 126 return instance, nil 127 } 128 129 func (p *XenProvider) getVolPath(volId string) (string, error) { 130 131 v, err := p.GetVolume(volId) 132 if err != nil { 133 return "", err 134 } 135 return getVolumePath(v.Name), nil 136 137 } 138 139 func removeDevFromDeviceName(devName string) string { 140 141 const prefix = "/dev/" 142 143 if strings.HasPrefix(devName, prefix) { 144 devName = devName[len(prefix):] 145 } 146 147 return devName 148 }