virtcontainers: Initial Store implementation

Store is a replacement for the current resource storage virtcontainers
implementation and the Manager is the front-end for it. The back-ends
will provide actual storage capabilities and the first one will be the
filesystem one, for storing virtcontainers Items on a local filesystem.

The main design goals for Store are the following ones:

- Simplicity: The API should be short and simple.
- Transparency: The core virtcontainers code should not care about
  the storage backend details.
- Extensibility: It should be easily extensible to add non local and in
  memory backends.

Manger provides a very short and simple API for the rest of the virtcontainers
code base to consume:

New: Creates a new Store, if needed.
Load: Loads an Item from a Store
Store: Stores an Item into a Store.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz 2018-12-20 11:19:08 +01:00
parent d3c63e66e3
commit 4be76e9969
2 changed files with 177 additions and 0 deletions

View File

@ -0,0 +1,156 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package store
import (
"context"
"net/url"
"sync"
opentracing "github.com/opentracing/opentracing-go"
"github.com/sirupsen/logrus"
)
// Item represents a virtcontainers items that will be managed through the store.
type Item uint8
const (
// Configuration represents a configuration item to be stored
Configuration Item = iota
// State represents a state item to be stored.
State
// Network represents a networking item to be stored.
Network
// Hypervisor represents an hypervisor item to be stored.
Hypervisor
// Agent represents a agent item to be stored.
Agent
// Process represents a container process item to be stored.
Process
// Lock represents a lock item to be stored.
Lock
// Mounts represents a set of mounts related item to be stored.
Mounts
// Devices represents a set of devices related item to be stored.
Devices
// DeviceIDs represents a set of reference IDs item to be stored.
DeviceIDs
)
func (i Item) String() string {
switch i {
case Configuration:
return "Configuration"
case State:
return "State"
case Network:
return "Network"
case Hypervisor:
return "Hypervisor"
case Agent:
return "Agent"
case Process:
return "Process"
case Lock:
return "Lock"
case Mounts:
return "Mounts"
case Devices:
return "Devices"
case DeviceIDs:
return "Device IDs"
}
return ""
}
// Store is an opaque structure representing a virtcontainers Store.
type Store struct {
sync.RWMutex
ctx context.Context
url string
scheme string
path string
host string
}
// New will return a new virtcontainers Store.
// If there is already a Store for the URL, we will re-use it.
// Otherwise a new Store is created.
func New(ctx context.Context, storeURL string) (*Store, error) {
u, err := url.Parse(storeURL)
if err != nil {
return nil, err
}
return &Store{
ctx: ctx,
url: storeURL,
scheme: u.Scheme,
path: u.Path,
host: u.Host,
}, nil
}
var storeLog = logrus.WithField("source", "virtcontainers/store")
// Logger returns a logrus logger appropriate for logging Store messages
func (s *Store) Logger() *logrus.Entry {
return storeLog.WithFields(logrus.Fields{
"subsystem": "store",
"path": s.path,
})
}
func (s *Store) trace(name string) (opentracing.Span, context.Context) {
if s.ctx == nil {
s.Logger().WithField("type", "bug").Error("trace called before context set")
s.ctx = context.Background()
}
span, ctx := opentracing.StartSpanFromContext(s.ctx, name)
span.SetTag("subsystem", "store")
span.SetTag("path", s.path)
return span, ctx
}
// Load loads a virtcontainers item from a Store.
func (s *Store) Load(item Item, data interface{}) error {
span, _ := s.trace("Load")
defer span.Finish()
span.SetTag("item", item)
s.RLock()
defer s.RUnlock()
return nil
}
// Store stores a virtcontainers item into a Store.
func (s *Store) Store(item Item, data interface{}) error {
span, _ := s.trace("Store")
defer span.Finish()
span.SetTag("item", item)
s.Lock()
defer s.Unlock()
return nil
}

View File

@ -0,0 +1,21 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package store
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewStore(t *testing.T) {
s, err := New(context.Background(), "file:///root/")
assert.Nil(t, err)
assert.Equal(t, s.scheme, "file")
assert.Equal(t, s.host, "")
assert.Equal(t, s.path, "/root/")
}