Skip to content

Commit 76552be

Browse files
authored
Merge pull request #5961 from oasisprotocol/peternose/feature/hot-loading
go/runtime: Support hot-loading of runtime bundles
2 parents 907d604 + 3716fee commit 76552be

File tree

50 files changed

+2796
-1043
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2796
-1043
lines changed

.changelog/5962.cfg.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
go/runtime: Support hot-loading of runtime bundles
2+
3+
The node can now fetch and verify runtime bundles from remote repositories
4+
and automatically update to new versions.
5+
6+
The following configuration option has been removed:
7+
8+
- `runtime.components`
9+
10+
The following configuration option has been deprecated:
11+
12+
- `runtime.config`
13+
14+
The following configuration options have been added:
15+
16+
- `runtime.runtimes.id` is the runtime identifier,
17+
18+
- `runtime.runtimes.components` is the list of components to configure,
19+
20+
- `runtime.runtimes.config` is the runtime local configuration,
21+
22+
- `runtime.runtimes.repositories` is the list of runtime specific URLs
23+
used to fetch runtime bundle metadata,
24+
25+
- `runtime.repositories` is the list of global URLs used to fetch
26+
runtime bundle metadata,
27+
28+
- `runtime.max_bundle_size` is the maximum allowed bundle size.

go/common/version/version.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ func (v Version) ValidateBasic() error {
3939
return nil
4040
}
4141

