virtcontainers: store: Add a Raw API

The Raw API creates a raw item, i.e. an item that must be handled
directly by the caller. A raw item is one that's not defined by the
store.Item enum, i.e. it is a custom, caller defined one.
The caller gets a URL back and is responsible for handling the item
directly from this URL.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz 2019-01-08 15:55:52 +01:00
parent c25c60898b
commit 6e9256f483
5 changed files with 77 additions and 2 deletions

View File

@ -48,4 +48,9 @@ type backend interface {
delete() error
load(item Item, data interface{}) error
store(item Item, data interface{}) error
// raw creates a raw Store item. A raw item is one that is
// not defined through the Item enum.
// The caller gets an item URL back and handles it directly,
// outside of the top level Store API.
raw(id string) (string, error)
}

View File

@ -102,6 +102,7 @@ type filesystem struct {
ctx context.Context
path string
rawPath string
}
// Logger returns a logrus logger appropriate for logging Store filesystem messages
@ -144,13 +145,18 @@ func (f *filesystem) initialize() error {
}
// Our root path does not exist, we need to create the initial layout:
// The root directory and a lock file
// The root directory, a lock file and a raw files directory.
// Root directory
if err := os.MkdirAll(f.path, DirMode); err != nil {
return err
}
// Raw directory
if err := os.MkdirAll(f.rawPath, DirMode); err != nil {
return err
}
// Lock
lockPath := filepath.Join(f.path, LockFile)
@ -167,6 +173,7 @@ func (f *filesystem) initialize() error {
func (f *filesystem) new(ctx context.Context, path string, host string) error {
f.ctx = ctx
f.path = path
f.rawPath = filepath.Join(f.path, "raw")
f.logger().Debugf("New filesystem store backend for %s", path)
@ -225,3 +232,30 @@ func (f *filesystem) store(item Item, data interface{}) error {
return nil
}
func (f *filesystem) raw(id string) (string, error) {
span, _ := f.trace("raw")
defer span.Finish()
span.SetTag("id", id)
// We must use the item ID.
if id != "" {
filePath := filepath.Join(f.rawPath, id)
file, err := os.Create(filePath)
if err != nil {
return "", err
}
return filesystemScheme + "://" + file.Name(), nil
}
// Generate a random temporary file.
file, err := ioutil.TempFile(f.rawPath, "raw-")
if err != nil {
return "", err
}
defer file.Close()
return filesystemScheme + "://" + file.Name(), nil
}

View File

@ -87,3 +87,15 @@ func TestStoreFilesystemDelete(t *testing.T) {
_, err = os.Stat(f.path)
assert.NotNil(t, err)
}
func TestStoreFilesystemRaw(t *testing.T) {
f := filesystem{}
err := f.new(context.Background(), rootPath, "")
defer f.delete()
assert.Nil(t, err)
path, err := f.raw("roah")
assert.Nil(t, err)
assert.Equal(t, path, filesystemScheme+"://"+filepath.Join(rootPath, "raw", "roah"))
}

View File

@ -248,3 +248,16 @@ func (s *Store) Delete() error {
return nil
}
// Raw creates a raw item to be handled directly by the API caller.
// It returns a full URL to the item and the caller is responsible
// for handling the item through this URL.
func (s *Store) Raw(id string) (string, error) {
span, _ := s.trace("Raw")
defer span.Finish()
s.Lock()
defer s.Unlock()
return s.backend.raw(id)
}

View File

@ -191,6 +191,17 @@ func (s *VCStore) LoadDevices() ([]api.Device, error) {
return devices, nil
}
// Raw creates a raw item in the virtcontainer state Store. A raw
// item is a custom one, not defined through the Item enum, and that
// the caller needs to handle directly.
// Typically this is used to create a custom virtcontainers file.
// For example the Firecracker code uses this API to create temp
// files under the sandbox state root path, and uses them as block
// driver backend placeholder.
func (s *VCStore) Raw(id string) (string, error) {
return s.state.Raw(id)
}
// Utilities for virtcontainers
// SandboxConfigurationRoot returns a virtcontainers sandbox configuration root URL.