github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/photon/stage.go (about)

     1  package photon
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"time"
     8  
     9  	"github.com/sirupsen/logrus"
    10  	"github.com/emc-advanced-dev/pkg/errors"
    11  	"github.com/solo-io/unik/pkg/providers/common"
    12  	"github.com/solo-io/unik/pkg/types"
    13  	"github.com/vmware/photon-controller-go-sdk/photon"
    14  )
    15  
    16  func createVmdk(params types.StageImageParams, workVmdk func(file string) (string, error)) (string, int64, error) {
    17  
    18  	localVmdkDir, err := ioutil.TempDir("", "vmdkdir.")
    19  	if err != nil {
    20  		return "", 0, errors.New("creating tmp file", err)
    21  	}
    22  	defer os.RemoveAll(localVmdkDir)
    23  	localVmdkFile := filepath.Join(localVmdkDir, "boot.vmdk")
    24  
    25  	logrus.WithField("raw-image", params.RawImage).Infof("creating boot volume from raw image")
    26  	if err := common.ConvertRawToNewVmdk(params.RawImage.LocalImagePath, localVmdkFile); err != nil {
    27  		return "", 0, errors.New("converting raw image to vmdk", err)
    28  	}
    29  
    30  	rawImageFile, err := os.Stat(localVmdkFile)
    31  	if err != nil {
    32  		return "", 0, errors.New("statting raw image file", err)
    33  	}
    34  	sizeMb := rawImageFile.Size() >> 20
    35  
    36  	logrus.WithFields(logrus.Fields{
    37  		"name": params.Name,
    38  		"id":   params.Name,
    39  		"size": sizeMb,
    40  	}).Infof("importing base vmdk for unikernel image")
    41  
    42  	imgId, err := workVmdk(localVmdkFile)
    43  	return imgId, sizeMb, err
    44  
    45  }
    46  
    47  func (p *PhotonProvider) Stage(params types.StageImageParams) (_ *types.Image, err error) {
    48  	images, err := p.ListImages()
    49  	if err != nil {
    50  		return nil, errors.New("retrieving image list for existing image", err)
    51  	}
    52  	for _, image := range images {
    53  		if image.Name == params.Name {
    54  			if !params.Force {
    55  				return nil, errors.New("an image already exists with name '"+params.Name+"', try again with --force", nil)
    56  			} else {
    57  				logrus.WithField("image", image).Warnf("force: deleting previous image with name " + params.Name)
    58  				if err := p.DeleteImage(image.Id, true); err != nil {
    59  					logrus.Warn(errors.New("failed removing previously existing image", err))
    60  				}
    61  			}
    62  		}
    63  	}
    64  
    65  	// create vmdk
    66  	imgId, sizeMb, err := createVmdk(params, func(vmdkFile string) (string, error) {
    67  		options := &photon.ImageCreateOptions{
    68  			ReplicationType: "EAGER",
    69  		}
    70  		task, err := p.client.Images.CreateFromFile(vmdkFile, options)
    71  		if err != nil {
    72  			return "", errors.New("error creating photon image", err)
    73  		}
    74  
    75  		task, err = p.waitForTaskSuccess(task)
    76  		if err != nil {
    77  			return "", errors.New("error waiting for task creating photon image", err)
    78  		}
    79  
    80  		return task.Entity.ID, nil
    81  	})
    82  	if err != nil {
    83  		return nil, errors.New("importing base boot.vmdk to photon", err)
    84  	}
    85  
    86  	// upload images
    87  	image := &types.Image{
    88  		Id:             imgId,
    89  		Name:           params.Name,
    90  		StageSpec:      params.RawImage.StageSpec,
    91  		RunSpec:        params.RawImage.RunSpec,
    92  		SizeMb:         sizeMb,
    93  		Infrastructure: types.Infrastructure_PHOTON,
    94  		Created:        time.Now(),
    95  	}
    96  
    97  	if err := p.state.ModifyImages(func(images map[string]*types.Image) error {
    98  		images[params.Name] = image
    99  		return nil
   100  	}); err != nil {
   101  		return nil, errors.New("modifying image map in state", err)
   102  	}
   103  
   104  	logrus.WithFields(logrus.Fields{"image": image}).Infof("image created succesfully")
   105  	return image, nil
   106  }