Skip to content

Commit

Permalink
Adding crio implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Vishesh Tanksale <[email protected]>
  • Loading branch information
visheshtanksale committed Jul 13, 2024
1 parent 6d8c662 commit bf10744
Show file tree
Hide file tree
Showing 7 changed files with 411 additions and 66 deletions.
107 changes: 48 additions & 59 deletions cmd/k8s-kata-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"path/filepath"
"strconv"
"syscall"
"time"

"github.com/pelletier/go-toml"
"github.com/urfave/cli/v2"
Expand All @@ -42,12 +41,14 @@ import (
"github.com/NVIDIA/k8s-kata-manager/internal/oras"
"github.com/NVIDIA/k8s-kata-manager/internal/runtime"
containerd "github.com/NVIDIA/k8s-kata-manager/internal/runtime/containerd"
"github.com/NVIDIA/k8s-kata-manager/internal/runtime/crio"
"github.com/NVIDIA/k8s-kata-manager/internal/version"
)

const (
defaultContainerdConfigFilePath = "/etc/containerd/config.toml"
defaultContainerdSocketFilePath = "/run/containerd/containerd.sock"
defaultCrioConfigFilePath = "/etc/crio/crio.conf"

cdiRoot = "/var/run/cdi"
)
Expand All @@ -74,6 +75,8 @@ type worker struct {
ContainerdSocket string
LoadKernelModules bool
CDIEnabled bool
Runtime string
CrioConfig string
}

// newWorker returns a new worker struct
Expand Down Expand Up @@ -146,6 +149,20 @@ func main() {
Destination: &worker.CDIEnabled,
EnvVars: []string{"CDI_ENABLED"},
},
&cli.StringFlag{
Name: "runtime",
Usage: "Runtime name",
Value: "",
Destination: &worker.Runtime,
EnvVars: []string{"RUNTIME"},
},
&cli.StringFlag{
Name: "crio-config",
Usage: "Path to the CRI-O config file",
Value: defaultCrioConfigFilePath,
Destination: &worker.CrioConfig,
EnvVars: []string{"CRIO_CONFIG"},
},
}

c.Before = func(c *cli.Context) error {
Expand Down Expand Up @@ -245,9 +262,7 @@ func (w *worker) Run(c *cli.Context) error {
return fmt.Errorf("failed to generate CDI spec: %w", err)
}
}

