mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-11-01 05:56:41 +00:00
infrakit: Move the hyperkit instance plugin into the source directory
- The tools directory ideally should not contain source code - Removes double vendoring of packagages - Makes it easer to hook the build into the top-level Makefile Eventually, the plugin should be moved to the infrakit repo. Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
This commit is contained in:
30
src/cmd/infrakit-instance-hyperkit/hyperkit.json
Normal file
30
src/cmd/infrakit-instance-hyperkit/hyperkit.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"ID": "cattle",
|
||||
"Properties": {
|
||||
"Allocation": {
|
||||
"Size": 1
|
||||
},
|
||||
"Instance": {
|
||||
"Plugin": "instance-hyperkit",
|
||||
"Properties": {
|
||||
"Moby": "../../moby",
|
||||
"Disk" : 512,
|
||||
"CPUs" : 2,
|
||||
"Memory" : 1024
|
||||
}
|
||||
},
|
||||
"Flavor": {
|
||||
"Plugin": "flavor-vanilla",
|
||||
"Properties": {
|
||||
"Init": [
|
||||
"test1",
|
||||
"test2"
|
||||
],
|
||||
"Tags": {
|
||||
"tier": "sample",
|
||||
"project": "infrakit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
221
src/cmd/infrakit-instance-hyperkit/instance.go
Normal file
221
src/cmd/infrakit-instance-hyperkit/instance.go
Normal file
@@ -0,0 +1,221 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/docker/hyperkit/go"
|
||||
|
||||
"github.com/docker/infrakit/pkg/spi/instance"
|
||||
"github.com/docker/infrakit/pkg/types"
|
||||
)
|
||||
|
||||
// NewHyperKitPlugin creates an instance plugin for hyperkit.
|
||||
func NewHyperKitPlugin(vmDir, hyperkit, vpnkitSock string) instance.Plugin {
|
||||
return &hyperkitPlugin{VMDir: vmDir,
|
||||
HyperKit: hyperkit,
|
||||
VPNKitSock: vpnkitSock,
|
||||
}
|
||||
}
|
||||
|
||||
type hyperkitPlugin struct {
|
||||
// VMDir is the path to a directory where per VM state is kept
|
||||
VMDir string
|
||||
|
||||
// Hyperkit is the path to the hyperkit executable
|
||||
HyperKit string
|
||||
|
||||
// VPNKitSock is the path to the VPNKit Unix domain socket.
|
||||
VPNKitSock string
|
||||
}
|
||||
|
||||
// Validate performs local validation on a provision request.
|
||||
func (p hyperkitPlugin) Validate(req *types.Any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provision creates a new instance.
|
||||
func (p hyperkitPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
|
||||
|
||||
var properties map[string]interface{}
|
||||
|
||||
if spec.Properties != nil {
|
||||
if err := spec.Properties.Decode(&properties); err != nil {
|
||||
return nil, fmt.Errorf("Invalid instance properties: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if properties["Moby"] == nil {
|
||||
return nil, errors.New("Property 'Moby' must be set")
|
||||
}
|
||||
if properties["CPUs"] == nil {
|
||||
properties["CPUs"] = 1
|
||||
}
|
||||
if properties["Memory"] == nil {
|
||||
properties["Memory"] = 512
|
||||
}
|
||||
if properties["Disk"] == nil {
|
||||
properties["Disk"] = 256
|
||||
}
|
||||
|
||||
instanceDir, err := ioutil.TempDir(p.VMDir, "infrakit-")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id := instance.ID(path.Base(instanceDir))
|
||||
|
||||
// Start a HyperKit instance
|
||||
h, err := hyperkit.New(p.HyperKit, instanceDir, p.VPNKitSock, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.Kernel = properties["Moby"].(string) + "-bzImage"
|
||||
h.Initrd = properties["Moby"].(string) + "-initrd.img"
|
||||
h.CPUs = int(properties["CPUs"].(float64))
|
||||
h.Memory = int(properties["Memory"].(float64))
|
||||
h.DiskSize = int(properties["Disk"].(float64))
|
||||
h.UserData = spec.Init
|
||||
h.Console = hyperkit.ConsoleFile
|
||||
err = h.Start("console=ttyS0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Info("Started new VM: ", id)
|
||||
|
||||
tagData, err := types.AnyValue(spec.Tags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(path.Join(instanceDir, "tags"), tagData.Bytes(), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &id, nil
|
||||
}
|
||||
|
||||
// Label labels the instance
|
||||
func (p hyperkitPlugin) Label(instance instance.ID, labels map[string]string) error {
|
||||
instanceDir := path.Join(p.VMDir, string(instance))
|
||||
tagFile := path.Join(instanceDir, "tags")
|
||||
buff, err := ioutil.ReadFile(tagFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := map[string]string{}
|
||||
err = types.AnyBytes(buff).Decode(&tags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range labels {
|
||||
tags[k] = v
|
||||
}
|
||||
|
||||
encoded, err := types.AnyValue(tags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(tagFile, encoded.Bytes(), 0644)
|
||||
}
|
||||
|
||||
// Destroy terminates an existing instance.
|
||||
func (p hyperkitPlugin) Destroy(id instance.ID) error {
|
||||
log.Info("Destroying VM: ", id)
|
||||
|
||||
instanceDir := path.Join(p.VMDir, string(id))
|
||||
_, err := os.Stat(instanceDir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errors.New("Instance does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
h, err := hyperkit.FromState(instanceDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = h.Stop()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = h.Remove(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DescribeInstances returns descriptions of all instances matching all of the provided tags.
|
||||
func (p hyperkitPlugin) DescribeInstances(tags map[string]string) ([]instance.Description, error) {
|
||||
files, err := ioutil.ReadDir(p.VMDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
descriptions := []instance.Description{}
|
||||
|
||||
for _, file := range files {
|
||||
if !file.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
instanceDir := path.Join(p.VMDir, file.Name())
|
||||
|
||||
tagData, err := ioutil.ReadFile(path.Join(instanceDir, "tags"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
instanceTags := map[string]string{}
|
||||
if err := types.AnyBytes(tagData).Decode(&instanceTags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allMatched := true
|
||||
for k, v := range tags {
|
||||
value, exists := instanceTags[k]
|
||||
if !exists || v != value {
|
||||
allMatched = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if allMatched {
|
||||
var logicalID *instance.LogicalID
|
||||
id := instance.ID(file.Name())
|
||||
|
||||
h, err := hyperkit.FromState(instanceDir)
|
||||
if err != nil {
|
||||
log.Warningln("Could not get instance data. Id: ", id)
|
||||
p.Destroy(id)
|
||||
continue
|
||||
}
|
||||
if !h.IsRunning() {
|
||||
log.Warningln("Instance is not running. Id: ", id)
|
||||
p.Destroy(id)
|
||||
continue
|
||||
}
|
||||
lid := instance.LogicalID(h.Pid)
|
||||
logicalID = &lid
|
||||
|
||||
descriptions = append(descriptions, instance.Description{
|
||||
ID: id,
|
||||
LogicalID: logicalID,
|
||||
Tags: instanceTags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return descriptions, nil
|
||||
}
|
||||
89
src/cmd/infrakit-instance-hyperkit/main.go
Normal file
89
src/cmd/infrakit-instance-hyperkit/main.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/infrakit/pkg/cli"
|
||||
"github.com/docker/infrakit/pkg/plugin/metadata"
|
||||
instance_plugin "github.com/docker/infrakit/pkg/rpc/instance"
|
||||
metadata_plugin "github.com/docker/infrakit/pkg/rpc/metadata"
|
||||
instance_spi "github.com/docker/infrakit/pkg/spi/instance"
|
||||
)
|
||||
|
||||
var (
|
||||
// Version is the build release identifier.
|
||||
Version = "Unspecified"
|
||||
|
||||
// Revision is the build source control revision.
|
||||
Revision = "Unspecified"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: os.Args[0],
|
||||
Short: "HyperKit instance plugin",
|
||||
}
|
||||
|
||||
defaultVMDir := filepath.Join(getHome(), ".infrakit/hyperkit-vms")
|
||||
|
||||
name := cmd.Flags().String("name", "instance-hyperkit", "Plugin name to advertise for discovery")
|
||||
logLevel := cmd.Flags().Int("log", cli.DefaultLogLevel, "Logging level. 0 is least verbose. Max is 5")
|
||||
|
||||
vmDir := cmd.Flags().String("vm-dir", defaultVMDir, "Directory where to store VM state")
|
||||
hyperkit := cmd.Flags().String("hyperkit", "", "Path to HyperKit executable")
|
||||
|
||||
vpnkitSock := cmd.Flags().String("vpnkit-sock", "auto", "Path to VPNKit UNIX domain socket")
|
||||
|
||||
cmd.RunE = func(c *cobra.Command, args []string) error {
|
||||
os.MkdirAll(*vmDir, os.ModePerm)
|
||||
|
||||
cli.SetLogLevel(*logLevel)
|
||||
cli.RunPlugin(*name,
|
||||
instance_plugin.PluginServer(NewHyperKitPlugin(*vmDir, *hyperkit, *vpnkitSock)),
|
||||
metadata_plugin.PluginServer(metadata.NewPluginFromData(
|
||||
map[string]interface{}{
|
||||
"version": Version,
|
||||
"revision": Revision,
|
||||
"implements": instance_spi.InterfaceSpec,
|
||||
},
|
||||
)),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd.AddCommand(&cobra.Command{
|
||||
Use: "version",
|
||||
Short: "print build version information",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
buff, err := json.MarshalIndent(map[string]interface{}{
|
||||
"version": Version,
|
||||
"revision": Revision,
|
||||
}, " ", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(buff))
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
log.Error(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func getHome() string {
|
||||
if usr, err := user.Current(); err == nil {
|
||||
return usr.HomeDir
|
||||
}
|
||||
return os.Getenv("HOME")
|
||||
}
|
||||
Reference in New Issue
Block a user