Exemple #1
0
func TestCreateImageStore(t *testing.T) {
	storageImageLayer = spl.NewLookupCache(&MockDataStore{})

	s := &StorageHandlersImpl{}
	store := &models.ImageStore{
		Name: "testStore",
	}

	params := &storage.CreateImageStoreParams{
		Body: store,
	}

	result := s.CreateImageStore(*params)
	if !assert.NotNil(t, result) {
		return
	}

	// try to recreate the same image store
	result = s.CreateImageStore(*params)
	if !assert.NotNil(t, result) {
		return
	}

	// expect 409 since it already exists
	conflict := &storage.CreateImageStoreConflict{
		Payload: &models.Error{
			Code:    swag.Int64(http.StatusConflict),
			Message: "An image store with that name already exists",
		},
	}
	if !assert.Equal(t, conflict, result) {
		return
	}
}
Exemple #2
0
func setup(t *testing.T) (*portlayer.NameLookupCache, *session.Session, string, error) {
	logrus.SetLevel(logrus.DebugLevel)

	client := datastore.Session(context.TODO(), t)
	if client == nil {
		return nil, nil, "", fmt.Errorf("skip")
	}

	storeURL := &url.URL{
		Path: datastore.TestName("imageTests"),
		Host: client.DatastorePath}

	op := trace.NewOperation(context.Background(), "setup")
	vsImageStore, err := NewImageStore(op, client, storeURL)
	if err != nil {
		if err.Error() == "can't find the hosting vm" {
			t.Skip("Skipping: test must be run in a VM")
		}
		return nil, nil, "", err
	}

	s := portlayer.NewLookupCache(vsImageStore)

	return s, client, storeURL.Path, nil
}
Exemple #3
0
func setup(t *testing.T) (*portlayer.NameLookupCache, *session.Session, error) {
	logrus.SetLevel(logrus.DebugLevel)
	StorageParentDir = datastore.TestName("imageTests")

	client := datastore.Session(context.TODO(), t)
	if client == nil {
		return nil, nil, fmt.Errorf("skip")
	}

	storeURL := &url.URL{
		Path: StorageParentDir,
		Host: client.DatastorePath}

	vsImageStore, err := NewImageStore(context.TODO(), client, storeURL)
	if err != nil {
		if err.Error() == "can't find the hosting vm" {
			t.Skip("Skipping: test must be run in a VM")
		}
		return nil, nil, err
	}

	s := portlayer.NewLookupCache(vsImageStore)

	return s, client, nil
}
Exemple #4
0
func TestWriteImage(t *testing.T) {
	storageImageLayer = spl.NewLookupCache(&MockDataStore{})

	// create image store
	_, err := storageImageLayer.CreateImageStore(context.TODO(), testStoreName)
	if err != nil {
		return
	}

	s := &StorageHandlersImpl{}

	eMeta := make(map[string]string)
	eMeta["foo"] = "bar"

	name := new(string)
	val := new(string)
	*name = "foo"
	*val = eMeta["foo"]

	params := &storage.WriteImageParams{
		StoreName:   testStoreName,
		ImageID:     testImageID,
		ParentID:    "scratch",
		Sum:         testImageSum,
		Metadatakey: name,
		Metadataval: val,
		ImageFile:   nil,
	}

	expected := &storage.WriteImageCreated{
		Payload: &models.Image{
			ID:       testImageID,
			Parent:   nil,
			Store:    testStoreURL.String(),
			Metadata: eMeta,
			SelfLink: nil,
		},
	}

	result := s.WriteImage(*params)
	if !assert.NotNil(t, result) {
		return
	}
	if !assert.Equal(t, expected, result) {
		return
	}
}
Exemple #5
0
// Configure assigns functions to all the storage api handlers
func (handler *StorageHandlersImpl) Configure(api *operations.PortLayerAPI, handlerCtx *HandlerContext) {
	var err error

	ctx := context.Background()

	sessionconfig := &session.Config{
		Service:        options.PortLayerOptions.SDK,
		Insecure:       options.PortLayerOptions.Insecure,
		Keepalive:      options.PortLayerOptions.Keepalive,
		DatacenterPath: options.PortLayerOptions.DatacenterPath,
		ClusterPath:    options.PortLayerOptions.ClusterPath,
		PoolPath:       options.PortLayerOptions.PoolPath,
		DatastorePath:  options.PortLayerOptions.DatastorePath,
	}

	storageSession, err := session.NewSession(sessionconfig).Create(ctx)
	if err != nil {
		log.Fatalf("StorageHandler ERROR: %s", err)
	}
	if len(spl.Config.ImageStores) == 0 {
		log.Panicf("No image stores provided; unable to instantiate storage layer")
	}
	imageStoreURL := spl.Config.ImageStores[0]
	// TODO: support multiple image stores. Right now we only support the first one
	if len(spl.Config.ImageStores) > 1 {
		log.Warningf("Multiple image stores found. Multiple image stores are not yet supported. Using [%s] %s", imageStoreURL.Host, imageStoreURL.Path)
	}
	ds, err := vsphereSpl.NewImageStore(ctx, storageSession, &imageStoreURL)
	if err != nil {
		log.Panicf("Cannot instantiate storage layer: %s", err)
	}

	// The imagestore is implemented via a cache which is backed via an
	// implementation that writes to disks.  The cache is used to avoid
	// expensive metadata lookups.
	storageImageLayer = spl.NewLookupCache(ds)
	vsVolumeStore, err := vsphereSpl.NewVolumeStore(context.TODO(), storageSession)
	if err != nil {
		log.Panicf("Cannot instantiate the volume store: %s", err)
	}

	// Get the datastores for volumes.
	// Each volume store name maps to a datastore + path, which can be referred to by the name.
	dstores, err := datastore.GetDatastores(context.TODO(), storageSession, spl.Config.VolumeLocations)
	if err != nil {
		log.Panicf("Cannot find datastores: %s", err)
	}

	// Add datastores to the vsphere volume store impl
	for volStoreName, volDatastore := range dstores {
		log.Infof("Adding volume store %s (%s)", volStoreName, volDatastore.RootURL)
		_, err := vsVolumeStore.AddStore(context.TODO(), volDatastore, volStoreName)
		if err != nil {
			log.Errorf("volume addition error %s", err)
		}
	}

	storageVolumeLayer, err = spl.NewVolumeLookupCache(context.TODO(), vsVolumeStore)
	if err != nil {
		log.Panicf("Cannot instantiate the Volume Lookup cache: %s", err)
	}

	api.StorageCreateImageStoreHandler = storage.CreateImageStoreHandlerFunc(handler.CreateImageStore)
	api.StorageGetImageHandler = storage.GetImageHandlerFunc(handler.GetImage)
	api.StorageGetImageTarHandler = storage.GetImageTarHandlerFunc(handler.GetImageTar)
	api.StorageListImagesHandler = storage.ListImagesHandlerFunc(handler.ListImages)
	api.StorageWriteImageHandler = storage.WriteImageHandlerFunc(handler.WriteImage)

	api.StorageVolumeStoresListHandler = storage.VolumeStoresListHandlerFunc(handler.VolumeStoresList)
	api.StorageCreateVolumeHandler = storage.CreateVolumeHandlerFunc(handler.CreateVolume)
	api.StorageRemoveVolumeHandler = storage.RemoveVolumeHandlerFunc(handler.RemoveVolume)
	api.StorageVolumeJoinHandler = storage.VolumeJoinHandlerFunc(handler.VolumeJoin)
	api.StorageListVolumesHandler = storage.ListVolumesHandlerFunc(handler.VolumesList)
}
Exemple #6
0
func TestListImages(t *testing.T) {
	storageImageLayer = spl.NewLookupCache(&MockDataStore{})

	s := &StorageHandlersImpl{}

	params := &storage.ListImagesParams{
		StoreName: testStoreName,
	}

	// expect 404 if image store doesn't exist
	notFound := &storage.ListImagesNotFound{
		Payload: &models.Error{
			Code:    swag.Int64(http.StatusNotFound),
			Message: fmt.Sprintf("store (%s) doesn't exist", testStoreURL.String()),
		},
	}

	outImages := s.ListImages(*params)
	if !assert.NotNil(t, outImages) {
		return
	}
	if !assert.Equal(t, notFound, outImages) {
		return
	}

	// create the image store
	url, err := storageImageLayer.CreateImageStore(context.TODO(), testStoreName)
	if !assert.NoError(t, err) {
		return
	}
	if !assert.NotNil(t, url) {
		return
	}

	// create a set of images
	images := make(map[string]*spl.Image)
	parent := spl.Scratch
	parent.Store = &testStoreURL
	for i := 1; i < 50; i++ {
		id := fmt.Sprintf("id-%d", i)
		img, err := storageImageLayer.WriteImage(context.TODO(), &parent, id, nil, testImageSum, nil)
		if !assert.NoError(t, err) {
			return
		}
		if !assert.NotNil(t, img) {
			return
		}
		images[id] = img
	}

	// List all images
	outImages = s.ListImages(*params)
	assert.IsType(t, &storage.ListImagesOK{}, outImages)
	assert.Equal(t, len(outImages.(*storage.ListImagesOK).Payload), len(images))

	for _, img := range outImages.(*storage.ListImagesOK).Payload {
		_, ok := images[img.ID]
		if !assert.True(t, ok) {
			return
		}
	}

	// List specific images
	var ids []string

	// query for odd-numbered image ids
	for i := 1; i < 50; i += 2 {
		ids = append(ids, fmt.Sprintf("id-%d", i))
	}
	params.Ids = ids
	outImages = s.ListImages(*params)
	assert.IsType(t, &storage.ListImagesOK{}, outImages)
	assert.Equal(t, len(outImages.(*storage.ListImagesOK).Payload), len(ids))

	outmap := make(map[string]*models.Image)
	for _, image := range outImages.(*storage.ListImagesOK).Payload {
		outmap[image.ID] = image
	}

	// ensure no even-numbered image ids in our result
	for i := 2; i < 50; i += 2 {
		id := fmt.Sprintf("id-%d", i)
		_, ok := outmap[id]
		if !assert.False(t, ok) {
			return
		}
	}
}
Exemple #7
0
func TestGetImage(t *testing.T) {
	storageImageLayer = spl.NewLookupCache(&MockDataStore{})

	s := &StorageHandlersImpl{}

	params := &storage.GetImageParams{
		ID:        testImageID,
		StoreName: testStoreName,
	}

	// expect 404 since no image store exists by that name
	storeNotFound := &storage.GetImageNotFound{
		Payload: &models.Error{
			Code:    swag.Int64(http.StatusNotFound),
			Message: fmt.Sprintf("store (%s) doesn't exist", testStoreURL.String()),
		},
	}

	result := s.GetImage(*params)
	if !assert.NotNil(t, result) {
		return
	}
	if !assert.Equal(t, storeNotFound, result) {
		return
	}

	// create the image store
	url, err := storageImageLayer.CreateImageStore(context.TODO(), testStoreName)
	// TODO(jzt): these are testing NameLookupCache, do we need them here?
	if !assert.Nil(t, err, "Error while creating image store") {
		return
	}
	if !assert.Equal(t, testStoreURL.String(), url.String()) {
		return
	}

	// expect 404 since no image exists by that name in that store
	imageNotFound := &storage.GetImageNotFound{
		Payload: &models.Error{
			Code:    swag.Int64(http.StatusNotFound),
			Message: fmt.Sprintf("store (%s) doesn't have image %s", testStoreURL.String(), testImageID),
		},
	}
	// try GetImage again
	result = s.GetImage(*params)
	if !assert.NotNil(t, result) {
		return
	}
	if !assert.Equal(t, imageNotFound, result) {
		return
	}

	// add image to store
	parent := spl.Image{
		ID:       "scratch",
		SelfLink: nil,
		Parent:   nil,
		Store:    &testStoreURL,
	}

	expectedMeta := make(map[string][]byte)
	expectedMeta["foo"] = []byte("bar")
	// add the image to the store
	image, err := storageImageLayer.WriteImage(context.TODO(), &parent, testImageID, expectedMeta, testImageSum, nil)
	if !assert.NoError(t, err) || !assert.NotNil(t, image) {
		return
	}

	eMeta := make(map[string]string)
	eMeta["foo"] = "bar"
	// expect our image back now that we've created it
	expected := &storage.GetImageOK{
		Payload: &models.Image{
			ID:       image.ID,
			SelfLink: nil,
			Parent:   nil,
			Store:    testStoreURL.String(),
			Metadata: eMeta,
		},
	}

	result = s.GetImage(*params)
	if !assert.NotNil(t, result) {
		return
	}
	if !assert.Equal(t, expected, result) {
		return
	}
}
Exemple #8
0
func TestWriteImage(t *testing.T) {
	ic := spl.NewLookupCache(&MockDataStore{})

	// create image store
	op := trace.NewOperation(context.Background(), "test")
	_, err := ic.CreateImageStore(op, testStoreName)
	if err != nil {
		return
	}

	s := &StorageHandlersImpl{
		imageCache: ic,
	}

	eMeta := make(map[string]string)
	eMeta["foo"] = "bar"

	name := new(string)
	val := new(string)
	*name = "foo"
	*val = eMeta["foo"]

	params := &storage.WriteImageParams{
		StoreName:   testStoreName,
		ImageID:     testImageID,
		ParentID:    "scratch",
		Sum:         testImageSum,
		Metadatakey: name,
		Metadataval: val,
		ImageFile:   nil,
	}

	parentlink, err := util.ImageURL(testStoreName, params.ParentID)
	if !assert.NoError(t, err) {
		return
	}
	p := parentlink.String()

	selflink, err := util.ImageURL(testStoreName, testImageID)
	if !assert.NoError(t, err) {
		return
	}
	sl := selflink.String()

	expected := &storage.WriteImageCreated{
		Payload: &models.Image{
			ID:       testImageID,
			Parent:   &p,
			SelfLink: &sl,
			Store:    testStoreURL.String(),
			Metadata: eMeta,
		},
	}

	result := s.WriteImage(*params)
	if !assert.NotNil(t, result) {
		return
	}
	if !assert.Equal(t, expected, result) {
		return
	}
}
Exemple #9
0
// Configure assigns functions to all the storage api handlers
func (h *StorageHandlersImpl) Configure(api *operations.PortLayerAPI, handlerCtx *HandlerContext) {
	var err error

	ctx := context.Background()
	op := trace.NewOperation(ctx, "configure")

	if len(spl.Config.ImageStores) == 0 {
		log.Panicf("No image stores provided; unable to instantiate storage layer")
	}
	imageStoreURL := spl.Config.ImageStores[0]
	// TODO: support multiple image stores. Right now we only support the first one
	if len(spl.Config.ImageStores) > 1 {
		log.Warningf("Multiple image stores found. Multiple image stores are not yet supported. Using [%s] %s", imageStoreURL.Host, imageStoreURL.Path)
	}

	ds, err := vsphereSpl.NewImageStore(op, handlerCtx.Session, &imageStoreURL)
	if err != nil {
		log.Panicf("Cannot instantiate storage layer: %s", err)
	}

	// The imagestore is implemented via a cache which is backed via an
	// implementation that writes to disks.  The cache is used to avoid
	// expensive metadata lookups.
	h.imageCache = spl.NewLookupCache(ds)

	// The same is done for volumes.  It's implemented via a cache which writes
	// to an implementation that takes a datastore to write to.
	vsVolumeStore, err := vsphereSpl.NewVolumeStore(op, handlerCtx.Session)
	if err != nil {
		log.Panicf("Cannot instantiate the volume store: %s", err)
	}

	// Get the datastores for volumes.
	// Each volume store name maps to a datastore + path, which can be referred to by the name.
	dstores, err := datastore.GetDatastores(context.TODO(), handlerCtx.Session, spl.Config.VolumeLocations)
	if err != nil {
		log.Panicf("Cannot find datastores: %s", err)
	}

	// Add datastores to the vsphere volume store impl
	for volStoreName, volDatastore := range dstores {
		log.Infof("Adding volume store %s (%s)", volStoreName, volDatastore.RootURL)
		_, err := vsVolumeStore.AddStore(op, volDatastore, volStoreName)
		if err != nil {
			log.Errorf("volume addition error %s", err)
		}
	}

	h.volumeCache, err = spl.NewVolumeLookupCache(op, vsVolumeStore)
	if err != nil {
		log.Panicf("Cannot instantiate the Volume Lookup cache: %s", err)
	}

	api.StorageCreateImageStoreHandler = storage.CreateImageStoreHandlerFunc(h.CreateImageStore)
	api.StorageGetImageHandler = storage.GetImageHandlerFunc(h.GetImage)
	api.StorageGetImageTarHandler = storage.GetImageTarHandlerFunc(h.GetImageTar)
	api.StorageListImagesHandler = storage.ListImagesHandlerFunc(h.ListImages)
	api.StorageWriteImageHandler = storage.WriteImageHandlerFunc(h.WriteImage)
	api.StorageDeleteImageHandler = storage.DeleteImageHandlerFunc(h.DeleteImage)

	api.StorageVolumeStoresListHandler = storage.VolumeStoresListHandlerFunc(h.VolumeStoresList)
	api.StorageCreateVolumeHandler = storage.CreateVolumeHandlerFunc(h.CreateVolume)
	api.StorageRemoveVolumeHandler = storage.RemoveVolumeHandlerFunc(h.RemoveVolume)
	api.StorageVolumeJoinHandler = storage.VolumeJoinHandlerFunc(h.VolumeJoin)
	api.StorageListVolumesHandler = storage.ListVolumesHandlerFunc(h.VolumesList)
	api.StorageGetVolumeHandler = storage.GetVolumeHandlerFunc(h.GetVolume)
}