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  }