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 }
// 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 }
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 }
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 } } }