options := runtime.Options{Path: w.ContainerdConfig, RuntimeType: "io.containerd.kata.v2", PodAnnotations: []string{"io.katacontainers.*"}}
ctrdConfig, err := containerd.Setup(&options)
runtimeConfig, err := w.getRuntimeConfig()
if err != nil {
klog.Errorf("error creating containerd.config client : %s", err)
return err
Expand Down Expand Up @@ -292,7 +307,7 @@ func (w *worker) Run(c *cli.Context) error {
return fmt.Errorf("error transforming kata configuration file: %w", err)
}

err = ctrdConfig.AddRuntime(
err = runtimeConfig.AddRuntime(
rc.Name,
kataConfigPath,
false,
Expand All @@ -302,23 +317,21 @@ func (w *worker) Run(c *cli.Context) error {
}

}

n, err := ctrdConfig.Save(w.ContainerdConfig)
n, err := runtimeConfig.Save()
if err != nil {
return fmt.Errorf("unable to flush config: %w", err)
}

if n == 0 {
klog.Infof("Removed empty config from %v", w.ContainerdConfig)
klog.Infof("Removed empty config")
} else {
klog.Infof("Wrote updated config to %v", w.ContainerdConfig)
klog.Infof("Wrote updated config")
}

klog.Infof("Restarting containerd")
if err := restartContainerd(w.ContainerdSocket); err != nil {
return fmt.Errorf("unable to restart containerd: %w", err)
klog.Infof("Restarting runtime")
if err := runtimeConfig.Restart(); err != nil {
return fmt.Errorf("unable to restart runtime service: %w", err)
}
klog.Info("containerd successfully restarted")
klog.Info("runtime successfully restarted")

if err := waitForSignal(); err != nil {
return fmt.Errorf("unable to wait for signal: %w", err)
Expand All @@ -331,7 +344,25 @@ func (w *worker) Run(c *cli.Context) error {
return nil
}

// CleanUp reverts the containerd config to remove the nvidia-container-runtime
func (w *worker) getRuntimeConfig() (runtime.Runtime, error) {
var ctrdConfig runtime.Runtime
var err error
klog.Infof("Vishesh RUNTIME %s", w.Runtime)
if w.Runtime == "crio" {
options := runtime.Options{Path: w.CrioConfig, RuntimeType: "vm", PodAnnotations: []string{"io.katacontainers.*"}}
ctrdConfig, err = crio.Setup(&options)
} else if w.Runtime == "containerd" {
options := runtime.Options{Path: w.ContainerdConfig, RuntimeType: "io.containerd.kata.v2", PodAnnotations: []string{"io.katacontainers.*"}, Socket: w.ContainerdSocket}
ctrdConfig, err = containerd.Setup(&options)
}
if err != nil {
klog.Errorf("error creating containerd.config client : %s", err)
return nil, err
}
return ctrdConfig, nil
}

// CleanUp reverts the runtime config added by kata manager
func (w *worker) CleanUp() error {
ctrdConfig, err := containerd.New(
containerd.WithPath(w.ContainerdConfig),
Expand All @@ -346,7 +377,7 @@ func (w *worker) CleanUp() error {
return fmt.Errorf("unable to revert config for runtime class '%v': %w", rc, err)
}
}
n, err := ctrdConfig.Save(w.ContainerdConfig)
n, err := ctrdConfig.Save()
if err != nil {
return fmt.Errorf("unable to flush config: %w", err)
}
Expand All @@ -356,7 +387,7 @@ func (w *worker) CleanUp() error {
} else {
klog.Infof("Wrote updated config to %v", w.ContainerdConfig)
}
if err := restartContainerd(w.ContainerdSocket); err != nil {
if err := ctrdConfig.Restart(); err != nil {
return fmt.Errorf("unable to restart containerd: %w", err)
}
return nil
Expand Down Expand Up @@ -385,48 +416,6 @@ func initialize() error {
return nil
}

func restartContainerd(containerdSocket string) error {

// Create a channel to receive signals
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGHUP)

// Set up a timer to ignore the signal for 5 seconds
ignoreTimer := time.NewTimer(5 * time.Second)

// Create a channel to signal when the function has finished executing
done := make(chan error)

// Start the function in a goroutine
go func() {
// Execute your function here
err := containerd.RestartContainerd(containerdSocket)
if err != nil {
klog.Errorf("error restarting containerd: %v", err)
done <- err
}
// Since we are restarintg Containerd we need to
// Ignore the SIGTERM signal for 5 seconds
<-ignoreTimer.C
// Signal that the function has finished executing
done <- nil
}()

// Wait for the function to finish executing or for the signal to be received
select {
case err := <-done:
if err != nil {
return err
}
case s := <-sigs:
fmt.Printf("Received signal %v", s)
// Reset the timer to ignore the signal for another 5 seconds
ignoreTimer.Reset(5 * time.Second)
}

return nil
}

func transformKataConfig(path string) error {
config, err := toml.LoadFile(path)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion internal/cdi/nvpci-interface_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 54 additions & 5 deletions internal/runtime/containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ package containerd
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"

"github.com/pelletier/go-toml"
"k8s.io/klog/v2"

"github.com/NVIDIA/k8s-kata-manager/internal/runtime"
)
Expand All @@ -31,13 +35,16 @@ type Config struct {
RuntimeType string
UseDefaultRuntimeName bool
PodAnnotations []string
Path string
Socket string
}

func Setup(o *runtime.Options) (runtime.Runtime, error) {
ctrdConfig, err := New(
WithPath(o.Path),
WithPodAnnotations(o.PodAnnotations...),
WithRuntimeType(o.RuntimeType),
WithSocket(o.Socket),
)
return ctrdConfig, err
}
Expand Down Expand Up @@ -134,29 +141,29 @@ func (c *Config) RemoveRuntime(name string) error {
}

// Save writes the config to the specified path
func (c *Config) Save(path string) (int64, error) {
func (c *Config) Save() (int64, error) {
config := c.Tree
output, err := config.ToTomlString()
if err != nil {
return 0, fmt.Errorf("unable to convert to TOML: %w", err)
}

if path == "" {
if c.Path == "" {
os.Stdout.WriteString(fmt.Sprintf("%s\n", output))
return int64(len(output)), nil
}

if len(output) == 0 {
err := os.Remove(path)
err := os.Remove(c.Path)
if err != nil {
return 0, fmt.Errorf("unable to remove empty file: %w", err)
}
return 0, nil
}

f, err := os.Create(path)
f, err := os.Create(c.Path)
if err != nil {
return 0, fmt.Errorf("unable to open '%s' for writing: %w", path, err)
return 0, fmt.Errorf("unable to open '%s' for writing: %w", c.Path, err)
}
defer f.Close()

Expand All @@ -167,3 +174,45 @@ func (c *Config) Save(path string) (int64, error) {

return int64(n), err
}

func (c *Config) Restart() error {

// Create a channel to receive signals
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGHUP)

// Set up a timer to ignore the signal for 5 seconds
ignoreTimer := time.NewTimer(5 * time.Second)

// Create a channel to signal when the function has finished executing
done := make(chan error)

// Start the function in a goroutine
go func() {
// Execute your function here
err := RestartContainerd(c.Socket)
if err != nil {
klog.Errorf("error restarting containerd: %v", err)
done <- err
}
// Since we are restarintg Containerd we need to
// Ignore the SIGTERM signal for 5 seconds
<-ignoreTimer.C
// Signal that the function has finished executing
done <- nil
}()

// Wait for the function to finish executing or for the signal to be received
select {
case err := <-done:
if err != nil {
return err
}
case s := <-sigs:
fmt.Printf("Received signal %v", s)
// Reset the timer to ignore the signal for another 5 seconds
ignoreTimer.Reset(5 * time.Second)
}

return nil
}
10 changes: 10 additions & 0 deletions internal/runtime/containerd/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type builder struct {
runtimeType string
useLegacyConfig bool
podAnnotations []string
socket string
}

// Option defines a function that can be used to configure the config builder
Expand Down Expand Up @@ -66,6 +67,13 @@ func WithPodAnnotations(podAnnotations ...string) Option {
}
}

// WithSocket sets the socket for the config builder
func WithSocket(socket string) Option {
return func(b *builder) {
b.socket = socket
}
}

func (b *builder) build() (*Config, error) {
if b.path == "" {
return &Config{}, fmt.Errorf("config path is empty")
Expand All @@ -82,6 +90,8 @@ func (b *builder) build() (*Config, error) {
config.RuntimeType = b.runtimeType
config.UseDefaultRuntimeName = !b.useLegacyConfig
config.PodAnnotations = b.podAnnotations
config.Path = b.path
config.Socket = b.socket

return config, nil
}
Expand Down
Loading

0 comments on commit bf10744

Please sign in to comment.