diff --git a/.gitignore b/.gitignore index 9b0bef8..fd77b2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ device-files/ -virsh-device-daemon -virsh-device-daemon-win64.exe -vendor/*/ +target/ diff --git a/Makefile b/Makefile index 5defabd..d60acf0 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,26 @@ -build: - GOOS=linux GOARCH=amd64 go build github.com/fapiko/virsh-device-daemon - GOOS=windows GOARCH=amd64 go build -o virsh-device-daemon-win64.exe github.com/fapiko/virsh-device-daemon +build-prep: + rm -rf target + mkdir target + +build-linux64: build-prep + GOOS=linux GOARCH=amd64 go build -o target/virsh-device-daemon github.com/fapiko/virsh-device-daemon + +build: build-linux64 + GOOS=windows GOARCH=amd64 go build -o target/virsh-device-daemon-win64.exe github.com/fapiko/virsh-device-daemon + +deb: build-linux64 + cp -r build/deb target/ + mkdir -p target/deb/usr/sbin + chmod 0755 target/virsh-device-daemon + mv target/virsh-device-daemon target/deb/usr/sbin + find ./target/deb -type d | xargs chmod 0755 + fakeroot dpkg-deb --build target/deb + mv target/deb.deb target/virsh-device-daemon_0.1.0_amd64.deb + +test-deb: deb + cp -r build/docker target/ + cp target/virsh-device-daemon_0.1.0_amd64.deb target/docker/ + docker build -t virsh-device-daemon target/docker + +shell-test-deb: + docker run -it virsh-device-daemon /bin/bash diff --git a/build/deb/DEBIAN/control b/build/deb/DEBIAN/control new file mode 100644 index 0000000..bf485a8 --- /dev/null +++ b/build/deb/DEBIAN/control @@ -0,0 +1,6 @@ +Package: virsh-device-daemon +Version: 0.1.0 +Maintainer: Lucas Jandrew +Architecture: amd64 +Depends: +Description: This is a service which manages attaching and detaching devices to virtual machines using VIRSH. diff --git a/build/deb/DEBIAN/postinst b/build/deb/DEBIAN/postinst new file mode 100755 index 0000000..4d31c91 --- /dev/null +++ b/build/deb/DEBIAN/postinst @@ -0,0 +1,79 @@ +#!/bin/sh +# postinst script for virsh-device-daemon +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + +service=virsh-device-daemon +user=vdd +group=vdd +userdesc="Virsh Device Daemon" + +# create group +if ! getent group ${group} >/dev/null; then + addgroup --system ${group} +fi + +# create user +if ! getent passwd ${user} >/dev/null; then + adduser --system --ingroup ${group} --home /var/lib/${user} \ + --no-create-home --gecos "${userdesc}" \ + --disabled-login ${user} +fi + +# attach to libvirtd group +if ! getent group libvirtd | grep ${user}; then + usermod -a -G libvirtd ${user} +fi + +mkdir -p /var/log/${service} +mkdir -p /etc/${service} +chmod 2750 /etc/${service} +chown -R ${user}:adm /var/log/${service} +chown -R ${user}:${group} /etc/${service} + +# Update profile to enable autocompletion +. /etc/profile + +case "$1" in + configure) + if test -z "$2"; then + # This is a fresh install of the package. + + # On a fresh install, we want to limit permissions on the + # log directory to the owner and the group. Others won't + # have any access to log files: this is in case sensitive + # data are accidentally logged (like process crash data). + chmod 2750 /var/log/${service} + else + # The package was already configured: it's an upgrade over + # a previously installed version, or it's an install over + # a non-purged version (i.e. deinstalled but configuration + # files and data are still there). + true + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile new file mode 100644 index 0000000..1f0aa4a --- /dev/null +++ b/build/docker/Dockerfile @@ -0,0 +1,5 @@ +FROM ubuntu:16.04 + +COPY virsh-device-daemon_0.1.0_amd64.deb virsh-device-daemon_0.1.0_amd64.deb +RUN dpkg -i virsh-device-daemon_0.1.0_amd64.deb && \ + rm virsh-device-daemon_0.1.0_amd64.deb diff --git a/config.go b/config.go new file mode 100644 index 0000000..4037e0f --- /dev/null +++ b/config.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + + "gopkg.in/yaml.v1" +) + +/* +Config holds the configuration data for running the app in daemon mode +*/ +type Config struct { + Name string `yaml:"name"` + Devices string `yaml:"devices"` + DeviceFiles []string `yaml:"-"` +} + +func parseConfig(path string) (*Config, error) { + configData, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + config := &Config{} + err = yaml.Unmarshal(configData, config) + if err != nil { + return nil, err + } + + if config.Devices != "" { + files, err := ioutil.ReadDir(config.Devices) + if err != nil { + return nil, err + } + + for _, f := range files { + if f.IsDir() == false { + config.DeviceFiles = append(config.DeviceFiles, fmt.Sprintf("%s%s%s", + config.Devices, string(os.PathSeparator), f.Name())) + } + } + } + + return config, err +} diff --git a/main.go b/main.go index 7ef19a8..46c6ca2 100644 --- a/main.go +++ b/main.go @@ -14,12 +14,18 @@ import ( type deviceFilesFlag []string var attachArg bool +var configFile string var detachArg bool var deviceFiles deviceFilesFlag var hostname string var serverMode bool var vmName string +const ( + configFileDescription = "Path to config file" + serverModeDescription = "Run as a server" +) + func (deviceFiles *deviceFilesFlag) String() string { return fmt.Sprint(*deviceFiles) } @@ -32,8 +38,10 @@ func (deviceFiles *deviceFilesFlag) Set(deviceFile string) error { func init() { log.SetLevel(log.DebugLevel) - flag.BoolVar(&serverMode, "s", false, "Run as a server") - flag.BoolVar(&serverMode, "server", false, "Run as a server") + flag.BoolVar(&serverMode, "s", false, serverModeDescription) + flag.BoolVar(&serverMode, "server", false, serverModeDescription) + flag.StringVar(&configFile, "c", "", configFileDescription) + flag.StringVar(&configFile, "config", "", configFileDescription) flag.Var(&deviceFiles, "f", "Path to device file") flag.Var(&deviceFiles, "device-file", "Path to device file") flag.StringVar(&vmName, "n", "", "Name of the VM to manage") @@ -54,6 +62,17 @@ func main() { // 2) As client that sends command based on CLI args if serverMode { + // If config file is not empty, use that instead of CLI arguments + if configFile != "" { + config, err := parseConfig(configFile) + if err != nil { + log.Panic(err) + } + + vmName = config.Name + deviceFiles = config.DeviceFiles + } + if vmName == "" { log.Error("VM name must be provided when starting in server mode") os.Exit(1) diff --git a/server.go b/server.go index b5998e1..45adbdc 100644 --- a/server.go +++ b/server.go @@ -32,6 +32,7 @@ func detach(request *restful.Request, response *restful.Response) { if err != nil { log.Error(err) response.WriteErrorString(500, err.Error()) + return } } } @@ -46,6 +47,7 @@ func attach(request *restful.Request, response *restful.Response) { if err != nil { log.Error(err) response.WriteErrorString(500, err.Error()) + return } } }