mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-28 11:34:40 +01:00
Add a `store.SetLogger()` API to allow the store package to log with the standard set of fields (as expected by the log parser [1]. Fixes #1297. --- [1] - https://github.com/kata-containers/tests/tree/master/cmd/log-parser#logfile-requirements Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
281 lines
5.4 KiB
Go
281 lines
5.4 KiB
Go
// Copyright (c) 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package store
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"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
|
|
|
|
backend backend
|
|
}
|
|
|
|
type manager struct {
|
|
sync.RWMutex
|
|
stores map[string]*Store
|
|
}
|
|
|
|
var stores = &manager{stores: make(map[string]*Store)}
|
|
|
|
func (m *manager) addStore(s *Store) (err error) {
|
|
if s == nil {
|
|
return fmt.Errorf("Store can not be nil")
|
|
}
|
|
|
|
if s.url == "" {
|
|
return fmt.Errorf("Store URL can not be nil")
|
|
}
|
|
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
if m.stores[s.url] != nil {
|
|
return fmt.Errorf("Store %s already added", s.url)
|
|
}
|
|
|
|
m.stores[s.url] = s
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *manager) removeStore(url string) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
|
|
delete(m.stores, url)
|
|
}
|
|
|
|
func (m *manager) findStore(url string) *Store {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
|
|
return m.stores[url]
|
|
}
|
|
|
|
// 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) {
|
|
// Do we already have such store?
|
|
if s := stores.findStore(storeURL); s != nil {
|
|
return s, nil
|
|
}
|
|
|
|
u, err := url.Parse(storeURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s := &Store{
|
|
ctx: ctx,
|
|
url: storeURL,
|
|
scheme: u.Scheme,
|
|
path: u.Path,
|
|
host: u.Host,
|
|
}
|
|
|
|
backend, err := newBackend(s.scheme)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.backend = backend
|
|
|
|
// Create new backend
|
|
if err := s.backend.new(ctx, s.path, s.host); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := stores.addStore(s); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
// DeleteAll deletes all Stores from the manager.
|
|
func DeleteAll() {
|
|
for _, s := range stores.stores {
|
|
s.Delete()
|
|
}
|
|
}
|
|
|
|
var storeLog = logrus.WithField("source", "virtcontainers/store")
|
|
|
|
// SetLogger sets the custom logger to be used by this package. If not called,
|
|
// the package will create its own logger.
|
|
func SetLogger(logger *logrus.Entry) {
|
|
fields := storeLog.Data
|
|
storeLog = logger.WithFields(fields)
|
|
}
|
|
|
|
// 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 s.backend.load(item, data)
|
|
}
|
|
|
|
// 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 s.backend.store(item, data)
|
|
}
|
|
|
|
// Delete deletes all artifacts created by a Store.
|
|
// The Store is also removed from the manager.
|
|
func (s *Store) Delete() error {
|
|
span, _ := s.trace("Store")
|
|
defer span.Finish()
|
|
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
|
|
if err := s.backend.delete(); err != nil {
|
|
return err
|
|
}
|
|
|
|
stores.removeStore(s.url)
|
|
s.url = ""
|
|
|
|
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)
|
|
}
|
|
|
|
// ItemLock takes a lock on an item.
|
|
func (s *Store) ItemLock(item Item, exclusive bool) (string, error) {
|
|
return s.backend.lock(item, exclusive)
|
|
}
|
|
|
|
// ItemUnlock unlocks an item.
|
|
func (s *Store) ItemUnlock(item Item, token string) error {
|
|
return s.backend.unlock(item, token)
|
|
}
|