Example #1
0
File: volume.go Project: vmware/vic
func (v *Volume) Parse(u *url.URL) error {
	// Check the path isn't malformed.
	if !filepath.IsAbs(u.Path) {
		return errors.New("invalid uri path")
	}

	segments := strings.Split(filepath.Clean(u.Path), "/")[1:]

	if segments[0] != util.StorageURLPath {
		return errors.New("not a storage path")
	}

	if len(segments) < 3 {
		return errors.New("uri path mismatch")
	}

	store, err := util.VolumeStoreNameToURL(segments[2])
	if err != nil {
		return err
	}

	id := segments[3]

	var SelfLink url.URL
	SelfLink = *u

	v.ID = id
	v.SelfLink = &SelfLink
	v.Store = store

	return nil
}
Example #2
0
//CreateVolume : Create a Volume
func (h *StorageHandlersImpl) CreateVolume(params storage.CreateVolumeParams) middleware.Responder {
	defer trace.End(trace.Begin("storage_handlers.CreateVolume"))

	//TODO: FIXME: add more errorcodes as we identify error scenarios.
	storeURL, err := util.VolumeStoreNameToURL(params.VolumeRequest.Store)
	if err != nil {
		log.Errorf("storagehandler: VolumeStoreName error: %s", err)
		return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{
			Code:    swag.Int64(http.StatusInternalServerError),
			Message: err.Error(),
		})
	}

	byteMap := make(map[string][]byte)
	for key, value := range params.VolumeRequest.Metadata {
		byteMap[key] = []byte(value)
	}

	capacity := uint64(0)
	if params.VolumeRequest.Capacity < 0 {
		capacity = uint64(1024) //FIXME: this should look for a default cap and set or fail here.
	} else {
		capacity = uint64(params.VolumeRequest.Capacity)
	}

	op := trace.NewOperation(context.Background(), fmt.Sprintf("VolumeCreate(%s)", params.VolumeRequest.Name))
	volume, err := h.volumeCache.VolumeCreate(op, params.VolumeRequest.Name, storeURL, capacity*1024, byteMap)
	if err != nil {
		log.Errorf("storagehandler: VolumeCreate error: %#v", err)

		if os.IsExist(err) {
			return storage.NewCreateVolumeConflict().WithPayload(&models.Error{
				Code:    swag.Int64(http.StatusConflict),
				Message: err.Error(),
			})
		}

		if _, ok := err.(spl.VolumeStoreNotFoundError); ok {
			return storage.NewCreateVolumeNotFound().WithPayload(&models.Error{
				Code:    swag.Int64(http.StatusNotFound),
				Message: err.Error(),
			})
		}

		return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{
			Code:    swag.Int64(http.StatusInternalServerError),
			Message: err.Error(),
		})
	}

	response := volumeToCreateResponse(volume, params.VolumeRequest)
	return storage.NewCreateVolumeCreated().WithPayload(&response)
}
Example #3
0
// AddStore adds a volumestore by uri.
//
// ds is the Datastore (+ path) volumes will be created under.
//       The resulting path will be parentDir/VIC/volumes.
// storeName is the name used to refer to the datastore + path (ds above).
//
// returns the URL used to refer to the volume store
func (v *VolumeStore) AddStore(ctx context.Context, ds *datastore.Helper, storeName string) (*url.URL, error) {
	u, err := util.VolumeStoreNameToURL(storeName)
	if err != nil {
		return nil, err
	}

	if _, ok := v.ds[*u]; ok {
		return nil, fmt.Errorf("volumestore (%s) already added", u.String())
	}

	if _, err = ds.Mkdir(ctx, true, volumesDir); err != nil {
		return nil, err
	}

	v.ds[*u] = ds
	return u, nil
}
Example #4
0
File: volume.go Project: vmware/vic
// AddStore adds a volumestore by uri.
//
// ds is the Datastore (+ path) volumes will be created under.
//       The resulting path will be parentDir/VIC/volumes.
// storeName is the name used to refer to the datastore + path (ds above).
//
// returns the URL used to refer to the volume store
func (v *VolumeStore) AddStore(op trace.Operation, ds *datastore.Helper, storeName string) (*url.URL, error) {
	v.dsLock.Lock()
	defer v.dsLock.Unlock()

	u, err := util.VolumeStoreNameToURL(storeName)
	if err != nil {
		return nil, err
	}

	if _, ok := v.ds[*u]; ok {
		return nil, fmt.Errorf("volumestore (%s) already added", u.String())
	}

	if _, err = ds.Mkdir(op, true, VolumesDir); err != nil && !os.IsExist(err) {
		return nil, err
	}

	v.ds[*u] = ds
	return u, nil
}
Example #5
0
// Create 2 store caches but use the same backing datastore.  Create images
// with the first cache, then get the image with the second.  This simulates
// restart since the second cache is empty and has to go to the backing store.
func TestVolumeCacheRestart(t *testing.T) {
	mvs := NewMockVolumeStore()
	op := trace.NewOperation(context.Background(), "test")
	firstCache, err := NewVolumeLookupCache(op, mvs)
	if !assert.NoError(t, err) || !assert.NotNil(t, firstCache) {
		return
	}

	storeURL, err := util.VolumeStoreNameToURL("testStore")
	if !assert.NoError(t, err) || !assert.NotNil(t, storeURL) {
		return
	}

	// Create a set of volumes
	inVols := make(map[string]*Volume)
	for i := 1; i < 50; i++ {
		id := fmt.Sprintf("ID-%d", i)

		// Write to the datastore
		vol, err := firstCache.VolumeCreate(op, id, storeURL, 0, nil)
		if !assert.NoError(t, err) || !assert.NotNil(t, vol) {
			return
		}

		inVols[id] = vol
	}

	secondCache, err := NewVolumeLookupCache(op, mvs)
	if !assert.NoError(t, err) || !assert.NotNil(t, secondCache) {
		return
	}

	// get the vols from the second cache to ensure it goes to the ds
	for _, expectedVol := range inVols {
		vol, err := secondCache.VolumeGet(op, expectedVol.ID)
		if !assert.NoError(t, err) || !assert.Equal(t, expectedVol, vol) {
			return
		}
	}
}
Example #6
0
//CreateVolume : Create a Volume
func (handler *StorageHandlersImpl) CreateVolume(params storage.CreateVolumeParams) middleware.Responder {
	defer trace.End(trace.Begin("storage_handlers.CreateVolume"))

	//TODO: FIXME: add more errorcodes as we identify error scenarios.
	storeURL, err := util.VolumeStoreNameToURL(params.VolumeRequest.Store)
	if err != nil {
		log.Errorf("storagehandler: VolumeStoreName error: %s", err)

		return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{
			Code:    swag.Int64(http.StatusInternalServerError),
			Message: err.Error(),
		})
	}

	byteMap := make(map[string][]byte)
	for key, value := range params.VolumeRequest.Metadata {
		byteMap[key] = []byte(value)
	}

	capacity := uint64(0)
	if params.VolumeRequest.Capacity < 0 {
		capacity = uint64(1024) //FIXME: this should look for a default cap and set or fail here.
	} else {
		capacity = uint64(params.VolumeRequest.Capacity)
	}

	volume, err := storageVolumeLayer.VolumeCreate(context.TODO(), params.VolumeRequest.Name, storeURL, capacity*1024, byteMap)
	if err != nil {
		log.Errorf("storagehandler: VolumeCreate error: %s", err)
		return storage.NewCreateVolumeInternalServerError().WithPayload(&models.Error{
			Code:    swag.Int64(http.StatusInternalServerError),
			Message: err.Error(),
		})
	}

	response := volumeToCreateResponse(volume, params.VolumeRequest)
	return storage.NewCreateVolumeCreated().WithPayload(&response)
}
Example #7
0
func TestVolumeCreateGetListAndDelete(t *testing.T) {
	op := trace.NewOperation(context.Background(), "test")
	mvs := NewMockVolumeStore()
	v, err := NewVolumeLookupCache(op, mvs)
	if !assert.NoError(t, err) {
		return
	}

	storeURL, err := util.VolumeStoreNameToURL("testStore")
	if !assert.NoError(t, err) || !assert.NotNil(t, storeURL) {
		return
	}

	inVols := make(map[string]*Volume)
	inVolsM := &sync.Mutex{}

	wg := &sync.WaitGroup{}
	createFn := func(i int) {
		defer wg.Done()

		id := fmt.Sprintf("ID-%d", i)

		// Write to the datastore
		vol, err := v.VolumeCreate(op, id, storeURL, 0, nil)
		if !assert.NoError(t, err) || !assert.NotNil(t, vol) {
			return
		}

		inVolsM.Lock()
		inVols[id] = vol
		inVolsM.Unlock()
	}

	// Create a set of volumes
	numVolumes := 5
	wg.Add(numVolumes)
	for i := 0; i < numVolumes; i++ {
		go createFn(i)
	}
	wg.Wait()

	getFn := func(inVol *Volume) {
		vol, err := v.VolumeGet(op, inVol.ID)
		if !assert.NoError(t, err) || !assert.NotNil(t, vol) {
			return
		}

		if !assert.Equal(t, inVol, vol) {
			return
		}
		wg.Done()
	}

	wg.Add(numVolumes)
	for _, inVol := range inVols {
		getFn(inVol)
	}
	wg.Wait()

	volumeList, err := v.VolumesList(op)
	if !assert.NoError(t, err) || !assert.Equal(t, numVolumes, len(volumeList)) {
		return
	}

	// Test that the list returned by VolumeList matches our inVols list.  Then
	// delete each vol via the cache, then check the datastore to ensure it's
	// empty
	for _, outVol := range volumeList {
		if !assert.Equal(t, inVols[outVol.ID], outVol) {
			return
		}

		if err = v.VolumeDestroy(op, outVol.ID); !assert.NoError(t, err) {
			return
		}
	}

	// check the datastore is empty.
	if !assert.Empty(t, mvs.db) {
		return
	}
}