Пример #1
0
func NewImageStore(op trace.Operation, s *session.Session, u *url.URL) (*ImageStore, error) {
	dm, err := disk.NewDiskManager(op, s)
	if err != nil {
		return nil, err
	}

	datastores, err := s.Finder.DatastoreList(op, u.Host)
	if err != nil {
		return nil, fmt.Errorf("Host returned error when trying to locate provided datastore %s: %s", u.String(), err.Error())
	}

	if len(datastores) != 1 {
		return nil, fmt.Errorf("Found %d datastores with provided datastore path %s. Cannot create image store.", len(datastores), u)
	}

	ds, err := datastore.NewHelper(op, s, datastores[0], path.Join(u.Path, StorageParentDir))
	if err != nil {
		return nil, err
	}

	vis := &ImageStore{
		dm: dm,
		ds: ds,
		s:  s,
	}

	return vis, nil
}
Пример #2
0
// NewDatastoreKeyValue will validate the supplied name and create a datastore
// backed key / value store
//
// The file will be located at the init datastoreURL  -- currently that's in the
// appliance directory under the {dsFolder} folder (i.e. [datastore]vch-appliance/{dsFolder}/{name})
func NewDatastoreKeyValue(ctx context.Context, session *session.Session, name string) (kvstore.KeyValueStore, error) {
	defer trace.End(trace.Begin(name))

	mgr.m.Lock()
	defer mgr.m.Unlock()

	// validate the name
	err := validateStoreName(name)
	if err != nil {
		return nil, err
	}
	// get a ds helper for this ds url
	dsHelper, err := datastore.NewHelper(trace.NewOperation(ctx, "datastore helper creation"), session,
		session.Datastore, fmt.Sprintf("%s/%s", mgr.datastoreURL.Path, KVStoreFolder))
	if err != nil {
		return nil, fmt.Errorf("unable to get datastore helper for %s store creation: %s", name, err.Error())
	}

	// create or restore the specified K/V store
	keyVal, err := kvstore.NewKeyValueStore(ctx, kvstore.NewDatastoreBackend(dsHelper), name)
	if err != nil && !os.IsExist(err) {
		return nil, fmt.Errorf("unable to create %s datastore backed store: %s", name, err.Error())
	}
	// throw it in the store map
	mgr.dsStores[name] = keyVal

	return keyVal, nil
}
Пример #3
0
func (d *Dispatcher) createVolumeStores(conf *config.VirtualContainerHostConfigSpec) error {
	defer trace.End(trace.Begin(""))
	for _, url := range conf.VolumeLocations {
		ds, err := d.session.Finder.Datastore(d.ctx, url.Host)
		if err != nil {
			return errors.Errorf("Could not retrieve datastore with host %q due to error %s", url.Host, err)
		}

		if url.Path == "/" || url.Path == "" {
			url.Path = vsphere.StorageParentDir
		}

		nds, err := datastore.NewHelper(d.ctx, d.session, ds, url.Path)
		if err != nil {
			return errors.Errorf("Could not create volume store due to error: %s", err)
		}
		// FIXME: (GitHub Issue #1301) this is not valid URL syntax and should be translated appropriately when time allows
		url.Path = nds.RootURL
	}
	return nil
}
Пример #4
0
func TestVolumeCreateListAndRestart(t *testing.T) {
	client := datastore.Session(context.TODO(), t)
	if client == nil {
		return
	}

	ctx := context.TODO()

	// Create the backing store on vsphere
	vsVolumeStore, err := NewVolumeStore(ctx, client)
	if !assert.NoError(t, err) || !assert.NotNil(t, vsVolumeStore) {
		return
	}

	// Root our datastore
	testStorePath := datastore.TestName("voltest")
	ds, err := datastore.NewHelper(ctx, client, client.Datastore, testStorePath)
	if !assert.NoError(t, err) || !assert.NotNil(t, ds) {
		return
	}

	// Add a volume store and give it a name ("testStoreName")
	volumeStore, err := vsVolumeStore.AddStore(ctx, ds, "testStoreName")
	if !assert.NoError(t, err) || !assert.NotNil(t, volumeStore) {
		return
	}

	// test we can list it
	m, err := vsVolumeStore.VolumeStoresList(ctx)
	if !assert.NoError(t, err) || !assert.NotNil(t, m) {
		return
	}

	// test the returned url matches
	s, ok := m["testStoreName"]
	if !assert.True(t, ok) || !assert.Equal(t, testStorePath, filepath.Base(s.String())) {
		return
	}

	// Clean up the mess
	defer func() {
		fm := object.NewFileManager(client.Vim25())
		tasks.WaitForResult(context.TODO(), func(ctx context.Context) (tasks.ResultWaiter, error) {
			return fm.DeleteDatastoreFile(ctx, client.Datastore.Path(testStorePath), client.Datacenter)
		})
	}()

	// Create the cache
	cache, err := portlayer.NewVolumeLookupCache(ctx, vsVolumeStore)
	if !assert.NoError(t, err) || !assert.NotNil(t, cache) {
		return
	}

	// Create the volumes (in parallel)
	numVols := 5
	wg := &sync.WaitGroup{}
	wg.Add(numVols)
	volumes := make(map[string]*portlayer.Volume)
	for i := 0; i < numVols; i++ {
		go func(idx int) {
			defer wg.Done()
			ID := fmt.Sprintf("testvolume-%d", idx)

			// add some metadata if i is even
			var info map[string][]byte

			if idx%2 == 0 {
				info = make(map[string][]byte)
				info[ID] = []byte(ID)
			}

			outVol, err := cache.VolumeCreate(ctx, ID, volumeStore, 10240, info)
			if !assert.NoError(t, err) || !assert.NotNil(t, outVol) {
				return
			}

			volumes[ID] = outVol
		}(i)
	}

	wg.Wait()

	// list using the datastore (skipping the cache)
	outVols, err := vsVolumeStore.VolumesList(ctx)
	if !assert.NoError(t, err) || !assert.NotNil(t, outVols) || !assert.Equal(t, numVols, len(outVols)) {
		return
	}

	for _, outVol := range outVols {
		if !assert.Equal(t, volumes[outVol.ID], outVol) {
			return
		}
	}

	// Test restart

	// Create a new vs and cache to the same datastore (simulating restart) and compare
	secondVStore, err := NewVolumeStore(ctx, client)
	if !assert.NoError(t, err) || !assert.NotNil(t, vsVolumeStore) {
		return
	}

	volumeStore, err = secondVStore.AddStore(ctx, ds, "testStoreName")
	if !assert.NoError(t, err) || !assert.NotNil(t, volumeStore) {
		return
	}
	secondCache, err := portlayer.NewVolumeLookupCache(ctx, secondVStore)
	if !assert.NoError(t, err) || !assert.NotNil(t, cache) {
		return
	}

	secondOutVols, err := secondCache.VolumesList(ctx)
	if !assert.NoError(t, err) || !assert.NotNil(t, secondOutVols) || !assert.Equal(t, numVols, len(secondOutVols)) {
		return
	}

	for _, outVol := range secondOutVols {
		// XXX we could compare the Volumes, but the paths are different the
		// second time around on vsan since the vsan UUID is not included.
		if !assert.NotEmpty(t, volumes[outVol.ID].Device.DiskPath()) {
			return
		}
	}
}