forked from kata-containers/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
manager.go
281 lines (216 loc) · 5.45 KB
/
manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
// 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
// UUID represents a set of uuids item to be stored.
UUID
)
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) (rs *Store, err error) {
if s == nil {
return nil, fmt.Errorf("Store can not be nil")
}
if s.url == "" {
return nil, fmt.Errorf("Store URL can not be nil")
}
m.Lock()
defer m.Unlock()
if m.stores[s.url] == nil {
m.stores[s.url] = s
}
return m.stores[s.url], 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 s, 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)
}