commit
1548cb78e9
|
@ -1,9 +1,14 @@
|
|||
language: go
|
||||
os: linux
|
||||
sudo: require
|
||||
dist: trusty
|
||||
|
||||
go:
|
||||
- 1.7.1
|
||||
go_import_path: k8s.io/minikube
|
||||
|
||||
install:
|
||||
- echo "Don't run anything."
|
||||
- sudo apt-get -qqy install libvirt-dev
|
||||
script:
|
||||
- make test
|
||||
after_success:
|
||||
|
|
|
@ -102,6 +102,11 @@
|
|||
"ImportPath": "github.com/abbot/go-http-auth",
|
||||
"Rev": "c0ef4539dfab4d21c8ef20ba2924f9fc6f186d35"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/alexzorin/libvirt-go",
|
||||
"Comment": "v2.13.0-6-g9359c4f",
|
||||
"Rev": "9359c4feb97212380aa05213fa30c4b7348365f0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/appc/spec/schema",
|
||||
"Comment": "v0.8.1-6-gab50d12",
|
||||
|
@ -683,6 +688,11 @@
|
|||
"Comment": "v3.0.0-4-g01aeca5",
|
||||
"Rev": "01aeca54ebda6e0fbfafd0a524d234159c05ec20"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/dhiltgen/docker-machine-kvm",
|
||||
"Comment": "v0.5.6-10-g37bb4cc",
|
||||
"Rev": "37bb4cc6778c35860a0ce502f3a2d1a96dc3fd67"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docker/distribution/digest",
|
||||
"Comment": "v2.4.0-rc.1-38-gcd27f179",
|
||||
|
|
2
Makefile
2
Makefile
|
@ -70,7 +70,7 @@ out/minikube-darwin-amd64: $(GOPATH)/src/$(ORG) pkg/minikube/assets/assets.go $(
|
|||
CGO_ENABLED=0 GOARCH=amd64 GOOS=darwin go build --installsuffix cgo -ldflags="$(MINIKUBE_LDFLAGS) $(K8S_VERSION_LDFLAGS)" -a -o $(BUILD_DIR)/minikube-darwin-amd64 k8s.io/minikube/cmd/minikube
|
||||
|
||||
out/minikube-linux-amd64: $(GOPATH)/src/$(ORG) pkg/minikube/assets/assets.go $(shell $(MINIKUBEFILES))
|
||||
CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build --installsuffix cgo -ldflags="$(MINIKUBE_LDFLAGS) $(K8S_VERSION_LDFLAGS)" -a -o $(BUILD_DIR)/minikube-linux-amd64 k8s.io/minikube/cmd/minikube
|
||||
CGO_ENABLED=1 GOARCH=amd64 GOOS=linux go build --installsuffix cgo -ldflags="$(MINIKUBE_LDFLAGS) $(K8S_VERSION_LDFLAGS)" -a -o $(BUILD_DIR)/minikube-linux-amd64 k8s.io/minikube/cmd/minikube
|
||||
|
||||
out/minikube-windows-amd64.exe: $(GOPATH)/src/$(ORG) pkg/minikube/assets/assets.go $(shell $(MINIKUBEFILES))
|
||||
CGO_ENABLED=0 GOARCH=amd64 GOOS=windows go build --installsuffix cgo -ldflags="$(MINIKUBE_LDFLAGS) $(K8S_VERSION_LDFLAGS)" -a -o $(BUILD_DIR)/minikube-windows-amd64.exe k8s.io/minikube/cmd/minikube
|
||||
|
|
|
@ -29,6 +29,8 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
const useVendoredDriver = "use-vendored-driver"
|
||||
|
||||
type setFn func(string, string) error
|
||||
|
||||
type Setting struct {
|
||||
|
@ -149,6 +151,10 @@ var settings = []Setting{
|
|||
name: "hyperv-virtual-switch",
|
||||
set: SetString,
|
||||
},
|
||||
{
|
||||
name: useVendoredDriver,
|
||||
set: SetBool,
|
||||
},
|
||||
}
|
||||
|
||||
var ConfigCmd = &cobra.Command{
|
||||
|
|
|
@ -21,11 +21,10 @@ import (
|
|||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -56,7 +55,12 @@ var addonsOpenCmd = &cobra.Command{
|
|||
os.Exit(1)
|
||||
}
|
||||
addonName := args[0]
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
//TODO(r2d4): config should not reference API, pull this out
|
||||
api, err := machine.NewAPIClient(GetClientType())
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
cluster.EnsureMinikubeRunningOrExit(api, 1)
|
||||
|
@ -67,7 +71,7 @@ To see the list of available addons run:
|
|||
minikube addons list`, addonName))
|
||||
os.Exit(1)
|
||||
}
|
||||
ok, err := addon.IsEnabled()
|
||||
ok, err = addon.IsEnabled()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
|
|
|
@ -18,15 +18,16 @@ package config
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/sshutil"
|
||||
)
|
||||
|
||||
|
@ -79,12 +80,25 @@ func SetBool(m config.MinikubeConfig, name string, val string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func GetClientType() machine.ClientType {
|
||||
if viper.GetBool(useVendoredDriver) {
|
||||
return machine.ClientTypeLocal
|
||||
}
|
||||
return machine.ClientTypeRPC
|
||||
}
|
||||
|
||||
func EnableOrDisableAddon(name string, val string) error {
|
||||
enable, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
errors.Wrapf(err, "error attempted to parse enabled/disable value addon %s", name)
|
||||
}
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
|
||||
//TODO(r2d4): config package should not reference API, pull this out
|
||||
api, err := machine.NewAPIClient(GetClientType())
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
cluster.EnsureMinikubeRunningOrExit(api, 0)
|
||||
|
||||
|
|
|
@ -22,12 +22,11 @@ import (
|
|||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/browser"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
|
||||
commonutil "k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
@ -42,14 +41,18 @@ var dashboardCmd = &cobra.Command{
|
|||
Short: "Opens/displays the kubernetes dashboard URL for your local cluster",
|
||||
Long: `Opens/displays the kubernetes dashboard URL for your local cluster`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
cluster.EnsureMinikubeRunningOrExit(api, 1)
|
||||
namespace := "kube-system"
|
||||
service := "kubernetes-dashboard"
|
||||
|
||||
if err := commonutil.RetryAfter(20, func() error { return cluster.CheckService(namespace, service) }, 6*time.Second); err != nil {
|
||||
if err = commonutil.RetryAfter(20, func() error { return cluster.CheckService(namespace, service) }, 6*time.Second); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not find finalized endpoint being pointed to by %s: %s\n", service, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/spf13/cobra"
|
||||
cmdUtil "k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// deleteCmd represents the delete command
|
||||
|
@ -34,10 +34,14 @@ var deleteCmd = &cobra.Command{
|
|||
associated files.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Deleting local Kubernetes cluster...")
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
if err := cluster.DeleteHost(api); err != nil {
|
||||
if err = cluster.DeleteHost(api); err != nil {
|
||||
fmt.Println("Errors occurred deleting machine: ", err)
|
||||
cmdUtil.MaybeReportErrorAndExit(err)
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
cmdUtil "k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -156,7 +157,7 @@ func shellCfgSet(api libmachine.API) (*ShellConfig, error) {
|
|||
return shellCfg, nil
|
||||
}
|
||||
|
||||
func shellCfgUnset(api libmachine.API) (*ShellConfig, error) {
|
||||
func shellCfgUnset() (*ShellConfig, error) {
|
||||
|
||||
userShell, err := getShell(forceShell)
|
||||
if err != nil {
|
||||
|
@ -229,16 +230,17 @@ var dockerEnvCmd = &cobra.Command{
|
|||
Long: `sets up docker env variables; similar to '$(docker-machine env)'`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
var (
|
||||
err error
|
||||
shellCfg *ShellConfig
|
||||
)
|
||||
var shellCfg *ShellConfig
|
||||
|
||||
if unset {
|
||||
shellCfg, err = shellCfgUnset(api)
|
||||
shellCfg, err = shellCfgUnset()
|
||||
if err != nil {
|
||||
glog.Errorln("Error setting machine env variable(s):", err)
|
||||
cmdUtil.MaybeReportErrorAndExit(err)
|
||||
|
|
|
@ -20,10 +20,10 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// ipCmd represents the ip command
|
||||
|
@ -32,7 +32,11 @@ var ipCmd = &cobra.Command{
|
|||
Short: "Retrieve the IP address of the running cluster.",
|
||||
Long: `Retrieves the IP address of the running cluster, and writes it to STDOUT.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
|
|
|
@ -21,11 +21,10 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/spf13/cobra"
|
||||
cmdUtil "k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// logsCmd represents the logs command
|
||||
|
@ -34,7 +33,11 @@ var logsCmd = &cobra.Command{
|
|||
Short: "Gets the logs of the running localkube instance, used for debugging minikube, not user code.",
|
||||
Long: `Gets the logs of the running localkube instance, used for debugging minikube, not user code.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
s, err := cluster.GetHostLogs(api)
|
||||
if err != nil {
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
"k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/notify"
|
||||
)
|
||||
|
||||
|
@ -49,11 +50,13 @@ var dirs = [...]string{
|
|||
|
||||
const (
|
||||
showLibmachineLogs = "show-libmachine-logs"
|
||||
useVendoredDriver = "use-vendored-driver"
|
||||
)
|
||||
|
||||
var (
|
||||
enableUpdateNotification = true
|
||||
enableKubectlDownloadMsg = true
|
||||
clientType machine.ClientType
|
||||
)
|
||||
|
||||
var viperWhiteList = []string{
|
||||
|
@ -81,6 +84,9 @@ Please use --v=3 to show libmachine logs, and --v=7 for debug level libmachine l
|
|||
`)
|
||||
}
|
||||
|
||||
//TODO(r2d4): config should not reference API
|
||||
clientType = configCmd.GetClientType()
|
||||
|
||||
// Log level 3 or greater enables libmachine logs
|
||||
if !glog.V(3) {
|
||||
log.SetOutWriter(ioutil.Discard)
|
||||
|
@ -128,6 +134,7 @@ func setFlagsUsingViper() {
|
|||
|
||||
func init() {
|
||||
RootCmd.PersistentFlags().Bool(showLibmachineLogs, false, "Deprecated: To enable libmachine logs, set --v=3 or higher")
|
||||
RootCmd.PersistentFlags().Bool(useVendoredDriver, false, "Use the vendored in drivers instead of RPC")
|
||||
RootCmd.AddCommand(configCmd.ConfigCmd)
|
||||
RootCmd.AddCommand(configCmd.AddonsCmd)
|
||||
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
|
|
|
@ -21,12 +21,11 @@ import (
|
|||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/1.5/pkg/api/v1"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -59,7 +58,11 @@ var serviceCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
service := args[0]
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
cluster.EnsureMinikubeRunningOrExit(api, 1)
|
||||
|
|
|
@ -21,13 +21,12 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
var serviceListNamespace string
|
||||
|
@ -38,7 +37,11 @@ var serviceListCmd = &cobra.Command{
|
|||
Short: "Lists the URLs for the services in your local cluster",
|
||||
Long: `Lists the URLs for the services in your local cluster`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
serviceURLs, err := cluster.GetServiceURLs(api, serviceListNamespace, serviceURLTemplate)
|
||||
if err != nil {
|
||||
|
|
|
@ -17,14 +17,14 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// sshCmd represents the docker-ssh command
|
||||
|
@ -33,12 +33,15 @@ var sshCmd = &cobra.Command{
|
|||
Short: "Log into or run a command on a machine with SSH; similar to 'docker-machine ssh'",
|
||||
Long: "Log into or run a command on a machine with SSH; similar to 'docker-machine ssh'",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
defer api.Close()
|
||||
err := cluster.CreateSSHShell(api, args)
|
||||
err = errors.Wrap(err, "Error attempting to ssh/run-ssh-command")
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
err = cluster.CreateSSHShell(api, args)
|
||||
if err != nil {
|
||||
glog.Errorln(errors.Wrap(err, "Error attempting to ssh/run-ssh-command"))
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
"time"
|
||||
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -35,6 +34,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/kubeconfig"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
pkgutil "k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
@ -73,7 +73,11 @@ assumes you already have Virtualbox installed.`,
|
|||
|
||||
func runStart(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Starting local Kubernetes cluster...")
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
diskSize := viper.GetString(humanReadableDiskSize)
|
||||
|
@ -108,7 +112,7 @@ func runStart(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
return err
|
||||
}
|
||||
err := util.RetryAfter(5, start, 2*time.Second)
|
||||
err = util.RetryAfter(5, start, 2*time.Second)
|
||||
if err != nil {
|
||||
glog.Errorln("Error starting host: ", err)
|
||||
cmdUtil.MaybeReportErrorAndExit(err)
|
||||
|
|
|
@ -17,16 +17,17 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
cmdUtil "k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
var statusFormat string
|
||||
|
@ -42,7 +43,11 @@ var statusCmd = &cobra.Command{
|
|||
Short: "Gets the status of a local kubernetes cluster.",
|
||||
Long: `Gets the status of a local kubernetes cluster.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
ms, err := cluster.GetHostStatus(api)
|
||||
if err != nil {
|
||||
|
|
|
@ -18,12 +18,12 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/spf13/cobra"
|
||||
cmdUtil "k8s.io/minikube/cmd/util"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
)
|
||||
|
||||
// stopCmd represents the stop command
|
||||
|
@ -34,10 +34,14 @@ var stopCmd = &cobra.Command{
|
|||
itself, leaving all files intact. The cluster can be started again with the "start" command.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Stopping local Kubernetes cluster...")
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
api, err := machine.NewAPIClient(clientType)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error getting client: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer api.Close()
|
||||
|
||||
if err := cluster.StopHost(api); err != nil {
|
||||
if err = cluster.StopHost(api); err != nil {
|
||||
fmt.Println("Error stopping machine: ", err)
|
||||
cmdUtil.MaybeReportErrorAndExit(err)
|
||||
}
|
||||
|
|
|
@ -254,6 +254,7 @@ _minikube_addons_disable()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -280,6 +281,7 @@ _minikube_addons_enable()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -306,6 +308,7 @@ _minikube_addons_list()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -337,6 +340,7 @@ _minikube_addons_open()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -369,6 +373,7 @@ _minikube_addons()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -395,6 +400,7 @@ _minikube_completion()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -421,6 +427,7 @@ _minikube_config_get()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -447,6 +454,7 @@ _minikube_config_set()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -473,6 +481,7 @@ _minikube_config_unset()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -501,6 +510,7 @@ _minikube_config_view()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -531,6 +541,7 @@ _minikube_config()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -559,6 +570,7 @@ _minikube_dashboard()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -585,6 +597,7 @@ _minikube_delete()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -618,6 +631,7 @@ _minikube_docker-env()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -644,6 +658,7 @@ _minikube_get-k8s-versions()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -670,6 +685,7 @@ _minikube_ip()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -696,6 +712,7 @@ _minikube_logs()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -726,6 +743,7 @@ _minikube_service_list()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -761,6 +779,7 @@ _minikube_service()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -787,6 +806,7 @@ _minikube_ssh()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -847,6 +867,7 @@ _minikube_start()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -875,6 +896,7 @@ _minikube_status()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -901,6 +923,7 @@ _minikube_stop()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -927,6 +950,7 @@ _minikube_version()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
@ -968,6 +992,7 @@ _minikube()
|
|||
flags+=("--logtostderr")
|
||||
flags+=("--show-libmachine-logs")
|
||||
flags+=("--stderrthreshold=")
|
||||
flags+=("--use-vendored-driver")
|
||||
flags+=("--v=")
|
||||
two_word_flags+=("-v")
|
||||
flags+=("--vmodule=")
|
||||
|
|
|
@ -16,6 +16,7 @@ Minikube is a CLI tool that provisions and manages single-node Kubernetes cluste
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -28,6 +28,7 @@ For the list of accessible variables for the template, see the struct values her
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube addons disable ADDON_NAME
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube addons enable ADDON_NAME
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube addons list
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -28,6 +28,7 @@ minikube addons open ADDON_NAME
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -35,6 +35,7 @@ minikube completion SHELL
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -29,6 +29,7 @@ Configurable fields:
|
|||
* ingress
|
||||
* registry-creds
|
||||
* hyperv-virtual-switch
|
||||
* use-vendored-driver
|
||||
|
||||
```
|
||||
minikube config SUBCOMMAND [flags]
|
||||
|
@ -43,6 +44,7 @@ minikube config SUBCOMMAND [flags]
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube config get PROPERTY_NAME
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -21,6 +21,7 @@ minikube config set PROPERTY_NAME PROPERTY_VALUE
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube config unset PROPERTY_NAME
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -28,6 +28,7 @@ For the list of accessible variables for the template, see the struct values her
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -26,6 +26,7 @@ minikube dashboard
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -21,6 +21,7 @@ minikube delete
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -28,6 +28,7 @@ minikube docker-env
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube get-k8s-versions
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube ip
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube logs
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -29,6 +29,7 @@ minikube service [flags] SERVICE
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -27,6 +27,7 @@ minikube service list [flags]
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube ssh
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -46,6 +46,7 @@ minikube start
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -29,6 +29,7 @@ localkube: {{.LocalkubeStatus}}
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -21,6 +21,7 @@ minikube stop
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,6 +20,7 @@ minikube version
|
|||
--logtostderr log to standard error instead of files
|
||||
--show-libmachine-logs Deprecated: To enable libmachine logs, set --v=3 or higher
|
||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||
--use-vendored-driver Use the vendored in drivers instead of RPC
|
||||
-v, --v Level log level for V logs
|
||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||
```
|
||||
|
|
|
@ -20,27 +20,13 @@ import (
|
|||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
kvm "github.com/dhiltgen/docker-machine-kvm"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
type kvmDriver struct {
|
||||
*drivers.BaseDriver
|
||||
|
||||
Memory int
|
||||
DiskSize int
|
||||
CPU int
|
||||
Network string
|
||||
PrivateNetwork string
|
||||
ISO string
|
||||
Boot2DockerURL string
|
||||
DiskPath string
|
||||
CacheMode string
|
||||
IOMode string
|
||||
}
|
||||
|
||||
func createKVMHost(config MachineConfig) *kvmDriver {
|
||||
return &kvmDriver{
|
||||
func createKVMHost(config MachineConfig) *kvm.Driver {
|
||||
return &kvm.Driver{
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: constants.MachineName,
|
||||
StorePath: constants.Minipath,
|
||||
|
|
|
@ -18,23 +18,174 @@ package machine
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"net"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
|
||||
"github.com/docker/machine/drivers/hyperv"
|
||||
"github.com/docker/machine/drivers/virtualbox"
|
||||
"github.com/docker/machine/drivers/vmwarefusion"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/cert"
|
||||
"github.com/docker/machine/libmachine/check"
|
||||
"github.com/docker/machine/libmachine/drivers/plugin"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
|
||||
"github.com/docker/machine/libmachine/drivers/rpc"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/golang/glog"
|
||||
"github.com/docker/machine/libmachine/persist"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/docker/machine/libmachine/version"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type driverGetter func(string, []byte) (drivers.Driver, error)
|
||||
|
||||
type ClientType int
|
||||
type clientFactory interface {
|
||||
NewClient(string, string) libmachine.API
|
||||
}
|
||||
|
||||
type localClientFactory struct{}
|
||||
|
||||
func (*localClientFactory) NewClient(storePath, certsDir string) libmachine.API {
|
||||
return &LocalClient{
|
||||
certsDir: certsDir,
|
||||
storePath: storePath,
|
||||
Filestore: persist.NewFilestore(storePath, certsDir, certsDir),
|
||||
}
|
||||
}
|
||||
|
||||
type rpcClientFactory struct{}
|
||||
|
||||
func (*rpcClientFactory) NewClient(storePath, certsDir string) libmachine.API {
|
||||
return libmachine.NewClient(storePath, certsDir)
|
||||
}
|
||||
|
||||
var clientFactories = map[ClientType]clientFactory{
|
||||
ClientTypeLocal: &localClientFactory{},
|
||||
ClientTypeRPC: &rpcClientFactory{},
|
||||
}
|
||||
|
||||
const (
|
||||
ClientTypeLocal ClientType = iota
|
||||
ClientTypeRPC
|
||||
)
|
||||
|
||||
// Gets a new client depending on the clientType specified
|
||||
// defaults to the libmachine client
|
||||
func NewAPIClient(clientType ClientType) (libmachine.API, error) {
|
||||
storePath := constants.Minipath
|
||||
certsDir := constants.MakeMiniPath("certs")
|
||||
newClientFactory, ok := clientFactories[clientType]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("No implementation for API client type %d", clientType)
|
||||
}
|
||||
|
||||
return newClientFactory.NewClient(storePath, certsDir), nil
|
||||
}
|
||||
|
||||
func getDriver(driverName string, rawDriver []byte) (drivers.Driver, error) {
|
||||
driverGetter, ok := driverMap[driverName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Unknown driver %s for platform.", driverName)
|
||||
}
|
||||
driver, err := driverGetter(driverName, rawDriver)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error getting driver for %s", driverName)
|
||||
}
|
||||
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
func getVirtualboxDriver(_ string, rawDriver []byte) (drivers.Driver, error) {
|
||||
var driver drivers.Driver
|
||||
driver = virtualbox.NewDriver("", "")
|
||||
err := json.Unmarshal(rawDriver, driver)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Error unmarshalling virtualbox driver %s", string(rawDriver))
|
||||
}
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
func getDriverRPC(driverName string, rawDriver []byte) (drivers.Driver, error) {
|
||||
return rpcdriver.NewRPCClientDriverFactory().NewRPCClientDriver(driverName, rawDriver)
|
||||
}
|
||||
|
||||
// LocalClient is a non-RPC implemenation
|
||||
// of the libmachine API
|
||||
type LocalClient struct {
|
||||
certsDir string
|
||||
storePath string
|
||||
*persist.Filestore
|
||||
}
|
||||
|
||||
func (api *LocalClient) NewHost(driverName string, rawDriver []byte) (*host.Host, error) {
|
||||
driver, err := getDriver(driverName, rawDriver)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error getting driver")
|
||||
}
|
||||
return &host.Host{
|
||||
ConfigVersion: version.ConfigVersion,
|
||||
Name: driver.GetMachineName(),
|
||||
Driver: driver,
|
||||
DriverName: driver.DriverName(),
|
||||
HostOptions: &host.Options{
|
||||
AuthOptions: &auth.Options{
|
||||
CertDir: api.certsDir,
|
||||
CaCertPath: filepath.Join(api.certsDir, "ca.pem"),
|
||||
CaPrivateKeyPath: filepath.Join(api.certsDir, "ca-key.pem"),
|
||||
ClientCertPath: filepath.Join(api.certsDir, "cert.pem"),
|
||||
ClientKeyPath: filepath.Join(api.certsDir, "key.pem"),
|
||||
ServerCertPath: filepath.Join(api.GetMachinesDir(), "server.pem"),
|
||||
ServerKeyPath: filepath.Join(api.GetMachinesDir(), "server-key.pem"),
|
||||
},
|
||||
EngineOptions: &engine.Options{
|
||||
StorageDriver: "aufs",
|
||||
TLSVerify: true,
|
||||
},
|
||||
SwarmOptions: &swarm.Options{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (api *LocalClient) Load(name string) (*host.Host, error) {
|
||||
h, err := api.Filestore.Load(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error loading host from store")
|
||||
}
|
||||
|
||||
h.Driver, err = getDriver(h.DriverName, h.RawDriver)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error loading driver from host")
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (api *LocalClient) Close() error { return nil }
|
||||
|
||||
// TODO(r2d4): We can rewrite the create function,
|
||||
// for now, just defer to libmachine's implementation
|
||||
func (api *LocalClient) Create(h *host.Host) error {
|
||||
c := libmachine.NewClient(api.storePath, api.certsDir)
|
||||
return c.Create(h)
|
||||
}
|
||||
|
||||
func StartDriver() {
|
||||
cert.SetCertGenerator(&CertGenerator{})
|
||||
check.DefaultConnChecker = &ConnChecker{}
|
||||
if os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal {
|
||||
registerDriver(os.Getenv(localbinary.PluginEnvDriverName))
|
||||
}
|
||||
|
||||
localbinary.CurrentBinaryIsDockerMachine = true
|
||||
}
|
||||
|
||||
// CertGenerator is used to override the default machine CertGenerator with a longer timeout.
|
||||
type CertGenerator struct {
|
||||
cert.X509CertGenerator
|
||||
|
@ -70,26 +221,3 @@ func (cg *CertGenerator) ValidateCertificate(addr string, authOptions *auth.Opti
|
|||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// StartDriver starts the desired machine driver if necessary.
|
||||
func StartDriver() {
|
||||
cert.SetCertGenerator(&CertGenerator{})
|
||||
check.DefaultConnChecker = &ConnChecker{}
|
||||
|
||||
if os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal {
|
||||
driverName := os.Getenv(localbinary.PluginEnvDriverName)
|
||||
switch driverName {
|
||||
case "virtualbox":
|
||||
plugin.RegisterDriver(virtualbox.NewDriver("", ""))
|
||||
case "vmwarefusion":
|
||||
plugin.RegisterDriver(vmwarefusion.NewDriver("", ""))
|
||||
case "hyperv":
|
||||
plugin.RegisterDriver(hyperv.NewDriver("", ""))
|
||||
default:
|
||||
glog.Exitf("Unsupported driver: %s\n", driverName)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
localbinary.CurrentBinaryIsDockerMachine = true
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/docker/machine/drivers/virtualbox"
|
||||
"github.com/docker/machine/drivers/vmwarefusion"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/drivers/plugin"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var driverMap = map[string]driverGetter{
|
||||
"vmwarefusion": getVMWareFusionDriver,
|
||||
"xhyve": getXhyveDriver,
|
||||
"virtualbox": getVirtualboxDriver,
|
||||
}
|
||||
|
||||
func getVMWareFusionDriver(driverName string, rawDriver []byte) (drivers.Driver, error) {
|
||||
var driver drivers.Driver
|
||||
driver = &vmwarefusion.Driver{}
|
||||
if err := json.Unmarshal(rawDriver, &driver); err != nil {
|
||||
return nil, errors.Wrap(err, "Error unmarshalling vmwarefusion driver")
|
||||
}
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
// Xhyve driver not implemented yet for non-RPC access
|
||||
func getXhyveDriver(driverName string, rawDriver []byte) (drivers.Driver, error) {
|
||||
return nil, errors.New(`
|
||||
The Xhyve driver is not included in minikube yet. Please follow the directions at
|
||||
https://github.com/kubernetes/minikube/blob/master/DRIVERS.md#xhyve-driver
|
||||
`)
|
||||
}
|
||||
|
||||
// StartDriver starts the desired machine driver if necessary.
|
||||
func registerDriver(driverName string) {
|
||||
switch driverName {
|
||||
case "virtualbox":
|
||||
plugin.RegisterDriver(virtualbox.NewDriver("", ""))
|
||||
case "vmwarefusion":
|
||||
plugin.RegisterDriver(vmwarefusion.NewDriver("", ""))
|
||||
default:
|
||||
glog.Exitf("Unsupported driver: %s\n", driverName)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
kvm "github.com/dhiltgen/docker-machine-kvm"
|
||||
"github.com/docker/machine/drivers/virtualbox"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/drivers/plugin"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var driverMap = map[string]driverGetter{
|
||||
"kvm": getKVMDriver,
|
||||
"virtualbox": getVirtualboxDriver,
|
||||
}
|
||||
|
||||
func getKVMDriver(driverName string, rawDriver []byte) (drivers.Driver, error) {
|
||||
var driver drivers.Driver
|
||||
driver = &kvm.Driver{}
|
||||
if err := json.Unmarshal(rawDriver, &driver); err != nil {
|
||||
return nil, errors.Wrap(err, "Error unmarshalling kvm driver")
|
||||
}
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
// StartDriver starts the desired machine driver if necessary.
|
||||
func registerDriver(driverName string) {
|
||||
switch driverName {
|
||||
case "virtualbox":
|
||||
plugin.RegisterDriver(virtualbox.NewDriver("", ""))
|
||||
default:
|
||||
glog.Exitf("Unsupported driver: %s\n", driverName)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// +build !linux,!windows,!darwin
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package machine
|
||||
|
||||
import "github.com/golang/glog"
|
||||
|
||||
var driverMap = map[string]driverGetter{}
|
||||
|
||||
func registerDriver(driverName string) {
|
||||
glog.Errorf("Unsupported platform")
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package machine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/docker/machine/drivers/hyperv"
|
||||
"github.com/docker/machine/drivers/virtualbox"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/drivers/plugin"
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var driverMap = map[string]driverGetter{
|
||||
"hyperv": getHyperVDriver,
|
||||
"virtualbox": getVirtualboxDriver,
|
||||
}
|
||||
|
||||
func getHyperVDriver(driverName string, rawDriver []byte) (drivers.Driver, error) {
|
||||
var driver drivers.Driver
|
||||
driver = &hyperv.Driver{}
|
||||
if err := json.Unmarshal(rawDriver, &driver); err != nil {
|
||||
return nil, errors.Wrap(err, "Error unmarshalling hyperv driver")
|
||||
}
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
// StartDriver starts the desired machine driver if necessary.
|
||||
func registerDriver(driverName string) {
|
||||
switch driverName {
|
||||
case "virtualbox":
|
||||
plugin.RegisterDriver(virtualbox.NewDriver("", ""))
|
||||
case "hyperv":
|
||||
plugin.RegisterDriver(hyperv.NewDriver("", ""))
|
||||
default:
|
||||
glog.Exitf("Unsupported driver: %s\n", driverName)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
.vagrant
|
||||
/libvirt-go.test
|
|
@ -0,0 +1,37 @@
|
|||
language: go
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: require
|
||||
|
||||
go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
|
||||
env:
|
||||
- LIBVIRT=1.2.2 EXT=gz TAGS=""
|
||||
- LIBVIRT=1.2.14 EXT=gz TAGS="libvirt.1.2.14"
|
||||
- LIBVIRT=2.3.0 EXT=xz TAGS="libvirt.1.2.14"
|
||||
|
||||
install:
|
||||
- sudo apt-get -qqy build-dep libvirt
|
||||
- sudo apt-get -qqy install curl qemu-system-x86 sasl2-bin
|
||||
- sudo mkdir -p /usr/src && sudo chown $(id -u) /usr/src
|
||||
- curl -O -s https://libvirt.org/sources/libvirt-${LIBVIRT}.tar.${EXT}
|
||||
- tar -C /usr/src -xf libvirt-${LIBVIRT}.tar.${EXT}
|
||||
- pushd /usr/src/libvirt-${LIBVIRT}
|
||||
- |
|
||||
./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc \
|
||||
--without-polkit \
|
||||
--without-esx --without-vbox --without-xen --without-libxl \
|
||||
--with-qemu --with-lxc
|
||||
- make
|
||||
- sudo make install
|
||||
- popd
|
||||
- sudo libvirtd -d -l -f libvirtd.conf
|
||||
- sudo virtlogd -d || true
|
||||
- sudo chmod a+rwx /var/run/libvirt/libvirt-sock*
|
||||
- echo "pass" | sudo saslpasswd2 -p -a libvirt user
|
||||
|
||||
script:
|
||||
go test -timeout 1m -tags "${TAGS}" -v
|
|
@ -0,0 +1,19 @@
|
|||
#libvirt-go
|
||||
|
||||
##FAQ - Frequently asked questions
|
||||
|
||||
If your question is a good one, please ask it as a well-formatted patch to this
|
||||
repository, and we'll merge it along with the answer.
|
||||
|
||||
###Why does this fail when added to my project in travis?
|
||||
|
||||
This lib requires a newish version of the libvirt-dev library to compile. These
|
||||
are only available in the newer travis environment. You can add:
|
||||
|
||||
```
|
||||
sudo: true
|
||||
dist: trusty
|
||||
install: sudo apt-get install -y libvirt-dev
|
||||
```
|
||||
|
||||
to your `.travis.yaml` file to avoid these errors.
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2013 Alex Zorin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,61 @@
|
|||
# libvirt-go [](https://travis-ci.org/rgbkrk/libvirt-go) [](http://godoc.org/gopkg.in/alexzorin/libvirt-go.v2)
|
||||
|
||||
Go bindings for libvirt.
|
||||
|
||||
Make sure to have `libvirt-dev` package (or the development files otherwise somewhere in your include path)
|
||||
|
||||
## Version Support
|
||||
|
||||
The minimum supported version of libvirt is **1.2.2**. Due to the
|
||||
API/ABI compatibility promise of libvirt, more recent versions of
|
||||
libvirt should work too.
|
||||
|
||||
Some features require a more recent version of libvirt. They are
|
||||
disabled by default. If you want to enable them, build using one of
|
||||
those additional tags (you need to use only the most recent one you
|
||||
are interested in):
|
||||
|
||||
- **1.2.14**
|
||||
|
||||
For example:
|
||||
|
||||
go build -tags libvirt.1.2.14
|
||||
|
||||
### OS Compatibility Matrix
|
||||
|
||||
To quickly see what version of libvirt your OS can easily support (may be outdated). Obviously, nothing below 1.2.2 is usable with these bindings.
|
||||
|
||||
| OS Release | libvirt Version |
|
||||
| ------------ | ------------------------------ |
|
||||
| FC19 | 1.2.9 from libvirt.org/sources |
|
||||
| Debian 8 | 1.2.9 from jessie |
|
||||
| Debian 7 | 1.2.9 from wheezy-backports |
|
||||
| Ubuntu 14.04 | 1.2.2 from trusty |
|
||||
| Ubuntu 16.04 | 1.3.1 from xenial |
|
||||
| RHEL 7 | 1.2.17 |
|
||||
| RHEL 6 | 0.10.x |
|
||||
| RHEL 5 | 0.8.x |
|
||||
|
||||
|
||||
### 0.9.x Support
|
||||
|
||||
Previously there was support for libvirt 0.9.8 and below, however this is no longer being updated. These releases were tagged `v1.x` at `gopkg.in/alexzorin/libvirt-go.v1` [(docs)](http://gopkg.in/alexzorin/libvirt-go.v1).
|
||||
|
||||
## Documentation
|
||||
|
||||
* [api documentation for the bindings](http://godoc.org/github.com/rgbkrk/libvirt-go)
|
||||
* [api documentation for libvirt](http://libvirt.org/html/libvirt-libvirt.html)
|
||||
|
||||
## Contributing
|
||||
|
||||
Please fork and write tests.
|
||||
|
||||
Integration tests are available where functionality isn't provided by the test driver, see `integration_test.go`.
|
||||
|
||||
A `Vagrantfile` is included to run the integration tests:
|
||||
|
||||
* `cd ./vagrant`
|
||||
* `vagrant up` to provision the virtual machine
|
||||
* `vagrant ssh` to login to the virtual machine
|
||||
|
||||
Once inside, `sudo su -` and `go test -tags integration libvirt`.
|
|
@ -0,0 +1,76 @@
|
|||
package libvirt
|
||||
|
||||
// Helpers functions to register a Go callback function to a C
|
||||
// function. For a simple example, look at how SetErrorFunc works in
|
||||
// error.go.
|
||||
//
|
||||
// - Create a struct that will contain at least the Go callback to
|
||||
// invoke (errorContext).
|
||||
//
|
||||
// - Create an exported Golang function whose job will be to retrieve
|
||||
// the context and execute the callback in it
|
||||
// (connErrCallback). Such a function should receive a callback ID
|
||||
// and will use it to retrive the context.
|
||||
//
|
||||
// - Create a CGO function similar to the above function but with the
|
||||
// appropriate signature to be registered as a callback in C code
|
||||
// (connErrCallback_cgo). Notably, it will have a void* argument
|
||||
// that should be cast to long to retrieve the callback ID. It
|
||||
// should be just a thin wrapper to transform the opaque argument to
|
||||
// a callback ID.
|
||||
//
|
||||
// - Create a CGO function which will be a wrapper around the C
|
||||
// function to register the callback (virConnSetErrorFunc_cgo). Its
|
||||
// only role is to transform a callback ID (long) to an opaque (void*)
|
||||
// and call the C function.
|
||||
//
|
||||
// - When setting up a callback (SetErrorFunc), register the struct from first step
|
||||
// with registerCallbackId and invoke the CGO function from the
|
||||
// previous step with the appropriate ID.
|
||||
//
|
||||
// - When unregistering the callback, don't forget to call freecallbackId.
|
||||
//
|
||||
// If you need to associate some additional data with the connection,
|
||||
// look at saveConnectionData, getConnectionData and
|
||||
// releaseConnectionData.
|
||||
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
const firstGoCallbackId int = 100 // help catch some additional errors during test
|
||||
var goCallbackLock sync.RWMutex
|
||||
var goCallbacks = make(map[int]interface{})
|
||||
var nextGoCallbackId int = firstGoCallbackId
|
||||
|
||||
//export freeCallbackId
|
||||
func freeCallbackId(goCallbackId int) {
|
||||
goCallbackLock.Lock()
|
||||
delete(goCallbacks, goCallbackId)
|
||||
goCallbackLock.Unlock()
|
||||
}
|
||||
|
||||
func getCallbackId(goCallbackId int) interface{} {
|
||||
goCallbackLock.RLock()
|
||||
ctx := goCallbacks[goCallbackId]
|
||||
goCallbackLock.RUnlock()
|
||||
if ctx == nil {
|
||||
// If this happens there must be a bug in libvirt
|
||||
panic("Callback arrived after freeCallbackId was called")
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func registerCallbackId(ctx interface{}) int {
|
||||
goCallbackLock.Lock()
|
||||
goCallBackId := nextGoCallbackId
|
||||
nextGoCallbackId++
|
||||
for goCallbacks[nextGoCallbackId] != nil {
|
||||
nextGoCallbackId++
|
||||
}
|
||||
goCallbacks[goCallBackId] = ctx
|
||||
goCallbackLock.Unlock()
|
||||
return goCallBackId
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -Wno-implicit-function-declaration
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "go_libvirt.h"
|
||||
|
||||
void domainEventLifecycleCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int event, int detail, void *data)
|
||||
{
|
||||
domainEventLifecycleCallback(c, d, event, detail, data);
|
||||
}
|
||||
|
||||
void domainEventGenericCallback_cgo(virConnectPtr c, virDomainPtr d, void *data)
|
||||
{
|
||||
domainEventGenericCallback(c, d, data);
|
||||
}
|
||||
|
||||
void domainEventRTCChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
long long utcoffset, void *data)
|
||||
{
|
||||
domainEventRTCChangeCallback(c, d, utcoffset, data);
|
||||
}
|
||||
|
||||
void domainEventWatchdogCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int action, void *data)
|
||||
{
|
||||
domainEventWatchdogCallback(c, d, action, data);
|
||||
}
|
||||
|
||||
void domainEventIOErrorCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *srcPath, const char *devAlias,
|
||||
int action, void *data)
|
||||
{
|
||||
domainEventIOErrorCallback(c, d, srcPath, devAlias, action, data);
|
||||
}
|
||||
|
||||
void domainEventGraphicsCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int phase, const virDomainEventGraphicsAddress *local,
|
||||
const virDomainEventGraphicsAddress *remote,
|
||||
const char *authScheme,
|
||||
const virDomainEventGraphicsSubject *subject, void *data)
|
||||
{
|
||||
domainEventGraphicsCallback(c, d, phase, local, remote, authScheme, subject, data);
|
||||
}
|
||||
|
||||
void domainEventIOErrorReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *srcPath, const char *devAlias,
|
||||
int action, const char *reason, void *data)
|
||||
{
|
||||
domainEventIOErrorReasonCallback(c, d, srcPath, devAlias, action, reason, data);
|
||||
}
|
||||
|
||||
void domainEventBlockJobCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *disk, int type, int status, void *data)
|
||||
{
|
||||
domainEventBlockJobCallback(c, d, disk, type, status, data);
|
||||
}
|
||||
|
||||
void domainEventDiskChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *oldSrcPath, const char *newSrcPath,
|
||||
const char *devAlias, int reason, void *data)
|
||||
{
|
||||
domainEventDiskChangeCallback(c, d, oldSrcPath, newSrcPath, devAlias, reason, data);
|
||||
}
|
||||
|
||||
void domainEventTrayChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *devAlias, int reason, void *data)
|
||||
{
|
||||
domainEventTrayChangeCallback(c, d, devAlias, reason, data);
|
||||
}
|
||||
|
||||
void domainEventReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int reason, void *data)
|
||||
{
|
||||
domainEventReasonCallback(c, d, reason, data);
|
||||
}
|
||||
|
||||
void domainEventBalloonChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
unsigned long long actual, void *data)
|
||||
{
|
||||
domainEventBalloonChangeCallback(c, d, actual, data);
|
||||
}
|
||||
|
||||
void domainEventDeviceRemovedCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *devAlias, void *data)
|
||||
{
|
||||
domainEventDeviceRemovedCallback(c, d, devAlias, data);
|
||||
}
|
||||
|
||||
void freeGoCallback_cgo(void* goCallbackId) {
|
||||
freeCallbackId((long)goCallbackId);
|
||||
}
|
||||
|
||||
int virConnectDomainEventRegisterAny_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int eventID, virConnectDomainEventGenericCallback cb,
|
||||
long goCallbackId) {
|
||||
void* id = (void*)goCallbackId;
|
||||
return virConnectDomainEventRegisterAny(c, d, eventID, cb, id, freeGoCallback_cgo);
|
||||
}
|
||||
|
||||
void errorGlobalCallback_cgo(void *userData, virErrorPtr error)
|
||||
{
|
||||
globalErrorCallback(error);
|
||||
}
|
||||
|
||||
void errorConnCallback_cgo(void *userData, virErrorPtr error)
|
||||
{
|
||||
connErrorCallback((long)userData, error);
|
||||
}
|
||||
|
||||
void virConnSetErrorFunc_cgo(virConnectPtr c, long goCallbackId, virErrorFunc cb)
|
||||
{
|
||||
void* id = (void*)goCallbackId;
|
||||
virConnSetErrorFunc(c, id, cb);
|
||||
}
|
||||
|
||||
void closeCallback_cgo(virConnectPtr conn, int reason, void *opaque)
|
||||
{
|
||||
closeCallback(conn, reason, (long)opaque);
|
||||
}
|
||||
|
||||
int authCb(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
auth_cb_data *data = (auth_cb_data*)cbdata;
|
||||
for (i = 0; i < ncred; i++) {
|
||||
if (cred[i].type == VIR_CRED_AUTHNAME) {
|
||||
cred[i].result = strndup(data->username, data->username_len);
|
||||
if (cred[i].result == NULL)
|
||||
return -1;
|
||||
cred[i].resultlen = strlen(cred[i].result);
|
||||
}
|
||||
else if (cred[i].type == VIR_CRED_PASSPHRASE) {
|
||||
cred[i].result = strndup(data->passphrase, data->passphrase_len);
|
||||
if (cred[i].result == NULL)
|
||||
return -1;
|
||||
cred[i].resultlen = strlen(cred[i].result);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
auth_cb_data* authData(char* username, uint username_len, char* passphrase, uint passphrase_len) {
|
||||
auth_cb_data * data = malloc(sizeof(auth_cb_data));
|
||||
data->username = username;
|
||||
data->username_len = username_len;
|
||||
data->passphrase = passphrase;
|
||||
data->passphrase_len = passphrase_len;
|
||||
return data;
|
||||
}
|
||||
|
||||
int* authMechs() {
|
||||
int* authMechs = malloc(2*sizeof(VIR_CRED_AUTHNAME));
|
||||
authMechs[0] = VIR_CRED_AUTHNAME;
|
||||
authMechs[1] = VIR_CRED_PASSPHRASE;
|
||||
return authMechs;
|
||||
}
|
||||
|
||||
int virConnectRegisterCloseCallback_cgo(virConnectPtr c, virConnectCloseFunc cb, long goCallbackId)
|
||||
{
|
||||
void *id = (void*)goCallbackId;
|
||||
return virConnectRegisterCloseCallback(c, cb, id, freeGoCallback_cgo);
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
|
@ -0,0 +1,551 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef VIR_DOMAIN_UNDEFINE_NVRAM
|
||||
#define VIR_DOMAIN_UNDEFINE_NVRAM (1 << 2)
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// virDomainState
|
||||
const (
|
||||
VIR_DOMAIN_NOSTATE = C.VIR_DOMAIN_NOSTATE
|
||||
VIR_DOMAIN_RUNNING = C.VIR_DOMAIN_RUNNING
|
||||
VIR_DOMAIN_BLOCKED = C.VIR_DOMAIN_BLOCKED
|
||||
VIR_DOMAIN_PAUSED = C.VIR_DOMAIN_PAUSED
|
||||
VIR_DOMAIN_SHUTDOWN = C.VIR_DOMAIN_SHUTDOWN
|
||||
VIR_DOMAIN_CRASHED = C.VIR_DOMAIN_CRASHED
|
||||
VIR_DOMAIN_PMSUSPENDED = C.VIR_DOMAIN_PMSUSPENDED
|
||||
VIR_DOMAIN_SHUTOFF = C.VIR_DOMAIN_SHUTOFF
|
||||
)
|
||||
|
||||
//virConnectCloseReason
|
||||
const (
|
||||
VIR_CONNECT_CLOSE_REASON_ERROR = C.VIR_CONNECT_CLOSE_REASON_ERROR
|
||||
VIR_CONNECT_CLOSE_REASON_EOF = C.VIR_CONNECT_CLOSE_REASON_EOF
|
||||
VIR_CONNECT_CLOSE_REASON_KEEPALIVE = C.VIR_CONNECT_CLOSE_REASON_KEEPALIVE
|
||||
VIR_CONNECT_CLOSE_REASON_CLIENT = C.VIR_CONNECT_CLOSE_REASON_CLIENT
|
||||
)
|
||||
|
||||
//virConnectListAllDomainsFlags
|
||||
const (
|
||||
VIR_CONNECT_LIST_DOMAINS_ACTIVE = C.VIR_CONNECT_LIST_DOMAINS_ACTIVE
|
||||
VIR_CONNECT_LIST_DOMAINS_INACTIVE = C.VIR_CONNECT_LIST_DOMAINS_INACTIVE
|
||||
VIR_CONNECT_LIST_DOMAINS_PERSISTENT = C.VIR_CONNECT_LIST_DOMAINS_PERSISTENT
|
||||
VIR_CONNECT_LIST_DOMAINS_TRANSIENT = C.VIR_CONNECT_LIST_DOMAINS_TRANSIENT
|
||||
VIR_CONNECT_LIST_DOMAINS_RUNNING = C.VIR_CONNECT_LIST_DOMAINS_RUNNING
|
||||
VIR_CONNECT_LIST_DOMAINS_PAUSED = C.VIR_CONNECT_LIST_DOMAINS_PAUSED
|
||||
VIR_CONNECT_LIST_DOMAINS_SHUTOFF = C.VIR_CONNECT_LIST_DOMAINS_SHUTOFF
|
||||
VIR_CONNECT_LIST_DOMAINS_OTHER = C.VIR_CONNECT_LIST_DOMAINS_OTHER
|
||||
VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE = C.VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE
|
||||
VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE = C.VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE
|
||||
VIR_CONNECT_LIST_DOMAINS_AUTOSTART = C.VIR_CONNECT_LIST_DOMAINS_AUTOSTART
|
||||
VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART = C.VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART
|
||||
VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT = C.VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT
|
||||
VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT = C.VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT
|
||||
)
|
||||
|
||||
// virDomainMetadataType
|
||||
const (
|
||||
VIR_DOMAIN_METADATA_DESCRIPTION = C.VIR_DOMAIN_METADATA_DESCRIPTION
|
||||
VIR_DOMAIN_METADATA_TITLE = C.VIR_DOMAIN_METADATA_TITLE
|
||||
VIR_DOMAIN_METADATA_ELEMENT = C.VIR_DOMAIN_METADATA_ELEMENT
|
||||
)
|
||||
|
||||
// virDomainVcpuFlags
|
||||
const (
|
||||
VIR_DOMAIN_VCPU_CONFIG = C.VIR_DOMAIN_VCPU_CONFIG
|
||||
VIR_DOMAIN_VCPU_CURRENT = C.VIR_DOMAIN_VCPU_CURRENT
|
||||
VIR_DOMAIN_VCPU_LIVE = C.VIR_DOMAIN_VCPU_LIVE
|
||||
VIR_DOMAIN_VCPU_MAXIMUM = C.VIR_DOMAIN_VCPU_MAXIMUM
|
||||
VIR_DOMAIN_VCPU_GUEST = C.VIR_DOMAIN_VCPU_GUEST
|
||||
)
|
||||
|
||||
// virDomainModificationImpact
|
||||
const (
|
||||
VIR_DOMAIN_AFFECT_CONFIG = C.VIR_DOMAIN_AFFECT_CONFIG
|
||||
VIR_DOMAIN_AFFECT_CURRENT = C.VIR_DOMAIN_AFFECT_CURRENT
|
||||
VIR_DOMAIN_AFFECT_LIVE = C.VIR_DOMAIN_AFFECT_LIVE
|
||||
)
|
||||
|
||||
// virDomainMemoryModFlags
|
||||
const (
|
||||
VIR_DOMAIN_MEM_CONFIG = C.VIR_DOMAIN_AFFECT_CONFIG
|
||||
VIR_DOMAIN_MEM_CURRENT = C.VIR_DOMAIN_AFFECT_CURRENT
|
||||
VIR_DOMAIN_MEM_LIVE = C.VIR_DOMAIN_AFFECT_LIVE
|
||||
VIR_DOMAIN_MEM_MAXIMUM = C.VIR_DOMAIN_MEM_MAXIMUM
|
||||
)
|
||||
|
||||
// virStoragePoolState
|
||||
const (
|
||||
VIR_STORAGE_POOL_INACTIVE = C.VIR_STORAGE_POOL_INACTIVE // Not running
|
||||
VIR_STORAGE_POOL_BUILDING = C.VIR_STORAGE_POOL_BUILDING // Initializing pool,not available
|
||||
VIR_STORAGE_POOL_RUNNING = C.VIR_STORAGE_POOL_RUNNING // Running normally
|
||||
VIR_STORAGE_POOL_DEGRADED = C.VIR_STORAGE_POOL_DEGRADED // Running degraded
|
||||
VIR_STORAGE_POOL_INACCESSIBLE = C.VIR_STORAGE_POOL_INACCESSIBLE // Running,but not accessible
|
||||
)
|
||||
|
||||
// virStoragePoolBuildFlags
|
||||
const (
|
||||
VIR_STORAGE_POOL_BUILD_NEW = C.VIR_STORAGE_POOL_BUILD_NEW // Regular build from scratch
|
||||
VIR_STORAGE_POOL_BUILD_REPAIR = C.VIR_STORAGE_POOL_BUILD_REPAIR // Repair / reinitialize
|
||||
VIR_STORAGE_POOL_BUILD_RESIZE = C.VIR_STORAGE_POOL_BUILD_RESIZE // Extend existing pool
|
||||
VIR_STORAGE_POOL_BUILD_NO_OVERWRITE = C.VIR_STORAGE_POOL_BUILD_NO_OVERWRITE // Do not overwrite existing pool
|
||||
VIR_STORAGE_POOL_BUILD_OVERWRITE = C.VIR_STORAGE_POOL_BUILD_OVERWRITE // Overwrite data
|
||||
)
|
||||
|
||||
// virDomainDestroyFlags
|
||||
const (
|
||||
VIR_DOMAIN_DESTROY_DEFAULT = C.VIR_DOMAIN_DESTROY_DEFAULT
|
||||
VIR_DOMAIN_DESTROY_GRACEFUL = C.VIR_DOMAIN_DESTROY_GRACEFUL
|
||||
)
|
||||
|
||||
// virDomainShutdownFlags
|
||||
const (
|
||||
VIR_DOMAIN_SHUTDOWN_DEFAULT = C.VIR_DOMAIN_SHUTDOWN_DEFAULT
|
||||
VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN = C.VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN
|
||||
VIR_DOMAIN_SHUTDOWN_GUEST_AGENT = C.VIR_DOMAIN_SHUTDOWN_GUEST_AGENT
|
||||
VIR_DOMAIN_SHUTDOWN_INITCTL = C.VIR_DOMAIN_SHUTDOWN_INITCTL
|
||||
VIR_DOMAIN_SHUTDOWN_SIGNAL = C.VIR_DOMAIN_SHUTDOWN_SIGNAL
|
||||
)
|
||||
|
||||
// virDomainUndefineFlags
|
||||
const (
|
||||
VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = C.VIR_DOMAIN_UNDEFINE_MANAGED_SAVE // Also remove any managed save
|
||||
VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = C.VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA // If last use of domain, then also remove any snapshot metadata
|
||||
VIR_DOMAIN_UNDEFINE_NVRAM = C.VIR_DOMAIN_UNDEFINE_NVRAM // Also remove any nvram file
|
||||
)
|
||||
|
||||
// virDomainAttachDeviceFlags
|
||||
const (
|
||||
VIR_DOMAIN_DEVICE_MODIFY_CONFIG = C.VIR_DOMAIN_AFFECT_CONFIG
|
||||
VIR_DOMAIN_DEVICE_MODIFY_CURRENT = C.VIR_DOMAIN_AFFECT_CURRENT
|
||||
VIR_DOMAIN_DEVICE_MODIFY_LIVE = C.VIR_DOMAIN_AFFECT_LIVE
|
||||
VIR_DOMAIN_DEVICE_MODIFY_FORCE = C.VIR_DOMAIN_DEVICE_MODIFY_FORCE
|
||||
)
|
||||
|
||||
// virStorageVolCreateFlags
|
||||
const (
|
||||
VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA = C.VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
|
||||
)
|
||||
|
||||
// virStorageVolDeleteFlags
|
||||
const (
|
||||
VIR_STORAGE_VOL_DELETE_NORMAL = C.VIR_STORAGE_VOL_DELETE_NORMAL // Delete metadata only (fast)
|
||||
VIR_STORAGE_VOL_DELETE_ZEROED = C.VIR_STORAGE_VOL_DELETE_ZEROED // Clear all data to zeros (slow)
|
||||
)
|
||||
|
||||
// virStorageVolResizeFlags
|
||||
const (
|
||||
VIR_STORAGE_VOL_RESIZE_ALLOCATE = C.VIR_STORAGE_VOL_RESIZE_ALLOCATE // force allocation of new size
|
||||
VIR_STORAGE_VOL_RESIZE_DELTA = C.VIR_STORAGE_VOL_RESIZE_DELTA // size is relative to current
|
||||
VIR_STORAGE_VOL_RESIZE_SHRINK = C.VIR_STORAGE_VOL_RESIZE_SHRINK // allow decrease in capacity
|
||||
)
|
||||
|
||||
// virStorageVolType
|
||||
const (
|
||||
VIR_STORAGE_VOL_FILE = C.VIR_STORAGE_VOL_FILE // Regular file based volumes
|
||||
VIR_STORAGE_VOL_BLOCK = C.VIR_STORAGE_VOL_BLOCK // Block based volumes
|
||||
VIR_STORAGE_VOL_DIR = C.VIR_STORAGE_VOL_DIR // Directory-passthrough based volume
|
||||
VIR_STORAGE_VOL_NETWORK = C.VIR_STORAGE_VOL_NETWORK //Network volumes like RBD (RADOS Block Device)
|
||||
VIR_STORAGE_VOL_NETDIR = C.VIR_STORAGE_VOL_NETDIR // Network accessible directory that can contain other network volumes
|
||||
)
|
||||
|
||||
// virStorageVolWipeAlgorithm
|
||||
const (
|
||||
VIR_STORAGE_VOL_WIPE_ALG_ZERO = C.VIR_STORAGE_VOL_WIPE_ALG_ZERO // 1-pass, all zeroes
|
||||
VIR_STORAGE_VOL_WIPE_ALG_NNSA = C.VIR_STORAGE_VOL_WIPE_ALG_NNSA // 4-pass NNSA Policy Letter NAP-14.1-C (XVI-8)
|
||||
VIR_STORAGE_VOL_WIPE_ALG_DOD = C.VIR_STORAGE_VOL_WIPE_ALG_DOD // 4-pass DoD 5220.22-M section 8-306 procedure
|
||||
VIR_STORAGE_VOL_WIPE_ALG_BSI = C.VIR_STORAGE_VOL_WIPE_ALG_BSI // 9-pass method recommended by the German Center of Security in Information Technologies
|
||||
VIR_STORAGE_VOL_WIPE_ALG_GUTMANN = C.VIR_STORAGE_VOL_WIPE_ALG_GUTMANN // The canonical 35-pass sequence
|
||||
VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER = C.VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER // 7-pass method described by Bruce Schneier in "Applied Cryptography" (1996)
|
||||
VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 = C.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7 // 7-pass random
|
||||
VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 = C.VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33 // 33-pass random
|
||||
VIR_STORAGE_VOL_WIPE_ALG_RANDOM = C.VIR_STORAGE_VOL_WIPE_ALG_RANDOM // 1-pass random
|
||||
)
|
||||
|
||||
// virSecretUsageType
|
||||
const (
|
||||
VIR_SECRET_USAGE_TYPE_NONE = C.VIR_SECRET_USAGE_TYPE_NONE
|
||||
VIR_SECRET_USAGE_TYPE_VOLUME = C.VIR_SECRET_USAGE_TYPE_VOLUME
|
||||
VIR_SECRET_USAGE_TYPE_CEPH = C.VIR_SECRET_USAGE_TYPE_CEPH
|
||||
VIR_SECRET_USAGE_TYPE_ISCSI = C.VIR_SECRET_USAGE_TYPE_ISCSI
|
||||
)
|
||||
|
||||
// virConnectListAllNetworksFlags
|
||||
const (
|
||||
VIR_CONNECT_LIST_NETWORKS_INACTIVE = C.VIR_CONNECT_LIST_NETWORKS_INACTIVE
|
||||
VIR_CONNECT_LIST_NETWORKS_ACTIVE = C.VIR_CONNECT_LIST_NETWORKS_ACTIVE
|
||||
VIR_CONNECT_LIST_NETWORKS_PERSISTENT = C.VIR_CONNECT_LIST_NETWORKS_PERSISTENT
|
||||
VIR_CONNECT_LIST_NETWORKS_TRANSIENT = C.VIR_CONNECT_LIST_NETWORKS_TRANSIENT
|
||||
VIR_CONNECT_LIST_NETWORKS_AUTOSTART = C.VIR_CONNECT_LIST_NETWORKS_AUTOSTART
|
||||
VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART = C.VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART
|
||||
)
|
||||
|
||||
// virConnectListAllStoragePoolsFlags
|
||||
const (
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE = C.VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE = C.VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT = C.VIR_CONNECT_LIST_STORAGE_POOLS_PERSISTENT
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT = C.VIR_CONNECT_LIST_STORAGE_POOLS_TRANSIENT
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART = C.VIR_CONNECT_LIST_STORAGE_POOLS_AUTOSTART
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART = C.VIR_CONNECT_LIST_STORAGE_POOLS_NO_AUTOSTART
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_DIR = C.VIR_CONNECT_LIST_STORAGE_POOLS_DIR
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_FS = C.VIR_CONNECT_LIST_STORAGE_POOLS_FS
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_NETFS = C.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL = C.VIR_CONNECT_LIST_STORAGE_POOLS_LOGICAL
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_DISK = C.VIR_CONNECT_LIST_STORAGE_POOLS_DISK
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI = C.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_SCSI = C.VIR_CONNECT_LIST_STORAGE_POOLS_SCSI
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_MPATH = C.VIR_CONNECT_LIST_STORAGE_POOLS_MPATH
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_RBD = C.VIR_CONNECT_LIST_STORAGE_POOLS_RBD
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG = C.VIR_CONNECT_LIST_STORAGE_POOLS_SHEEPDOG
|
||||
VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER = C.VIR_CONNECT_LIST_STORAGE_POOLS_GLUSTER
|
||||
)
|
||||
|
||||
// virStreamFlags
|
||||
const (
|
||||
VIR_STREAM_NONBLOCK = C.VIR_STREAM_NONBLOCK
|
||||
)
|
||||
|
||||
// virKeycodeSet
|
||||
const (
|
||||
VIR_KEYCODE_SET_LINUX = C.VIR_KEYCODE_SET_LINUX
|
||||
VIR_KEYCODE_SET_XT = C.VIR_KEYCODE_SET_XT
|
||||
VIR_KEYCODE_SET_ATSET1 = C.VIR_KEYCODE_SET_ATSET1
|
||||
VIR_KEYCODE_SET_ATSET2 = C.VIR_KEYCODE_SET_ATSET2
|
||||
VIR_KEYCODE_SET_ATSET3 = C.VIR_KEYCODE_SET_ATSET3
|
||||
VIR_KEYCODE_SET_OSX = C.VIR_KEYCODE_SET_OSX
|
||||
VIR_KEYCODE_SET_XT_KBD = C.VIR_KEYCODE_SET_XT_KBD
|
||||
VIR_KEYCODE_SET_USB = C.VIR_KEYCODE_SET_USB
|
||||
VIR_KEYCODE_SET_WIN32 = C.VIR_KEYCODE_SET_WIN32
|
||||
VIR_KEYCODE_SET_RFB = C.VIR_KEYCODE_SET_RFB
|
||||
)
|
||||
|
||||
// virDomainCreateFlags
|
||||
const (
|
||||
VIR_DOMAIN_NONE = C.VIR_DOMAIN_NONE
|
||||
VIR_DOMAIN_START_PAUSED = C.VIR_DOMAIN_START_PAUSED
|
||||
VIR_DOMAIN_START_AUTODESTROY = C.VIR_DOMAIN_START_AUTODESTROY
|
||||
VIR_DOMAIN_START_BYPASS_CACHE = C.VIR_DOMAIN_START_BYPASS_CACHE
|
||||
VIR_DOMAIN_START_FORCE_BOOT = C.VIR_DOMAIN_START_FORCE_BOOT
|
||||
)
|
||||
|
||||
const VIR_DOMAIN_MEMORY_PARAM_UNLIMITED = C.VIR_DOMAIN_MEMORY_PARAM_UNLIMITED
|
||||
|
||||
// virDomainEventID
|
||||
const (
|
||||
// event parameter in the callback is of type DomainLifecycleEvent
|
||||
VIR_DOMAIN_EVENT_ID_LIFECYCLE = C.VIR_DOMAIN_EVENT_ID_LIFECYCLE
|
||||
|
||||
// event parameter in the callback is nil
|
||||
VIR_DOMAIN_EVENT_ID_REBOOT = C.VIR_DOMAIN_EVENT_ID_REBOOT
|
||||
|
||||
// event parameter in the callback is of type DomainRTCChangeEvent
|
||||
VIR_DOMAIN_EVENT_ID_RTC_CHANGE = C.VIR_DOMAIN_EVENT_ID_RTC_CHANGE
|
||||
|
||||
// event parameter in the callback is of type DomainWatchdogEvent
|
||||
VIR_DOMAIN_EVENT_ID_WATCHDOG = C.VIR_DOMAIN_EVENT_ID_WATCHDOG
|
||||
|
||||
// event parameter in the callback is of type DomainIOErrorEvent
|
||||
VIR_DOMAIN_EVENT_ID_IO_ERROR = C.VIR_DOMAIN_EVENT_ID_IO_ERROR
|
||||
|
||||
// event parameter in the callback is of type DomainGraphicsEvent
|
||||
VIR_DOMAIN_EVENT_ID_GRAPHICS = C.VIR_DOMAIN_EVENT_ID_GRAPHICS
|
||||
|
||||
// virConnectDomainEventIOErrorReasonCallback
|
||||
VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = C.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON
|
||||
|
||||
// event parameter in the callback is nil
|
||||
VIR_DOMAIN_EVENT_ID_CONTROL_ERROR = C.VIR_DOMAIN_EVENT_ID_CONTROL_ERROR
|
||||
|
||||
// event parameter in the callback is of type DomainBlockJobEvent
|
||||
VIR_DOMAIN_EVENT_ID_BLOCK_JOB = C.VIR_DOMAIN_EVENT_ID_BLOCK_JOB
|
||||
|
||||
// event parameter in the callback is of type DomainDiskChangeEvent
|
||||
VIR_DOMAIN_EVENT_ID_DISK_CHANGE = C.VIR_DOMAIN_EVENT_ID_DISK_CHANGE
|
||||
|
||||
// event parameter in the callback is of type DomainTrayChangeEvent
|
||||
VIR_DOMAIN_EVENT_ID_TRAY_CHANGE = C.VIR_DOMAIN_EVENT_ID_TRAY_CHANGE
|
||||
|
||||
// event parameter in the callback is of type DomainReasonEvent
|
||||
VIR_DOMAIN_EVENT_ID_PMWAKEUP = C.VIR_DOMAIN_EVENT_ID_PMWAKEUP
|
||||
|
||||
// event parameter in the callback is of type DomainReasonEvent
|
||||
VIR_DOMAIN_EVENT_ID_PMSUSPEND = C.VIR_DOMAIN_EVENT_ID_PMSUSPEND
|
||||
|
||||
// event parameter in the callback is of type DomainBalloonChangeEvent
|
||||
VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE = C.VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE
|
||||
|
||||
// event parameter in the callback is of type DomainReasonEvent
|
||||
VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK = C.VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK
|
||||
|
||||
// event parameter in the callback is of type DomainDeviceRemovedEvent
|
||||
VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED = C.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED
|
||||
|
||||
// TODO Post 1.2.4, enable later
|
||||
// event parameter in the callback is of type DomainBlockJobEvent
|
||||
// VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 = C.VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2
|
||||
)
|
||||
|
||||
// virDomainEventType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_DEFINED = C.VIR_DOMAIN_EVENT_DEFINED
|
||||
VIR_DOMAIN_EVENT_UNDEFINED = C.VIR_DOMAIN_EVENT_UNDEFINED
|
||||
VIR_DOMAIN_EVENT_STARTED = C.VIR_DOMAIN_EVENT_STARTED
|
||||
VIR_DOMAIN_EVENT_SUSPENDED = C.VIR_DOMAIN_EVENT_SUSPENDED
|
||||
VIR_DOMAIN_EVENT_RESUMED = C.VIR_DOMAIN_EVENT_RESUMED
|
||||
VIR_DOMAIN_EVENT_STOPPED = C.VIR_DOMAIN_EVENT_STOPPED
|
||||
VIR_DOMAIN_EVENT_SHUTDOWN = C.VIR_DOMAIN_EVENT_SHUTDOWN
|
||||
VIR_DOMAIN_EVENT_PMSUSPENDED = C.VIR_DOMAIN_EVENT_PMSUSPENDED
|
||||
VIR_DOMAIN_EVENT_CRASHED = C.VIR_DOMAIN_EVENT_CRASHED
|
||||
)
|
||||
|
||||
// virDomainEventWatchdogAction:
|
||||
// The action that is to be taken due to the watchdog device firing
|
||||
const (
|
||||
// No action, watchdog ignored
|
||||
VIR_DOMAIN_EVENT_WATCHDOG_NONE = C.VIR_DOMAIN_EVENT_WATCHDOG_NONE
|
||||
|
||||
// Guest CPUs are paused
|
||||
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE = C.VIR_DOMAIN_EVENT_WATCHDOG_PAUSE
|
||||
|
||||
// Guest CPUs are reset
|
||||
VIR_DOMAIN_EVENT_WATCHDOG_RESET = C.VIR_DOMAIN_EVENT_WATCHDOG_RESET
|
||||
|
||||
// Guest is forcibly powered off
|
||||
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF = C.VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF
|
||||
|
||||
// Guest is requested to gracefully shutdown
|
||||
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN = C.VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN
|
||||
|
||||
// No action, a debug message logged
|
||||
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG = C.VIR_DOMAIN_EVENT_WATCHDOG_DEBUG
|
||||
)
|
||||
|
||||
// virDomainEventIOErrorAction
|
||||
// The action that is to be taken due to an IO error occurring
|
||||
const (
|
||||
// No action, IO error ignored
|
||||
VIR_DOMAIN_EVENT_IO_ERROR_NONE = C.VIR_DOMAIN_EVENT_IO_ERROR_NONE
|
||||
|
||||
// Guest CPUs are paused
|
||||
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE = C.VIR_DOMAIN_EVENT_IO_ERROR_PAUSE
|
||||
|
||||
// IO error reported to guest OS
|
||||
VIR_DOMAIN_EVENT_IO_ERROR_REPORT = C.VIR_DOMAIN_EVENT_IO_ERROR_REPORT
|
||||
)
|
||||
|
||||
// virDomainEventGraphicsPhase
|
||||
// The phase of the graphics client connection
|
||||
const (
|
||||
// Initial socket connection established
|
||||
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = C.VIR_DOMAIN_EVENT_GRAPHICS_CONNECT
|
||||
|
||||
// Authentication & setup completed
|
||||
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE = C.VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE
|
||||
|
||||
// Final socket disconnection
|
||||
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT = C.VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT
|
||||
)
|
||||
|
||||
// virDomainEventGraphicsAddressType
|
||||
const (
|
||||
// IPv4 address
|
||||
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4 = C.VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4
|
||||
|
||||
// IPv6 address
|
||||
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6 = C.VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6
|
||||
|
||||
// UNIX socket path
|
||||
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_UNIX = C.VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_UNIX
|
||||
)
|
||||
|
||||
// virDomainBlockJobType
|
||||
const (
|
||||
// Placeholder
|
||||
VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN = C.VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN
|
||||
|
||||
// Block Pull (virDomainBlockPull, or virDomainBlockRebase without
|
||||
// flags), job ends on completion
|
||||
VIR_DOMAIN_BLOCK_JOB_TYPE_PULL = C.VIR_DOMAIN_BLOCK_JOB_TYPE_PULL
|
||||
|
||||
// Block Copy (virDomainBlockCopy, or virDomainBlockRebase with
|
||||
// flags), job exists as long as mirroring is active
|
||||
VIR_DOMAIN_BLOCK_JOB_TYPE_COPY = C.VIR_DOMAIN_BLOCK_JOB_TYPE_COPY
|
||||
|
||||
// Block Commit (virDomainBlockCommit without flags), job ends on
|
||||
// completion
|
||||
VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT = C.VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT
|
||||
|
||||
// TODO Post 1.2.4, enable later
|
||||
// Active Block Commit (virDomainBlockCommit with flags), job
|
||||
// exists as long as sync is active
|
||||
// VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT = C.VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT
|
||||
)
|
||||
|
||||
// virConnectDomainEventBlockJobStatus
|
||||
const (
|
||||
VIR_DOMAIN_BLOCK_JOB_COMPLETED = C.VIR_DOMAIN_BLOCK_JOB_COMPLETED
|
||||
VIR_DOMAIN_BLOCK_JOB_FAILED = C.VIR_DOMAIN_BLOCK_JOB_FAILED
|
||||
VIR_DOMAIN_BLOCK_JOB_CANCELED = C.VIR_DOMAIN_BLOCK_JOB_CANCELED
|
||||
VIR_DOMAIN_BLOCK_JOB_READY = C.VIR_DOMAIN_BLOCK_JOB_READY
|
||||
)
|
||||
|
||||
// virConnectDomainEventDiskChangeReason
|
||||
const (
|
||||
// OldSrcPath is set
|
||||
VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = C.VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START
|
||||
VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START = C.VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START
|
||||
)
|
||||
|
||||
// virConnectDomainEventTrayChangeReason
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN = C.VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN
|
||||
VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE = C.VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE
|
||||
)
|
||||
|
||||
// virDomainRunningReason
|
||||
const (
|
||||
VIR_DOMAIN_RUNNING_UNKNOWN = C.VIR_DOMAIN_RUNNING_UNKNOWN
|
||||
VIR_DOMAIN_RUNNING_BOOTED = C.VIR_DOMAIN_RUNNING_BOOTED /* normal startup from boot */
|
||||
VIR_DOMAIN_RUNNING_MIGRATED = C.VIR_DOMAIN_RUNNING_MIGRATED /* migrated from another host */
|
||||
VIR_DOMAIN_RUNNING_RESTORED = C.VIR_DOMAIN_RUNNING_RESTORED /* restored from a state file */
|
||||
VIR_DOMAIN_RUNNING_FROM_SNAPSHOT = C.VIR_DOMAIN_RUNNING_FROM_SNAPSHOT /* restored from snapshot */
|
||||
VIR_DOMAIN_RUNNING_UNPAUSED = C.VIR_DOMAIN_RUNNING_UNPAUSED /* returned from paused state */
|
||||
VIR_DOMAIN_RUNNING_MIGRATION_CANCELED = C.VIR_DOMAIN_RUNNING_MIGRATION_CANCELED /* returned from migration */
|
||||
VIR_DOMAIN_RUNNING_SAVE_CANCELED = C.VIR_DOMAIN_RUNNING_SAVE_CANCELED /* returned from failed save process */
|
||||
VIR_DOMAIN_RUNNING_WAKEUP = C.VIR_DOMAIN_RUNNING_WAKEUP /* returned from pmsuspended due to wakeup event */
|
||||
VIR_DOMAIN_RUNNING_CRASHED = C.VIR_DOMAIN_RUNNING_CRASHED /* resumed from crashed */
|
||||
)
|
||||
|
||||
// virDomainPausedReason
|
||||
const (
|
||||
VIR_DOMAIN_PAUSED_UNKNOWN = C.VIR_DOMAIN_PAUSED_UNKNOWN /* the reason is unknown */
|
||||
VIR_DOMAIN_PAUSED_USER = C.VIR_DOMAIN_PAUSED_USER /* paused on user request */
|
||||
VIR_DOMAIN_PAUSED_MIGRATION = C.VIR_DOMAIN_PAUSED_MIGRATION /* paused for offline migration */
|
||||
VIR_DOMAIN_PAUSED_SAVE = C.VIR_DOMAIN_PAUSED_SAVE /* paused for save */
|
||||
VIR_DOMAIN_PAUSED_DUMP = C.VIR_DOMAIN_PAUSED_DUMP /* paused for offline core dump */
|
||||
VIR_DOMAIN_PAUSED_IOERROR = C.VIR_DOMAIN_PAUSED_IOERROR /* paused due to a disk I/O error */
|
||||
VIR_DOMAIN_PAUSED_WATCHDOG = C.VIR_DOMAIN_PAUSED_WATCHDOG /* paused due to a watchdog event */
|
||||
VIR_DOMAIN_PAUSED_FROM_SNAPSHOT = C.VIR_DOMAIN_PAUSED_FROM_SNAPSHOT /* paused after restoring from snapshot */
|
||||
VIR_DOMAIN_PAUSED_SHUTTING_DOWN = C.VIR_DOMAIN_PAUSED_SHUTTING_DOWN /* paused during shutdown process */
|
||||
VIR_DOMAIN_PAUSED_SNAPSHOT = C.VIR_DOMAIN_PAUSED_SNAPSHOT /* paused while creating a snapshot */
|
||||
VIR_DOMAIN_PAUSED_CRASHED = C.VIR_DOMAIN_PAUSED_CRASHED /* paused due to a guest crash */
|
||||
)
|
||||
|
||||
// virDomainXMLFlags
|
||||
const (
|
||||
VIR_DOMAIN_XML_SECURE = C.VIR_DOMAIN_XML_SECURE /* dump security sensitive information too */
|
||||
VIR_DOMAIN_XML_INACTIVE = C.VIR_DOMAIN_XML_INACTIVE /* dump inactive domain information */
|
||||
VIR_DOMAIN_XML_UPDATE_CPU = C.VIR_DOMAIN_XML_UPDATE_CPU /* update guest CPU requirements according to host CPU */
|
||||
VIR_DOMAIN_XML_MIGRATABLE = C.VIR_DOMAIN_XML_MIGRATABLE /* dump XML suitable for migration */
|
||||
)
|
||||
|
||||
/*
|
||||
* QMP has two different kinds of ways to talk to QEMU. One is legacy (HMP,
|
||||
* or 'human' monitor protocol. The default is QMP, which is all-JSON.
|
||||
*
|
||||
* QMP json commands are of the format:
|
||||
* {"execute" : "query-cpus"}
|
||||
*
|
||||
* whereas the same command in 'HMP' would be:
|
||||
* 'info cpus'
|
||||
*/
|
||||
const (
|
||||
VIR_DOMAIN_QEMU_MONITOR_COMMAND_DEFAULT = 0
|
||||
VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP = (1 << 0)
|
||||
)
|
||||
|
||||
// virDomainEventDefinedDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_DEFINED_ADDED = C.VIR_DOMAIN_EVENT_DEFINED_ADDED
|
||||
VIR_DOMAIN_EVENT_DEFINED_UPDATED = C.VIR_DOMAIN_EVENT_DEFINED_UPDATED
|
||||
)
|
||||
|
||||
// virDomainEventUndefinedDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_UNDEFINED_REMOVED = C.VIR_DOMAIN_EVENT_UNDEFINED_REMOVED
|
||||
)
|
||||
|
||||
// virDomainEventStartedDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED = C.VIR_DOMAIN_EVENT_STARTED_BOOTED
|
||||
VIR_DOMAIN_EVENT_STARTED_MIGRATED = C.VIR_DOMAIN_EVENT_STARTED_MIGRATED
|
||||
VIR_DOMAIN_EVENT_STARTED_RESTORED = C.VIR_DOMAIN_EVENT_STARTED_RESTORED
|
||||
VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT = C.VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT
|
||||
VIR_DOMAIN_EVENT_STARTED_WAKEUP = C.VIR_DOMAIN_EVENT_STARTED_WAKEUP
|
||||
)
|
||||
|
||||
// virDomainEventSuspendedDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED = C.VIR_DOMAIN_EVENT_SUSPENDED_PAUSED
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED = C.VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_IOERROR = C.VIR_DOMAIN_EVENT_SUSPENDED_IOERROR
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG = C.VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_RESTORED = C.VIR_DOMAIN_EVENT_SUSPENDED_RESTORED
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT = C.VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR = C.VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR
|
||||
)
|
||||
|
||||
// virDomainEventResumedDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED = C.VIR_DOMAIN_EVENT_RESUMED_UNPAUSED
|
||||
VIR_DOMAIN_EVENT_RESUMED_MIGRATED = C.VIR_DOMAIN_EVENT_RESUMED_MIGRATED
|
||||
VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT = C.VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT
|
||||
)
|
||||
|
||||
// virDomainEventStoppedDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN = C.VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN
|
||||
VIR_DOMAIN_EVENT_STOPPED_DESTROYED = C.VIR_DOMAIN_EVENT_STOPPED_DESTROYED
|
||||
VIR_DOMAIN_EVENT_STOPPED_CRASHED = C.VIR_DOMAIN_EVENT_STOPPED_CRASHED
|
||||
VIR_DOMAIN_EVENT_STOPPED_MIGRATED = C.VIR_DOMAIN_EVENT_STOPPED_MIGRATED
|
||||
VIR_DOMAIN_EVENT_STOPPED_SAVED = C.VIR_DOMAIN_EVENT_STOPPED_SAVED
|
||||
VIR_DOMAIN_EVENT_STOPPED_FAILED = C.VIR_DOMAIN_EVENT_STOPPED_FAILED
|
||||
VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT = C.VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT
|
||||
)
|
||||
|
||||
// virDomainEventShutdownDetailType
|
||||
const (
|
||||
VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED = C.VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED
|
||||
)
|
||||
|
||||
// virDomainMemoryStatTags
|
||||
const (
|
||||
VIR_DOMAIN_MEMORY_STAT_LAST = C.VIR_DOMAIN_MEMORY_STAT_NR
|
||||
VIR_DOMAIN_MEMORY_STAT_SWAP_IN = C.VIR_DOMAIN_MEMORY_STAT_SWAP_IN
|
||||
VIR_DOMAIN_MEMORY_STAT_SWAP_OUT = C.VIR_DOMAIN_MEMORY_STAT_SWAP_OUT
|
||||
VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT = C.VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT
|
||||
VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT = C.VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT
|
||||
VIR_DOMAIN_MEMORY_STAT_UNUSED = C.VIR_DOMAIN_MEMORY_STAT_UNUSED
|
||||
VIR_DOMAIN_MEMORY_STAT_AVAILABLE = C.VIR_DOMAIN_MEMORY_STAT_AVAILABLE
|
||||
VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON = C.VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON
|
||||
VIR_DOMAIN_MEMORY_STAT_RSS = C.VIR_DOMAIN_MEMORY_STAT_RSS
|
||||
VIR_DOMAIN_MEMORY_STAT_NR = C.VIR_DOMAIN_MEMORY_STAT_NR
|
||||
)
|
||||
|
||||
// virDomainCPUStatsTags
|
||||
const (
|
||||
VIR_DOMAIN_CPU_STATS_CPUTIME = C.VIR_DOMAIN_CPU_STATS_CPUTIME
|
||||
VIR_DOMAIN_CPU_STATS_SYSTEMTIME = C.VIR_DOMAIN_CPU_STATS_SYSTEMTIME
|
||||
VIR_DOMAIN_CPU_STATS_USERTIME = C.VIR_DOMAIN_CPU_STATS_USERTIME
|
||||
VIR_DOMAIN_CPU_STATS_VCPUTIME = C.VIR_DOMAIN_CPU_STATS_VCPUTIME
|
||||
)
|
||||
|
||||
// virDomainInterfaceAddressesSource
|
||||
const (
|
||||
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0
|
||||
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT = 1
|
||||
)
|
||||
|
||||
// virIPAddrType
|
||||
const (
|
||||
VIR_IP_ADDR_TYPE_IPV4 = 0
|
||||
VIR_IP_ADDR_TYPE_IPV6 = 1
|
||||
)
|
|
@ -0,0 +1,823 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt-qemu -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/libvirt-qemu.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirDomain struct {
|
||||
ptr C.virDomainPtr
|
||||
}
|
||||
|
||||
type VirDomainBlockInfo struct {
|
||||
ptr C.virDomainBlockInfo
|
||||
}
|
||||
|
||||
type VirDomainInfo struct {
|
||||
ptr C.virDomainInfo
|
||||
}
|
||||
|
||||
type VirTypedParameter struct {
|
||||
Name string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
type VirDomainMemoryStat struct {
|
||||
Tag int32
|
||||
Val uint64
|
||||
}
|
||||
|
||||
type VirVcpuInfo struct {
|
||||
Number uint32
|
||||
State int32
|
||||
CpuTime uint64
|
||||
Cpu int32
|
||||
CpuMap []uint32
|
||||
}
|
||||
|
||||
type VirTypedParameters []VirTypedParameter
|
||||
|
||||
func (dest *VirTypedParameters) loadFromCPtr(params C.virTypedParameterPtr, nParams int) {
|
||||
// reset slice
|
||||
*dest = VirTypedParameters{}
|
||||
|
||||
// transform that C array to a go slice
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(params)),
|
||||
Len: int(nParams),
|
||||
Cap: int(nParams),
|
||||
}
|
||||
rawParams := *(*[]C.struct__virTypedParameter)(unsafe.Pointer(&hdr))
|
||||
|
||||
// there is probably a more elegant way to deal with that union
|
||||
for _, rawParam := range rawParams {
|
||||
name := C.GoStringN(&rawParam.field[0], C.VIR_TYPED_PARAM_FIELD_LENGTH)
|
||||
if nbIdx := strings.Index(name, "\x00"); nbIdx != -1 {
|
||||
name = name[:nbIdx]
|
||||
}
|
||||
switch rawParam._type {
|
||||
case C.VIR_TYPED_PARAM_INT:
|
||||
*dest = append(*dest, VirTypedParameter{name, int(*(*C.int)(unsafe.Pointer(&rawParam.value[0])))})
|
||||
case C.VIR_TYPED_PARAM_UINT:
|
||||
*dest = append(*dest, VirTypedParameter{name, uint32(*(*C.uint)(unsafe.Pointer(&rawParam.value[0])))})
|
||||
case C.VIR_TYPED_PARAM_LLONG:
|
||||
*dest = append(*dest, VirTypedParameter{name, int64(*(*C.longlong)(unsafe.Pointer(&rawParam.value[0])))})
|
||||
case C.VIR_TYPED_PARAM_ULLONG:
|
||||
*dest = append(*dest, VirTypedParameter{name, uint64(*(*C.ulonglong)(unsafe.Pointer(&rawParam.value[0])))})
|
||||
case C.VIR_TYPED_PARAM_DOUBLE:
|
||||
*dest = append(*dest, VirTypedParameter{name, float64(*(*C.double)(unsafe.Pointer(&rawParam.value[0])))})
|
||||
case C.VIR_TYPED_PARAM_BOOLEAN:
|
||||
if int(*(*C.char)(unsafe.Pointer(&rawParam.value[0]))) == 1 {
|
||||
*dest = append(*dest, VirTypedParameter{name, true})
|
||||
} else {
|
||||
*dest = append(*dest, VirTypedParameter{name, false})
|
||||
}
|
||||
case C.VIR_TYPED_PARAM_STRING:
|
||||
*dest = append(*dest, VirTypedParameter{name, C.GoString((*C.char)(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&rawParam.value[0])))))})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VirDomain) Free() error {
|
||||
if result := C.virDomainFree(d.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Create() error {
|
||||
result := C.virDomainCreate(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) CreateWithFlags(flags uint) error {
|
||||
result := C.virDomainCreateWithFlags(d.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Destroy() error {
|
||||
result := C.virDomainDestroy(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Shutdown() error {
|
||||
result := C.virDomainShutdown(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Reboot(flags uint) error {
|
||||
result := C.virDomainReboot(d.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) IsActive() (bool, error) {
|
||||
result := C.virDomainIsActive(d.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) IsPersistent() (bool, error) {
|
||||
result := C.virDomainIsPersistent(d.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetAutostart(autostart bool) error {
|
||||
var cAutostart C.int
|
||||
switch autostart {
|
||||
case true:
|
||||
cAutostart = 1
|
||||
default:
|
||||
cAutostart = 0
|
||||
}
|
||||
result := C.virDomainSetAutostart(d.ptr, cAutostart)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetAutostart() (bool, error) {
|
||||
var out C.int
|
||||
result := C.virDomainGetAutostart(d.ptr, (*C.int)(unsafe.Pointer(&out)))
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
switch out {
|
||||
case 1:
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetBlockInfo(disk string, flag uint) (VirDomainBlockInfo, error) {
|
||||
bi := VirDomainBlockInfo{}
|
||||
var ptr C.virDomainBlockInfo
|
||||
cDisk := C.CString(disk)
|
||||
defer C.free(unsafe.Pointer(cDisk))
|
||||
result := C.virDomainGetBlockInfo(d.ptr, cDisk, (*C.virDomainBlockInfo)(unsafe.Pointer(&ptr)), C.uint(flag))
|
||||
if result == -1 {
|
||||
return bi, GetLastError()
|
||||
}
|
||||
bi.ptr = ptr
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
func (b *VirDomainBlockInfo) Allocation() uint64 {
|
||||
return uint64(b.ptr.allocation)
|
||||
}
|
||||
|
||||
func (b *VirDomainBlockInfo) Capacity() uint64 {
|
||||
return uint64(b.ptr.capacity)
|
||||
}
|
||||
|
||||
func (b *VirDomainBlockInfo) Physical() uint64 {
|
||||
return uint64(b.ptr.physical)
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetName() (string, error) {
|
||||
name := C.virDomainGetName(d.ptr)
|
||||
if name == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(name), nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetState() ([]int, error) {
|
||||
var cState C.int
|
||||
var cReason C.int
|
||||
result := C.virDomainGetState(d.ptr,
|
||||
(*C.int)(unsafe.Pointer(&cState)),
|
||||
(*C.int)(unsafe.Pointer(&cReason)),
|
||||
0)
|
||||
if int(result) == -1 {
|
||||
return []int{}, GetLastError()
|
||||
}
|
||||
return []int{int(cState), int(cReason)}, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetID() (uint, error) {
|
||||
id := uint(C.virDomainGetID(d.ptr))
|
||||
if id == ^uint(0) {
|
||||
return id, GetLastError()
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetUUID() ([]byte, error) {
|
||||
var cUuid [C.VIR_UUID_BUFLEN](byte)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virDomainGetUUID(d.ptr, (*C.uchar)(cuidPtr))
|
||||
if result != 0 {
|
||||
return []byte{}, GetLastError()
|
||||
}
|
||||
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetUUIDString() (string, error) {
|
||||
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virDomainGetUUIDString(d.ptr, (*C.char)(cuidPtr))
|
||||
if result != 0 {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString((*C.char)(cuidPtr)), nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetInfo() (VirDomainInfo, error) {
|
||||
di := VirDomainInfo{}
|
||||
var ptr C.virDomainInfo
|
||||
result := C.virDomainGetInfo(d.ptr, (*C.virDomainInfo)(unsafe.Pointer(&ptr)))
|
||||
if result == -1 {
|
||||
return di, GetLastError()
|
||||
}
|
||||
di.ptr = ptr
|
||||
return di, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virDomainGetXMLDesc(d.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
||||
|
||||
func (i *VirDomainInfo) GetState() uint8 {
|
||||
return uint8(i.ptr.state)
|
||||
}
|
||||
|
||||
func (i *VirDomainInfo) GetMaxMem() uint64 {
|
||||
return uint64(i.ptr.maxMem)
|
||||
}
|
||||
|
||||
func (i *VirDomainInfo) GetMemory() uint64 {
|
||||
return uint64(i.ptr.memory)
|
||||
}
|
||||
|
||||
func (i *VirDomainInfo) GetNrVirtCpu() uint16 {
|
||||
return uint16(i.ptr.nrVirtCpu)
|
||||
}
|
||||
|
||||
func (i *VirDomainInfo) GetCpuTime() uint64 {
|
||||
return uint64(i.ptr.cpuTime)
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetCPUStats(params *VirTypedParameters, nParams int, startCpu int, nCpus uint32, flags uint32) (int, error) {
|
||||
var cParams C.virTypedParameterPtr
|
||||
var cParamsLen int
|
||||
|
||||
cParamsLen = int(nCpus) * nParams
|
||||
|
||||
if params != nil && cParamsLen > 0 {
|
||||
cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(cParamsLen), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{}))))
|
||||
defer C.virTypedParamsFree(cParams, C.int(cParamsLen))
|
||||
} else {
|
||||
cParamsLen = 0
|
||||
cParams = nil
|
||||
}
|
||||
|
||||
result := int(C.virDomainGetCPUStats(d.ptr, (C.virTypedParameterPtr)(cParams), C.uint(nParams), C.int(startCpu), C.uint(nCpus), C.uint(flags)))
|
||||
if result == -1 {
|
||||
return result, GetLastError()
|
||||
}
|
||||
|
||||
if cParamsLen > 0 {
|
||||
params.loadFromCPtr(cParams, cParamsLen)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Warning: No test written for this function
|
||||
func (d *VirDomain) GetInterfaceParameters(device string, params *VirTypedParameters, nParams *int, flags uint32) (int, error) {
|
||||
var cParams C.virTypedParameterPtr
|
||||
|
||||
if params != nil && *nParams > 0 {
|
||||
cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(*nParams), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{}))))
|
||||
defer C.virTypedParamsFree(cParams, C.int(*nParams))
|
||||
} else {
|
||||
cParams = nil
|
||||
}
|
||||
|
||||
cDevice := C.CString(device)
|
||||
defer C.free(unsafe.Pointer(cDevice))
|
||||
result := int(C.virDomainGetInterfaceParameters(d.ptr, cDevice,
|
||||
(C.virTypedParameterPtr)(cParams), (*C.int)(unsafe.Pointer(nParams)), C.uint(flags)))
|
||||
if result == -1 {
|
||||
return result, GetLastError()
|
||||
}
|
||||
|
||||
if params != nil && *nParams > 0 {
|
||||
params.loadFromCPtr(cParams, *nParams)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetMetadata(tipus int, uri string, flags uint32) (string, error) {
|
||||
var cUri *C.char
|
||||
if uri != "" {
|
||||
cUri = C.CString(uri)
|
||||
defer C.free(unsafe.Pointer(cUri))
|
||||
}
|
||||
|
||||
result := C.virDomainGetMetadata(d.ptr, C.int(tipus), cUri, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
|
||||
}
|
||||
defer C.free(unsafe.Pointer(result))
|
||||
return C.GoString(result), nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetMetadata(metaDataType int, metaDataCont, uriKey, uri string, flags uint32) error {
|
||||
var cMetaDataCont *C.char
|
||||
var cUriKey *C.char
|
||||
var cUri *C.char
|
||||
|
||||
cMetaDataCont = C.CString(metaDataCont)
|
||||
defer C.free(unsafe.Pointer(cMetaDataCont))
|
||||
|
||||
if metaDataType == VIR_DOMAIN_METADATA_ELEMENT {
|
||||
cUriKey = C.CString(uriKey)
|
||||
defer C.free(unsafe.Pointer(cUriKey))
|
||||
cUri = C.CString(uri)
|
||||
defer C.free(unsafe.Pointer(cUri))
|
||||
}
|
||||
result := C.virDomainSetMetadata(d.ptr, C.int(metaDataType), cMetaDataCont, cUriKey, cUri, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Undefine() error {
|
||||
result := C.virDomainUndefine(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) UndefineFlags(flags uint) error {
|
||||
result := C.virDomainUndefineFlags(d.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetMaxMemory(memory uint) error {
|
||||
result := C.virDomainSetMaxMemory(d.ptr, C.ulong(memory))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetMemory(memory uint64) error {
|
||||
result := C.virDomainSetMemory(d.ptr, C.ulong(memory))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetMemoryFlags(memory uint64, flags uint32) error {
|
||||
result := C.virDomainSetMemoryFlags(d.ptr, C.ulong(memory), C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetMemoryStatsPeriod(period int, flags uint) error {
|
||||
result := C.virDomainSetMemoryStatsPeriod(d.ptr, C.int(period), C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetVcpus(vcpu uint16) error {
|
||||
result := C.virDomainSetVcpus(d.ptr, C.uint(vcpu))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SetVcpusFlags(vcpu uint16, flags uint) error {
|
||||
result := C.virDomainSetVcpusFlags(d.ptr, C.uint(vcpu), C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Suspend() error {
|
||||
result := C.virDomainSuspend(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Resume() error {
|
||||
result := C.virDomainResume(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) AbortJob() error {
|
||||
result := C.virDomainAbortJob(d.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) DestroyFlags(flags uint) error {
|
||||
result := C.virDomainDestroyFlags(d.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) ShutdownFlags(flags uint) error {
|
||||
result := C.virDomainShutdownFlags(d.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) AttachDevice(xml string) error {
|
||||
cXml := C.CString(xml)
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
result := C.virDomainAttachDevice(d.ptr, cXml)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) AttachDeviceFlags(xml string, flags uint) error {
|
||||
cXml := C.CString(xml)
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
result := C.virDomainAttachDeviceFlags(d.ptr, cXml, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) DetachDevice(xml string) error {
|
||||
cXml := C.CString(xml)
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
result := C.virDomainDetachDevice(d.ptr, cXml)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) DetachDeviceFlags(xml string, flags uint) error {
|
||||
cXml := C.CString(xml)
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
result := C.virDomainDetachDeviceFlags(d.ptr, cXml, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) UpdateDeviceFlags(xml string, flags uint) error {
|
||||
cXml := C.CString(xml)
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
result := C.virDomainUpdateDeviceFlags(d.ptr, cXml, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Screenshot(stream *VirStream, screen, flags uint) (string, error) {
|
||||
cType := C.virDomainScreenshot(d.ptr, stream.ptr, C.uint(screen), C.uint(flags))
|
||||
if cType == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
defer C.free(unsafe.Pointer(cType))
|
||||
|
||||
mimeType := C.GoString(cType)
|
||||
return mimeType, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SendKey(codeset, holdtime uint, keycodes []uint, flags uint) error {
|
||||
result := C.virDomainSendKey(d.ptr, C.uint(codeset), C.uint(holdtime), (*C.uint)(unsafe.Pointer(&keycodes[0])), C.int(len(keycodes)), C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) BlockStatsFlags(disk string, params *VirTypedParameters, nParams int, flags uint32) (int, error) {
|
||||
var cParams C.virTypedParameterPtr
|
||||
cDisk := C.CString(disk)
|
||||
defer C.free(unsafe.Pointer(cDisk))
|
||||
|
||||
cParamsLen := C.int(nParams)
|
||||
|
||||
if params != nil && nParams > 0 {
|
||||
cParams = (C.virTypedParameterPtr)(C.calloc(C.size_t(nParams), C.size_t(unsafe.Sizeof(C.struct__virTypedParameter{}))))
|
||||
defer C.virTypedParamsFree(cParams, cParamsLen)
|
||||
} else {
|
||||
cParams = nil
|
||||
}
|
||||
|
||||
result := int(C.virDomainBlockStatsFlags(d.ptr, cDisk, (C.virTypedParameterPtr)(cParams), &cParamsLen, C.uint(flags)))
|
||||
if result == -1 {
|
||||
return result, GetLastError()
|
||||
}
|
||||
|
||||
if cParamsLen > 0 && params != nil {
|
||||
params.loadFromCPtr(cParams, nParams)
|
||||
}
|
||||
|
||||
return int(cParamsLen), nil
|
||||
}
|
||||
|
||||
type VirDomainBlockStats struct {
|
||||
RdReq int64
|
||||
WrReq int64
|
||||
RdBytes int64
|
||||
WrBytes int64
|
||||
}
|
||||
|
||||
type VirDomainInterfaceStats struct {
|
||||
RxBytes int64
|
||||
RxPackets int64
|
||||
RxErrs int64
|
||||
RxDrop int64
|
||||
TxBytes int64
|
||||
TxPackets int64
|
||||
TxErrs int64
|
||||
TxDrop int64
|
||||
}
|
||||
|
||||
func (d *VirDomain) BlockStats(path string) (VirDomainBlockStats, error) {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
|
||||
size := C.size_t(unsafe.Sizeof(C.struct__virDomainBlockStats{}))
|
||||
|
||||
cStats := (C.virDomainBlockStatsPtr)(C.malloc(size))
|
||||
defer C.free(unsafe.Pointer(cStats))
|
||||
|
||||
result := C.virDomainBlockStats(d.ptr, cPath, (C.virDomainBlockStatsPtr)(cStats), size)
|
||||
|
||||
if result != 0 {
|
||||
return VirDomainBlockStats{}, GetLastError()
|
||||
}
|
||||
return VirDomainBlockStats{
|
||||
WrReq: int64(cStats.wr_req),
|
||||
RdReq: int64(cStats.rd_req),
|
||||
RdBytes: int64(cStats.rd_bytes),
|
||||
WrBytes: int64(cStats.wr_bytes),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) InterfaceStats(path string) (VirDomainInterfaceStats, error) {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
|
||||
size := C.size_t(unsafe.Sizeof(C.struct__virDomainInterfaceStats{}))
|
||||
|
||||
cStats := (C.virDomainInterfaceStatsPtr)(C.malloc(size))
|
||||
defer C.free(unsafe.Pointer(cStats))
|
||||
|
||||
result := C.virDomainInterfaceStats(d.ptr, cPath, (C.virDomainInterfaceStatsPtr)(cStats), size)
|
||||
|
||||
if result != 0 {
|
||||
return VirDomainInterfaceStats{}, GetLastError()
|
||||
}
|
||||
return VirDomainInterfaceStats{
|
||||
RxBytes: int64(cStats.rx_bytes),
|
||||
RxPackets: int64(cStats.rx_packets),
|
||||
RxErrs: int64(cStats.rx_errs),
|
||||
RxDrop: int64(cStats.rx_drop),
|
||||
TxBytes: int64(cStats.tx_bytes),
|
||||
TxPackets: int64(cStats.tx_packets),
|
||||
TxErrs: int64(cStats.tx_errs),
|
||||
TxDrop: int64(cStats.tx_drop),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) MemoryStats(nrStats uint32, flags uint32) ([]VirDomainMemoryStat, error) {
|
||||
ptr := make([]C.virDomainMemoryStatStruct, nrStats)
|
||||
|
||||
result := C.virDomainMemoryStats(
|
||||
d.ptr, (C.virDomainMemoryStatPtr)(unsafe.Pointer(&ptr[0])),
|
||||
C.uint(nrStats), C.uint(flags))
|
||||
|
||||
if result == -1 {
|
||||
return []VirDomainMemoryStat{}, GetLastError()
|
||||
}
|
||||
|
||||
out := make([]VirDomainMemoryStat, result)
|
||||
for i := 0; i < int(result); i++ {
|
||||
out = append(out, VirDomainMemoryStat{
|
||||
Tag: int32(ptr[i].tag),
|
||||
Val: uint64(ptr[i].val),
|
||||
})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetVcpus(maxInfo int32) ([]VirVcpuInfo, error) {
|
||||
ptr := make([]C.virVcpuInfo, maxInfo)
|
||||
|
||||
result := C.virDomainGetVcpus(
|
||||
d.ptr, (C.virVcpuInfoPtr)(unsafe.Pointer(&ptr[0])),
|
||||
C.int(maxInfo), nil, C.int(0))
|
||||
|
||||
if result == -1 {
|
||||
return []VirVcpuInfo{}, GetLastError()
|
||||
}
|
||||
|
||||
out := make([]VirVcpuInfo, 0)
|
||||
for i := 0; i < int(result); i++ {
|
||||
out = append(out, VirVcpuInfo{
|
||||
Number: uint32(ptr[i].number),
|
||||
State: int32(ptr[i].state),
|
||||
CpuTime: uint64(ptr[i].cpuTime),
|
||||
Cpu: int32(ptr[i].cpu),
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// libvirt-domain.h: VIR_CPU_MAPLEN
|
||||
func virCpuMapLen(cpu uint32) C.int {
|
||||
return C.int((cpu + 7) / 8)
|
||||
}
|
||||
|
||||
// extractCpuMask extracts an individual cpumask from a slice of cpumasks
|
||||
// and parses it into a slice of CPU ids
|
||||
func extractCpuMask(bytesCpuMaps []byte, n, mapLen int) []uint32 {
|
||||
const byteSize = uint(8)
|
||||
|
||||
// Repslice the big array to separate only mask number 'n'
|
||||
cpuMap := bytesCpuMaps[n*mapLen : (n+1)*mapLen]
|
||||
|
||||
out := make([]uint32, 0)
|
||||
for i, b := range cpuMap { // iterate over bytes of the mask
|
||||
for j := uint(0); j < byteSize; j++ { // iterate over bits in this byte
|
||||
if (b>>j)&0x1 == 1 {
|
||||
out = append(out, uint32(j+uint(i)*byteSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetVcpusCpuMap(maxInfo int, maxCPUs uint32) ([]VirVcpuInfo, error) {
|
||||
ptr := make([]C.virVcpuInfo, maxInfo)
|
||||
|
||||
mapLen := virCpuMapLen(maxCPUs) // Length of CPUs bitmask in bytes
|
||||
bufSize := int(mapLen) * int(maxInfo) // Length of the array of 'maxinfo' bitmasks
|
||||
cpuMaps := (*C.uchar)(C.malloc(C.size_t(bufSize))) // Array itself
|
||||
defer C.free(unsafe.Pointer(cpuMaps))
|
||||
|
||||
result := C.virDomainGetVcpus(
|
||||
d.ptr, (C.virVcpuInfoPtr)(unsafe.Pointer(&ptr[0])),
|
||||
C.int(maxInfo), cpuMaps, mapLen)
|
||||
|
||||
if result == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
|
||||
// Convert to golang []byte for easier handling
|
||||
bytesCpuMaps := C.GoBytes(unsafe.Pointer(cpuMaps), C.int(bufSize))
|
||||
|
||||
out := make([]VirVcpuInfo, 0)
|
||||
for i := 0; i < int(result); i++ {
|
||||
out = append(out, VirVcpuInfo{
|
||||
Number: uint32(ptr[i].number),
|
||||
State: int32(ptr[i].state),
|
||||
CpuTime: uint64(ptr[i].cpuTime),
|
||||
Cpu: int32(ptr[i].cpu),
|
||||
CpuMap: extractCpuMask(bytesCpuMaps, i, int(mapLen)),
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) GetVcpusFlags(flags uint32) (int32, error) {
|
||||
result := C.virDomainGetVcpusFlags(d.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return int32(result), nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) QemuMonitorCommand(flags uint32, command string) (string, error) {
|
||||
var cResult *C.char
|
||||
cCommand := C.CString(command)
|
||||
defer C.free(unsafe.Pointer(cCommand))
|
||||
result := C.virDomainQemuMonitorCommand(d.ptr, cCommand, &cResult, C.uint(flags))
|
||||
|
||||
if result != 0 {
|
||||
return "", GetLastError()
|
||||
}
|
||||
|
||||
rstring := C.GoString(cResult)
|
||||
C.free(unsafe.Pointer(cResult))
|
||||
return rstring, nil
|
||||
}
|
||||
|
||||
func cpuMask(cpuMap []uint32, maxCPUs uint32) (*C.uchar, C.int) {
|
||||
const byteSize = uint(8)
|
||||
|
||||
mapLen := virCpuMapLen(maxCPUs) // Length of CPUs bitmask in bytes
|
||||
bytesCpuMap := make([]byte, mapLen)
|
||||
|
||||
for _, c := range cpuMap {
|
||||
by := uint(c) / byteSize
|
||||
bi := uint(c) % byteSize
|
||||
bytesCpuMap[by] |= 1 << bi
|
||||
}
|
||||
|
||||
return (*C.uchar)(&bytesCpuMap[0]), mapLen
|
||||
}
|
||||
|
||||
func (d *VirDomain) PinVcpu(vcpu uint, cpuMap []uint32, maxCPUs uint32) error {
|
||||
|
||||
cpumap, maplen := cpuMask(cpuMap, maxCPUs)
|
||||
|
||||
result := C.virDomainPinVcpu(d.ptr, C.uint(vcpu), cpumap, maplen)
|
||||
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) PinVcpuFlags(vcpu uint, cpuMap []uint32, flags uint, maxCPUs uint32) error {
|
||||
cpumap, maplen := cpuMask(cpuMap, maxCPUs)
|
||||
|
||||
result := C.virDomainPinVcpuFlags(d.ptr, C.uint(vcpu), cpumap, maplen, C.uint(flags))
|
||||
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// +build libvirt.1.2.14
|
||||
|
||||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt-qemu -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/libvirt-qemu.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirDomainIPAddress struct {
|
||||
Type int
|
||||
Addr string
|
||||
Prefix uint
|
||||
}
|
||||
|
||||
type VirDomainInterface struct {
|
||||
Name string
|
||||
Hwaddr string
|
||||
Addrs []VirDomainIPAddress
|
||||
}
|
||||
|
||||
func (d *VirDomain) ListAllInterfaceAddresses(src uint) ([]VirDomainInterface, error) {
|
||||
var cList *C.virDomainInterfacePtr
|
||||
numIfaces := int(C.virDomainInterfaceAddresses(d.ptr, (**C.virDomainInterfacePtr)(&cList), C.uint(src), 0))
|
||||
if numIfaces == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cList)),
|
||||
Len: int(numIfaces),
|
||||
Cap: int(numIfaces),
|
||||
}
|
||||
|
||||
ifaces := make([]VirDomainInterface, numIfaces)
|
||||
ifaceSlice := *(*[]C.virDomainInterfacePtr)(unsafe.Pointer(&hdr))
|
||||
|
||||
for i := 0; i < numIfaces; i++ {
|
||||
ifaces[i].Name = C.GoString(ifaceSlice[i].name)
|
||||
ifaces[i].Hwaddr = C.GoString(ifaceSlice[i].hwaddr)
|
||||
|
||||
numAddr := int(ifaceSlice[i].naddrs)
|
||||
addrHdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(&ifaceSlice[i].addrs)),
|
||||
Len: int(numAddr),
|
||||
Cap: int(numAddr),
|
||||
}
|
||||
|
||||
ifaces[i].Addrs = make([]VirDomainIPAddress, numAddr)
|
||||
addrSlice := *(*[]C.virDomainIPAddressPtr)(unsafe.Pointer(&addrHdr))
|
||||
|
||||
for k := 0; k < numAddr; k++ {
|
||||
ifaces[i].Addrs[k] = VirDomainIPAddress{}
|
||||
ifaces[i].Addrs[k].Type = int(addrSlice[k]._type)
|
||||
ifaces[i].Addrs[k].Addr = C.GoString(addrSlice[k].addr)
|
||||
ifaces[i].Addrs[k].Prefix = uint(addrSlice[k].prefix)
|
||||
|
||||
}
|
||||
C.virDomainInterfaceFree(ifaceSlice[i])
|
||||
}
|
||||
C.free(unsafe.Pointer(cList))
|
||||
return ifaces, nil
|
||||
}
|
|
@ -0,0 +1,602 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef VIR_FROM_BHYVE
|
||||
#define VIR_FROM_BHYVE 57
|
||||
#endif
|
||||
|
||||
#ifndef VIR_FROM_CRYPTO
|
||||
#define VIR_FROM_CRYPTO 58
|
||||
#endif
|
||||
|
||||
#ifndef VIR_FROM_FIREWALL
|
||||
#define VIR_FROM_FIREWALL 59
|
||||
#endif
|
||||
|
||||
void errorGlobalCallback_cgo(void *userData, virErrorPtr error);
|
||||
void errorConnCallback_cgo(void *userData, virErrorPtr error);
|
||||
void virConnSetErrorFunc_cgo(virConnectPtr c, long goCallbackId, virErrorFunc cb);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// virErrorLevel
|
||||
const (
|
||||
VIR_ERR_NONE = C.VIR_ERR_NONE
|
||||
VIR_ERR_WARNING = C.VIR_ERR_WARNING
|
||||
VIR_ERR_ERROR = C.VIR_ERR_ERROR
|
||||
)
|
||||
|
||||
// virErrorNumber
|
||||
const (
|
||||
VIR_ERR_OK = C.VIR_ERR_OK
|
||||
|
||||
// internal error
|
||||
VIR_ERR_INTERNAL_ERROR = C.VIR_ERR_INTERNAL_ERROR
|
||||
|
||||
// memory allocation failure
|
||||
VIR_ERR_NO_MEMORY = C.VIR_ERR_NO_MEMORY
|
||||
|
||||
// no support for this function
|
||||
VIR_ERR_NO_SUPPORT = C.VIR_ERR_NO_SUPPORT
|
||||
|
||||
// could not resolve hostname
|
||||
VIR_ERR_UNKNOWN_HOST = C.VIR_ERR_UNKNOWN_HOST
|
||||
|
||||
// can't connect to hypervisor
|
||||
VIR_ERR_NO_CONNECT = C.VIR_ERR_NO_CONNECT
|
||||
|
||||
// invalid connection object
|
||||
VIR_ERR_INVALID_CONN = C.VIR_ERR_INVALID_CONN
|
||||
|
||||
// invalid domain object
|
||||
VIR_ERR_INVALID_DOMAIN = C.VIR_ERR_INVALID_DOMAIN
|
||||
|
||||
// invalid function argument
|
||||
VIR_ERR_INVALID_ARG = C.VIR_ERR_INVALID_ARG
|
||||
|
||||
// a command to hypervisor failed
|
||||
VIR_ERR_OPERATION_FAILED = C.VIR_ERR_OPERATION_FAILED
|
||||
|
||||
// a HTTP GET command to failed
|
||||
VIR_ERR_GET_FAILED = C.VIR_ERR_GET_FAILED
|
||||
|
||||
// a HTTP POST command to failed
|
||||
VIR_ERR_POST_FAILED = C.VIR_ERR_POST_FAILED
|
||||
|
||||
// unexpected HTTP error code
|
||||
VIR_ERR_HTTP_ERROR = C.VIR_ERR_HTTP_ERROR
|
||||
|
||||
// failure to serialize an S-Expr
|
||||
VIR_ERR_SEXPR_SERIAL = C.VIR_ERR_SEXPR_SERIAL
|
||||
|
||||
// could not open Xen hypervisor control
|
||||
VIR_ERR_NO_XEN = C.VIR_ERR_NO_XEN
|
||||
|
||||
// failure doing an hypervisor call
|
||||
VIR_ERR_XEN_CALL = C.VIR_ERR_XEN_CALL
|
||||
|
||||
// unknown OS type
|
||||
VIR_ERR_OS_TYPE = C.VIR_ERR_OS_TYPE
|
||||
|
||||
// missing kernel information
|
||||
VIR_ERR_NO_KERNEL = C.VIR_ERR_NO_KERNEL
|
||||
|
||||
// missing root device information
|
||||
VIR_ERR_NO_ROOT = C.VIR_ERR_NO_ROOT
|
||||
|
||||
// missing source device information
|
||||
VIR_ERR_NO_SOURCE = C.VIR_ERR_NO_SOURCE
|
||||
|
||||
// missing target device information
|
||||
VIR_ERR_NO_TARGET = C.VIR_ERR_NO_TARGET
|
||||
|
||||
// missing domain name information
|
||||
VIR_ERR_NO_NAME = C.VIR_ERR_NO_NAME
|
||||
|
||||
// missing domain OS information
|
||||
VIR_ERR_NO_OS = C.VIR_ERR_NO_OS
|
||||
|
||||
// missing domain devices information
|
||||
VIR_ERR_NO_DEVICE = C.VIR_ERR_NO_DEVICE
|
||||
|
||||
// could not open Xen Store control
|
||||
VIR_ERR_NO_XENSTORE = C.VIR_ERR_NO_XENSTORE
|
||||
|
||||
// too many drivers registered
|
||||
VIR_ERR_DRIVER_FULL = C.VIR_ERR_DRIVER_FULL
|
||||
|
||||
// not supported by the drivers (DEPRECATED)
|
||||
VIR_ERR_CALL_FAILED = C.VIR_ERR_CALL_FAILED
|
||||
|
||||
// an XML description is not well formed or broken
|
||||
VIR_ERR_XML_ERROR = C.VIR_ERR_XML_ERROR
|
||||
|
||||
// the domain already exist
|
||||
VIR_ERR_DOM_EXIST = C.VIR_ERR_DOM_EXIST
|
||||
|
||||
// operation forbidden on read-only connections
|
||||
VIR_ERR_OPERATION_DENIED = C.VIR_ERR_OPERATION_DENIED
|
||||
|
||||
// failed to open a conf file
|
||||
VIR_ERR_OPEN_FAILED = C.VIR_ERR_OPEN_FAILED
|
||||
|
||||
// failed to read a conf file
|
||||
VIR_ERR_READ_FAILED = C.VIR_ERR_READ_FAILED
|
||||
|
||||
// failed to parse a conf file
|
||||
VIR_ERR_PARSE_FAILED = C.VIR_ERR_PARSE_FAILED
|
||||
|
||||
// failed to parse the syntax of a conf file
|
||||
VIR_ERR_CONF_SYNTAX = C.VIR_ERR_CONF_SYNTAX
|
||||
|
||||
// failed to write a conf file
|
||||
VIR_ERR_WRITE_FAILED = C.VIR_ERR_WRITE_FAILED
|
||||
|
||||
// detail of an XML error
|
||||
VIR_ERR_XML_DETAIL = C.VIR_ERR_XML_DETAIL
|
||||
|
||||
// invalid network object
|
||||
VIR_ERR_INVALID_NETWORK = C.VIR_ERR_INVALID_NETWORK
|
||||
|
||||
// the network already exist
|
||||
VIR_ERR_NETWORK_EXIST = C.VIR_ERR_NETWORK_EXIST
|
||||
|
||||
// general system call failure
|
||||
VIR_ERR_SYSTEM_ERROR = C.VIR_ERR_SYSTEM_ERROR
|
||||
|
||||
// some sort of RPC error
|
||||
VIR_ERR_RPC = C.VIR_ERR_RPC
|
||||
|
||||
// error from a GNUTLS call
|
||||
VIR_ERR_GNUTLS_ERROR = C.VIR_ERR_GNUTLS_ERROR
|
||||
|
||||
// failed to start network
|
||||
VIR_WAR_NO_NETWORK = C.VIR_WAR_NO_NETWORK
|
||||
|
||||
// domain not found or unexpectedly disappeared
|
||||
VIR_ERR_NO_DOMAIN = C.VIR_ERR_NO_DOMAIN
|
||||
|
||||
// network not found
|
||||
VIR_ERR_NO_NETWORK = C.VIR_ERR_NO_NETWORK
|
||||
|
||||
// invalid MAC address
|
||||
VIR_ERR_INVALID_MAC = C.VIR_ERR_INVALID_MAC
|
||||
|
||||
// authentication failed
|
||||
VIR_ERR_AUTH_FAILED = C.VIR_ERR_AUTH_FAILED
|
||||
|
||||
// invalid storage pool object
|
||||
VIR_ERR_INVALID_STORAGE_POOL = C.VIR_ERR_INVALID_STORAGE_POOL
|
||||
|
||||
// invalid storage vol object
|
||||
VIR_ERR_INVALID_STORAGE_VOL = C.VIR_ERR_INVALID_STORAGE_VOL
|
||||
|
||||
// failed to start storage
|
||||
VIR_WAR_NO_STORAGE = C.VIR_WAR_NO_STORAGE
|
||||
|
||||
// storage pool not found
|
||||
VIR_ERR_NO_STORAGE_POOL = C.VIR_ERR_NO_STORAGE_POOL
|
||||
|
||||
// storage volume not found
|
||||
VIR_ERR_NO_STORAGE_VOL = C.VIR_ERR_NO_STORAGE_VOL
|
||||
|
||||
// failed to start node driver
|
||||
VIR_WAR_NO_NODE = C.VIR_WAR_NO_NODE
|
||||
|
||||
// invalid node device object
|
||||
VIR_ERR_INVALID_NODE_DEVICE = C.VIR_ERR_INVALID_NODE_DEVICE
|
||||
|
||||
// node device not found
|
||||
VIR_ERR_NO_NODE_DEVICE = C.VIR_ERR_NO_NODE_DEVICE
|
||||
|
||||
// security model not found
|
||||
VIR_ERR_NO_SECURITY_MODEL = C.VIR_ERR_NO_SECURITY_MODEL
|
||||
|
||||
// operation is not applicable at this time
|
||||
VIR_ERR_OPERATION_INVALID = C.VIR_ERR_OPERATION_INVALID
|
||||
|
||||
// failed to start interface driver
|
||||
VIR_WAR_NO_INTERFACE = C.VIR_WAR_NO_INTERFACE
|
||||
|
||||
// interface driver not running
|
||||
VIR_ERR_NO_INTERFACE = C.VIR_ERR_NO_INTERFACE
|
||||
|
||||
// invalid interface object
|
||||
VIR_ERR_INVALID_INTERFACE = C.VIR_ERR_INVALID_INTERFACE
|
||||
|
||||
// more than one matching interface found
|
||||
VIR_ERR_MULTIPLE_INTERFACES = C.VIR_ERR_MULTIPLE_INTERFACES
|
||||
|
||||
// failed to start nwfilter driver
|
||||
VIR_WAR_NO_NWFILTER = C.VIR_WAR_NO_NWFILTER
|
||||
|
||||
// invalid nwfilter object
|
||||
VIR_ERR_INVALID_NWFILTER = C.VIR_ERR_INVALID_NWFILTER
|
||||
|
||||
// nw filter pool not found
|
||||
VIR_ERR_NO_NWFILTER = C.VIR_ERR_NO_NWFILTER
|
||||
|
||||
// nw filter pool not found
|
||||
VIR_ERR_BUILD_FIREWALL = C.VIR_ERR_BUILD_FIREWALL
|
||||
|
||||
// failed to start secret storage
|
||||
VIR_WAR_NO_SECRET = C.VIR_WAR_NO_SECRET
|
||||
|
||||
// invalid secret
|
||||
VIR_ERR_INVALID_SECRET = C.VIR_ERR_INVALID_SECRET
|
||||
|
||||
// secret not found
|
||||
VIR_ERR_NO_SECRET = C.VIR_ERR_NO_SECRET
|
||||
|
||||
// unsupported configuration construct
|
||||
VIR_ERR_CONFIG_UNSUPPORTED = C.VIR_ERR_CONFIG_UNSUPPORTED
|
||||
|
||||
// timeout occurred during operation
|
||||
VIR_ERR_OPERATION_TIMEOUT = C.VIR_ERR_OPERATION_TIMEOUT
|
||||
|
||||
// a migration worked, but making the VM persist on the dest host failed
|
||||
VIR_ERR_MIGRATE_PERSIST_FAILED = C.VIR_ERR_MIGRATE_PERSIST_FAILED
|
||||
|
||||
// a synchronous hook script failed
|
||||
VIR_ERR_HOOK_SCRIPT_FAILED = C.VIR_ERR_HOOK_SCRIPT_FAILED
|
||||
|
||||
// invalid domain snapshot
|
||||
VIR_ERR_INVALID_DOMAIN_SNAPSHOT = C.VIR_ERR_INVALID_DOMAIN_SNAPSHOT
|
||||
|
||||
// domain snapshot not found
|
||||
VIR_ERR_NO_DOMAIN_SNAPSHOT = C.VIR_ERR_NO_DOMAIN_SNAPSHOT
|
||||
|
||||
// stream pointer not valid
|
||||
VIR_ERR_INVALID_STREAM = C.VIR_ERR_INVALID_STREAM
|
||||
|
||||
// valid API use but unsupported by the given driver
|
||||
VIR_ERR_ARGUMENT_UNSUPPORTED = C.VIR_ERR_ARGUMENT_UNSUPPORTED
|
||||
|
||||
// storage pool probe failed
|
||||
VIR_ERR_STORAGE_PROBE_FAILED = C.VIR_ERR_STORAGE_PROBE_FAILED
|
||||
|
||||
// storage pool already built
|
||||
VIR_ERR_STORAGE_POOL_BUILT = C.VIR_ERR_STORAGE_POOL_BUILT
|
||||
|
||||
// force was not requested for a risky domain snapshot revert
|
||||
VIR_ERR_SNAPSHOT_REVERT_RISKY = C.VIR_ERR_SNAPSHOT_REVERT_RISKY
|
||||
|
||||
// operation on a domain was canceled/aborted by user
|
||||
VIR_ERR_OPERATION_ABORTED = C.VIR_ERR_OPERATION_ABORTED
|
||||
|
||||
// authentication cancelled
|
||||
VIR_ERR_AUTH_CANCELLED = C.VIR_ERR_AUTH_CANCELLED
|
||||
|
||||
// The metadata is not present
|
||||
VIR_ERR_NO_DOMAIN_METADATA = C.VIR_ERR_NO_DOMAIN_METADATA
|
||||
|
||||
// Migration is not safe
|
||||
VIR_ERR_MIGRATE_UNSAFE = C.VIR_ERR_MIGRATE_UNSAFE
|
||||
|
||||
// integer overflow
|
||||
VIR_ERR_OVERFLOW = C.VIR_ERR_OVERFLOW
|
||||
|
||||
// action prevented by block copy job
|
||||
VIR_ERR_BLOCK_COPY_ACTIVE = C.VIR_ERR_BLOCK_COPY_ACTIVE
|
||||
|
||||
// The requested operation is not supported
|
||||
VIR_ERR_OPERATION_UNSUPPORTED = C.VIR_ERR_OPERATION_UNSUPPORTED
|
||||
|
||||
// error in ssh transport driver
|
||||
VIR_ERR_SSH = C.VIR_ERR_SSH
|
||||
|
||||
// guest agent is unresponsive, not running or not usable
|
||||
VIR_ERR_AGENT_UNRESPONSIVE = C.VIR_ERR_AGENT_UNRESPONSIVE
|
||||
|
||||
// resource is already in use
|
||||
VIR_ERR_RESOURCE_BUSY = C.VIR_ERR_RESOURCE_BUSY
|
||||
|
||||
// operation on the object/resource was denied
|
||||
VIR_ERR_ACCESS_DENIED = C.VIR_ERR_ACCESS_DENIED
|
||||
|
||||
// error from a dbus service
|
||||
VIR_ERR_DBUS_SERVICE = C.VIR_ERR_DBUS_SERVICE
|
||||
|
||||
// the storage vol already exists
|
||||
VIR_ERR_STORAGE_VOL_EXIST = C.VIR_ERR_STORAGE_VOL_EXIST
|
||||
|
||||
// given CPU is incompatible with host CPU
|
||||
// added in libvirt 1.2.6
|
||||
// VIR_ERR_CPU_INCOMPATIBLE = C.VIR_ERR_CPU_INCOMPATIBLE
|
||||
)
|
||||
|
||||
// virErrorDomain
|
||||
const (
|
||||
VIR_FROM_NONE = C.VIR_FROM_NONE
|
||||
|
||||
// Error at Xen hypervisor layer
|
||||
VIR_FROM_XEN = C.VIR_FROM_XEN
|
||||
|
||||
// Error at connection with xend daemon
|
||||
VIR_FROM_XEND = C.VIR_FROM_XEND
|
||||
|
||||
// Error at connection with xen store
|
||||
VIR_FROM_XENSTORE = C.VIR_FROM_XENSTORE
|
||||
|
||||
// Error in the S-Expression code
|
||||
VIR_FROM_SEXPR = C.VIR_FROM_SEXPR
|
||||
|
||||
// Error in the XML code
|
||||
VIR_FROM_XML = C.VIR_FROM_XML
|
||||
|
||||
// Error when operating on a domain
|
||||
VIR_FROM_DOM = C.VIR_FROM_DOM
|
||||
|
||||
// Error in the XML-RPC code
|
||||
VIR_FROM_RPC = C.VIR_FROM_RPC
|
||||
|
||||
// Error in the proxy code; unused since 0.8.6
|
||||
VIR_FROM_PROXY = C.VIR_FROM_PROXY
|
||||
|
||||
// Error in the configuration file handling
|
||||
VIR_FROM_CONF = C.VIR_FROM_CONF
|
||||
|
||||
// Error at the QEMU daemon
|
||||
VIR_FROM_QEMU = C.VIR_FROM_QEMU
|
||||
|
||||
// Error when operating on a network
|
||||
VIR_FROM_NET = C.VIR_FROM_NET
|
||||
|
||||
// Error from test driver
|
||||
VIR_FROM_TEST = C.VIR_FROM_TEST
|
||||
|
||||
// Error from remote driver
|
||||
VIR_FROM_REMOTE = C.VIR_FROM_REMOTE
|
||||
|
||||
// Error from OpenVZ driver
|
||||
VIR_FROM_OPENVZ = C.VIR_FROM_OPENVZ
|
||||
|
||||
// Error at Xen XM layer
|
||||
VIR_FROM_XENXM = C.VIR_FROM_XENXM
|
||||
|
||||
// Error in the Linux Stats code
|
||||
VIR_FROM_STATS_LINUX = C.VIR_FROM_STATS_LINUX
|
||||
|
||||
// Error from Linux Container driver
|
||||
VIR_FROM_LXC = C.VIR_FROM_LXC
|
||||
|
||||
// Error from storage driver
|
||||
VIR_FROM_STORAGE = C.VIR_FROM_STORAGE
|
||||
|
||||
// Error from network config
|
||||
VIR_FROM_NETWORK = C.VIR_FROM_NETWORK
|
||||
|
||||
// Error from domain config
|
||||
VIR_FROM_DOMAIN = C.VIR_FROM_DOMAIN
|
||||
|
||||
// Error at the UML driver
|
||||
VIR_FROM_UML = C.VIR_FROM_UML
|
||||
|
||||
// Error from node device monitor
|
||||
VIR_FROM_NODEDEV = C.VIR_FROM_NODEDEV
|
||||
|
||||
// Error from xen inotify layer
|
||||
VIR_FROM_XEN_INOTIFY = C.VIR_FROM_XEN_INOTIFY
|
||||
|
||||
// Error from security framework
|
||||
VIR_FROM_SECURITY = C.VIR_FROM_SECURITY
|
||||
|
||||
// Error from VirtualBox driver
|
||||
VIR_FROM_VBOX = C.VIR_FROM_VBOX
|
||||
|
||||
// Error when operating on an interface
|
||||
VIR_FROM_INTERFACE = C.VIR_FROM_INTERFACE
|
||||
|
||||
// The OpenNebula driver no longer exists. Retained for ABI/API compat only
|
||||
VIR_FROM_ONE = C.VIR_FROM_ONE
|
||||
|
||||
// Error from ESX driver
|
||||
VIR_FROM_ESX = C.VIR_FROM_ESX
|
||||
|
||||
// Error from IBM power hypervisor
|
||||
VIR_FROM_PHYP = C.VIR_FROM_PHYP
|
||||
|
||||
// Error from secret storage
|
||||
VIR_FROM_SECRET = C.VIR_FROM_SECRET
|
||||
|
||||
// Error from CPU driver
|
||||
VIR_FROM_CPU = C.VIR_FROM_CPU
|
||||
|
||||
// Error from XenAPI
|
||||
VIR_FROM_XENAPI = C.VIR_FROM_XENAPI
|
||||
|
||||
// Error from network filter driver
|
||||
VIR_FROM_NWFILTER = C.VIR_FROM_NWFILTER
|
||||
|
||||
// Error from Synchronous hooks
|
||||
VIR_FROM_HOOK = C.VIR_FROM_HOOK
|
||||
|
||||
// Error from domain snapshot
|
||||
VIR_FROM_DOMAIN_SNAPSHOT = C.VIR_FROM_DOMAIN_SNAPSHOT
|
||||
|
||||
// Error from auditing subsystem
|
||||
VIR_FROM_AUDIT = C.VIR_FROM_AUDIT
|
||||
|
||||
// Error from sysinfo/SMBIOS
|
||||
VIR_FROM_SYSINFO = C.VIR_FROM_SYSINFO
|
||||
|
||||
// Error from I/O streams
|
||||
VIR_FROM_STREAMS = C.VIR_FROM_STREAMS
|
||||
|
||||
// Error from VMware driver
|
||||
VIR_FROM_VMWARE = C.VIR_FROM_VMWARE
|
||||
|
||||
// Error from event loop impl
|
||||
VIR_FROM_EVENT = C.VIR_FROM_EVENT
|
||||
|
||||
// Error from libxenlight driver
|
||||
VIR_FROM_LIBXL = C.VIR_FROM_LIBXL
|
||||
|
||||
// Error from lock manager
|
||||
VIR_FROM_LOCKING = C.VIR_FROM_LOCKING
|
||||
|
||||
// Error from Hyper-V driver
|
||||
VIR_FROM_HYPERV = C.VIR_FROM_HYPERV
|
||||
|
||||
// Error from capabilities
|
||||
VIR_FROM_CAPABILITIES = C.VIR_FROM_CAPABILITIES
|
||||
|
||||
// Error from URI handling
|
||||
VIR_FROM_URI = C.VIR_FROM_URI
|
||||
|
||||
// Error from auth handling
|
||||
VIR_FROM_AUTH = C.VIR_FROM_AUTH
|
||||
|
||||
// Error from DBus
|
||||
VIR_FROM_DBUS = C.VIR_FROM_DBUS
|
||||
|
||||
// Error from Parallels
|
||||
VIR_FROM_PARALLELS = C.VIR_FROM_PARALLELS
|
||||
|
||||
// Error from Device
|
||||
VIR_FROM_DEVICE = C.VIR_FROM_DEVICE
|
||||
|
||||
// Error from libssh2 connection transport
|
||||
VIR_FROM_SSH = C.VIR_FROM_SSH
|
||||
|
||||
// Error from lockspace
|
||||
VIR_FROM_LOCKSPACE = C.VIR_FROM_LOCKSPACE
|
||||
|
||||
// Error from initctl device communication
|
||||
VIR_FROM_INITCTL = C.VIR_FROM_INITCTL
|
||||
|
||||
// Error from identity code
|
||||
VIR_FROM_IDENTITY = C.VIR_FROM_IDENTITY
|
||||
|
||||
// Error from cgroups
|
||||
VIR_FROM_CGROUP = C.VIR_FROM_CGROUP
|
||||
|
||||
// Error from access control manager
|
||||
VIR_FROM_ACCESS = C.VIR_FROM_ACCESS
|
||||
|
||||
// Error from systemd code
|
||||
VIR_FROM_SYSTEMD = C.VIR_FROM_SYSTEMD
|
||||
|
||||
// Error from bhyve driver
|
||||
VIR_FROM_BHYVE = C.VIR_FROM_BHYVE
|
||||
|
||||
// Error from crypto code
|
||||
VIR_FROM_CRYPTO = C.VIR_FROM_CRYPTO
|
||||
|
||||
// Error from firewall
|
||||
VIR_FROM_FIREWALL = C.VIR_FROM_FIREWALL
|
||||
)
|
||||
|
||||
type VirError struct {
|
||||
Code int
|
||||
Domain int
|
||||
Message string
|
||||
Level int
|
||||
}
|
||||
|
||||
func (err VirError) Error() string {
|
||||
return fmt.Sprintf("[Code-%d] [Domain-%d] %s",
|
||||
err.Code, err.Domain, err.Message)
|
||||
}
|
||||
|
||||
var ErrNoError = VirError{
|
||||
Code: VIR_ERR_OK,
|
||||
Domain: VIR_FROM_NONE,
|
||||
Message: "",
|
||||
Level: VIR_ERR_NONE,
|
||||
}
|
||||
|
||||
func GetLastError() VirError {
|
||||
err := C.virGetLastError()
|
||||
if err == nil {
|
||||
return ErrNoError
|
||||
}
|
||||
virErr := newError(err)
|
||||
C.virResetError(err)
|
||||
return virErr
|
||||
}
|
||||
|
||||
// Callback handling for errors
|
||||
type ErrorCallback func(error VirError, opaque func())
|
||||
type errorContext struct {
|
||||
cb ErrorCallback
|
||||
f func()
|
||||
}
|
||||
|
||||
func newError(err C.virErrorPtr) VirError {
|
||||
return VirError{
|
||||
Code: int(err.code),
|
||||
Domain: int(err.domain),
|
||||
Message: C.GoString(err.message),
|
||||
Level: int(err.level),
|
||||
}
|
||||
}
|
||||
|
||||
var globalErrorContext errorContext
|
||||
var globalErrorMutex sync.RWMutex
|
||||
|
||||
func SetErrorFunc(cb ErrorCallback, opaque func()) {
|
||||
globalErrorMutex.Lock()
|
||||
defer globalErrorMutex.Unlock()
|
||||
globalErrorContext = errorContext{
|
||||
cb: cb,
|
||||
f: opaque,
|
||||
}
|
||||
}
|
||||
|
||||
//export globalErrorCallback
|
||||
func globalErrorCallback(err C.virErrorPtr) {
|
||||
globalErrorMutex.RLock()
|
||||
defer globalErrorMutex.RUnlock()
|
||||
if globalErrorContext.cb != nil {
|
||||
globalErrorContext.cb(newError(err), globalErrorContext.f)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *VirConnection) SetErrorFunc(cb ErrorCallback, opaque func()) {
|
||||
c.UnsetErrorFunc()
|
||||
context := &errorContext{
|
||||
cb: cb,
|
||||
f: opaque,
|
||||
}
|
||||
goCallbackId := registerCallbackId(context)
|
||||
callbackPtr := unsafe.Pointer(C.errorConnCallback_cgo)
|
||||
C.virConnSetErrorFunc_cgo(c.ptr, C.long(goCallbackId), C.virErrorFunc(callbackPtr))
|
||||
connData := getConnectionData(c)
|
||||
connData.errCallbackId = &goCallbackId
|
||||
}
|
||||
|
||||
func (c *VirConnection) UnsetErrorFunc() {
|
||||
C.virConnSetErrorFunc(c.ptr, nil, nil)
|
||||
connData := getConnectionData(c)
|
||||
if connData.errCallbackId != nil {
|
||||
freeCallbackId(*connData.errCallbackId)
|
||||
connData.errCallbackId = nil
|
||||
}
|
||||
}
|
||||
|
||||
//export connErrorCallback
|
||||
func connErrorCallback(goCallbackId int, err C.virErrorPtr) {
|
||||
ctx := getCallbackId(goCallbackId)
|
||||
switch cctx := ctx.(type) {
|
||||
case *errorContext:
|
||||
cctx.cb(newError(err), cctx.f)
|
||||
default:
|
||||
panic("Inappropriate callback type called")
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
C.virSetErrorFunc(nil, C.virErrorFunc(unsafe.Pointer(C.errorGlobalCallback_cgo)))
|
||||
}
|
|
@ -0,0 +1,623 @@
|
|||
package libvirt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
|
||||
void domainEventLifecycleCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int event, int detail, void* data);
|
||||
|
||||
void domainEventGenericCallback_cgo(virConnectPtr c, virDomainPtr d, void* data);
|
||||
|
||||
void domainEventRTCChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
long long utcoffset, void* data);
|
||||
|
||||
void domainEventWatchdogCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int action, void* data);
|
||||
|
||||
void domainEventIOErrorCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *srcPath, const char *devAlias,
|
||||
int action, void* data);
|
||||
|
||||
void domainEventGraphicsCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int phase, const virDomainEventGraphicsAddress *local,
|
||||
const virDomainEventGraphicsAddress *remote,
|
||||
const char *authScheme,
|
||||
const virDomainEventGraphicsSubject *subject, void* data);
|
||||
|
||||
void domainEventIOErrorReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *srcPath, const char *devAlias,
|
||||
int action, const char *reason, void* data);
|
||||
|
||||
void domainEventBlockJobCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *disk, int type, int status, void* data);
|
||||
|
||||
void domainEventDiskChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *oldSrcPath, const char *newSrcPath,
|
||||
const char *devAlias, int reason, void* data);
|
||||
|
||||
void domainEventTrayChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *devAlias, int reason, void* data);
|
||||
|
||||
void domainEventReasonCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int reason, void* data);
|
||||
|
||||
void domainEventBalloonChangeCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
unsigned long long actual, void* data);
|
||||
|
||||
void domainEventDeviceRemovedCallback_cgo(virConnectPtr c, virDomainPtr d,
|
||||
const char *devAlias, void* data);
|
||||
|
||||
int virConnectDomainEventRegisterAny_cgo(virConnectPtr c, virDomainPtr d,
|
||||
int eventID, virConnectDomainEventGenericCallback cb,
|
||||
long goCallbackId);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type DomainLifecycleEvent struct {
|
||||
Event int
|
||||
Detail int
|
||||
}
|
||||
|
||||
type DomainRTCChangeEvent struct {
|
||||
Utcoffset int64
|
||||
}
|
||||
|
||||
type DomainWatchdogEvent struct {
|
||||
Action int
|
||||
}
|
||||
|
||||
type DomainIOErrorEvent struct {
|
||||
SrcPath string
|
||||
DevAlias string
|
||||
Action int
|
||||
}
|
||||
|
||||
type DomainEventGraphicsAddress struct {
|
||||
Family int
|
||||
Node string
|
||||
Service string
|
||||
}
|
||||
|
||||
type DomainEventGraphicsSubjectIdentity struct {
|
||||
Type string
|
||||
Name string
|
||||
}
|
||||
|
||||
type DomainGraphicsEvent struct {
|
||||
Phase int
|
||||
Local DomainEventGraphicsAddress
|
||||
Remote DomainEventGraphicsAddress
|
||||
AuthScheme string
|
||||
Subject []DomainEventGraphicsSubjectIdentity
|
||||
}
|
||||
|
||||
type DomainIOErrorReasonEvent struct {
|
||||
DomainIOErrorEvent
|
||||
Reason string
|
||||
}
|
||||
|
||||
type DomainBlockJobEvent struct {
|
||||
Disk string
|
||||
Type int
|
||||
Status int
|
||||
}
|
||||
|
||||
type DomainDiskChangeEvent struct {
|
||||
OldSrcPath string
|
||||
NewSrcPath string
|
||||
DevAlias string
|
||||
Reason int
|
||||
}
|
||||
|
||||
type DomainTrayChangeEvent struct {
|
||||
DevAlias string
|
||||
Reason int
|
||||
}
|
||||
|
||||
type DomainReasonEvent struct {
|
||||
Reason int
|
||||
}
|
||||
|
||||
type DomainBalloonChangeEvent struct {
|
||||
Actual uint64
|
||||
}
|
||||
|
||||
type DomainDeviceRemovedEvent struct {
|
||||
DevAlias string
|
||||
}
|
||||
|
||||
//export domainEventLifecycleCallback
|
||||
func domainEventLifecycleCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
event int, detail int,
|
||||
opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainLifecycleEvent{
|
||||
Event: event,
|
||||
Detail: detail,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventGenericCallback
|
||||
func domainEventGenericCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, nil)
|
||||
}
|
||||
|
||||
//export domainEventRTCChangeCallback
|
||||
func domainEventRTCChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
utcoffset int64, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainRTCChangeEvent{
|
||||
Utcoffset: utcoffset,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventWatchdogCallback
|
||||
func domainEventWatchdogCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
action int, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainWatchdogEvent{
|
||||
Action: action,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventIOErrorCallback
|
||||
func domainEventIOErrorCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
srcPath *C.char, devAlias *C.char, action int, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainIOErrorEvent{
|
||||
SrcPath: C.GoString(srcPath),
|
||||
DevAlias: C.GoString(devAlias),
|
||||
Action: action,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventGraphicsCallback
|
||||
func domainEventGraphicsCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
phase int,
|
||||
local C.virDomainEventGraphicsAddressPtr,
|
||||
remote C.virDomainEventGraphicsAddressPtr,
|
||||
authScheme *C.char,
|
||||
subject C.virDomainEventGraphicsSubjectPtr,
|
||||
opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
subjectGo := make([]DomainEventGraphicsSubjectIdentity, subject.nidentity)
|
||||
nidentities := int(subject.nidentity)
|
||||
identities := (*[1 << 30]C.virDomainEventGraphicsSubjectIdentity)(unsafe.Pointer(&subject.identities))[:nidentities:nidentities]
|
||||
for _, identity := range identities {
|
||||
subjectGo = append(subjectGo,
|
||||
DomainEventGraphicsSubjectIdentity{
|
||||
Type: C.GoString(identity._type),
|
||||
Name: C.GoString(identity.name),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
eventDetails := DomainGraphicsEvent{
|
||||
Phase: phase,
|
||||
Local: DomainEventGraphicsAddress{
|
||||
Family: int(local.family),
|
||||
Node: C.GoString(local.node),
|
||||
Service: C.GoString(local.service),
|
||||
},
|
||||
Remote: DomainEventGraphicsAddress{
|
||||
Family: int(remote.family),
|
||||
Node: C.GoString(remote.node),
|
||||
Service: C.GoString(remote.service),
|
||||
},
|
||||
AuthScheme: C.GoString(authScheme),
|
||||
Subject: subjectGo,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventIOErrorReasonCallback
|
||||
func domainEventIOErrorReasonCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
srcPath *C.char, devAlias *C.char, action int, reason *C.char,
|
||||
opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainIOErrorReasonEvent{
|
||||
DomainIOErrorEvent: DomainIOErrorEvent{
|
||||
SrcPath: C.GoString(srcPath),
|
||||
DevAlias: C.GoString(devAlias),
|
||||
Action: action,
|
||||
},
|
||||
Reason: C.GoString(reason),
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventBlockJobCallback
|
||||
func domainEventBlockJobCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
disk *C.char, _type int, status int, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainBlockJobEvent{
|
||||
Disk: C.GoString(disk),
|
||||
Type: _type,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventDiskChangeCallback
|
||||
func domainEventDiskChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
oldSrcPath *C.char, newSrcPath *C.char, devAlias *C.char,
|
||||
reason int, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainDiskChangeEvent{
|
||||
OldSrcPath: C.GoString(oldSrcPath),
|
||||
NewSrcPath: C.GoString(newSrcPath),
|
||||
DevAlias: C.GoString(devAlias),
|
||||
Reason: reason,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventTrayChangeCallback
|
||||
func domainEventTrayChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
devAlias *C.char, reason int, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainTrayChangeEvent{
|
||||
DevAlias: C.GoString(devAlias),
|
||||
Reason: reason,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventReasonCallback
|
||||
func domainEventReasonCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
reason int, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainReasonEvent{
|
||||
Reason: reason,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventBalloonChangeCallback
|
||||
func domainEventBalloonChangeCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
actual uint64, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainBalloonChangeEvent{
|
||||
Actual: actual,
|
||||
}
|
||||
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
//export domainEventDeviceRemovedCallback
|
||||
func domainEventDeviceRemovedCallback(c C.virConnectPtr, d C.virDomainPtr,
|
||||
devAlias *C.char, opaque int) {
|
||||
|
||||
domain := VirDomain{ptr: d}
|
||||
connection := VirConnection{ptr: c}
|
||||
|
||||
eventDetails := DomainDeviceRemovedEvent{
|
||||
DevAlias: C.GoString(devAlias),
|
||||
}
|
||||
callDomainCallbackId(opaque, &connection, &domain, eventDetails)
|
||||
}
|
||||
|
||||
// BUG(vincentbernat): The returned value of DomainEventCallback is
|
||||
// ignored and should be removed from the signature.
|
||||
|
||||
// DomainEventCallback is the signature of functions that can be
|
||||
// registered as a domain event callback. The event parameter should
|
||||
// be casted to the more specific event structure
|
||||
// (eg. DomainLifecycleEvent). The return code is ignored.
|
||||
type DomainEventCallback func(c *VirConnection, d *VirDomain,
|
||||
event interface{}, f func()) int
|
||||
|
||||
type domainCallbackContext struct {
|
||||
cb *DomainEventCallback
|
||||
f func()
|
||||
}
|
||||
|
||||
func callDomainCallbackId(goCallbackId int, c *VirConnection, d *VirDomain,
|
||||
event interface{}) {
|
||||
ctx := getCallbackId(goCallbackId)
|
||||
switch cctx := ctx.(type) {
|
||||
case *domainCallbackContext:
|
||||
(*cctx.cb)(c, d, event, cctx.f)
|
||||
default:
|
||||
panic("Inappropriate callback type called")
|
||||
}
|
||||
}
|
||||
|
||||
// BUG(vincentbernat): The returned value of DomainEventRegister, should be an
|
||||
// error instead of an int, for uniformity with other functions.
|
||||
|
||||
func (c *VirConnection) DomainEventRegister(dom VirDomain,
|
||||
eventId int,
|
||||
callback *DomainEventCallback,
|
||||
opaque func()) int {
|
||||
var callbackPtr unsafe.Pointer
|
||||
context := &domainCallbackContext{
|
||||
cb: callback,
|
||||
f: opaque,
|
||||
}
|
||||
goCallBackId := registerCallbackId(context)
|
||||
|
||||
switch eventId {
|
||||
case VIR_DOMAIN_EVENT_ID_LIFECYCLE:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventLifecycleCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_REBOOT, VIR_DOMAIN_EVENT_ID_CONTROL_ERROR:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventGenericCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_RTC_CHANGE:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventRTCChangeCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_WATCHDOG:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventWatchdogCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_IO_ERROR:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventIOErrorCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_GRAPHICS:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventGraphicsCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventIOErrorReasonCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_BLOCK_JOB:
|
||||
// TODO Post 1.2.4, uncomment later
|
||||
// case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventBlockJobCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_DISK_CHANGE:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventDiskChangeCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventTrayChangeCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_PMWAKEUP, VIR_DOMAIN_EVENT_ID_PMSUSPEND, VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventReasonCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventBalloonChangeCallback_cgo)
|
||||
case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED:
|
||||
callbackPtr = unsafe.Pointer(C.domainEventDeviceRemovedCallback_cgo)
|
||||
default:
|
||||
}
|
||||
ret := C.virConnectDomainEventRegisterAny_cgo(c.ptr, dom.ptr, C.int(eventId),
|
||||
C.virConnectDomainEventGenericCallback(callbackPtr),
|
||||
C.long(goCallBackId))
|
||||
if ret == -1 {
|
||||
freeCallbackId(goCallBackId)
|
||||
return -1
|
||||
}
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func (c *VirConnection) DomainEventDeregister(callbackId int) error {
|
||||
// Deregister the callback
|
||||
if i := int(C.virConnectDomainEventDeregisterAny(c.ptr, C.int(callbackId))); i != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func EventRegisterDefaultImpl() error {
|
||||
if i := int(C.virEventRegisterDefaultImpl()); i != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func EventRunDefaultImpl() error {
|
||||
if i := int(C.virEventRunDefaultImpl()); i != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e DomainLifecycleEvent) String() string {
|
||||
var detail, event string
|
||||
switch e.Event {
|
||||
case VIR_DOMAIN_EVENT_DEFINED:
|
||||
event = "defined"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_DEFINED_ADDED:
|
||||
detail = "added"
|
||||
case VIR_DOMAIN_EVENT_DEFINED_UPDATED:
|
||||
detail = "updated"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_EVENT_UNDEFINED:
|
||||
event = "undefined"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_UNDEFINED_REMOVED:
|
||||
detail = "removed"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_EVENT_STARTED:
|
||||
event = "started"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_STARTED_BOOTED:
|
||||
detail = "booted"
|
||||
case VIR_DOMAIN_EVENT_STARTED_MIGRATED:
|
||||
detail = "migrated"
|
||||
case VIR_DOMAIN_EVENT_STARTED_RESTORED:
|
||||
detail = "restored"
|
||||
case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT:
|
||||
detail = "snapshot"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED:
|
||||
event = "suspended"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED:
|
||||
detail = "paused"
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
|
||||
detail = "migrated"
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR:
|
||||
detail = "I/O error"
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG:
|
||||
detail = "watchdog"
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED:
|
||||
detail = "restored"
|
||||
case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT:
|
||||
detail = "snapshot"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_EVENT_RESUMED:
|
||||
event = "resumed"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
|
||||
detail = "unpaused"
|
||||
case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
|
||||
detail = "migrated"
|
||||
case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
|
||||
detail = "snapshot"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_EVENT_STOPPED:
|
||||
event = "stopped"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN:
|
||||
detail = "shutdown"
|
||||
case VIR_DOMAIN_EVENT_STOPPED_DESTROYED:
|
||||
detail = "destroyed"
|
||||
case VIR_DOMAIN_EVENT_STOPPED_CRASHED:
|
||||
detail = "crashed"
|
||||
case VIR_DOMAIN_EVENT_STOPPED_MIGRATED:
|
||||
detail = "migrated"
|
||||
case VIR_DOMAIN_EVENT_STOPPED_SAVED:
|
||||
detail = "saved"
|
||||
case VIR_DOMAIN_EVENT_STOPPED_FAILED:
|
||||
detail = "failed"
|
||||
case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
|
||||
detail = "snapshot"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_EVENT_SHUTDOWN:
|
||||
event = "shutdown"
|
||||
switch e.Detail {
|
||||
case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
|
||||
detail = "finished"
|
||||
default:
|
||||
detail = "unknown"
|
||||
}
|
||||
|
||||
default:
|
||||
event = "unknown"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Domain event=%q detail=%q", event, detail)
|
||||
}
|
||||
|
||||
func (e DomainRTCChangeEvent) String() string {
|
||||
return fmt.Sprintf("RTC change offset=%d", e.Utcoffset)
|
||||
}
|
||||
|
||||
func (e DomainWatchdogEvent) String() string {
|
||||
return fmt.Sprintf("Watchdog action=%d", e.Action)
|
||||
}
|
||||
|
||||
func (e DomainIOErrorEvent) String() string {
|
||||
return fmt.Sprintf("I/O error path=%q alias=%q action=%d",
|
||||
e.SrcPath, e.DevAlias, e.Action)
|
||||
}
|
||||
|
||||
func (e DomainGraphicsEvent) String() string {
|
||||
var phase string
|
||||
switch e.Phase {
|
||||
case VIR_DOMAIN_EVENT_GRAPHICS_CONNECT:
|
||||
phase = "connected"
|
||||
case VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE:
|
||||
phase = "initialized"
|
||||
case VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT:
|
||||
phase = "disconnected"
|
||||
default:
|
||||
phase = "unknown"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Graphics phase=%q", phase)
|
||||
}
|
||||
|
||||
func (e DomainIOErrorReasonEvent) String() string {
|
||||
return fmt.Sprintf("IO error path=%q alias=%q action=%d reason=%q",
|
||||
e.SrcPath, e.DevAlias, e.Action, e.Reason)
|
||||
}
|
||||
|
||||
func (e DomainBlockJobEvent) String() string {
|
||||
return fmt.Sprintf("Block job disk=%q status=%d type=%d",
|
||||
e.Disk, e.Status, e.Type)
|
||||
}
|
||||
|
||||
func (e DomainDiskChangeEvent) String() string {
|
||||
return fmt.Sprintf("Disk change old=%q new=%q alias=%q reason=%d",
|
||||
e.OldSrcPath, e.NewSrcPath, e.DevAlias, e.Reason)
|
||||
}
|
||||
|
||||
func (e DomainTrayChangeEvent) String() string {
|
||||
return fmt.Sprintf("Tray change dev=%q reason=%d",
|
||||
e.DevAlias, e.Reason)
|
||||
}
|
||||
|
||||
func (e DomainBalloonChangeEvent) String() string {
|
||||
return fmt.Sprintf("Ballon change %d", e.Actual)
|
||||
}
|
||||
|
||||
func (e DomainDeviceRemovedEvent) String() string {
|
||||
return fmt.Sprintf("Device %q removed ", e.DevAlias)
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef GO_LIBVIRT_H
|
||||
#define GO_LIBVIRT_H
|
||||
void closeCallback_cgo(virConnectPtr conn, int reason, void *opaque);
|
||||
int virConnectRegisterCloseCallback_cgo(virConnectPtr c, virConnectCloseFunc cb, long goCallbackId);
|
||||
|
||||
typedef struct auth_cb_data {
|
||||
char* username;
|
||||
uint username_len;
|
||||
char* passphrase;
|
||||
uint passphrase_len;
|
||||
} auth_cb_data;
|
||||
|
||||
int* authMechs();
|
||||
int authCb(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata);
|
||||
auth_cb_data* authData(char* username, uint username_len, char* passphrase, uint passphrase_len);
|
||||
|
||||
#endif /* GO_LIBVIRT_H */
|
|
@ -0,0 +1,87 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirInterface struct {
|
||||
ptr C.virInterfacePtr
|
||||
}
|
||||
|
||||
func (n *VirInterface) Create(flags uint32) error {
|
||||
result := C.virInterfaceCreate(n.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) Destroy(flags uint32) error {
|
||||
result := C.virInterfaceDestroy(n.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) IsActive() (bool, error) {
|
||||
result := C.virInterfaceIsActive(n.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) GetMACString() (string, error) {
|
||||
result := C.virInterfaceGetMACString(n.ptr)
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
mac := C.GoString(result)
|
||||
return mac, nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) GetName() (string, error) {
|
||||
result := C.virInterfaceGetName(n.ptr)
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
name := C.GoString(result)
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virInterfaceGetXMLDesc(n.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) Undefine() error {
|
||||
result := C.virInterfaceUndefine(n.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirInterface) Free() error {
|
||||
if result := C.virInterfaceFree(n.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,935 @@
|
|||
package libvirt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
#include "go_libvirt.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type VirConnection struct {
|
||||
ptr C.virConnectPtr
|
||||
}
|
||||
|
||||
// Additional data associated to the connection.
|
||||
type virConnectionData struct {
|
||||
errCallbackId *int
|
||||
closeCallbackId *int
|
||||
}
|
||||
|
||||
var connections map[C.virConnectPtr]*virConnectionData
|
||||
var connectionsLock sync.RWMutex
|
||||
|
||||
func init() {
|
||||
connections = make(map[C.virConnectPtr]*virConnectionData)
|
||||
}
|
||||
|
||||
func saveConnectionData(c *VirConnection, d *virConnectionData) {
|
||||
if c.ptr == nil {
|
||||
return // Or panic?
|
||||
}
|
||||
connectionsLock.Lock()
|
||||
defer connectionsLock.Unlock()
|
||||
connections[c.ptr] = d
|
||||
}
|
||||
|
||||
func getConnectionData(c *VirConnection) *virConnectionData {
|
||||
connectionsLock.RLock()
|
||||
d := connections[c.ptr]
|
||||
connectionsLock.RUnlock()
|
||||
if d != nil {
|
||||
return d
|
||||
}
|
||||
d = &virConnectionData{}
|
||||
saveConnectionData(c, d)
|
||||
return d
|
||||
}
|
||||
|
||||
func releaseConnectionData(c *VirConnection) {
|
||||
if c.ptr == nil {
|
||||
return
|
||||
}
|
||||
connectionsLock.Lock()
|
||||
defer connectionsLock.Unlock()
|
||||
delete(connections, c.ptr)
|
||||
}
|
||||
|
||||
func GetVersion() (uint32, error) {
|
||||
var version C.ulong
|
||||
if err := C.virGetVersion(&version, nil, nil); err < 0 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return uint32(version), nil
|
||||
}
|
||||
|
||||
func NewVirConnection(uri string) (VirConnection, error) {
|
||||
var cUri *C.char
|
||||
if uri != "" {
|
||||
cUri = C.CString(uri)
|
||||
defer C.free(unsafe.Pointer(cUri))
|
||||
}
|
||||
ptr := C.virConnectOpen(cUri)
|
||||
if ptr == nil {
|
||||
return VirConnection{}, GetLastError()
|
||||
}
|
||||
obj := VirConnection{ptr: ptr}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func NewVirConnectionWithAuth(uri string, username string, password string) (VirConnection, error) {
|
||||
var cUri *C.char
|
||||
|
||||
authMechs := C.authMechs()
|
||||
defer C.free(unsafe.Pointer(authMechs))
|
||||
cUsername := C.CString(username)
|
||||
defer C.free(unsafe.Pointer(cUsername))
|
||||
cPassword := C.CString(password)
|
||||
defer C.free(unsafe.Pointer(cPassword))
|
||||
cbData := C.authData(cUsername, C.uint(len(username)), cPassword, C.uint(len(password)))
|
||||
defer C.free(unsafe.Pointer(cbData))
|
||||
|
||||
auth := C.virConnectAuth{
|
||||
credtype: authMechs,
|
||||
ncredtype: C.uint(2),
|
||||
cb: C.virConnectAuthCallbackPtr(unsafe.Pointer(C.authCb)),
|
||||
cbdata: unsafe.Pointer(cbData),
|
||||
}
|
||||
|
||||
if uri != "" {
|
||||
cUri = C.CString(uri)
|
||||
defer C.free(unsafe.Pointer(cUri))
|
||||
}
|
||||
ptr := C.virConnectOpenAuth(cUri, (*C.struct__virConnectAuth)(unsafe.Pointer(&auth)), C.uint(0))
|
||||
if ptr == nil {
|
||||
return VirConnection{}, GetLastError()
|
||||
}
|
||||
obj := VirConnection{ptr: ptr}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func NewVirConnectionReadOnly(uri string) (VirConnection, error) {
|
||||
var cUri *C.char
|
||||
if uri != "" {
|
||||
cUri = C.CString(uri)
|
||||
defer C.free(unsafe.Pointer(cUri))
|
||||
}
|
||||
ptr := C.virConnectOpenReadOnly(cUri)
|
||||
if ptr == nil {
|
||||
return VirConnection{}, GetLastError()
|
||||
}
|
||||
obj := VirConnection{ptr: ptr}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) CloseConnection() (int, error) {
|
||||
c.UnsetErrorFunc()
|
||||
result := int(C.virConnectClose(c.ptr))
|
||||
if result == -1 {
|
||||
return result, GetLastError()
|
||||
}
|
||||
if result == 0 {
|
||||
// No more reference to this connection, release data.
|
||||
releaseConnectionData(c)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type CloseCallback func(conn VirConnection, reason int, opaque func())
|
||||
type closeContext struct {
|
||||
cb CloseCallback
|
||||
f func()
|
||||
}
|
||||
|
||||
// Register a close callback for the given destination. Only one
|
||||
// callback per connection is allowed. Setting a callback will remove
|
||||
// the previous one.
|
||||
func (c *VirConnection) RegisterCloseCallback(cb CloseCallback, opaque func()) error {
|
||||
c.UnregisterCloseCallback()
|
||||
context := &closeContext{
|
||||
cb: cb,
|
||||
f: opaque,
|
||||
}
|
||||
goCallbackId := registerCallbackId(context)
|
||||
callbackPtr := unsafe.Pointer(C.closeCallback_cgo)
|
||||
res := C.virConnectRegisterCloseCallback_cgo(c.ptr, C.virConnectCloseFunc(callbackPtr), C.long(goCallbackId))
|
||||
if res != 0 {
|
||||
freeCallbackId(goCallbackId)
|
||||
return GetLastError()
|
||||
}
|
||||
connData := getConnectionData(c)
|
||||
connData.closeCallbackId = &goCallbackId
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) UnregisterCloseCallback() error {
|
||||
connData := getConnectionData(c)
|
||||
if connData.closeCallbackId == nil {
|
||||
return nil
|
||||
}
|
||||
callbackPtr := unsafe.Pointer(C.closeCallback_cgo)
|
||||
res := C.virConnectUnregisterCloseCallback(c.ptr, C.virConnectCloseFunc(callbackPtr))
|
||||
if res != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
connData.closeCallbackId = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
//export closeCallback
|
||||
func closeCallback(conn C.virConnectPtr, reason int, goCallbackId int) {
|
||||
ctx := getCallbackId(goCallbackId)
|
||||
switch cctx := ctx.(type) {
|
||||
case *closeContext:
|
||||
cctx.cb(VirConnection{ptr: conn}, reason, cctx.f)
|
||||
default:
|
||||
panic("Inappropriate callback type called")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetCapabilities() (string, error) {
|
||||
str := C.virConnectGetCapabilities(c.ptr)
|
||||
if str == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
capabilities := C.GoString(str)
|
||||
C.free(unsafe.Pointer(str))
|
||||
return capabilities, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetNodeInfo() (VirNodeInfo, error) {
|
||||
ni := VirNodeInfo{}
|
||||
var ptr C.virNodeInfo
|
||||
result := C.virNodeGetInfo(c.ptr, (*C.virNodeInfo)(unsafe.Pointer(&ptr)))
|
||||
if result == -1 {
|
||||
return ni, GetLastError()
|
||||
}
|
||||
ni.ptr = ptr
|
||||
return ni, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetHostname() (string, error) {
|
||||
str := C.virConnectGetHostname(c.ptr)
|
||||
if str == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
hostname := C.GoString(str)
|
||||
C.free(unsafe.Pointer(str))
|
||||
return hostname, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetLibVersion() (uint32, error) {
|
||||
var version C.ulong
|
||||
if err := C.virConnectGetLibVersion(c.ptr, &version); err < 0 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return uint32(version), nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetType() (string, error) {
|
||||
str := C.virConnectGetType(c.ptr)
|
||||
if str == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
hypDriver := C.GoString(str)
|
||||
return hypDriver, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) IsAlive() (bool, error) {
|
||||
result := C.virConnectIsAlive(c.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) IsEncrypted() (bool, error) {
|
||||
result := C.virConnectIsEncrypted(c.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) IsSecure() (bool, error) {
|
||||
result := C.virConnectIsSecure(c.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListDefinedDomains() ([]string, error) {
|
||||
var names [1024](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numDomains := C.virConnectListDefinedDomains(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
1024)
|
||||
if numDomains == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numDomains)
|
||||
for k := 0; k < int(numDomains); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListDomains() ([]uint32, error) {
|
||||
var cDomainsIds [512](uint32)
|
||||
cDomainsPointer := unsafe.Pointer(&cDomainsIds)
|
||||
numDomains := C.virConnectListDomains(c.ptr, (*C.int)(cDomainsPointer), 512)
|
||||
if numDomains == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
|
||||
return cDomainsIds[:numDomains], nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListInterfaces() ([]string, error) {
|
||||
const maxIfaces = 1024
|
||||
var names [maxIfaces](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numIfaces := C.virConnectListInterfaces(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
maxIfaces)
|
||||
if numIfaces == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numIfaces)
|
||||
for k := 0; k < int(numIfaces); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListNetworks() ([]string, error) {
|
||||
const maxNets = 1024
|
||||
var names [maxNets](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numNetworks := C.virConnectListNetworks(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
maxNets)
|
||||
if numNetworks == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numNetworks)
|
||||
for k := 0; k < int(numNetworks); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListStoragePools() ([]string, error) {
|
||||
const maxPools = 1024
|
||||
var names [maxPools](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numStoragePools := C.virConnectListStoragePools(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
maxPools)
|
||||
if numStoragePools == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numStoragePools)
|
||||
for k := 0; k < int(numStoragePools); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupDomainById(id uint32) (VirDomain, error) {
|
||||
ptr := C.virDomainLookupByID(c.ptr, C.int(id))
|
||||
if ptr == nil {
|
||||
return VirDomain{}, GetLastError()
|
||||
}
|
||||
return VirDomain{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupDomainByName(id string) (VirDomain, error) {
|
||||
cName := C.CString(id)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virDomainLookupByName(c.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirDomain{}, GetLastError()
|
||||
}
|
||||
return VirDomain{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupByUUIDString(uuid string) (VirDomain, error) {
|
||||
cUuid := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUuid))
|
||||
ptr := C.virDomainLookupByUUIDString(c.ptr, cUuid)
|
||||
if ptr == nil {
|
||||
return VirDomain{}, GetLastError()
|
||||
}
|
||||
return VirDomain{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) DomainCreateXMLFromFile(xmlFile string, flags uint32) (VirDomain, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirDomain{}, err
|
||||
}
|
||||
return c.DomainCreateXML(string(xmlConfig), flags)
|
||||
}
|
||||
|
||||
func (c *VirConnection) DomainCreateXML(xmlConfig string, flags uint32) (VirDomain, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virDomainCreateXML(c.ptr, cXml, C.uint(flags))
|
||||
if ptr == nil {
|
||||
return VirDomain{}, GetLastError()
|
||||
}
|
||||
return VirDomain{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) DomainDefineXMLFromFile(xmlFile string) (VirDomain, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirDomain{}, err
|
||||
}
|
||||
return c.DomainDefineXML(string(xmlConfig))
|
||||
}
|
||||
|
||||
func (c *VirConnection) DomainDefineXML(xmlConfig string) (VirDomain, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virDomainDefineXML(c.ptr, cXml)
|
||||
if ptr == nil {
|
||||
return VirDomain{}, GetLastError()
|
||||
}
|
||||
return VirDomain{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListDefinedInterfaces() ([]string, error) {
|
||||
const maxIfaces = 1024
|
||||
var names [maxIfaces](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numIfaces := C.virConnectListDefinedInterfaces(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
maxIfaces)
|
||||
if numIfaces == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numIfaces)
|
||||
for k := 0; k < int(numIfaces); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListDefinedNetworks() ([]string, error) {
|
||||
const maxNets = 1024
|
||||
var names [maxNets](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numNetworks := C.virConnectListDefinedNetworks(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
maxNets)
|
||||
if numNetworks == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numNetworks)
|
||||
for k := 0; k < int(numNetworks); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListDefinedStoragePools() ([]string, error) {
|
||||
const maxPools = 1024
|
||||
var names [maxPools](*C.char)
|
||||
namesPtr := unsafe.Pointer(&names)
|
||||
numStoragePools := C.virConnectListDefinedStoragePools(
|
||||
c.ptr,
|
||||
(**C.char)(namesPtr),
|
||||
maxPools)
|
||||
if numStoragePools == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
goNames := make([]string, numStoragePools)
|
||||
for k := 0; k < int(numStoragePools); k++ {
|
||||
goNames[k] = C.GoString(names[k])
|
||||
C.free(unsafe.Pointer(names[k]))
|
||||
}
|
||||
return goNames, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfDefinedInterfaces() (int, error) {
|
||||
result := int(C.virConnectNumOfDefinedInterfaces(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfDefinedNetworks() (int, error) {
|
||||
result := int(C.virConnectNumOfDefinedNetworks(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfDefinedStoragePools() (int, error) {
|
||||
result := int(C.virConnectNumOfDefinedStoragePools(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfDomains() (int, error) {
|
||||
result := int(C.virConnectNumOfDomains(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfInterfaces() (int, error) {
|
||||
result := int(C.virConnectNumOfInterfaces(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfNetworks() (int, error) {
|
||||
result := int(C.virConnectNumOfNetworks(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfNWFilters() (int, error) {
|
||||
result := int(C.virConnectNumOfNWFilters(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NumOfSecrets() (int, error) {
|
||||
result := int(C.virConnectNumOfSecrets(c.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NetworkDefineXMLFromFile(xmlFile string) (VirNetwork, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirNetwork{}, err
|
||||
}
|
||||
return c.NetworkDefineXML(string(xmlConfig))
|
||||
}
|
||||
|
||||
func (c *VirConnection) NetworkDefineXML(xmlConfig string) (VirNetwork, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virNetworkDefineXML(c.ptr, cXml)
|
||||
if ptr == nil {
|
||||
return VirNetwork{}, GetLastError()
|
||||
}
|
||||
return VirNetwork{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NetworkCreateXML(xmlConfig string) (VirNetwork, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virNetworkCreateXML(c.ptr, cXml)
|
||||
if ptr == nil {
|
||||
return VirNetwork{}, GetLastError()
|
||||
}
|
||||
return VirNetwork{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupNetworkByName(name string) (VirNetwork, error) {
|
||||
cName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virNetworkLookupByName(c.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirNetwork{}, GetLastError()
|
||||
}
|
||||
return VirNetwork{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupNetworkByUUIDString(uuid string) (VirNetwork, error) {
|
||||
cUuid := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUuid))
|
||||
ptr := C.virNetworkLookupByUUIDString(c.ptr, cUuid)
|
||||
if ptr == nil {
|
||||
return VirNetwork{}, GetLastError()
|
||||
}
|
||||
return VirNetwork{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) SetKeepAlive(interval int, count uint) error {
|
||||
res := int(C.virConnectSetKeepAlive(c.ptr, C.int(interval), C.uint(count)))
|
||||
switch res {
|
||||
case 0:
|
||||
return nil
|
||||
default:
|
||||
return GetLastError()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetSysinfo(flags uint) (string, error) {
|
||||
cStr := C.virConnectGetSysinfo(c.ptr, C.uint(flags))
|
||||
if cStr == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
info := C.GoString(cStr)
|
||||
C.free(unsafe.Pointer(cStr))
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetURI() (string, error) {
|
||||
cStr := C.virConnectGetURI(c.ptr)
|
||||
if cStr == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
uri := C.GoString(cStr)
|
||||
C.free(unsafe.Pointer(cStr))
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) GetMaxVcpus(typeAttr string) (int, error) {
|
||||
var cTypeAttr *C.char
|
||||
if typeAttr != "" {
|
||||
cTypeAttr = C.CString(typeAttr)
|
||||
defer C.free(unsafe.Pointer(cTypeAttr))
|
||||
}
|
||||
result := int(C.virConnectGetMaxVcpus(c.ptr, cTypeAttr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) InterfaceDefineXMLFromFile(xmlFile string) (VirInterface, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirInterface{}, err
|
||||
}
|
||||
return c.InterfaceDefineXML(string(xmlConfig), 0)
|
||||
}
|
||||
|
||||
func (c *VirConnection) InterfaceDefineXML(xmlConfig string, flags uint32) (VirInterface, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virInterfaceDefineXML(c.ptr, cXml, C.uint(flags))
|
||||
if ptr == nil {
|
||||
return VirInterface{}, GetLastError()
|
||||
}
|
||||
return VirInterface{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupInterfaceByName(name string) (VirInterface, error) {
|
||||
cName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virInterfaceLookupByName(c.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirInterface{}, GetLastError()
|
||||
}
|
||||
return VirInterface{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupInterfaceByMACString(mac string) (VirInterface, error) {
|
||||
cName := C.CString(mac)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virInterfaceLookupByMACString(c.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirInterface{}, GetLastError()
|
||||
}
|
||||
return VirInterface{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) StoragePoolDefineXMLFromFile(xmlFile string) (VirStoragePool, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirStoragePool{}, err
|
||||
}
|
||||
return c.StoragePoolDefineXML(string(xmlConfig), 0)
|
||||
}
|
||||
|
||||
func (c *VirConnection) StoragePoolDefineXML(xmlConfig string, flags uint32) (VirStoragePool, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virStoragePoolDefineXML(c.ptr, cXml, C.uint(flags))
|
||||
if ptr == nil {
|
||||
return VirStoragePool{}, GetLastError()
|
||||
}
|
||||
return VirStoragePool{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupStoragePoolByName(name string) (VirStoragePool, error) {
|
||||
cName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virStoragePoolLookupByName(c.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirStoragePool{}, GetLastError()
|
||||
}
|
||||
return VirStoragePool{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupStoragePoolByUUIDString(uuid string) (VirStoragePool, error) {
|
||||
cUuid := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUuid))
|
||||
ptr := C.virStoragePoolLookupByUUIDString(c.ptr, cUuid)
|
||||
if ptr == nil {
|
||||
return VirStoragePool{}, GetLastError()
|
||||
}
|
||||
return VirStoragePool{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) NWFilterDefineXMLFromFile(xmlFile string) (VirNWFilter, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirNWFilter{}, err
|
||||
}
|
||||
return c.NWFilterDefineXML(string(xmlConfig))
|
||||
}
|
||||
|
||||
func (c *VirConnection) NWFilterDefineXML(xmlConfig string) (VirNWFilter, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virNWFilterDefineXML(c.ptr, cXml)
|
||||
if ptr == nil {
|
||||
return VirNWFilter{}, GetLastError()
|
||||
}
|
||||
return VirNWFilter{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupNWFilterByName(name string) (VirNWFilter, error) {
|
||||
cName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virNWFilterLookupByName(c.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirNWFilter{}, GetLastError()
|
||||
}
|
||||
return VirNWFilter{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupNWFilterByUUIDString(uuid string) (VirNWFilter, error) {
|
||||
cUuid := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUuid))
|
||||
ptr := C.virNWFilterLookupByUUIDString(c.ptr, cUuid)
|
||||
if ptr == nil {
|
||||
return VirNWFilter{}, GetLastError()
|
||||
}
|
||||
return VirNWFilter{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupStorageVolByKey(key string) (VirStorageVol, error) {
|
||||
cKey := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(cKey))
|
||||
ptr := C.virStorageVolLookupByKey(c.ptr, cKey)
|
||||
if ptr == nil {
|
||||
return VirStorageVol{}, GetLastError()
|
||||
}
|
||||
return VirStorageVol{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupStorageVolByPath(path string) (VirStorageVol, error) {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
ptr := C.virStorageVolLookupByPath(c.ptr, cPath)
|
||||
if ptr == nil {
|
||||
return VirStorageVol{}, GetLastError()
|
||||
}
|
||||
return VirStorageVol{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) SecretDefineXMLFromFile(xmlFile string) (VirSecret, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirSecret{}, err
|
||||
}
|
||||
return c.SecretDefineXML(string(xmlConfig), 0)
|
||||
}
|
||||
|
||||
func (c *VirConnection) SecretDefineXML(xmlConfig string, flags uint32) (VirSecret, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virSecretDefineXML(c.ptr, cXml, C.uint(flags))
|
||||
if ptr == nil {
|
||||
return VirSecret{}, GetLastError()
|
||||
}
|
||||
return VirSecret{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) SecretSetValue(uuid, value string) error {
|
||||
cUuid := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUuid))
|
||||
ptr := C.virSecretLookupByUUIDString(c.ptr, cUuid)
|
||||
if ptr == nil {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
secret, err := base64.StdEncoding.DecodeString(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cSecret := C.CString(string(secret))
|
||||
defer C.free(unsafe.Pointer(cSecret))
|
||||
|
||||
res := C.virSecretSetValue(ptr, (*C.uchar)(unsafe.Pointer(cSecret)), C.size_t(len(secret)), 0)
|
||||
if res != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupSecretByUUIDString(uuid string) (VirSecret, error) {
|
||||
cUuid := C.CString(uuid)
|
||||
defer C.free(unsafe.Pointer(cUuid))
|
||||
ptr := C.virSecretLookupByUUIDString(c.ptr, cUuid)
|
||||
if ptr == nil {
|
||||
return VirSecret{}, GetLastError()
|
||||
}
|
||||
return VirSecret{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) LookupSecretByUsage(usageType int, usageID string) (VirSecret, error) {
|
||||
cUsageID := C.CString(usageID)
|
||||
defer C.free(unsafe.Pointer(cUsageID))
|
||||
ptr := C.virSecretLookupByUsage(c.ptr, C.int(usageType), cUsageID)
|
||||
if ptr == nil {
|
||||
return VirSecret{}, GetLastError()
|
||||
}
|
||||
return VirSecret{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListAllInterfaces(flags uint32) ([]VirInterface, error) {
|
||||
var cList *C.virInterfacePtr
|
||||
numIfaces := C.virConnectListAllInterfaces(c.ptr, (**C.virInterfacePtr)(&cList), C.uint(flags))
|
||||
if numIfaces == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cList)),
|
||||
Len: int(numIfaces),
|
||||
Cap: int(numIfaces),
|
||||
}
|
||||
var ifaces []VirInterface
|
||||
slice := *(*[]C.virInterfacePtr)(unsafe.Pointer(&hdr))
|
||||
for _, ptr := range slice {
|
||||
ifaces = append(ifaces, VirInterface{ptr})
|
||||
}
|
||||
C.free(unsafe.Pointer(cList))
|
||||
return ifaces, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListAllNetworks(flags uint32) ([]VirNetwork, error) {
|
||||
var cList *C.virNetworkPtr
|
||||
numNets := C.virConnectListAllNetworks(c.ptr, (**C.virNetworkPtr)(&cList), C.uint(flags))
|
||||
if numNets == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cList)),
|
||||
Len: int(numNets),
|
||||
Cap: int(numNets),
|
||||
}
|
||||
var nets []VirNetwork
|
||||
slice := *(*[]C.virNetworkPtr)(unsafe.Pointer(&hdr))
|
||||
for _, ptr := range slice {
|
||||
nets = append(nets, VirNetwork{ptr})
|
||||
}
|
||||
C.free(unsafe.Pointer(cList))
|
||||
return nets, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListAllDomains(flags uint32) ([]VirDomain, error) {
|
||||
var cList *C.virDomainPtr
|
||||
numDomains := C.virConnectListAllDomains(c.ptr, (**C.virDomainPtr)(&cList), C.uint(flags))
|
||||
if numDomains == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cList)),
|
||||
Len: int(numDomains),
|
||||
Cap: int(numDomains),
|
||||
}
|
||||
var domains []VirDomain
|
||||
slice := *(*[]C.virDomainPtr)(unsafe.Pointer(&hdr))
|
||||
for _, ptr := range slice {
|
||||
domains = append(domains, VirDomain{ptr})
|
||||
}
|
||||
C.free(unsafe.Pointer(cList))
|
||||
return domains, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListAllNWFilters(flags uint32) ([]VirNWFilter, error) {
|
||||
var cList *C.virNWFilterPtr
|
||||
numNWFilters := C.virConnectListAllNWFilters(c.ptr, (**C.virNWFilterPtr)(&cList), C.uint(flags))
|
||||
if numNWFilters == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cList)),
|
||||
Len: int(numNWFilters),
|
||||
Cap: int(numNWFilters),
|
||||
}
|
||||
var filters []VirNWFilter
|
||||
slice := *(*[]C.virNWFilterPtr)(unsafe.Pointer(&hdr))
|
||||
for _, ptr := range slice {
|
||||
filters = append(filters, VirNWFilter{ptr})
|
||||
}
|
||||
C.free(unsafe.Pointer(cList))
|
||||
return filters, nil
|
||||
}
|
||||
|
||||
func (c *VirConnection) ListAllStoragePools(flags uint32) ([]VirStoragePool, error) {
|
||||
var cList *C.virStoragePoolPtr
|
||||
numPools := C.virConnectListAllStoragePools(c.ptr, (**C.virStoragePoolPtr)(&cList), C.uint(flags))
|
||||
if numPools == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cList)),
|
||||
Len: int(numPools),
|
||||
Cap: int(numPools),
|
||||
}
|
||||
var pools []VirStoragePool
|
||||
slice := *(*[]C.virStoragePoolPtr)(unsafe.Pointer(&hdr))
|
||||
for _, ptr := range slice {
|
||||
pools = append(pools, VirStoragePool{ptr})
|
||||
}
|
||||
C.free(unsafe.Pointer(cList))
|
||||
return pools, nil
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
listen_tls = 0
|
||||
listen_tcp = 1
|
||||
tcp_port = "16509"
|
||||
listen_addr = "127.0.0.1"
|
||||
auth_unix_rw = "none"
|
||||
auth_tcp = "sasl"
|
|
@ -0,0 +1,147 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirNetwork struct {
|
||||
ptr C.virNetworkPtr
|
||||
}
|
||||
|
||||
func (n *VirNetwork) Free() error {
|
||||
if result := C.virNetworkFree(n.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) Create() error {
|
||||
result := C.virNetworkCreate(n.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) Destroy() error {
|
||||
result := C.virNetworkDestroy(n.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) IsActive() (bool, error) {
|
||||
result := C.virNetworkIsActive(n.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) IsPersistent() (bool, error) {
|
||||
result := C.virNetworkIsPersistent(n.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) GetAutostart() (bool, error) {
|
||||
var out C.int
|
||||
result := C.virNetworkGetAutostart(n.ptr, (*C.int)(unsafe.Pointer(&out)))
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
switch out {
|
||||
case 1:
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (n *VirNetwork) SetAutostart(autostart bool) error {
|
||||
var cAutostart C.int
|
||||
switch autostart {
|
||||
case true:
|
||||
cAutostart = 1
|
||||
default:
|
||||
cAutostart = 0
|
||||
}
|
||||
result := C.virNetworkSetAutostart(n.ptr, cAutostart)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) GetName() (string, error) {
|
||||
name := C.virNetworkGetName(n.ptr)
|
||||
if name == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(name), nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) GetUUID() ([]byte, error) {
|
||||
var cUuid [C.VIR_UUID_BUFLEN](byte)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virNetworkGetUUID(n.ptr, (*C.uchar)(cuidPtr))
|
||||
if result != 0 {
|
||||
return []byte{}, GetLastError()
|
||||
}
|
||||
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) GetUUIDString() (string, error) {
|
||||
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virNetworkGetUUIDString(n.ptr, (*C.char)(cuidPtr))
|
||||
if result != 0 {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString((*C.char)(cuidPtr)), nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) GetBridgeName() (string, error) {
|
||||
result := C.virNetworkGetBridgeName(n.ptr)
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
bridge := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return bridge, nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virNetworkGetXMLDesc(n.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
||||
|
||||
func (n *VirNetwork) Undefine() error {
|
||||
result := C.virNetworkUndefine(n.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// +build libvirt.1.2.14
|
||||
|
||||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (n *VirNetwork) GetDHCPLeases() ([]VirNetworkDHCPLease, error) {
|
||||
var cLeases *C.virNetworkDHCPLeasePtr
|
||||
numLeases := C.virNetworkGetDHCPLeases(n.ptr, nil, (**C.virNetworkDHCPLeasePtr)(&cLeases), C.uint(0))
|
||||
if numLeases == -1 {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
hdr := reflect.SliceHeader{
|
||||
Data: uintptr(unsafe.Pointer(cLeases)),
|
||||
Len: int(numLeases),
|
||||
Cap: int(numLeases),
|
||||
}
|
||||
var leases []VirNetworkDHCPLease
|
||||
slice := *(*[]C.virNetworkDHCPLeasePtr)(unsafe.Pointer(&hdr))
|
||||
for _, ptr := range slice {
|
||||
leases = append(leases, VirNetworkDHCPLease{ptr})
|
||||
}
|
||||
C.free(unsafe.Pointer(cLeases))
|
||||
return leases, nil
|
||||
}
|
||||
|
||||
type VirNetworkDHCPLease struct {
|
||||
ptr C.virNetworkDHCPLeasePtr
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetIface() string {
|
||||
return C.GoString(l.ptr.iface)
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetExpiryTime() time.Time {
|
||||
return time.Unix(int64(l.ptr.expirytime), 0)
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetMACAddress() string {
|
||||
return C.GoString(l.ptr.mac)
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetIPAddress() string {
|
||||
return C.GoString(l.ptr.ipaddr)
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetIPPrefix() uint {
|
||||
return uint(l.ptr.prefix)
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetHostname() string {
|
||||
return C.GoString(l.ptr.hostname)
|
||||
}
|
||||
|
||||
func (l *VirNetworkDHCPLease) GetClientID() string {
|
||||
return C.GoString(l.ptr.clientid)
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirNodeInfo struct {
|
||||
ptr C.virNodeInfo
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetModel() string {
|
||||
model := C.GoString((*C.char)(unsafe.Pointer(&ni.ptr.model)))
|
||||
return model
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetMemoryKB() uint64 {
|
||||
return uint64(ni.ptr.memory)
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetCPUs() uint32 {
|
||||
return uint32(ni.ptr.cpus)
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetMhz() uint32 {
|
||||
return uint32(ni.ptr.mhz)
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetNodes() uint32 {
|
||||
return uint32(ni.ptr.nodes)
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetSockets() uint32 {
|
||||
return uint32(ni.ptr.sockets)
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetCores() uint32 {
|
||||
return uint32(ni.ptr.cores)
|
||||
}
|
||||
|
||||
func (ni *VirNodeInfo) GetThreads() uint32 {
|
||||
return uint32(ni.ptr.threads)
|
||||
}
|
||||
|
||||
// libvirt.h: VIR_NODEINFO_MAXCPUS
|
||||
func (ni *VirNodeInfo) GetMaxCPUs() uint32 {
|
||||
return ni.GetNodes() * ni.GetSockets() * ni.GetCores() * ni.GetThreads()
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirNWFilter struct {
|
||||
ptr C.virNWFilterPtr
|
||||
}
|
||||
|
||||
func (f *VirNWFilter) Free() error {
|
||||
if result := C.virNWFilterFree(f.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *VirNWFilter) GetName() (string, error) {
|
||||
name := C.virNWFilterGetName(f.ptr)
|
||||
if name == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(name), nil
|
||||
}
|
||||
|
||||
func (f *VirNWFilter) Undefine() error {
|
||||
result := C.virNWFilterUndefine(f.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *VirNWFilter) GetUUID() ([]byte, error) {
|
||||
var cUuid [C.VIR_UUID_BUFLEN](byte)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virNWFilterGetUUID(f.ptr, (*C.uchar)(cuidPtr))
|
||||
if result != 0 {
|
||||
return []byte{}, GetLastError()
|
||||
}
|
||||
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
|
||||
}
|
||||
|
||||
func (f *VirNWFilter) GetUUIDString() (string, error) {
|
||||
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virNWFilterGetUUIDString(f.ptr, (*C.char)(cuidPtr))
|
||||
if result != 0 {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString((*C.char)(cuidPtr)), nil
|
||||
}
|
||||
|
||||
func (f *VirNWFilter) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virNWFilterGetXMLDesc(f.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirSecret struct {
|
||||
ptr C.virSecretPtr
|
||||
}
|
||||
|
||||
func (s *VirSecret) Free() error {
|
||||
if result := C.virSecretFree(s.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *VirSecret) Undefine() error {
|
||||
result := C.virSecretUndefine(s.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *VirSecret) GetUUID() ([]byte, error) {
|
||||
var cUuid [C.VIR_UUID_BUFLEN](byte)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virSecretGetUUID(s.ptr, (*C.uchar)(cuidPtr))
|
||||
if result != 0 {
|
||||
return []byte{}, GetLastError()
|
||||
}
|
||||
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
|
||||
}
|
||||
|
||||
func (s *VirSecret) GetUUIDString() (string, error) {
|
||||
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virSecretGetUUIDString(s.ptr, (*C.char)(cuidPtr))
|
||||
if result != 0 {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString((*C.char)(cuidPtr)), nil
|
||||
}
|
||||
|
||||
func (s *VirSecret) GetUsageID() (string, error) {
|
||||
result := C.virSecretGetUsageID(s.ptr)
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(result), nil
|
||||
}
|
||||
|
||||
func (s *VirSecret) GetUsageType() (int, error) {
|
||||
result := int(C.virSecretGetUsageType(s.ptr))
|
||||
if result == -1 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *VirSecret) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virSecretGetXMLDesc(s.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirDomainSnapshot struct {
|
||||
ptr C.virDomainSnapshotPtr
|
||||
}
|
||||
|
||||
func (s *VirDomainSnapshot) Free() error {
|
||||
if result := C.virDomainSnapshotFree(s.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *VirDomainSnapshot) Delete(flags uint32) error {
|
||||
result := C.virDomainSnapshotDelete(s.ptr, C.uint(flags))
|
||||
if result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *VirDomainSnapshot) RevertToSnapshot(flags uint32) error {
|
||||
result := C.virDomainRevertToSnapshot(s.ptr, C.uint(flags))
|
||||
if result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) CreateSnapshotXML(xml string, flags uint32) (VirDomainSnapshot, error) {
|
||||
cXml := C.CString(xml)
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
result := C.virDomainSnapshotCreateXML(d.ptr, cXml, C.uint(flags))
|
||||
if result == nil {
|
||||
return VirDomainSnapshot{}, GetLastError()
|
||||
}
|
||||
return VirDomainSnapshot{ptr: result}, nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) Save(destFile string) error {
|
||||
cPath := C.CString(destFile)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
result := C.virDomainSave(d.ptr, cPath)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *VirDomain) SaveFlags(destFile string, destXml string, flags uint32) error {
|
||||
cDestFile := C.CString(destFile)
|
||||
cDestXml := C.CString(destXml)
|
||||
defer C.free(unsafe.Pointer(cDestXml))
|
||||
defer C.free(unsafe.Pointer(cDestFile))
|
||||
result := C.virDomainSaveFlags(d.ptr, cDestFile, cDestXml, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (conn VirConnection) Restore(srcFile string) error {
|
||||
cPath := C.CString(srcFile)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
if result := C.virDomainRestore(conn.ptr, cPath); result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (conn VirConnection) RestoreFlags(srcFile, xmlConf string, flags uint32) error {
|
||||
cPath := C.CString(srcFile)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
var cXmlConf *C.char
|
||||
if xmlConf != "" {
|
||||
cXmlConf = C.CString(xmlConf)
|
||||
defer C.free(unsafe.Pointer(cXmlConf))
|
||||
}
|
||||
if result := C.virDomainRestoreFlags(conn.ptr, cPath, cXmlConf, C.uint(flags)); result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirStoragePool struct {
|
||||
ptr C.virStoragePoolPtr
|
||||
}
|
||||
|
||||
type VirStoragePoolInfo struct {
|
||||
ptr C.virStoragePoolInfo
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Build(flags uint32) error {
|
||||
result := C.virStoragePoolBuild(p.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Create(flags uint32) error {
|
||||
result := C.virStoragePoolCreate(p.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Delete(flags uint32) error {
|
||||
result := C.virStoragePoolDelete(p.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Destroy() error {
|
||||
result := C.virStoragePoolDestroy(p.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Free() error {
|
||||
if result := C.virStoragePoolFree(p.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) GetAutostart() (bool, error) {
|
||||
var out C.int
|
||||
result := C.virStoragePoolGetAutostart(p.ptr, (*C.int)(unsafe.Pointer(&out)))
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
switch out {
|
||||
case 1:
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) GetInfo() (VirStoragePoolInfo, error) {
|
||||
pi := VirStoragePoolInfo{}
|
||||
var ptr C.virStoragePoolInfo
|
||||
result := C.virStoragePoolGetInfo(p.ptr, (*C.virStoragePoolInfo)(unsafe.Pointer(&ptr)))
|
||||
if result == -1 {
|
||||
return pi, GetLastError()
|
||||
}
|
||||
pi.ptr = ptr
|
||||
return pi, nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) GetName() (string, error) {
|
||||
name := C.virStoragePoolGetName(p.ptr)
|
||||
if name == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(name), nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) GetUUID() ([]byte, error) {
|
||||
var cUuid [C.VIR_UUID_BUFLEN](byte)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virStoragePoolGetUUID(p.ptr, (*C.uchar)(cuidPtr))
|
||||
if result != 0 {
|
||||
return []byte{}, GetLastError()
|
||||
}
|
||||
return C.GoBytes(cuidPtr, C.VIR_UUID_BUFLEN), nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) GetUUIDString() (string, error) {
|
||||
var cUuid [C.VIR_UUID_STRING_BUFLEN](C.char)
|
||||
cuidPtr := unsafe.Pointer(&cUuid)
|
||||
result := C.virStoragePoolGetUUIDString(p.ptr, (*C.char)(cuidPtr))
|
||||
if result != 0 {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString((*C.char)(cuidPtr)), nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virStoragePoolGetXMLDesc(p.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) IsActive() (bool, error) {
|
||||
result := C.virStoragePoolIsActive(p.ptr)
|
||||
if result == -1 {
|
||||
return false, GetLastError()
|
||||
}
|
||||
if result == 1 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) SetAutostart(autostart bool) error {
|
||||
var cAutostart C.int
|
||||
switch autostart {
|
||||
case true:
|
||||
cAutostart = 1
|
||||
default:
|
||||
cAutostart = 0
|
||||
}
|
||||
result := C.virStoragePoolSetAutostart(p.ptr, cAutostart)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Refresh(flags uint32) error {
|
||||
result := C.virStoragePoolRefresh(p.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) Undefine() error {
|
||||
result := C.virStoragePoolUndefine(p.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *VirStoragePoolInfo) GetState() uint8 {
|
||||
return uint8(i.ptr.state)
|
||||
}
|
||||
|
||||
func (i *VirStoragePoolInfo) GetCapacityInBytes() uint64 {
|
||||
return uint64(i.ptr.capacity)
|
||||
}
|
||||
|
||||
func (i *VirStoragePoolInfo) GetAllocationInBytes() uint64 {
|
||||
return uint64(i.ptr.allocation)
|
||||
}
|
||||
|
||||
func (i *VirStoragePoolInfo) GetAvailableInBytes() uint64 {
|
||||
return uint64(i.ptr.available)
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) StorageVolCreateXMLFromFile(xmlFile string, flags uint32) (VirStorageVol, error) {
|
||||
xmlConfig, err := ioutil.ReadFile(xmlFile)
|
||||
if err != nil {
|
||||
return VirStorageVol{}, err
|
||||
}
|
||||
return p.StorageVolCreateXML(string(xmlConfig), flags)
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) StorageVolCreateXML(xmlConfig string, flags uint32) (VirStorageVol, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virStorageVolCreateXML(p.ptr, cXml, C.uint(flags))
|
||||
if ptr == nil {
|
||||
return VirStorageVol{}, GetLastError()
|
||||
}
|
||||
return VirStorageVol{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) StorageVolCreateXMLFrom(xmlConfig string, clonevol VirStorageVol, flags uint32) (VirStorageVol, error) {
|
||||
cXml := C.CString(string(xmlConfig))
|
||||
defer C.free(unsafe.Pointer(cXml))
|
||||
ptr := C.virStorageVolCreateXMLFrom(p.ptr, cXml, clonevol.ptr, C.uint(flags))
|
||||
if ptr == nil {
|
||||
return VirStorageVol{}, GetLastError()
|
||||
}
|
||||
return VirStorageVol{ptr: ptr}, nil
|
||||
}
|
||||
|
||||
func (p *VirStoragePool) LookupStorageVolByName(name string) (VirStorageVol, error) {
|
||||
cName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
ptr := C.virStorageVolLookupByName(p.ptr, cName)
|
||||
if ptr == nil {
|
||||
return VirStorageVol{}, GetLastError()
|
||||
}
|
||||
return VirStorageVol{ptr: ptr}, nil
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirStorageVol struct {
|
||||
ptr C.virStorageVolPtr
|
||||
}
|
||||
|
||||
type VirStorageVolInfo struct {
|
||||
ptr C.virStorageVolInfo
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) Delete(flags uint32) error {
|
||||
result := C.virStorageVolDelete(v.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) Free() error {
|
||||
if result := C.virStorageVolFree(v.ptr); result != 0 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) GetInfo() (VirStorageVolInfo, error) {
|
||||
vi := VirStorageVolInfo{}
|
||||
var ptr C.virStorageVolInfo
|
||||
result := C.virStorageVolGetInfo(v.ptr, (*C.virStorageVolInfo)(unsafe.Pointer(&ptr)))
|
||||
if result == -1 {
|
||||
return vi, GetLastError()
|
||||
}
|
||||
vi.ptr = ptr
|
||||
return vi, nil
|
||||
}
|
||||
|
||||
func (i *VirStorageVolInfo) GetType() int {
|
||||
return int(i.ptr._type)
|
||||
}
|
||||
|
||||
func (i *VirStorageVolInfo) GetCapacityInBytes() uint64 {
|
||||
return uint64(i.ptr.capacity)
|
||||
}
|
||||
|
||||
func (i *VirStorageVolInfo) GetAllocationInBytes() uint64 {
|
||||
return uint64(i.ptr.allocation)
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) GetKey() (string, error) {
|
||||
key := C.virStorageVolGetKey(v.ptr)
|
||||
if key == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(key), nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) GetName() (string, error) {
|
||||
name := C.virStorageVolGetName(v.ptr)
|
||||
if name == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
return C.GoString(name), nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) GetPath() (string, error) {
|
||||
result := C.virStorageVolGetPath(v.ptr)
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
path := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) GetXMLDesc(flags uint32) (string, error) {
|
||||
result := C.virStorageVolGetXMLDesc(v.ptr, C.uint(flags))
|
||||
if result == nil {
|
||||
return "", GetLastError()
|
||||
}
|
||||
xml := C.GoString(result)
|
||||
C.free(unsafe.Pointer(result))
|
||||
return xml, nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) Resize(capacity uint64, flags uint32) error {
|
||||
result := C.virStorageVolResize(v.ptr, C.ulonglong(capacity), C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) Wipe(flags uint32) error {
|
||||
result := C.virStorageVolWipe(v.ptr, C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (v *VirStorageVol) WipePattern(algorithm uint32, flags uint32) error {
|
||||
result := C.virStorageVolWipePattern(v.ptr, C.uint(algorithm), C.uint(flags))
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) Upload(stream *VirStream, offset, length uint64, flags uint32) error {
|
||||
if C.virStorageVolUpload(v.ptr, stream.ptr, C.ulonglong(offset),
|
||||
C.ulonglong(length), C.uint(flags)) == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) Download(stream *VirStream, offset, length uint64, flags uint32) error {
|
||||
if C.virStorageVolDownload(v.ptr, stream.ptr, C.ulonglong(offset),
|
||||
C.ulonglong(length), C.uint(flags)) == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStorageVol) LookupPoolByVolume() (VirStoragePool, error) {
|
||||
poolPtr := C.virStoragePoolLookupByVolume(v.ptr)
|
||||
if poolPtr == nil {
|
||||
return VirStoragePool{}, GetLastError()
|
||||
}
|
||||
return VirStoragePool{ptr: poolPtr}, nil
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package libvirt
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lvirt
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"io"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type VirStream struct {
|
||||
ptr C.virStreamPtr
|
||||
}
|
||||
|
||||
func NewVirStream(c *VirConnection, flags uint) (*VirStream, error) {
|
||||
virStream := C.virStreamNew(c.ptr, C.uint(flags))
|
||||
if virStream == nil {
|
||||
return nil, GetLastError()
|
||||
}
|
||||
|
||||
return &VirStream{
|
||||
ptr: virStream,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *VirStream) Abort() error {
|
||||
result := C.virStreamAbort(v.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStream) Close() error {
|
||||
result := C.virStreamFinish(v.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStream) Free() error {
|
||||
result := C.virStreamFree(v.ptr)
|
||||
if result == -1 {
|
||||
return GetLastError()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VirStream) Read(p []byte) (int, error) {
|
||||
n := C.virStreamRecv(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
|
||||
if n < 0 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
if n == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
return int(n), nil
|
||||
}
|
||||
|
||||
func (v *VirStream) Write(p []byte) (int, error) {
|
||||
n := C.virStreamSend(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
|
||||
if n < 0 {
|
||||
return 0, GetLastError()
|
||||
}
|
||||
if n == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
return int(n), nil
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
cmd/docker-machine-driver-kvm/docker-machine-driver-kvm
|
||||
*.sw*
|
|
@ -0,0 +1,191 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2014 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,67 @@
|
|||
# docker-machine-kvm
|
||||
KVM driver for docker-machine
|
||||
|
||||
This driver leverages the new [plugin architecture](https://github.com/docker/machine/issues/1626) being
|
||||
developed for Docker Machine.
|
||||
|
||||
# Quick start instructions
|
||||
|
||||
* Install `libvirt` and `qemu-kvm` on your system (e.g., `sudo apt-get install libvirt-bin qemu-kvm`)
|
||||
* Add yourself to the `libvirtd` group (may vary by linux distro) so you don't need to sudo
|
||||
* Install [docker-machine](https://github.com/docker/machine/releases)
|
||||
* Go to the
|
||||
[releases](https://github.com/dhiltgen/docker-machine-kvm/releases)
|
||||
page and download the docker-machine-driver-kvm binary, putting it
|
||||
in your PATH.
|
||||
* You can now create virtual machines using this driver with
|
||||
`docker-machine create -d kvm myengine0`.
|
||||
|
||||
# Dependencies
|
||||
|
||||
This driver leverages [libvirt](http://libvirt.org/) and the [libvirt-go
|
||||
library](https://github.com/alexzorin/libvirt-go) to create and manage
|
||||
KVM based virtual machines. It has been tested with Ubuntu 12.04 through 15.04
|
||||
and should work on most platforms with KVM/libvirt support. If you run into
|
||||
compatibility problems, please file an [issue](https://github.com/dhiltgen/docker-machine-kvm/issues).
|
||||
|
||||
Typically you'll run `docker-machine` as yourself, so you'll want to
|
||||
follow your distro specific instructions on allowing libvirt access
|
||||
from your account. For most distro's, you accomplish this by adding
|
||||
your account to the `libvirtd` group.
|
||||
|
||||
|
||||
# Capabilities
|
||||
|
||||
## Images
|
||||
By default `docker-machine-kvm` uses a [boot2docker.iso](https://github.com/boot2docker/boot2docker) as guest os for the kvm hypervisior. It's also possible to use every guest os image that is derived from [boot2docker.iso](https://github.com/boot2docker/boot2docker) as well.
|
||||
For using another image use the `--kvm-boot2docker-url` parameter.
|
||||
|
||||
Community Members did some tests and it works with [rancher/os](https://github.com/rancher/os) as guest os too.
|
||||
|
||||
## Dual Network
|
||||
|
||||
* **eth1** - A host private network called **docker-machines** is automatically created to ensure we always have connectivity to the VMs. The `docker-machine ip` command will always return this IP address which is only accessible from your local system.
|
||||
* **eth0** - You can specify any libvirt named network. If you don't specify one, the "default" named network will be used.
|
||||
* If you have exotic networking topolgies (openvswitch, etc.), you can use `virsh edit mymachinename` after creation, modify the first network definition by hand, then reboot the VM for the changes to take effect.
|
||||
* Typically this would be your "public" network accessible from external systems
|
||||
* To retrieve the IP address of this network, you can run a command like the following:
|
||||
```bash
|
||||
docker-machine ssh mymachinename "ip -one -4 addr show dev eth0|cut -f7 -d' '"
|
||||
```
|
||||
|
||||
## Driver Parameters
|
||||
|
||||
Here are all currently driver parameters listed that you can use.
|
||||
|
||||
| Parameter | Description|
|
||||
| ------------- | ------------- |
|
||||
| **--kvm-cpu-count** | Sets the used CPU Cores for the KVM Machine. Defaults to `1` . |
|
||||
| **--kvm-disk-size** | Sets the kvm machine Disk size in MB. Defaults to `20000` . |
|
||||
| **--kvm-memory** | Sets the Memory of the kvm machine in MB. Defaults to `1024`. |
|
||||
| **--kvm-network** | Sets the Network of the kvm machinee which it should connect to. Defaults to `default`. |
|
||||
| **--kvm-boot2docker-url** | Sets the url from which host the image is loaded. By default it's not set. |
|
||||
| **--kvm-cache-mode** | Sets the caching mode of the kvm machine. Defaults to `default`. |
|
||||
| **--kvm-io-mode-url** | Sets the disk io mode of the kvm machine. Defaults to `threads`. |
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,750 @@
|
|||
package kvm
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/alexzorin/libvirt-go"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnflag"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
const (
|
||||
connectionString = "qemu:///system"
|
||||
privateNetworkName = "docker-machines"
|
||||
isoFilename = "boot2docker.iso"
|
||||
dnsmasqLeases = "/var/lib/libvirt/dnsmasq/%s.leases"
|
||||
dnsmasqStatus = "/var/lib/libvirt/dnsmasq/%s.status"
|
||||
|
||||
domainXMLTemplate = `<domain type='kvm'>
|
||||
<name>{{.MachineName}}</name> <memory unit='M'>{{.Memory}}</memory>
|
||||
<vcpu>{{.CPU}}</vcpu>
|
||||
<features><acpi/><apic/><pae/></features>
|
||||
<os>
|
||||
<type>hvm</type>
|
||||
<boot dev='cdrom'/>
|
||||
<boot dev='hd'/>
|
||||
<bootmenu enable='no'/>
|
||||
</os>
|
||||
<devices>
|
||||
<disk type='file' device='cdrom'>
|
||||
<source file='{{.ISO}}'/>
|
||||
<target dev='hdc' bus='ide'/>
|
||||
<readonly/>
|
||||
</disk>
|
||||
<disk type='file' device='disk'>
|
||||
<driver name='qemu' type='raw' cache='{{.CacheMode}}' io='{{.IOMode}}' />
|
||||
<source file='{{.DiskPath}}'/>
|
||||
<target dev='hda' bus='ide'/>
|
||||
</disk>
|
||||
<graphics type='vnc' autoport='yes' listen='127.0.0.1'>
|
||||
<listen type='address' address='127.0.0.1'/>
|
||||
</graphics>
|
||||
<interface type='network'>
|
||||
<source network='{{.Network}}'/>
|
||||
</interface>
|
||||
<interface type='network'>
|
||||
<source network='{{.PrivateNetwork}}'/>
|
||||
</interface>
|
||||
</devices>
|
||||
</domain>`
|
||||
networkXML = `<network>
|
||||
<name>%s</name>
|
||||
<ip address='%s' netmask='%s'>
|
||||
<dhcp>
|
||||
<range start='%s' end='%s'/>
|
||||
</dhcp>
|
||||
</ip>
|
||||
</network>`
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
*drivers.BaseDriver
|
||||
|
||||
Memory int
|
||||
DiskSize int
|
||||
CPU int
|
||||
Network string
|
||||
PrivateNetwork string
|
||||
ISO string
|
||||
Boot2DockerURL string
|
||||
CaCertPath string
|
||||
PrivateKeyPath string
|
||||
DiskPath string
|
||||
CacheMode string
|
||||
IOMode string
|
||||
connectionString string
|
||||
conn *libvirt.VirConnection
|
||||
VM *libvirt.VirDomain
|
||||
vmLoaded bool
|
||||
}
|
||||
|
||||
func (d *Driver) GetCreateFlags() []mcnflag.Flag {
|
||||
return []mcnflag.Flag{
|
||||
mcnflag.IntFlag{
|
||||
Name: "kvm-memory",
|
||||
Usage: "Size of memory for host in MB",
|
||||
Value: 1024,
|
||||
},
|
||||
mcnflag.IntFlag{
|
||||
Name: "kvm-disk-size",
|
||||
Usage: "Size of disk for host in MB",
|
||||
Value: 20000,
|
||||
},
|
||||
mcnflag.IntFlag{
|
||||
Name: "kvm-cpu-count",
|
||||
Usage: "Number of CPUs",
|
||||
Value: 1,
|
||||
},
|
||||
// TODO - support for multiple networks
|
||||
mcnflag.StringFlag{
|
||||
Name: "kvm-network",
|
||||
Usage: "Name of network to connect to",
|
||||
Value: "default",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
EnvVar: "KVM_BOOT2DOCKER_URL",
|
||||
Name: "kvm-boot2docker-url",
|
||||
Usage: "The URL of the boot2docker image. Defaults to the latest available version",
|
||||
Value: "",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
Name: "kvm-cache-mode",
|
||||
Usage: "Disk cache mode: default, none, writethrough, writeback, directsync, or unsafe",
|
||||
Value: "default",
|
||||
},
|
||||
mcnflag.StringFlag{
|
||||
Name: "kvm-io-mode",
|
||||
Usage: "Disk IO mode: threads, native",
|
||||
Value: "threads",
|
||||
},
|
||||
/* Not yet implemented
|
||||
mcnflag.Flag{
|
||||
Name: "kvm-no-share",
|
||||
Usage: "Disable the mount of your home directory",
|
||||
},
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetMachineName() string {
|
||||
return d.MachineName
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
return d.GetIP()
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHKeyPath() string {
|
||||
return d.ResolveStorePath("id_rsa")
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHPort() (int, error) {
|
||||
if d.SSHPort == 0 {
|
||||
d.SSHPort = 22
|
||||
}
|
||||
|
||||
return d.SSHPort, nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHUsername() string {
|
||||
if d.SSHUser == "" {
|
||||
d.SSHUser = "docker"
|
||||
}
|
||||
|
||||
return d.SSHUser
|
||||
}
|
||||
|
||||
func (d *Driver) DriverName() string {
|
||||
return "kvm"
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
||||
log.Debugf("SetConfigFromFlags called")
|
||||
d.Memory = flags.Int("kvm-memory")
|
||||
d.DiskSize = flags.Int("kvm-disk-size")
|
||||
d.CPU = flags.Int("kvm-cpu-count")
|
||||
d.Network = flags.String("kvm-network")
|
||||
d.Boot2DockerURL = flags.String("kvm-boot2docker-url")
|
||||
d.CacheMode = flags.String("kvm-cache-mode")
|
||||
d.IOMode = flags.String("kvm-io-mode")
|
||||
|
||||
d.SwarmMaster = flags.Bool("swarm-master")
|
||||
d.SwarmHost = flags.String("swarm-host")
|
||||
d.SwarmDiscovery = flags.String("swarm-discovery")
|
||||
d.ISO = d.ResolveStorePath(isoFilename)
|
||||
d.SSHUser = "docker"
|
||||
d.SSHPort = 22
|
||||
d.DiskPath = d.ResolveStorePath(fmt.Sprintf("%s.img", d.MachineName))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetURL() (string, error) {
|
||||
log.Debugf("GetURL called")
|
||||
ip, err := d.GetIP()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to get IP: %s", err)
|
||||
return "", err
|
||||
}
|
||||
if ip == "" {
|
||||
return "", nil
|
||||
}
|
||||
return fmt.Sprintf("tcp://%s:2376", ip), nil // TODO - don't hardcode the port!
|
||||
}
|
||||
|
||||
func (d *Driver) getConn() (*libvirt.VirConnection, error) {
|
||||
if d.conn == nil {
|
||||
conn, err := libvirt.NewVirConnection(connectionString)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to connect to libvirt: %s", err)
|
||||
return &libvirt.VirConnection{}, errors.New("Unable to connect to kvm driver, did you add yourself to the libvirtd group?")
|
||||
}
|
||||
d.conn = &conn
|
||||
}
|
||||
return d.conn, nil
|
||||
}
|
||||
|
||||
// Create, or verify the private network is properly configured
|
||||
func (d *Driver) validatePrivateNetwork() error {
|
||||
log.Debug("Validating private network")
|
||||
conn, err := d.getConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
network, err := conn.LookupNetworkByName(d.PrivateNetwork)
|
||||
if err == nil {
|
||||
xmldoc, err := network.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
/* XML structure:
|
||||
<network>
|
||||
...
|
||||
<ip address='a.b.c.d' netmask='255.255.255.0'>
|
||||
<dhcp>
|
||||
<range start='a.b.c.d' end='w.x.y.z'/>
|
||||
</dhcp>
|
||||
*/
|
||||
type Ip struct {
|
||||
Address string `xml:"address,attr"`
|
||||
Netmask string `xml:"netmask,attr"`
|
||||
}
|
||||
type Network struct {
|
||||
Ip Ip `xml:"ip"`
|
||||
}
|
||||
|
||||
var nw Network
|
||||
err = xml.Unmarshal([]byte(xmldoc), &nw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if nw.Ip.Address == "" {
|
||||
return fmt.Errorf("%s network doesn't have DHCP configured properly", d.PrivateNetwork)
|
||||
}
|
||||
// Corner case, but might happen...
|
||||
if active, err := network.IsActive(); !active {
|
||||
log.Debugf("Reactivating private network: %s", err)
|
||||
err = network.Create()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to Start network: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// TODO - try a couple pre-defined networks and look for conflicts before
|
||||
// settling on one
|
||||
xml := fmt.Sprintf(networkXML, d.PrivateNetwork,
|
||||
"192.168.42.1",
|
||||
"255.255.255.0",
|
||||
"192.168.42.2",
|
||||
"192.168.42.254")
|
||||
|
||||
network, err = conn.NetworkDefineXML(xml)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to create private network: %s", err)
|
||||
return nil
|
||||
}
|
||||
err = network.SetAutostart(true)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to set private network to autostart: %s", err)
|
||||
}
|
||||
err = network.Create()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to Start network: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) validateNetwork(name string) error {
|
||||
log.Debugf("Validating network %s", name)
|
||||
conn, err := d.getConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = conn.LookupNetworkByName(name)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to locate network %s", name)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) PreCreateCheck() error {
|
||||
conn, err := d.getConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO We could look at conn.GetCapabilities()
|
||||
// parse the XML, and look for kvm
|
||||
log.Debug("About to check libvirt version")
|
||||
|
||||
// TODO might want to check minimum version
|
||||
_, err = conn.GetLibVersion()
|
||||
if err != nil {
|
||||
log.Warnf("Unable to get libvirt version")
|
||||
return err
|
||||
}
|
||||
err = d.validatePrivateNetwork()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.validateNetwork(d.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Others...?
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
|
||||
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Creating SSH key...")
|
||||
if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(d.ResolveStorePath("."), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Libvirt typically runs as a deprivileged service account and
|
||||
// needs the execute bit set for directories that contain disks
|
||||
for dir := d.ResolveStorePath("."); dir != "/"; dir = filepath.Dir(dir) {
|
||||
log.Debugf("Verifying executable bit set on %s", dir)
|
||||
info, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mode := info.Mode()
|
||||
if mode&0001 != 1 {
|
||||
log.Debugf("Setting executable bit set on %s", dir)
|
||||
mode |= 0001
|
||||
os.Chmod(dir, mode)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Creating VM data disk...")
|
||||
if err := d.generateDiskImage(d.DiskSize); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Defining VM...")
|
||||
tmpl, err := template.New("domain").Parse(domainXMLTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var xml bytes.Buffer
|
||||
err = tmpl.Execute(&xml, d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, err := d.getConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vm, err := conn.DomainDefineXML(xml.String())
|
||||
if err != nil {
|
||||
log.Warnf("Failed to create the VM: %s", err)
|
||||
return err
|
||||
}
|
||||
d.VM = &vm
|
||||
d.vmLoaded = true
|
||||
|
||||
return d.Start()
|
||||
}
|
||||
|
||||
func (d *Driver) Start() error {
|
||||
log.Debugf("Starting VM %s", d.MachineName)
|
||||
if err := d.validateVMRef(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.VM.Create(); err != nil {
|
||||
log.Warnf("Failed to start: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// They wont start immediately
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
for i := 0; i < 90; i++ {
|
||||
time.Sleep(time.Second)
|
||||
ip, _ := d.GetIP()
|
||||
if ip != "" {
|
||||
// Add a second to let things settle
|
||||
time.Sleep(time.Second)
|
||||
return nil
|
||||
}
|
||||
log.Debugf("Waiting for the VM to come up... %d", i)
|
||||
}
|
||||
log.Warnf("Unable to determine VM's IP address, did it fail to boot?")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Stop() error {
|
||||
log.Debugf("Stopping VM %s", d.MachineName)
|
||||
if err := d.validateVMRef(); err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s != state.Stopped {
|
||||
err := d.VM.DestroyFlags(libvirt.VIR_DOMAIN_DESTROY_GRACEFUL)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to gracefully shutdown VM")
|
||||
return err
|
||||
}
|
||||
for i := 0; i < 90; i++ {
|
||||
time.Sleep(time.Second)
|
||||
s, _ := d.GetState()
|
||||
log.Debugf("VM state: %s", s)
|
||||
if s == state.Stopped {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("VM Failed to gracefully shutdown, try the kill command")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Remove() error {
|
||||
log.Debugf("Removing VM %s", d.MachineName)
|
||||
if err := d.validateVMRef(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Note: If we switch to qcow disks instead of raw the user
|
||||
// could take a snapshot. If you do, then Undefine
|
||||
// will fail unless we nuke the snapshots first
|
||||
d.VM.Destroy() // Ignore errors
|
||||
return d.VM.Undefine()
|
||||
}
|
||||
|
||||
func (d *Driver) Restart() error {
|
||||
log.Debugf("Restarting VM %s", d.MachineName)
|
||||
if err := d.Stop(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.Start()
|
||||
}
|
||||
|
||||
func (d *Driver) Kill() error {
|
||||
log.Debugf("Killing VM %s", d.MachineName)
|
||||
if err := d.validateVMRef(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.VM.Destroy()
|
||||
}
|
||||
|
||||
func (d *Driver) GetState() (state.State, error) {
|
||||
log.Debugf("Getting current state...")
|
||||
if err := d.validateVMRef(); err != nil {
|
||||
return state.None, err
|
||||
}
|
||||
states, err := d.VM.GetState()
|
||||
if err != nil {
|
||||
return state.None, err
|
||||
}
|
||||
switch states[0] {
|
||||
case libvirt.VIR_DOMAIN_NOSTATE:
|
||||
return state.None, nil
|
||||
case libvirt.VIR_DOMAIN_RUNNING:
|
||||
return state.Running, nil
|
||||
case libvirt.VIR_DOMAIN_BLOCKED:
|
||||
// TODO - Not really correct, but does it matter?
|
||||
return state.Error, nil
|
||||
case libvirt.VIR_DOMAIN_PAUSED:
|
||||
return state.Paused, nil
|
||||
case libvirt.VIR_DOMAIN_SHUTDOWN:
|
||||
return state.Stopped, nil
|
||||
case libvirt.VIR_DOMAIN_CRASHED:
|
||||
return state.Error, nil
|
||||
case libvirt.VIR_DOMAIN_PMSUSPENDED:
|
||||
return state.Saved, nil
|
||||
case libvirt.VIR_DOMAIN_SHUTOFF:
|
||||
return state.Stopped, nil
|
||||
}
|
||||
return state.None, nil
|
||||
}
|
||||
|
||||
func (d *Driver) validateVMRef() error {
|
||||
if !d.vmLoaded {
|
||||
log.Debugf("Fetching VM...")
|
||||
conn, err := d.getConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vm, err := conn.LookupDomainByName(d.MachineName)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to fetch machine")
|
||||
} else {
|
||||
d.VM = &vm
|
||||
d.vmLoaded = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This implementation is specific to default networking in libvirt
|
||||
// with dnsmasq
|
||||
func (d *Driver) getMAC() (string, error) {
|
||||
if err := d.validateVMRef(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
xmldoc, err := d.VM.GetXMLDesc(0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
/* XML structure:
|
||||
<domain>
|
||||
...
|
||||
<devices>
|
||||
...
|
||||
<interface type='network'>
|
||||
...
|
||||
<mac address='52:54:00:d2:3f:ba'/>
|
||||
...
|
||||
</interface>
|
||||
...
|
||||
*/
|
||||
type Mac struct {
|
||||
Address string `xml:"address,attr"`
|
||||
}
|
||||
type Source struct {
|
||||
Network string `xml:"network,attr"`
|
||||
}
|
||||
type Interface struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Mac Mac `xml:"mac"`
|
||||
Source Source `xml:"source"`
|
||||
}
|
||||
type Devices struct {
|
||||
Interfaces []Interface `xml:"interface"`
|
||||
}
|
||||
type Domain struct {
|
||||
Devices Devices `xml:"devices"`
|
||||
}
|
||||
|
||||
var dom Domain
|
||||
err = xml.Unmarshal([]byte(xmldoc), &dom)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Always assume the second interface is the one we want
|
||||
if len(dom.Devices.Interfaces) < 2 {
|
||||
return "", fmt.Errorf("VM doesn't have enough network interfaces. Expected at least 2, found %d",
|
||||
len(dom.Devices.Interfaces))
|
||||
}
|
||||
return dom.Devices.Interfaces[1].Mac.Address, nil
|
||||
}
|
||||
|
||||
func (d *Driver) getIPByMACFromLeaseFile(mac string) (string, error) {
|
||||
leaseFile := fmt.Sprintf(dnsmasqLeases, d.PrivateNetwork)
|
||||
data, err := ioutil.ReadFile(leaseFile)
|
||||
if err != nil {
|
||||
log.Debugf("Failed to retrieve dnsmasq leases from %s", leaseFile)
|
||||
return "", err
|
||||
}
|
||||
for lineNum, line := range strings.Split(string(data), "\n") {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
entries := strings.Split(line, " ")
|
||||
if len(entries) < 3 {
|
||||
log.Warnf("Malformed dnsmasq line %d", lineNum+1)
|
||||
return "", errors.New("Malformed dnsmasq file")
|
||||
}
|
||||
if strings.ToLower(entries[1]) == strings.ToLower(mac) {
|
||||
log.Debugf("IP address: %s", entries[2])
|
||||
return entries[2], nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *Driver) getIPByMacFromSettings(mac string) (string, error) {
|
||||
conn, err := d.getConn()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
network, err := conn.LookupNetworkByName(d.PrivateNetwork)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to find network: %s", err)
|
||||
return "", err
|
||||
}
|
||||
bridge_name, err := network.GetBridgeName()
|
||||
if err != nil {
|
||||
log.Warnf("Failed to get network bridge: %s", err)
|
||||
return "", err
|
||||
}
|
||||
statusFile := fmt.Sprintf(dnsmasqStatus, bridge_name)
|
||||
data, err := ioutil.ReadFile(statusFile)
|
||||
type Lease struct {
|
||||
Ip_address string `json:"ip-address"`
|
||||
Mac_address string `json:"mac-address"`
|
||||
// Other unused fields omitted
|
||||
}
|
||||
var s []Lease
|
||||
|
||||
err = json.Unmarshal(data, &s)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to decode dnsmasq lease status: %s", err)
|
||||
return "", err
|
||||
}
|
||||
ipAddr := ""
|
||||
for _, value := range s {
|
||||
if strings.ToLower(value.Mac_address) == strings.ToLower(mac) {
|
||||
// If there are multiple entries,
|
||||
// the last one is the most current
|
||||
ipAddr = value.Ip_address
|
||||
}
|
||||
}
|
||||
if ipAddr != "" {
|
||||
log.Debugf("IP Address: %s", ipAddr)
|
||||
}
|
||||
return ipAddr, nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetIP() (string, error) {
|
||||
log.Debugf("GetIP called for %s", d.MachineName)
|
||||
mac, err := d.getMAC()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
/*
|
||||
* TODO - Figure out what version of libvirt changed behavior and
|
||||
* be smarter about selecting which algorithm to use
|
||||
*/
|
||||
ip, err := d.getIPByMACFromLeaseFile(mac)
|
||||
if ip == "" {
|
||||
ip, err = d.getIPByMacFromSettings(mac)
|
||||
}
|
||||
log.Debugf("Unable to locate IP address for MAC %s", mac)
|
||||
return ip, err
|
||||
}
|
||||
|
||||
func (d *Driver) publicSSHKeyPath() string {
|
||||
return d.GetSSHKeyPath() + ".pub"
|
||||
}
|
||||
|
||||
// Make a boot2docker VM disk image.
|
||||
func (d *Driver) generateDiskImage(size int) error {
|
||||
log.Debugf("Creating %d MB hard disk image...", size)
|
||||
|
||||
magicString := "boot2docker, please format-me"
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
tw := tar.NewWriter(buf)
|
||||
|
||||
// magicString first so the automount script knows to format the disk
|
||||
file := &tar.Header{Name: magicString, Size: int64(len(magicString))}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(magicString)); err != nil {
|
||||
return err
|
||||
}
|
||||
// .ssh/key.pub => authorized_keys
|
||||
file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
raw := bytes.NewReader(buf.Bytes())
|
||||
return createDiskImage(d.DiskPath, size, raw)
|
||||
}
|
||||
|
||||
// createDiskImage makes a disk image at dest with the given size in MB. If r is
|
||||
// not nil, it will be read as a raw disk image to convert from.
|
||||
func createDiskImage(dest string, size int, r io.Reader) error {
|
||||
// Convert a raw image from stdin to the dest VMDK image.
|
||||
sizeBytes := int64(size) << 20 // usually won't fit in 32-bit int (max 2GB)
|
||||
f, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(f, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Rely on seeking to create a sparse raw file for qemu
|
||||
f.Seek(sizeBytes-1, 0)
|
||||
f.Write([]byte{0})
|
||||
return f.Close()
|
||||
}
|
||||
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
PrivateNetwork: privateNetworkName,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue