github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/ukvm/run_instance.go (about) 1 package ukvm 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "os/exec" 8 "time" 9 10 "github.com/sirupsen/logrus" 11 "github.com/emc-advanced-dev/pkg/errors" 12 "github.com/solo-io/unik/pkg/compilers" 13 "github.com/solo-io/unik/pkg/providers/common" 14 "github.com/solo-io/unik/pkg/types" 15 "github.com/solo-io/unik/pkg/util" 16 ) 17 18 func (p *UkvmProvider) 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. ukvm 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 image.RunSpec.Compiler != compilers.MIRAGE_OCAML_UKVM.String() { 35 return nil, errors.New("ukvm only supports mirage / ukvm", nil) 36 } 37 38 if err := common.VerifyMntsInput(p, image, params.MntPointsToVolumeIds); err != nil { 39 return nil, errors.New("invalid mapping for volume", err) 40 } 41 42 volumeIdInOrder := make([]string, len(params.MntPointsToVolumeIds)) 43 44 for mntPoint, volumeId := range params.MntPointsToVolumeIds { 45 46 controllerPort, err := common.GetControllerPortForMnt(image, mntPoint) 47 if err != nil { 48 return nil, err 49 } 50 volumeIdInOrder[controllerPort] = volumeId 51 } 52 53 logrus.Debugf("creating ukvm vm") 54 55 volImagesInOrder, err := p.getVolumeImages(volumeIdInOrder) 56 if err != nil { 57 return nil, errors.New("can't get volumes", err) 58 } 59 60 volArgs := volPathToUkvmArgs(volImagesInOrder) 61 62 ukvmArgs := []string{} 63 64 if p.config.Tap != "" { 65 ukvmArgs = append(ukvmArgs, fmt.Sprintf("--net=%s", p.config.Tap)) 66 67 } 68 69 ukvmArgs = append(ukvmArgs, volArgs...) 70 ukvmArgs = append(ukvmArgs, getKernelPath(image.Name)) 71 cmd := exec.Command(getUkvmPath(image.Name), ukvmArgs...) 72 73 stdout, err := cmd.StdoutPipe() 74 if err != nil { 75 logrus.WithError(err).Warning("Can't get stdout for logs") 76 } 77 78 instanceLogName := getInstanceLogName(params.Name) 79 80 go func() { 81 f, err := os.Create(instanceLogName) 82 if err != nil { 83 logrus.WithError(err).Warning("Failed to create stdout log for instance " + params.Name) 84 } 85 defer f.Close() 86 io.Copy(f, stdout) 87 88 }() 89 90 util.LogCommand(cmd, true) 91 92 if err := cmd.Start(); err != nil { 93 return nil, errors.New("can't start ukvm.", nil) 94 } 95 // close command resources 96 go cmd.Wait() 97 98 var instanceIp string 99 100 instance := &types.Instance{ 101 Id: fmt.Sprintf("%v", cmd.Process.Pid), 102 Name: params.Name, 103 State: types.InstanceState_Running, 104 IpAddress: instanceIp, 105 Infrastructure: types.Infrastructure_UKVM, 106 ImageId: image.Id, 107 Created: time.Now(), 108 } 109 110 if err := p.state.ModifyInstances(func(instances map[string]*types.Instance) error { 111 instances[instance.Id] = instance 112 return nil 113 }); err != nil { 114 return nil, errors.New("modifying instance map in state", err) 115 } 116 117 logrus.WithField("instance", instance).Infof("instance created successfully") 118 119 return instance, nil 120 } 121 122 func (p *UkvmProvider) getVolumeImages(volumeIdInOrder []string) ([]string, error) { 123 124 var volPath []string 125 for _, v := range volumeIdInOrder { 126 v, err := p.GetVolume(v) 127 if err != nil { 128 return nil, err 129 } 130 volPath = append(volPath, getVolumePath(v.Name)) 131 } 132 return volPath, nil 133 } 134 135 func volPathToUkvmArgs(volPaths []string) []string { 136 var res []string 137 for _, v := range volPaths { 138 res = append(res, fmt.Sprintf("--disk=%s", v)) 139 } 140 return res 141 }