42+
// Cmp returns a negative number when the given version is larger, a positive
43+
// number when smaller, and zero when both versions are equal.
44+
func (v Version) Cmp(other Version) int {
45+
if v.Major != other.Major {
46+
return int(v.Major) - int(other.Major)
47+
}
48+
if v.Minor != other.Minor {
49+
return int(v.Minor) - int(other.Minor)
50+
}
51+
return int(v.Patch) - int(other.Patch)
52+
}
53+
4254
// ToU64 returns the version as platform-dependent uint64.
4355
func (v Version) ToU64() uint64 {
4456
return (uint64(v.Major) << 32) | (uint64(v.Minor) << 16) | (uint64(v.Patch))

go/control/api/api.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ import (
1111
"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
1212
"github.com/oasisprotocol/oasis-core/go/common/errors"
1313
"github.com/oasisprotocol/oasis-core/go/common/node"
14+
"github.com/oasisprotocol/oasis-core/go/common/version"
1415
"github.com/oasisprotocol/oasis-core/go/config"
1516
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
1617
p2p "github.com/oasisprotocol/oasis-core/go/p2p/api"
1718
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
1819
block "github.com/oasisprotocol/oasis-core/go/roothash/api/block"
20+
"github.com/oasisprotocol/oasis-core/go/runtime/bundle/component"
1921
storage "github.com/oasisprotocol/oasis-core/go/storage/api"
2022
upgrade "github.com/oasisprotocol/oasis-core/go/upgrade/api"
2123
commonWorker "github.com/oasisprotocol/oasis-core/go/worker/common/api"
@@ -85,6 +87,9 @@ type Status struct {
8587
// Runtimes is the status overview for each runtime supported by the node.
8688
Runtimes map[common.Namespace]RuntimeStatus `json:"runtimes,omitempty"`
8789

90+
// Bundles is the status overview of known runtime bundles.
91+
Bundles []BundleStatus `json:"bundles,omitempty"`
92+
8893
// Registration is the node's registration status.
8994
Registration *RegistrationStatus `json:"registration,omitempty"`
9095

@@ -188,6 +193,37 @@ type RuntimeStatus struct {
188193
Provisioner string `json:"provisioner,omitempty"`
189194
}
190195

196+
// BundleStatus is the per-runtime bundle status overview.
197+
type BundleStatus struct {
198+
// Name is the optional human readable runtime name.
199+
Name string `json:"name,omitempty"`
200+
201+
// ID is the runtime identifier.
202+
ID common.Namespace `json:"id"`
203+
204+
// Components contains statuses of the runtime components.
205+
Components []ComponentStatus `json:"components,omitempty"`
206+
}
207+
208+
// ComponentStatus is the component status overview.
209+
type ComponentStatus struct {
210+
// Kind is the component kind.
211+
Kind component.Kind `json:"kind"`
212+
213+
// Name is the name of the component.
214+
Name string `json:"name,omitempty"`
215+
216+
// Version is the component version.
217+
Version version.Version `json:"version,omitempty"`
218+
219+
// Detached specifies whether the component was in a detached bundle.
220+
Detached bool `json:"detached,omitempty"`
221+
222+
// Disabled specifies whether the component is disabled by default
223+
// and needs to be explicitly enabled via node configuration to be used.
224+
Disabled bool `json:"disabled,omitempty"`
225+
}
226+
191227
// SeedStatus is the status of the seed node.
192228
type SeedStatus struct {
193229
// ChainContext is the chain domain separation context.

go/oasis-net-runner/fixtures/default.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,11 @@ func newDefaultFixture() (*oasis.NetworkFixture, error) {
241241
GovernanceModel: registry.GovernanceEntity,
242242
Deployments: []oasis.DeploymentCfg{
243243
{
244-
Version: rtVersion,
245244
ValidFrom: 0,
246245
Components: []oasis.ComponentCfg{
247246
{
248-
Kind: component.RONL,
247+
Kind: component.RONL,
248+
Version: rtVersion,
249249
Binaries: map[node.TEEHardware]string{
250250
tee: rt,
251251
},

go/oasis-node/cmd/node/flags.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/flags"
1010
cmdGrpc "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/grpc"
1111
cmdSigner "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/signer"
12-
runtimeRegistry "github.com/oasisprotocol/oasis-core/go/runtime/registry"
12+
"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
1313
workerStorage "github.com/oasisprotocol/oasis-core/go/worker/storage"
1414
)
1515

@@ -38,7 +38,7 @@ func init() {
3838
for _, v := range []*flag.FlagSet{
3939
cmdGrpc.ServerLocalFlags,
4040
cmdSigner.Flags,
41-
runtimeRegistry.Flags,
41+
bundle.Flags,
4242
workerStorage.Flags,
4343
crash.InitFlags(),
4444
} {

go/oasis-node/cmd/node/node.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func (n *Node) initRuntimeWorkers() error {
232232
if err != nil {
233233
return err
234234
}
235-
n.svcMgr.RegisterCleanupOnly(n.RuntimeRegistry, "runtime registry")
235+
n.svcMgr.Register(n.RuntimeRegistry)
236236

237237
// Initialize the common worker.
238238
n.CommonWorker, err = workerCommon.New(
@@ -353,6 +353,11 @@ func (n *Node) initRuntimeWorkers() error {
353353
}
354354

355355
func (n *Node) startRuntimeWorkers() error {
356+
// Start the runtime registry.
357+
if err := n.RuntimeRegistry.Start(); err != nil {
358+
return err
359+
}
360+
356361
// Start the common worker.
357362
if err := n.CommonWorker.Start(); err != nil {
358363
return err

go/oasis-node/cmd/node/node_control.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ func (n *Node) GetStatus(ctx context.Context) (*control.Status, error) {
135135
return nil, fmt.Errorf("failed to get runtime status: %w", err)
136136
}
137137

138+
bundles, err := n.getBundleStatus()
139+
if err != nil {
140+
return nil, fmt.Errorf("failed to get bundle status: %w", err)
141+
}
142+
138143
kms, err := n.getKeymanagerStatus()
139144
if err != nil {
140145
return nil, fmt.Errorf("failed to get key manager worker status: %w", err)
@@ -165,6 +170,7 @@ func (n *Node) GetStatus(ctx context.Context) (*control.Status, error) {
165170
Consensus: cs,
166171
LightClient: lcs,
167172
Runtimes: runtimes,
173+
Bundles: bundles,
168174
Keymanager: kms,
169175
Registration: rs,
170176
PendingUpgrades: pendingUpgrades,
@@ -199,6 +205,10 @@ func (n *Node) getRuntimeStatus(ctx context.Context) (map[common.Namespace]contr
199205
runtimes := make(map[common.Namespace]control.RuntimeStatus)
200206

201207
for _, rt := range n.RuntimeRegistry.Runtimes() {
208+
if !rt.IsManaged() {
209+
continue
210+
}
211+
202212
var status control.RuntimeStatus
203213

204214
// Fetch runtime registry descriptor. Do not wait too long for the descriptor to become
@@ -343,6 +353,41 @@ func (n *Node) getRuntimeStatus(ctx context.Context) (map[common.Namespace]contr
343353
return runtimes, nil
344354
}
345355

356+
func (n *Node) getBundleStatus() ([]control.BundleStatus, error) {
357+
bundleRegistry := n.RuntimeRegistry.GetBundleRegistry()
358+
manifests := bundleRegistry.GetManifests()
359+
bundles := make([]control.BundleStatus, 0, len(manifests))
360+
361+
for _, manifest := range manifests {
362+
explodedComponents, err := bundleRegistry.GetComponents(manifest.ID, manifest.GetVersion())
363+
if err != nil {
364+
return nil, err
365+
}
366+
367+
components := make([]control.ComponentStatus, 0, len(explodedComponents))
368+
for _, comp := range explodedComponents {
369+
component := control.ComponentStatus{
370+
Kind: comp.Kind,
371+
Name: comp.Name,
372+
Version: comp.Version,
373+
Detached: comp.Detached,
374+
Disabled: comp.Disabled,
375+
}
376+
components = append(components, component)
377+
}
378+
379+
bundle := control.BundleStatus{
380+
Name: manifest.Name,
381+
ID: manifest.ID,
382+
Components: components,
383+
}
384+
385+
bundles = append(bundles, bundle)
386+
}
387+
388+
return bundles, nil
389+
}
390+
346391
func (n *Node) getKeymanagerStatus() (*keymanagerWorker.Status, error) {
347392
if n.KeymanagerWorker == nil || !n.KeymanagerWorker.Enabled() {
348393
return nil, nil

go/oasis-node/cmd/storage/storage.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/oasisprotocol/oasis-core/go/config"
1818
cmdCommon "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common"
1919
roothash "github.com/oasisprotocol/oasis-core/go/roothash/api"
20+
"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
2021
"github.com/oasisprotocol/oasis-core/go/runtime/history"
2122
"github.com/oasisprotocol/oasis-core/go/runtime/registry"
2223
db "github.com/oasisprotocol/oasis-core/go/storage/mkvs/db/api"
@@ -284,8 +285,8 @@ func doRenameNs(_ *cobra.Command, args []string) error {
284285

285286
// Register registers the client sub-command and all of its children.
286287
func Register(parentCmd *cobra.Command) {
287-
storageMigrateCmd.Flags().AddFlagSet(registry.Flags)
288-
storageCheckCmd.Flags().AddFlagSet(registry.Flags)
288+
storageMigrateCmd.Flags().AddFlagSet(bundle.Flags)
289+
storageCheckCmd.Flags().AddFlagSet(bundle.Flags)
289290
storageCmd.AddCommand(storageMigrateCmd)
290291
storageCmd.AddCommand(storageCheckCmd)
291292
storageCmd.AddCommand(storageRenameNsCmd)

go/oasis-node/node_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ import (
3535
registryTests "github.com/oasisprotocol/oasis-core/go/registry/tests"
3636
roothash "github.com/oasisprotocol/oasis-core/go/roothash/api"
3737
roothashTests "github.com/oasisprotocol/oasis-core/go/roothash/tests"
38+
"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
3839
runtimeClient "github.com/oasisprotocol/oasis-core/go/runtime/client/api"
3940
clientTests "github.com/oasisprotocol/oasis-core/go/runtime/client/tests"
4041
runtimeConfig "github.com/oasisprotocol/oasis-core/go/runtime/config"
41-
runtimeRegistry "github.com/oasisprotocol/oasis-core/go/runtime/registry"
4242
scheduler "github.com/oasisprotocol/oasis-core/go/scheduler/api"
4343
schedulerTests "github.com/oasisprotocol/oasis-core/go/scheduler/tests"
4444
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
@@ -164,7 +164,7 @@ func newTestNode(t *testing.T) *testNode {
164164

165165
config.GlobalConfig.Common.DataDir = dataDir
166166
config.GlobalConfig.Common.Log.File = filepath.Join(dataDir, "test-node.log")
167-
viper.Set(runtimeRegistry.CfgDebugMockIDs, []string{
167+
viper.Set(bundle.CfgDebugMockIDs, []string{
168168
testRuntimeID.String(),
169169
})
170170
for _, kv := range testNodeStaticConfig {

go/oasis-test-runner/oasis/keymanager.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/env"
1818
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
1919
"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
20+
runtimeCfg "github.com/oasisprotocol/oasis-core/go/runtime/config"
2021
runtimeConfig "github.com/oasisprotocol/oasis-core/go/runtime/config"
2122
keymanagerConfig "github.com/oasisprotocol/oasis-core/go/worker/keymanager/config"
2223
)
@@ -296,7 +297,14 @@ func (km *Keymanager) ModifyConfig() error {
296297
km.Config.Runtime.Provisioner = km.runtimeProvisioner
297298
km.Config.Runtime.SGXLoader = km.net.cfg.RuntimeSGXLoaderBinary
298299
km.Config.Runtime.AttestInterval = km.net.cfg.RuntimeAttestInterval
300+
301+
rtCfg := runtimeCfg.RuntimeConfig{
302+
ID: km.runtime.cfgSave.id,
303+
}
304+
305+
km.Config.Runtime.Runtimes = append(km.Config.Runtime.Runtimes, rtCfg)
299306
km.Config.Runtime.Paths = append(km.Config.Runtime.Paths, km.runtime.BundlePaths()...)
307+
km.Config.Runtime.Repositories = []string{fmt.Sprintf("http://127.0.0.1:%d", km.net.getProvisionedPort(netPortRepository))}
300308

301309
km.Config.Keymanager.RuntimeID = km.runtime.ID().String()
302310
km.Config.Keymanager.PrivatePeerPubKeys = km.privatePeerPubKeys

0 commit comments

Comments
 (0)