Basic functionality of wwctl vnfs build worked out
This commit is contained in:
@@ -19,7 +19,7 @@ var (
|
||||
|
||||
func init() {
|
||||
baseCmd.PersistentFlags().BoolVarP(&BuildAll, "all", "a", false, "Build all overlays (runtime and system)")
|
||||
baseCmd.PersistentFlags().BoolVarP(&ByNode, "node", "n", false, "Build overlay for a particular node")
|
||||
baseCmd.PersistentFlags().BoolVarP(&ByNode, "node", "n", false, "Build overlay for a particular node(s)")
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
|
||||
57
internal/app/wwctl/vnfs/build/main.go
Normal file
57
internal/app/wwctl/vnfs/build/main.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
"github.com/hpcng/warewulf/internal/pkg/vnfs"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
var nodes []assets.NodeInfo
|
||||
set := make(map[string]int)
|
||||
|
||||
if len(args) == 1 && ByNode == true {
|
||||
var err error
|
||||
nodes, err = assets.SearchByName(args[0])
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not find nodes for search term: %s\n", args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
set[node.Vnfs] ++
|
||||
}
|
||||
|
||||
} else if BuildAll == true {
|
||||
var err error
|
||||
nodes, err = assets.FindAllNodes()
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not get list of nodes: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
set[node.Vnfs] ++
|
||||
}
|
||||
|
||||
} else if len(args) == 1 {
|
||||
set[args[0]] ++
|
||||
} else {
|
||||
cmd.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for v := range set {
|
||||
fmt.Printf("Building VNFS: %s\n", v)
|
||||
err := vnfs.Build(v, BuildForce)
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
28
internal/app/wwctl/vnfs/build/root.go
Normal file
28
internal/app/wwctl/vnfs/build/root.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package build
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
var (
|
||||
baseCmd = &cobra.Command{
|
||||
Use: "build (vnfs location | node search pattern)",
|
||||
Short: "VNFS Image Build",
|
||||
Long: "VNFS kernel images",
|
||||
RunE: CobraRunE,
|
||||
Args: cobra.RangeArgs(0,1),
|
||||
|
||||
}
|
||||
BuildForce bool
|
||||
BuildAll bool
|
||||
ByNode bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
baseCmd.PersistentFlags().BoolVarP(&BuildAll, "all", "a", false, "(re)Build all VNFS images for all nodes")
|
||||
baseCmd.PersistentFlags().BoolVarP(&BuildForce, "force", "f", false, "Force rebuild, even if it isn't necessary")
|
||||
baseCmd.PersistentFlags().BoolVarP(&ByNode, "node", "n", false, "Build VNFS for a particular node(s)")
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
return baseCmd
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package vnfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/app/wwctl/vnfs/build"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -10,13 +10,12 @@ var (
|
||||
Use: "vnfs",
|
||||
Short: "VNFS image management",
|
||||
Long: "Virtual Node File System (VNFS) image management",
|
||||
RunE: CobraRunE,
|
||||
}
|
||||
test bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
baseCmd.PersistentFlags().BoolVarP(&test, "test", "t", false, "Testing.")
|
||||
baseCmd.AddCommand(build.GetCommand())
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +24,3 @@ func GetCommand() *cobra.Command {
|
||||
return baseCmd
|
||||
}
|
||||
|
||||
func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf("Vnfs: Hello World\n")
|
||||
return nil
|
||||
}
|
||||
64
internal/pkg/vnfs/containerdir.go
Normal file
64
internal/pkg/vnfs/containerdir.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package vnfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/config"
|
||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
func BuildContainerdir(v VnfsObject, buildForce bool) {
|
||||
config := config.New()
|
||||
|
||||
if _, err := os.Stat(v.Source()); err != nil {
|
||||
wwlog.Printf(wwlog.INFO, "%-35s: Skipping (bad path)\n", v.Name())
|
||||
return
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.DEBUG, "Checking if there have been any updates to the VNFS directory\n")
|
||||
if util.PathIsNewer(v.Source(), config.VnfsImage(v.NameClean())) {
|
||||
if buildForce == false {
|
||||
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", v.Name())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.DEBUG, "Making the directory: %s\n", path.Dir(config.VnfsImage(v.NameClean())))
|
||||
err := os.MkdirAll(path.Dir(config.VnfsImage(v.NameClean())), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.DEBUG, "Making the directory: %s\n", path.Dir(config.VnfsChroot(v.NameClean())))
|
||||
err = os.MkdirAll(path.Dir(config.VnfsChroot(v.NameClean())), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.DEBUG, "Building VNFS image: '%s' -> '%s'\n", v.Source(), config.VnfsImage(v.NameClean()))
|
||||
err = buildVnfs(v.Source(), config.VnfsImage(v.NameClean()))
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Setup links from OCI rootfs to chroot path
|
||||
_ = os.Remove(config.VnfsChroot(v.NameClean()) + "-link")
|
||||
err = os.Symlink(v.Source(), config.VnfsChroot(v.NameClean())+"-link")
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Chroot: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = os.Rename(config.VnfsChroot(v.NameClean())+"-link", config.VnfsChroot(v.NameClean()))
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", v.Name())
|
||||
|
||||
}
|
||||
101
internal/pkg/vnfs/docker.go
Normal file
101
internal/pkg/vnfs/docker.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package vnfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/hpcng/warewulf/internal/pkg/config"
|
||||
"github.com/hpcng/warewulf/internal/pkg/oci"
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
|
||||
func BuildDocker(v VnfsObject, buildForce bool) {
|
||||
wwlog.Printf(wwlog.VERBOSE, "Building OCI Container: %s\n", v.Source())
|
||||
config := config.New()
|
||||
|
||||
OciCacheDir := config.LocalStateDir + "/oci"
|
||||
VnfsHashDir := config.LocalStateDir + "/oci/vnfs"
|
||||
|
||||
c, err := oci.NewCache(oci.OptSetCachePath(OciCacheDir))
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Downloading OCI container layers\n")
|
||||
sourcePath, err := c.Pull(context.Background(), v.Source(), nil)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
hashDestination := VnfsHashDir + path.Base(sourcePath)
|
||||
|
||||
name, err := os.Readlink(config.VnfsImage(v.NameClean()))
|
||||
if err == nil {
|
||||
if name == hashDestination && buildForce == false {
|
||||
wwlog.Printf(wwlog.INFO, "%-35s: Skipping, VNFS is current\n", v.Name())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = os.MkdirAll(VnfsHashDir, 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
err = os.MkdirAll(path.Dir(config.VnfsImage(v.NameClean())), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
err = os.MkdirAll(path.Dir(config.VnfsChroot(v.NameClean())), 0755)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Building bootable VNFS image\n")
|
||||
|
||||
err = buildVnfs(sourcePath, hashDestination)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Finalizing Build\n")
|
||||
|
||||
// Setup links from OCI image to provision path
|
||||
_ = os.Remove(config.VnfsImage(v.NameClean()) + "-link")
|
||||
err = os.Symlink(hashDestination, config.VnfsImage(v.NameClean())+"-link")
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Image: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = os.Rename(config.VnfsImage(v.NameClean())+"-link", config.VnfsImage(v.NameClean()))
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Setup links from OCI rootfs to chroot path
|
||||
_ = os.Remove(config.VnfsChroot(v.NameClean()) + "-link")
|
||||
err = os.Symlink(sourcePath, config.VnfsChroot(v.NameClean())+"-link")
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not create symlink for Chroot: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = os.Rename(config.VnfsChroot(v.NameClean())+"-link", config.VnfsChroot(v.NameClean()))
|
||||
if err != nil {
|
||||
wwlog.Printf(wwlog.ERROR, "Could not rename link: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
||||
wwlog.Printf(wwlog.INFO, "%-35s: Done\n", v.Name())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
14
internal/pkg/vnfs/util.go
Normal file
14
internal/pkg/vnfs/util.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package vnfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func buildVnfs(source string, dest string) error {
|
||||
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s\"", source, dest)
|
||||
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run()
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package vnfs
|
||||
|
||||
import (
|
||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type VnfsObject struct {
|
||||
SourcePath string
|
||||
SourcePath string
|
||||
}
|
||||
|
||||
func New(s string) VnfsObject {
|
||||
@@ -48,4 +49,22 @@ func (self *VnfsObject) Source() string {
|
||||
}
|
||||
|
||||
return self.SourcePath
|
||||
}
|
||||
}
|
||||
|
||||
func Build(uri string, force bool) error {
|
||||
v := New(uri)
|
||||
|
||||
wwlog.Printf(wwlog.VERBOSE, "Building VNFS: %s\n", uri)
|
||||
if strings.HasPrefix(uri, "/") {
|
||||
if strings.HasSuffix(uri, "tar.gz") {
|
||||
//wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball: %s\n", uri)
|
||||
wwlog.Printf(wwlog.WARN, "Building VNFS from local tarball is not supported yet: %s\n", uri)
|
||||
} else {
|
||||
BuildContainerdir(v, force)
|
||||
}
|
||||
} else {
|
||||
BuildDocker(v, force)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user