<commit_before>package ginpprof

import (
	"net/http/pprof"

	gin "gopkg.in/gin-gonic/gin.v1"
)

// Wrap adds several routes from package `net/http/pprof` to *gin.Engine object
func Wrap(router *gin.Engine) {
	router.GET("/debug/pprof/", IndexHandler())
	router.GET("/debug/pprof/heap", HeapHandler())
	router.GET("/debug/pprof/goroutine", GoroutineHandler())
	router.GET("/debug/pprof/block", BlockHandler())
	router.GET("/debug/pprof/threadcreate", ThreadCreateHandler())
	router.GET("/debug/pprof/cmdline", CmdlineHandler())
	router.GET("/debug/pprof/profile", ProfileHandler())
	router.GET("/debug/pprof/symbol", SymbolHandler())
	router.POST("/debug/pprof/symbol", SymbolHandler())
	router.GET("/debug/pprof/trace", TraceHandler())
}

// Wrappers make sure we are backward compatible
var Wrapper = Wrap

// IndexHandler will pass the call from /debug/pprof to pprof
func IndexHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Index(ctx.Writer, ctx.Request)
	}
}

// HeapHandler will pass the call from /debug/pprof/heap to pprof
func HeapHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("heap").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// GoroutineHandler will pass the call from /debug/pprof/goroutine to pprof
func GoroutineHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("goroutine").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// BlockHandler will pass the call from /debug/pprof/block to pprof
func BlockHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("block").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// ThreadCreateHandler will pass the call from /debug/pprof/threadcreate to pprof
func ThreadCreateHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("threadcreate").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// CmdlineHandler will pass the call from /debug/pprof/cmdline to pprof
func CmdlineHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Cmdline(ctx.Writer, ctx.Request)
	}
}

// ProfileHandler will pass the call from /debug/pprof/profile to pprof
func ProfileHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Profile(ctx.Writer, ctx.Request)
	}
}

// SymbolHandler will pass the call from /debug/pprof/symbol to pprof
func SymbolHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Symbol(ctx.Writer, ctx.Request)
	}
}

// TraceHandler will pass the call from /debug/pprof/trace to pprof
func TraceHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Trace(ctx.Writer, ctx.Request)
	}
}
<commit_msg>updated by original file<commit_after>package ginpprof

import (
	"net/http/pprof"
	"strings"

	gin "gopkg.in/gin-gonic/gin.v1"
)

// Note::This source code is from https://github.com/DeanThompson/ginpprof/blob/master/pprof.go

// Wrap adds several routes from package `net/http/pprof` to *gin.Engine object
func Wrap(router *gin.Engine) {
	WrapGroup(&router.RouterGroup)
}

// Wrapper make sure we are backward compatible
var Wrapper = Wrap

// WrapGroup adds several routes from package `net/http/pprof` to *gin.RouterGroup object
func WrapGroup(router *gin.RouterGroup) {
	routers := []struct {
		Method  string
		Path    string
		Handler gin.HandlerFunc
	}{
		{"GET", "/debug/pprof/", IndexHandler()},
		{"GET", "/debug/pprof/heap", HeapHandler()},
		{"GET", "/debug/pprof/goroutine", GoroutineHandler()},
		{"GET", "/debug/pprof/block", BlockHandler()},
		{"GET", "/debug/pprof/threadcreate", ThreadCreateHandler()},
		{"GET", "/debug/pprof/cmdline", CmdlineHandler()},
		{"GET", "/debug/pprof/profile", ProfileHandler()},
		{"GET", "/debug/pprof/symbol", SymbolHandler()},
		{"POST", "/debug/pprof/symbol", SymbolHandler()},
		{"GET", "/debug/pprof/trace", TraceHandler()},
		{"GET", "/debug/pprof/mutex", MutexHandler()},
	}

	basePath := strings.TrimSuffix(router.BasePath(), "/")
	var prefix string

	switch {
	case basePath == "":
		prefix = ""
	case strings.HasSuffix(basePath, "/debug"):
		prefix = "/debug"
	case strings.HasSuffix(basePath, "/debug/pprof"):
		prefix = "/debug/pprof"
	}

	for _, r := range routers {
		router.Handle(r.Method, strings.TrimPrefix(r.Path, prefix), r.Handler)
	}
}

// IndexHandler will pass the call from /debug/pprof to pprof
func IndexHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Index(ctx.Writer, ctx.Request)
	}
}

// HeapHandler will pass the call from /debug/pprof/heap to pprof
func HeapHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("heap").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// GoroutineHandler will pass the call from /debug/pprof/goroutine to pprof
func GoroutineHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("goroutine").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// BlockHandler will pass the call from /debug/pprof/block to pprof
func BlockHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("block").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// ThreadCreateHandler will pass the call from /debug/pprof/threadcreate to pprof
func ThreadCreateHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("threadcreate").ServeHTTP(ctx.Writer, ctx.Request)
	}
}

// CmdlineHandler will pass the call from /debug/pprof/cmdline to pprof
func CmdlineHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Cmdline(ctx.Writer, ctx.Request)
	}
}

// ProfileHandler will pass the call from /debug/pprof/profile to pprof
func ProfileHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Profile(ctx.Writer, ctx.Request)
	}
}

// SymbolHandler will pass the call from /debug/pprof/symbol to pprof
func SymbolHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Symbol(ctx.Writer, ctx.Request)
	}
}

// TraceHandler will pass the call from /debug/pprof/trace to pprof
func TraceHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Trace(ctx.Writer, ctx.Request)
	}
}

// MutexHandler will pass the call from /debug/pprof/mutex to pprof
func MutexHandler() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		pprof.Handler("mutex").ServeHTTP(ctx.Writer, ctx.Request)
	}
}
<|endoftext|>


<commit_before>// The manager of the lifecycle of some apps in a program.
package lifecycle

// LifeCycleManager manage the lifecycle of some apps in a program.
type LifeCycleManager struct {
	callbacks []func()
}

// NewLifeCycleManager returns a new LifeCycleManager.
func NewLifeCycleManager() *LifeCycleManager {
	return &LifeCycleManager{
		callbacks: make([]func(), 0, 8),
	}
}

// RegisterChannel is same as Register, but using the channel, not the callback.
//
// The parameter in is used to notice the app to end. And out is used to notice
// the manager that the app has cleaned and ended successfully.
func (self *LifeCycleManager) RegisterChannel(in chan<- interface{}, out <-chan interface{}) {
	self.Register(func() {
		in <- true
		<-out
	})
}

// Register registers a callback function for the app.
//
// When calling Stop(), the callback function will be called in turn
// by the order that they are registered.
func (self *LifeCycleManager) Register(f func()) *LifeCycleManager {
	self.callbacks = append(self.callbacks, f)
	return self
}

// Stop terminates all the apps.
func (self LifeCycleManager) Stop() {
	for _, f := range self.callbacks {
		f()
	}
}
<commit_msg>Ignore the panic<commit_after>// The manager of the lifecycle of some apps in a program.
package lifecycle

// LifeCycleManager manage the lifecycle of some apps in a program.
type LifeCycleManager struct {
	callbacks []func()
}

// NewLifeCycleManager returns a new LifeCycleManager.
func NewLifeCycleManager() *LifeCycleManager {
	return &LifeCycleManager{
		callbacks: make([]func(), 0, 8),
	}
}

// RegisterChannel is same as Register, but using the channel, not the callback.
//
// The parameter in is used to notice the app to end. And out is used to notice
// the manager that the app has cleaned and ended successfully.
func (self *LifeCycleManager) RegisterChannel(in chan<- interface{}, out <-chan interface{}) {
	self.Register(func() {
		in <- true
		<-out
	})
}

// Register registers a callback function for the app.
//
// When calling Stop(), the callback function will be called in turn
// by the order that they are registered.
func (self *LifeCycleManager) Register(f func()) *LifeCycleManager {
	self.callbacks = append(self.callbacks, f)
	return self
}

// Stop terminates and cleans all the apps.
//
// This method will be blocked until all the apps finish the clean.
// If the cleaning function of a certain app panics, ignore it and continue to
// call the cleaning function of the next app.
func (self LifeCycleManager) Stop() {
	for _, f := range self.callbacks {
		// f()
		callFuncAndIgnorePanic(f)
	}
}

func callFuncAndIgnorePanic(f func()) {
	defer func() {
		recover()
	}()
	f()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"os"
	"time"

	"github.com/coreos/go-systemd/dbus"
	"github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/updateengine"
)

var (
	cmdDaemon = &Command{
		Name:        "daemon",
		Summary:     "Daemon for reboot needed signal and if reboot able.",
		Description: `Daemon waits for the reboot needed signal coming out of update engine and attempts to acquire the reboot lock. If the reboot lock is acquired then the machine will reboot.`,
		Run:         runDaemon,
	}
)

const (
	initialTimeout = time.Second * 5
	maxTimeout     = time.Minute * 5
)

const (
	StrategyReboot     = "reboot"      // Reboot immediatly.
	StrategyEtcdLock   = "etcd-lock"   // Always take a lock from etcd.
	StrategyBestEffort = "best-effort" // If etcd is running then lock.
)

func expBackoff(try int) time.Duration {
	sleep := time.Duration(math.Pow(2, float64(try))) * initialTimeout
	if sleep > maxTimeout {
		sleep = maxTimeout
	}

	return sleep
}

func rebootAndSleep(lgn *login1.Conn) {
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the lock was acquired and the reboot worked.
func lockAndReboot(lck *lock.Lock, lgn *login1.Conn) {
	tries := 0
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			sleep := expBackoff(tries)
			fmt.Println("Retrying in %v. Error locking: %v", sleep, err)
			time.Sleep(sleep)
			tries = tries + 1

			continue
		}

		rebootAndSleep(lgn)

		return
	}
}

func unlockIfHeld(lck *lock.Lock) {
	tries := 0
	for {
		err := lck.Unlock()
		if err == nil {
			fmt.Println("Unlocked existing lock for this machine")
			return
		} else if err == lock.ErrNotExist {
			return
		}

		sleep := expBackoff(tries)
		fmt.Println("Retrying in %v. Error unlocking: %v", sleep, err)
		time.Sleep(sleep)
		tries = tries + 1
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := lock.NewEtcdLockClient(nil)
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	unlockIfHeld(lck)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (running bool, err error) {
	sys, err := dbus.New()
	if err != nil {
		return false, err
	}

	prop, err := sys.GetUnitProperty("etcd.service", "ActiveState")
	if err != nil {
		return false, fmt.Errorf("Error getting etcd.service ActiveState: %v", err)
	}

	if prop.Value.Value().(string) == "inactive" {
		return false, nil
	}

	return true, nil
}

func reboot(useLock bool, lck *lock.Lock, lgn *login1.Conn) {
	if useLock {
		lockAndReboot(lck, lgn)
	}

	rebootAndSleep(lgn)
	fmt.Println("Error: reboot attempt never finished")
}

func runDaemon(args []string) int {
	var lck *lock.Lock

	useLock := false
	switch s := os.ExpandEnv("${LOCKSMITH_STRATEGY}"); {
	case s == StrategyEtcdLock:
		useLock = true
	case s == StrategyBestEffort:
		running, err := etcdActive()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}
		if running {
			fmt.Println("etcd.service is active")
			useLock = true
		} else {
			fmt.Println("etcd.service is inactive")
			useLock = false
		}
	case s == StrategyReboot:
		useLock = false
	case s == "":
		useLock = false
	default:
		fmt.Fprintln(os.Stderr, "Unknown strategy:", s)
		return 1
	}

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	if useLock {
		lck, err = setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch)

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	if result.CurrentOperation == updateengine.UpdateStatusUpdatedNeedReboot {
		reboot(useLock, lck, lgn)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q useLock=%t\n",
		result.CurrentOperation,
		os.ExpandEnv("${LOCKSMITH_STRATEGY}"),
		useLock,
	)

	// Wait for a reboot needed signal
	<-ch
	reboot(useLock, lck, lgn)

	return 1
}
<commit_msg>fix(locksmithctl): remove and cleanup comments<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"time"

	"github.com/coreos/go-systemd/dbus"
	"github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/updateengine"
)

var (
	cmdDaemon = &Command{
		Name:        "daemon",
		Summary:     "Daemon for reboot needed signal and if reboot able.",
		Description: `Daemon waits for the reboot needed signal coming out of update engine and attempts to acquire the reboot lock. If the reboot lock is acquired then the machine will reboot.`,
		Run:         runDaemon,
	}
)

const (
	initialTimeout = time.Second * 5
	maxTimeout     = time.Minute * 5
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
)

func expBackoff(try int) time.Duration {
	sleep := time.Duration(math.Pow(2, float64(try))) * initialTimeout
	if sleep > maxTimeout {
		sleep = maxTimeout
	}

	return sleep
}

func rebootAndSleep(lgn *login1.Conn) {
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func lockAndReboot(lck *lock.Lock, lgn *login1.Conn) {
	tries := 0
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			sleep := expBackoff(tries)
			fmt.Println("Retrying in %v. Error locking: %v", sleep, err)
			time.Sleep(sleep)
			tries = tries + 1

			continue
		}

		rebootAndSleep(lgn)

		return
	}
}

func unlockIfHeld(lck *lock.Lock) {
	tries := 0
	for {
		err := lck.Unlock()
		if err == nil {
			fmt.Println("Unlocked existing lock for this machine")
			return
		} else if err == lock.ErrNotExist {
			return
		}

		sleep := expBackoff(tries)
		fmt.Println("Retrying in %v. Error unlocking: %v", sleep, err)
		time.Sleep(sleep)
		tries = tries + 1
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := lock.NewEtcdLockClient(nil)
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	unlockIfHeld(lck)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (running bool, err error) {
	sys, err := dbus.New()
	if err != nil {
		return false, err
	}

	prop, err := sys.GetUnitProperty("etcd.service", "ActiveState")
	if err != nil {
		return false, fmt.Errorf("Error getting etcd.service ActiveState: %v", err)
	}

	if prop.Value.Value().(string) == "inactive" {
		return false, nil
	}

	return true, nil
}

func reboot(useLock bool, lck *lock.Lock, lgn *login1.Conn) {
	if useLock {
		lockAndReboot(lck, lgn)
	}

	rebootAndSleep(lgn)
	fmt.Println("Error: reboot attempt never finished")
}

func runDaemon(args []string) int {
	var lck *lock.Lock

	useLock := false
	switch s := os.ExpandEnv("${LOCKSMITH_STRATEGY}"); {
	case s == StrategyEtcdLock:
		useLock = true
	case s == StrategyBestEffort:
		running, err := etcdActive()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}
		if running {
			fmt.Println("etcd.service is active")
			useLock = true
		} else {
			fmt.Println("etcd.service is inactive")
			useLock = false
		}
	case s == StrategyReboot:
		useLock = false
	case s == "":
		useLock = false
	default:
		fmt.Fprintln(os.Stderr, "Unknown strategy:", s)
		return 1
	}

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	if useLock {
		lck, err = setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch)

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	if result.CurrentOperation == updateengine.UpdateStatusUpdatedNeedReboot {
		reboot(useLock, lck, lgn)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q useLock=%t\n",
		result.CurrentOperation,
		os.ExpandEnv("${LOCKSMITH_STRATEGY}"),
		useLock,
	)

	// Wait for a reboot needed signal
	<-ch
	reboot(useLock, lck, lgn)

	return 1
}
<|endoftext|>


<commit_before>package cluster

import (
	"database/sql"
	"fmt"
	"path/filepath"
	"sync/atomic"

	driver "github.com/canonical/go-dqlite/driver"
	"github.com/lxc/lxd/lxd/db/query"
	"github.com/lxc/lxd/lxd/db/schema"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/osarch"
	"github.com/lxc/lxd/shared/version"
	"github.com/pkg/errors"
)

// Open the cluster database object.
//
// The name argument is the name of the cluster database. It defaults to
// 'db.bin', but can be overwritten for testing.
//
// The dialer argument is a function that returns a gRPC dialer that can be
// used to connect to a database node using the gRPC SQL package.
func Open(name string, store driver.NodeStore, options ...driver.Option) (*sql.DB, error) {
	driver, err := driver.New(store, options...)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to create dqlite driver")
	}

	driverName := dqliteDriverName()
	sql.Register(driverName, driver)

	// Create the cluster db. This won't immediately establish any network
	// connection, that will happen only when a db transaction is started
	// (see the database/sql connection pooling code for more details).
	if name == "" {
		name = "db.bin"
	}
	db, err := sql.Open(driverName, name)
	if err != nil {
		return nil, fmt.Errorf("cannot open cluster database: %v", err)
	}

	return db, nil
}

// EnsureSchema applies all relevant schema updates to the cluster database.
//
// Before actually doing anything, this function will make sure that all nodes
// in the cluster have a schema version and a number of API extensions that
// match our one. If it's not the case, we either return an error (if some
// nodes have version greater than us and we need to be upgraded), or return
// false and no error (if some nodes have a lower version, and we need to wait
// till they get upgraded and restarted).
func EnsureSchema(db *sql.DB, address string, dir string) (bool, error) {
	someNodesAreBehind := false
	apiExtensions := version.APIExtensionsCount()

	backupDone := false
	hook := (func(version int, tx *sql.Tx) error {
		// Check if this is a fresh instance.
		isUpdate, err := schema.DoesSchemaTableExist(tx)
		if err != nil {
			return errors.Wrap(err, "failed to check if schema table exists")
		}

		if !isUpdate {
			return nil
		}

		// Check if we're clustered
		clustered := true
		n, err := selectUnclusteredNodesCount(tx)
		if err != nil {
			return errors.Wrap(err, "failed to fetch unclustered nodes count")
		}
		if n > 1 {
			// This should never happen, since we only add nodes with valid addresses..
			return fmt.Errorf("found more than one unclustered nodes")
		} else if n == 1 {
			clustered = false
		}

		// If we're not clustered, backup the local cluster database directory
		// before performing any schema change. This makes sense only in the
		// non-clustered case, because otherwise the directory would be
		// re-populated by replication.
		if !clustered && !backupDone {
			logger.Infof("Updating the LXD global schema. Backup made as \"global.bak\"")
			err := shared.DirCopy(
				filepath.Join(dir, "global"),
				filepath.Join(dir, "global.bak"),
			)
			if err != nil {
				return errors.Wrap(err, "failed to backup global database")
			}
			backupDone = true
		}

		if version == -1 {
			logger.Debugf("Running pre-update queries from file for global DB schema")
		} else {
			logger.Debugf("Updating global DB schema from %d to %d", version, version+1)
		}

		return nil
	})

	check := func(current int, tx *sql.Tx) error {
		// If we're bootstrapping a fresh schema, skip any check, since
		// it's safe to assume we are the only node.
		if current == 0 {
			return nil
		}

		// Check if we're clustered
		n, err := selectUnclusteredNodesCount(tx)
		if err != nil {
			return errors.Wrap(err, "failed to fetch unclustered nodes count")
		}
		if n > 1 {
			// This should never happen, since we only add nodes with valid addresses.
			return fmt.Errorf("found more than one unclustered nodes")
		} else if n == 1 {
			address = "0.0.0.0" // We're not clustered
		}

		// Update the schema and api_extension columns of ourselves.
		err = updateNodeVersion(tx, address, apiExtensions)
		if err != nil {
			return errors.Wrap(err, "failed to update node version info")
		}

		err = checkClusterIsUpgradable(tx, [2]int{len(updates), apiExtensions})
		if err == errSomeNodesAreBehind {
			someNodesAreBehind = true
			return schema.ErrGracefulAbort
		}
		return err
	}

	schema := Schema()
	schema.File(filepath.Join(dir, "patch.global.sql")) // Optional custom queries
	schema.Check(check)
	schema.Hook(hook)

	var initial int
	err := query.Retry(func() error {
		var err error
		initial, err = schema.Ensure(db)
		return err
	})
	if someNodesAreBehind {
		return false, nil
	}
	if err != nil {
		return false, err
	}

	// When creating a database from scratch, insert an entry for node
	// 1. This is needed for referential integrity with other tables. Also,
	// create a default profile.
	if initial == 0 {
		arch, err := osarch.ArchitectureGetLocalID()
		if err != nil {
			return false, err
		}
		err = query.Transaction(db, func(tx *sql.Tx) error {
			stmt := `
INSERT INTO nodes(id, name, address, schema, api_extensions, arch) VALUES(1, 'none', '0.0.0.0', ?, ?, ?)
`
			_, err = tx.Exec(stmt, SchemaVersion, apiExtensions, arch)
			if err != nil {
				return err
			}

			// Default project
			stmt = `
INSERT INTO projects (name, description) VALUES ('default', 'Default LXD project');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.images', 'true');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.profiles', 'true');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.storage.volumes', 'true');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.networks', 'true');
`
			_, err = tx.Exec(stmt)
			if err != nil {
				return err
			}

			// Default profile
			stmt = `
INSERT INTO profiles (name, description, project_id) VALUES ('default', 'Default LXD profile', 1)
`
			_, err = tx.Exec(stmt)
			if err != nil {
				return err
			}

			return nil
		})
		if err != nil {
			return false, err
		}
	}

	return true, err
}

// Generate a new name for the dqlite driver registration. We need it to be
// unique for testing, see below.
func dqliteDriverName() string {
	defer atomic.AddUint64(&dqliteDriverSerial, 1)
	return fmt.Sprintf("dqlite-%d", dqliteDriverSerial)
}

// Monotonic serial number for registering new instances of dqlite.Driver
// using the database/sql stdlib package. This is needed since there's no way
// to unregister drivers, and in unit tests more than one driver gets
// registered.
var dqliteDriverSerial uint64

func checkClusterIsUpgradable(tx *sql.Tx, target [2]int) error {
	// Get the current versions in the nodes table.
	versions, err := selectNodesVersions(tx)
	if err != nil {
		return errors.Wrap(err, "failed to fetch current nodes versions")
	}

	for _, version := range versions {
		n, err := util.CompareVersions(target, version)
		if err != nil {
			return err
		}
		switch n {
		case 0:
			// Versions are equal, there's hope for the
			// update. Let's check the next node.
			continue
		case 1:
			// Our version is bigger, we should stop here
			// and wait for other nodes to be upgraded and
			// restarted.
			return errSomeNodesAreBehind
		case 2:
			// Another node has a version greater than ours
			// and presumeably is waiting for other nodes
			// to upgrade. Let's error out and shutdown
			// since we need a greater version.
			return fmt.Errorf("this node's version is behind, please upgrade")
		default:
			panic("unexpected return value from compareVersions")
		}
	}
	return nil
}

var errSomeNodesAreBehind = fmt.Errorf("some nodes are behind this node's version")
<commit_msg>lxd/db/cluster: Add default cluster group on start<commit_after>package cluster

import (
	"database/sql"
	"fmt"
	"path/filepath"
	"sync/atomic"

	driver "github.com/canonical/go-dqlite/driver"
	"github.com/lxc/lxd/lxd/db/query"
	"github.com/lxc/lxd/lxd/db/schema"
	"github.com/lxc/lxd/lxd/util"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/logger"
	"github.com/lxc/lxd/shared/osarch"
	"github.com/lxc/lxd/shared/version"
	"github.com/pkg/errors"
)

// Open the cluster database object.
//
// The name argument is the name of the cluster database. It defaults to
// 'db.bin', but can be overwritten for testing.
//
// The dialer argument is a function that returns a gRPC dialer that can be
// used to connect to a database node using the gRPC SQL package.
func Open(name string, store driver.NodeStore, options ...driver.Option) (*sql.DB, error) {
	driver, err := driver.New(store, options...)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to create dqlite driver")
	}

	driverName := dqliteDriverName()
	sql.Register(driverName, driver)

	// Create the cluster db. This won't immediately establish any network
	// connection, that will happen only when a db transaction is started
	// (see the database/sql connection pooling code for more details).
	if name == "" {
		name = "db.bin"
	}
	db, err := sql.Open(driverName, name)
	if err != nil {
		return nil, fmt.Errorf("cannot open cluster database: %v", err)
	}

	return db, nil
}

// EnsureSchema applies all relevant schema updates to the cluster database.
//
// Before actually doing anything, this function will make sure that all nodes
// in the cluster have a schema version and a number of API extensions that
// match our one. If it's not the case, we either return an error (if some
// nodes have version greater than us and we need to be upgraded), or return
// false and no error (if some nodes have a lower version, and we need to wait
// till they get upgraded and restarted).
func EnsureSchema(db *sql.DB, address string, dir string) (bool, error) {
	someNodesAreBehind := false
	apiExtensions := version.APIExtensionsCount()

	backupDone := false
	hook := (func(version int, tx *sql.Tx) error {
		// Check if this is a fresh instance.
		isUpdate, err := schema.DoesSchemaTableExist(tx)
		if err != nil {
			return errors.Wrap(err, "failed to check if schema table exists")
		}

		if !isUpdate {
			return nil
		}

		// Check if we're clustered
		clustered := true
		n, err := selectUnclusteredNodesCount(tx)
		if err != nil {
			return errors.Wrap(err, "failed to fetch unclustered nodes count")
		}
		if n > 1 {
			// This should never happen, since we only add nodes with valid addresses..
			return fmt.Errorf("found more than one unclustered nodes")
		} else if n == 1 {
			clustered = false
		}

		// If we're not clustered, backup the local cluster database directory
		// before performing any schema change. This makes sense only in the
		// non-clustered case, because otherwise the directory would be
		// re-populated by replication.
		if !clustered && !backupDone {
			logger.Infof("Updating the LXD global schema. Backup made as \"global.bak\"")
			err := shared.DirCopy(
				filepath.Join(dir, "global"),
				filepath.Join(dir, "global.bak"),
			)
			if err != nil {
				return errors.Wrap(err, "failed to backup global database")
			}
			backupDone = true
		}

		if version == -1 {
			logger.Debugf("Running pre-update queries from file for global DB schema")
		} else {
			logger.Debugf("Updating global DB schema from %d to %d", version, version+1)
		}

		return nil
	})

	check := func(current int, tx *sql.Tx) error {
		// If we're bootstrapping a fresh schema, skip any check, since
		// it's safe to assume we are the only node.
		if current == 0 {
			return nil
		}

		// Check if we're clustered
		n, err := selectUnclusteredNodesCount(tx)
		if err != nil {
			return errors.Wrap(err, "failed to fetch unclustered nodes count")
		}
		if n > 1 {
			// This should never happen, since we only add nodes with valid addresses.
			return fmt.Errorf("found more than one unclustered nodes")
		} else if n == 1 {
			address = "0.0.0.0" // We're not clustered
		}

		// Update the schema and api_extension columns of ourselves.
		err = updateNodeVersion(tx, address, apiExtensions)
		if err != nil {
			return errors.Wrap(err, "failed to update node version info")
		}

		err = checkClusterIsUpgradable(tx, [2]int{len(updates), apiExtensions})
		if err == errSomeNodesAreBehind {
			someNodesAreBehind = true
			return schema.ErrGracefulAbort
		}
		return err
	}

	schema := Schema()
	schema.File(filepath.Join(dir, "patch.global.sql")) // Optional custom queries
	schema.Check(check)
	schema.Hook(hook)

	var initial int
	err := query.Retry(func() error {
		var err error
		initial, err = schema.Ensure(db)
		return err
	})
	if someNodesAreBehind {
		return false, nil
	}
	if err != nil {
		return false, err
	}

	// When creating a database from scratch, insert an entry for node
	// 1. This is needed for referential integrity with other tables. Also,
	// create a default profile.
	if initial == 0 {
		arch, err := osarch.ArchitectureGetLocalID()
		if err != nil {
			return false, err
		}
		err = query.Transaction(db, func(tx *sql.Tx) error {
			stmt := `
INSERT INTO nodes(id, name, address, schema, api_extensions, arch) VALUES(1, 'none', '0.0.0.0', ?, ?, ?)
`
			_, err = tx.Exec(stmt, SchemaVersion, apiExtensions, arch)
			if err != nil {
				return err
			}

			// Default project
			stmt = `
INSERT INTO projects (name, description) VALUES ('default', 'Default LXD project');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.images', 'true');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.profiles', 'true');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.storage.volumes', 'true');
INSERT INTO projects_config (project_id, key, value) VALUES (1, 'features.networks', 'true');
`
			_, err = tx.Exec(stmt)
			if err != nil {
				return err
			}

			// Default profile
			stmt = `
INSERT INTO profiles (name, description, project_id) VALUES ('default', 'Default LXD profile', 1)
`
			_, err = tx.Exec(stmt)
			if err != nil {
				return err
			}

			// Default cluster group
			stmt = `
INSERT INTO cluster_groups (name, description) VALUES ('default', 'Default cluster group');
INSERT INTO nodes_cluster_groups (node_id, group_id) VALUES(1, 1);
`
			_, err = tx.Exec(stmt)
			if err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return false, err
		}
	}

	return true, err
}

// Generate a new name for the dqlite driver registration. We need it to be
// unique for testing, see below.
func dqliteDriverName() string {
	defer atomic.AddUint64(&dqliteDriverSerial, 1)
	return fmt.Sprintf("dqlite-%d", dqliteDriverSerial)
}

// Monotonic serial number for registering new instances of dqlite.Driver
// using the database/sql stdlib package. This is needed since there's no way
// to unregister drivers, and in unit tests more than one driver gets
// registered.
var dqliteDriverSerial uint64

func checkClusterIsUpgradable(tx *sql.Tx, target [2]int) error {
	// Get the current versions in the nodes table.
	versions, err := selectNodesVersions(tx)
	if err != nil {
		return errors.Wrap(err, "failed to fetch current nodes versions")
	}

	for _, version := range versions {
		n, err := util.CompareVersions(target, version)
		if err != nil {
			return err
		}
		switch n {
		case 0:
			// Versions are equal, there's hope for the
			// update. Let's check the next node.
			continue
		case 1:
			// Our version is bigger, we should stop here
			// and wait for other nodes to be upgraded and
			// restarted.
			return errSomeNodesAreBehind
		case 2:
			// Another node has a version greater than ours
			// and presumeably is waiting for other nodes
			// to upgrade. Let's error out and shutdown
			// since we need a greater version.
			return fmt.Errorf("this node's version is behind, please upgrade")
		default:
			panic("unexpected return value from compareVersions")
		}
	}
	return nil
}

var errSomeNodesAreBehind = fmt.Errorf("some nodes are behind this node's version")
<|endoftext|>


<commit_before>package dnsmasq

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/lxc/lxd/lxd/project"
	"github.com/lxc/lxd/lxd/storage/filesystem"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/subprocess"
	"github.com/lxc/lxd/shared/version"
)

const staticAllocationDeviceSeparator = "."

// DHCPAllocation represents an IP allocation from dnsmasq.
type DHCPAllocation struct {
	IP             net.IP
	StaticFileName string
	MAC            net.HardwareAddr
}

// ConfigMutex used to coordinate access to the dnsmasq config files.
var ConfigMutex sync.Mutex

// UpdateStaticEntry writes a single dhcp-host line for a network/instance combination.
func UpdateStaticEntry(network string, projectName string, instanceName string, deviceName string, netConfig map[string]string, hwaddr string, ipv4Address string, ipv6Address string) error {
	hwaddr = strings.ToLower(hwaddr)
	line := hwaddr

	// Generate the dhcp-host line
	if ipv4Address != "" {
		line += fmt.Sprintf(",%s", ipv4Address)
	}

	if ipv6Address != "" {
		line += fmt.Sprintf(",[%s]", ipv6Address)
	}

	if netConfig["dns.mode"] == "" || netConfig["dns.mode"] == "managed" {
		line += fmt.Sprintf(",%s", project.DNS(projectName, instanceName))
	}

	if line == hwaddr {
		return nil
	}

	deviceStaticFileName := StaticAllocationFileName(projectName, instanceName, deviceName)
	err := ioutil.WriteFile(shared.VarPath("networks", network, "dnsmasq.hosts", deviceStaticFileName), []byte(line+"\n"), 0644)
	if err != nil {
		return err
	}

	return nil
}

// RemoveStaticEntry removes a single dhcp-host line for a network/instance combination.
func RemoveStaticEntry(network string, projectName string, instanceName string, deviceName string) error {
	deviceStaticFileName := StaticAllocationFileName(projectName, instanceName, deviceName)
	err := os.Remove(shared.VarPath("networks", network, "dnsmasq.hosts", deviceStaticFileName))
	if err != nil && !os.IsNotExist(err) {
		return err
	}

	return nil
}

// Kill kills dnsmasq for a particular network (or optionally reloads it).
func Kill(name string, reload bool) error {
	pidPath := shared.VarPath("networks", name, "dnsmasq.pid")

	// If the pid file doesn't exist, there is no process to kill.
	if !shared.PathExists(pidPath) {
		return nil
	}

	// Import saved subprocess details
	p, err := subprocess.ImportProcess(pidPath)
	if err != nil {
		return fmt.Errorf("Could not read pid file: %s", err)
	}

	if reload {
		err = p.Reload()
		if err != nil && err != subprocess.ErrNotRunning {
			return fmt.Errorf("Could not reload dnsmasq: %s", err)
		}

		return nil
	}

	err = p.Stop()
	if err != nil && err != subprocess.ErrNotRunning {
		return fmt.Errorf("Unable to kill dnsmasq: %s", err)
	}

	time.Sleep(100 * time.Millisecond) // Give OS time to release sockets.

	return nil
}

// GetVersion returns the version of dnsmasq.
func GetVersion() (*version.DottedVersion, error) {
	output, err := shared.RunCommandCLocale("dnsmasq", "--version")
	if err != nil {
		return nil, fmt.Errorf("Failed to check dnsmasq version: %w", err)
	}

	lines := strings.Split(string(output), " ")
	return version.Parse(lines[2])
}

// DHCPStaticAllocationPath returns the path to the DHCP static allocation file.
func DHCPStaticAllocationPath(network string, deviceStaticFileName string) string {
	return shared.VarPath("networks", network, "dnsmasq.hosts", deviceStaticFileName)
}

// DHCPStaticAllocation retrieves the dnsmasq statically allocated MAC and IPs for an instance device static file.
// Returns MAC, IPv4 and IPv6 DHCPAllocation structs respectively.
func DHCPStaticAllocation(network string, deviceStaticFileName string) (net.HardwareAddr, DHCPAllocation, DHCPAllocation, error) {
	var IPv4, IPv6 DHCPAllocation
	var mac net.HardwareAddr

	file, err := os.Open(DHCPStaticAllocationPath(network, deviceStaticFileName))
	if err != nil {
		return nil, IPv4, IPv6, err
	}

	defer func() { _ = file.Close() }()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fields := strings.SplitN(scanner.Text(), ",", -1)
		for _, field := range fields {
			// Check if field is IPv4 or IPv6 address.
			if strings.Count(field, ".") == 3 {
				IP := net.ParseIP(field)
				if IP.To4() == nil {
					return nil, IPv4, IPv6, fmt.Errorf("Error parsing IP address %q", field)
				}

				IPv4 = DHCPAllocation{StaticFileName: deviceStaticFileName, IP: IP.To4(), MAC: mac}
			} else if strings.HasPrefix(field, "[") && strings.HasSuffix(field, "]") {
				IP := net.ParseIP(field[1 : len(field)-1])
				if IP == nil {
					return nil, IPv4, IPv6, fmt.Errorf("Error parsing IP address %q", field)
				}

				IPv6 = DHCPAllocation{StaticFileName: deviceStaticFileName, IP: IP, MAC: mac}
			} else if strings.Count(field, ":") == 5 {
				// This field is expected to come first, so that mac variable can be used with
				// populating the DHCPAllocation structs too.
				mac, err = net.ParseMAC(field)
				if err != nil {
					return nil, IPv4, IPv6, fmt.Errorf("Error parsing MAC address %q", field)
				}
			}
		}
	}

	err = scanner.Err()
	if err != nil {
		return nil, IPv4, IPv6, err
	}

	return mac, IPv4, IPv6, nil
}

// DHCPAllAllocations returns a map of IPs currently allocated (statically and dynamically)
// in dnsmasq for a specific network. The returned map is keyed by a 16 byte array representing
// the net.IP format. The value of each map item is a DHCPAllocation struct containing at least
// whether the allocation was static or dynamic and optionally instance name or MAC address.
// MAC addresses are only included for dynamic IPv4 allocations (where name is not reliable).
// Static allocations are not overridden by dynamic allocations, allowing for instance name to be
// included for static IPv6 allocations. IPv6 addresses that are dynamically assigned cannot be
// reliably linked to instances using either name or MAC because dnsmasq does not record the MAC
// address for these records, and the recorded host name can be set by the instance if the dns.mode
// for the network is set to "dynamic" and so cannot be trusted, so in this case we do not return
// any identifying info.
func DHCPAllAllocations(network string) (map[[4]byte]DHCPAllocation, map[[16]byte]DHCPAllocation, error) {
	IPv4s := make(map[[4]byte]DHCPAllocation)
	IPv6s := make(map[[16]byte]DHCPAllocation)

	// First read all statically allocated IPs.
	files, err := ioutil.ReadDir(shared.VarPath("networks", network, "dnsmasq.hosts"))
	if err != nil && os.IsNotExist(err) {
		return nil, nil, err
	}

	for _, entry := range files {
		_, IPv4, IPv6, err := DHCPStaticAllocation(network, entry.Name())
		if err != nil {
			return nil, nil, err
		}

		if IPv4.IP != nil {
			var IPKey [4]byte
			copy(IPKey[:], IPv4.IP.To4())
			IPv4s[IPKey] = IPv4
		}

		if IPv6.IP != nil {
			var IPKey [16]byte
			copy(IPKey[:], IPv6.IP.To16())
			IPv6s[IPKey] = IPv6
		}
	}

	// Next read all dynamic allocated IPs.
	file, err := os.Open(shared.VarPath("networks", network, "dnsmasq.leases"))
	if err != nil {
		return nil, nil, err
	}

	defer func() { _ = file.Close() }()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fields := strings.Fields(scanner.Text())
		if len(fields) == 5 {
			IP := net.ParseIP(fields[2])
			if IP == nil {
				return nil, nil, fmt.Errorf("Error parsing IP address: %v", fields[2])
			}

			// Handle IPv6 addresses.
			if IP.To4() == nil {
				var IPKey [16]byte
				copy(IPKey[:], IP.To16())

				// Don't replace IPs from static config as more reliable.
				if IPv6s[IPKey].StaticFileName != "" {
					continue
				}

				IPv6s[IPKey] = DHCPAllocation{
					IP: IP.To16(),
				}
			} else {
				// MAC only available in IPv4 leases.
				MAC, err := net.ParseMAC(fields[1])
				if err != nil {
					return nil, nil, err
				}

				var IPKey [4]byte
				copy(IPKey[:], IP.To4())

				// Don't replace IPs from static config as more reliable.
				if IPv4s[IPKey].StaticFileName != "" {
					continue
				}

				IPv4s[IPKey] = DHCPAllocation{
					MAC: MAC,
					IP:  IP.To4(),
				}
			}
		}
	}

	err = scanner.Err()
	if err != nil {
		return nil, nil, err
	}

	return IPv4s, IPv6s, nil
}

// StaticAllocationFileName returns the file name to use for a dnsmasq instance device static allocation.
func StaticAllocationFileName(projectName string, instanceName string, deviceName string) string {
	escapedDeviceName := filesystem.PathNameEncode(deviceName)

	return strings.Join([]string{project.Instance(projectName, instanceName), escapedDeviceName}, staticAllocationDeviceSeparator)
}
<commit_msg>lxd/dnsmasq: move from io/ioutil to io and os packages<commit_after>package dnsmasq

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/lxc/lxd/lxd/project"
	"github.com/lxc/lxd/lxd/storage/filesystem"
	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/subprocess"
	"github.com/lxc/lxd/shared/version"
)

const staticAllocationDeviceSeparator = "."

// DHCPAllocation represents an IP allocation from dnsmasq.
type DHCPAllocation struct {
	IP             net.IP
	StaticFileName string
	MAC            net.HardwareAddr
}

// ConfigMutex used to coordinate access to the dnsmasq config files.
var ConfigMutex sync.Mutex

// UpdateStaticEntry writes a single dhcp-host line for a network/instance combination.
func UpdateStaticEntry(network string, projectName string, instanceName string, deviceName string, netConfig map[string]string, hwaddr string, ipv4Address string, ipv6Address string) error {
	hwaddr = strings.ToLower(hwaddr)
	line := hwaddr

	// Generate the dhcp-host line
	if ipv4Address != "" {
		line += fmt.Sprintf(",%s", ipv4Address)
	}

	if ipv6Address != "" {
		line += fmt.Sprintf(",[%s]", ipv6Address)
	}

	if netConfig["dns.mode"] == "" || netConfig["dns.mode"] == "managed" {
		line += fmt.Sprintf(",%s", project.DNS(projectName, instanceName))
	}

	if line == hwaddr {
		return nil
	}

	deviceStaticFileName := StaticAllocationFileName(projectName, instanceName, deviceName)
	err := os.WriteFile(shared.VarPath("networks", network, "dnsmasq.hosts", deviceStaticFileName), []byte(line+"\n"), 0644)
	if err != nil {
		return err
	}

	return nil
}

// RemoveStaticEntry removes a single dhcp-host line for a network/instance combination.
func RemoveStaticEntry(network string, projectName string, instanceName string, deviceName string) error {
	deviceStaticFileName := StaticAllocationFileName(projectName, instanceName, deviceName)
	err := os.Remove(shared.VarPath("networks", network, "dnsmasq.hosts", deviceStaticFileName))
	if err != nil && !os.IsNotExist(err) {
		return err
	}

	return nil
}

// Kill kills dnsmasq for a particular network (or optionally reloads it).
func Kill(name string, reload bool) error {
	pidPath := shared.VarPath("networks", name, "dnsmasq.pid")

	// If the pid file doesn't exist, there is no process to kill.
	if !shared.PathExists(pidPath) {
		return nil
	}

	// Import saved subprocess details
	p, err := subprocess.ImportProcess(pidPath)
	if err != nil {
		return fmt.Errorf("Could not read pid file: %s", err)
	}

	if reload {
		err = p.Reload()
		if err != nil && err != subprocess.ErrNotRunning {
			return fmt.Errorf("Could not reload dnsmasq: %s", err)
		}

		return nil
	}

	err = p.Stop()
	if err != nil && err != subprocess.ErrNotRunning {
		return fmt.Errorf("Unable to kill dnsmasq: %s", err)
	}

	time.Sleep(100 * time.Millisecond) // Give OS time to release sockets.

	return nil
}

// GetVersion returns the version of dnsmasq.
func GetVersion() (*version.DottedVersion, error) {
	output, err := shared.RunCommandCLocale("dnsmasq", "--version")
	if err != nil {
		return nil, fmt.Errorf("Failed to check dnsmasq version: %w", err)
	}

	lines := strings.Split(string(output), " ")
	return version.Parse(lines[2])
}

// DHCPStaticAllocationPath returns the path to the DHCP static allocation file.
func DHCPStaticAllocationPath(network string, deviceStaticFileName string) string {
	return shared.VarPath("networks", network, "dnsmasq.hosts", deviceStaticFileName)
}

// DHCPStaticAllocation retrieves the dnsmasq statically allocated MAC and IPs for an instance device static file.
// Returns MAC, IPv4 and IPv6 DHCPAllocation structs respectively.
func DHCPStaticAllocation(network string, deviceStaticFileName string) (net.HardwareAddr, DHCPAllocation, DHCPAllocation, error) {
	var IPv4, IPv6 DHCPAllocation
	var mac net.HardwareAddr

	file, err := os.Open(DHCPStaticAllocationPath(network, deviceStaticFileName))
	if err != nil {
		return nil, IPv4, IPv6, err
	}

	defer func() { _ = file.Close() }()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fields := strings.SplitN(scanner.Text(), ",", -1)
		for _, field := range fields {
			// Check if field is IPv4 or IPv6 address.
			if strings.Count(field, ".") == 3 {
				IP := net.ParseIP(field)
				if IP.To4() == nil {
					return nil, IPv4, IPv6, fmt.Errorf("Error parsing IP address %q", field)
				}

				IPv4 = DHCPAllocation{StaticFileName: deviceStaticFileName, IP: IP.To4(), MAC: mac}
			} else if strings.HasPrefix(field, "[") && strings.HasSuffix(field, "]") {
				IP := net.ParseIP(field[1 : len(field)-1])
				if IP == nil {
					return nil, IPv4, IPv6, fmt.Errorf("Error parsing IP address %q", field)
				}

				IPv6 = DHCPAllocation{StaticFileName: deviceStaticFileName, IP: IP, MAC: mac}
			} else if strings.Count(field, ":") == 5 {
				// This field is expected to come first, so that mac variable can be used with
				// populating the DHCPAllocation structs too.
				mac, err = net.ParseMAC(field)
				if err != nil {
					return nil, IPv4, IPv6, fmt.Errorf("Error parsing MAC address %q", field)
				}
			}
		}
	}

	err = scanner.Err()
	if err != nil {
		return nil, IPv4, IPv6, err
	}

	return mac, IPv4, IPv6, nil
}

// DHCPAllAllocations returns a map of IPs currently allocated (statically and dynamically)
// in dnsmasq for a specific network. The returned map is keyed by a 16 byte array representing
// the net.IP format. The value of each map item is a DHCPAllocation struct containing at least
// whether the allocation was static or dynamic and optionally instance name or MAC address.
// MAC addresses are only included for dynamic IPv4 allocations (where name is not reliable).
// Static allocations are not overridden by dynamic allocations, allowing for instance name to be
// included for static IPv6 allocations. IPv6 addresses that are dynamically assigned cannot be
// reliably linked to instances using either name or MAC because dnsmasq does not record the MAC
// address for these records, and the recorded host name can be set by the instance if the dns.mode
// for the network is set to "dynamic" and so cannot be trusted, so in this case we do not return
// any identifying info.
func DHCPAllAllocations(network string) (map[[4]byte]DHCPAllocation, map[[16]byte]DHCPAllocation, error) {
	IPv4s := make(map[[4]byte]DHCPAllocation)
	IPv6s := make(map[[16]byte]DHCPAllocation)

	// First read all statically allocated IPs.
	files, err := os.ReadDir(shared.VarPath("networks", network, "dnsmasq.hosts"))
	if err != nil && os.IsNotExist(err) {
		return nil, nil, err
	}

	for _, entry := range files {
		_, IPv4, IPv6, err := DHCPStaticAllocation(network, entry.Name())
		if err != nil {
			return nil, nil, err
		}

		if IPv4.IP != nil {
			var IPKey [4]byte
			copy(IPKey[:], IPv4.IP.To4())
			IPv4s[IPKey] = IPv4
		}

		if IPv6.IP != nil {
			var IPKey [16]byte
			copy(IPKey[:], IPv6.IP.To16())
			IPv6s[IPKey] = IPv6
		}
	}

	// Next read all dynamic allocated IPs.
	file, err := os.Open(shared.VarPath("networks", network, "dnsmasq.leases"))
	if err != nil {
		return nil, nil, err
	}

	defer func() { _ = file.Close() }()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fields := strings.Fields(scanner.Text())
		if len(fields) == 5 {
			IP := net.ParseIP(fields[2])
			if IP == nil {
				return nil, nil, fmt.Errorf("Error parsing IP address: %v", fields[2])
			}

			// Handle IPv6 addresses.
			if IP.To4() == nil {
				var IPKey [16]byte
				copy(IPKey[:], IP.To16())

				// Don't replace IPs from static config as more reliable.
				if IPv6s[IPKey].StaticFileName != "" {
					continue
				}

				IPv6s[IPKey] = DHCPAllocation{
					IP: IP.To16(),
				}
			} else {
				// MAC only available in IPv4 leases.
				MAC, err := net.ParseMAC(fields[1])
				if err != nil {
					return nil, nil, err
				}

				var IPKey [4]byte
				copy(IPKey[:], IP.To4())

				// Don't replace IPs from static config as more reliable.
				if IPv4s[IPKey].StaticFileName != "" {
					continue
				}

				IPv4s[IPKey] = DHCPAllocation{
					MAC: MAC,
					IP:  IP.To4(),
				}
			}
		}
	}

	err = scanner.Err()
	if err != nil {
		return nil, nil, err
	}

	return IPv4s, IPv6s, nil
}

// StaticAllocationFileName returns the file name to use for a dnsmasq instance device static allocation.
func StaticAllocationFileName(projectName string, instanceName string, deviceName string) string {
	escapedDeviceName := filesystem.PathNameEncode(deviceName)

	return strings.Join([]string{project.Instance(projectName, instanceName), escapedDeviceName}, staticAllocationDeviceSeparator)
}
<|endoftext|>


<commit_before>package template

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"path/filepath"
	"strings"
)

// ChrootLoader is a pong2 compatible file loader which restricts all accesses to a directory.
type ChrootLoader struct {
	Path string
}

// Abs resolves a filename relative to the base directory. Absolute paths are allowed.
// When there's no base dir set, the absolute path to the filename
// will be calculated based on either the provided base directory (which
// might be a path of a template which includes another template) or
// the current working directory.
func (l ChrootLoader) Abs(base string, name string) string {
	return filepath.Clean(fmt.Sprintf("%s/%s", l.Path, name))
}

// Get reads the path's content from your local filesystem.
func (l ChrootLoader) Get(path string) (io.Reader, error) {
	// Get the full path
	path, err := filepath.EvalSymlinks(path)
	if err != nil {
		return nil, err
	}

	basePath, err := filepath.EvalSymlinks(l.Path)
	if err != nil {
		return nil, err
	}

	// Validate that we're under the expected prefix
	if !strings.HasPrefix(path, basePath) {
		return nil, fmt.Errorf("Attempting to access a file outside the instance")
	}

	// Open and read the file
	buf, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return bytes.NewReader(buf), nil
}
<commit_msg>lxd/template: move from io/ioutil to io and os packages<commit_after>package template

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// ChrootLoader is a pong2 compatible file loader which restricts all accesses to a directory.
type ChrootLoader struct {
	Path string
}

// Abs resolves a filename relative to the base directory. Absolute paths are allowed.
// When there's no base dir set, the absolute path to the filename
// will be calculated based on either the provided base directory (which
// might be a path of a template which includes another template) or
// the current working directory.
func (l ChrootLoader) Abs(base string, name string) string {
	return filepath.Clean(fmt.Sprintf("%s/%s", l.Path, name))
}

// Get reads the path's content from your local filesystem.
func (l ChrootLoader) Get(path string) (io.Reader, error) {
	// Get the full path
	path, err := filepath.EvalSymlinks(path)
	if err != nil {
		return nil, err
	}

	basePath, err := filepath.EvalSymlinks(l.Path)
	if err != nil {
		return nil, err
	}

	// Validate that we're under the expected prefix
	if !strings.HasPrefix(path, basePath) {
		return nil, fmt.Errorf("Attempting to access a file outside the instance")
	}

	// Open and read the file
	buf, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return bytes.NewReader(buf), nil
}
<|endoftext|>


<commit_before>// Code generated by "tool/gen_mackerel_plugin.pl"; DO NOT EDIT
package main

import (
	"fmt"

	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-accesslog/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-apache2/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-cloudfront/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-dynamodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-cpucredit/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-ebs/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-kinesis-streams/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-lambda/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-rds/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ses/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-conntrack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-docker/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-fluentd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-flume/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-gostats/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-graphite/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-haproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-inode/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jmx-jolokia/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jvm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-linux/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mailq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-memcached/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mongodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-multicore/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-munin/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mysql/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nginx/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nvidia-smi/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-openldap/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-apc/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-fpm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-opcache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-plack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-postgres/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-proc-fd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-rabbitmq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-redis/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-sidekiq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-snmp/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-solr/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-squid/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-td-table-count/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-trafficserver/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-twemproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-unicorn/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uptime/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uwsgi-vassal/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-varnish/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-xentop/lib"
)

func runPlugin(plug string) error {
	switch plug {
	case "accesslog":
		mpaccesslog.Do()
	case "apache2":
		mpapache2.Do()
	case "aws-cloudfront":
		mpawscloudfront.Do()
	case "aws-dynamodb":
		mpawsdynamodb.Do()
	case "aws-ec2-cpucredit":
		mpawsec2cpucredit.Do()
	case "aws-ec2-ebs":
		mpawsec2ebs.Do()
	case "aws-elasticache":
		mpawselasticache.Do()
	case "aws-elasticsearch":
		mpawselasticsearch.Do()
	case "aws-elb":
		mpawselb.Do()
	case "aws-kinesis-streams":
		mpawskinesisstreams.Do()
	case "aws-lambda":
		mpawslambda.Do()
	case "aws-rds":
		mpawsrds.Do()
	case "aws-ses":
		mpawsses.Do()
	case "conntrack":
		mpconntrack.Do()
	case "docker":
		mpdocker.Do()
	case "elasticsearch":
		mpelasticsearch.Do()
	case "fluentd":
		mpfluentd.Do()
	case "flume":
		mpflume.Do()
	case "gostats":
		mpgostats.Do()
	case "graphite":
		mpgraphite.Do()
	case "haproxy":
		mphaproxy.Do()
	case "inode":
		mpinode.Do()
	case "jmx-jolokia":
		mpjmxjolokia.Do()
	case "jvm":
		mpjvm.Do()
	case "linux":
		mplinux.Do()
	case "mailq":
		mpmailq.Do()
	case "memcached":
		mpmemcached.Do()
	case "mongodb":
		mpmongodb.Do()
	case "multicore":
		mpmulticore.Do()
	case "munin":
		mpmunin.Do()
	case "mysql":
		mpmysql.Do()
	case "nginx":
		mpnginx.Do()
	case "nvidia-smi":
		mpnvidiasmi.Do()
	case "openldap":
		mpopenldap.Do()
	case "php-apc":
		mpphpapc.Do()
	case "php-fpm":
		mpphpfpm.Do()
	case "php-opcache":
		mpphpopcache.Do()
	case "plack":
		mpplack.Do()
	case "postgres":
		mppostgres.Do()
	case "proc-fd":
		mpprocfd.Do()
	case "rabbitmq":
		mprabbitmq.Do()
	case "redis":
		mpredis.Do()
	case "sidekiq":
		mpsidekiq.Do()
	case "snmp":
		mpsnmp.Do()
	case "solr":
		mpsolr.Do()
	case "squid":
		mpsquid.Do()
	case "td-table-count":
		mptdtablecount.Do()
	case "trafficserver":
		mptrafficserver.Do()
	case "twemproxy":
		mptwemproxy.Do()
	case "unicorn":
		mpunicorn.Do()
	case "uptime":
		mpuptime.Do()
	case "uwsgi-vassal":
		mpuwsgivassal.Do()
	case "varnish":
		mpvarnish.Do()
	case "xentop":
		mpxentop.Do()
	default:
		return fmt.Errorf("unknown plugin: %q", plug)
	}
	return nil
}

var plugins = []string{
	"accesslog",
	"apache2",
	"aws-cloudfront",
	"aws-dynamodb",
	"aws-ec2-cpucredit",
	"aws-ec2-ebs",
	"aws-elasticache",
	"aws-elasticsearch",
	"aws-elb",
	"aws-kinesis-streams",
	"aws-lambda",
	"aws-rds",
	"aws-ses",
	"conntrack",
	"docker",
	"elasticsearch",
	"fluentd",
	"flume",
	"gostats",
	"graphite",
	"haproxy",
	"inode",
	"jmx-jolokia",
	"jvm",
	"linux",
	"mailq",
	"memcached",
	"mongodb",
	"multicore",
	"munin",
	"mysql",
	"nginx",
	"nvidia-smi",
	"openldap",
	"php-apc",
	"php-fpm",
	"php-opcache",
	"plack",
	"postgres",
	"proc-fd",
	"rabbitmq",
	"redis",
	"sidekiq",
	"snmp",
	"solr",
	"squid",
	"td-table-count",
	"trafficserver",
	"twemproxy",
	"unicorn",
	"uptime",
	"uwsgi-vassal",
	"varnish",
	"xentop",
}
<commit_msg>go generate<commit_after>// Code generated by "tool/gen_mackerel_plugin.pl"; DO NOT EDIT
package main

import (
	"fmt"

	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-accesslog/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-apache2/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-cloudfront/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-dynamodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-cpucredit/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-ebs/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-kinesis-streams/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-lambda/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-rds/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ses/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-conntrack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-docker/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-fluentd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-flume/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-gostats/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-graphite/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-h2o/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-haproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-inode/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jmx-jolokia/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jvm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-linux/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mailq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-memcached/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mongodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-multicore/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-munin/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mysql/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nginx/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nvidia-smi/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-openldap/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-apc/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-fpm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-opcache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-plack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-postgres/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-proc-fd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-rabbitmq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-redis/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-sidekiq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-snmp/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-solr/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-squid/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-td-table-count/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-trafficserver/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-twemproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-unicorn/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uptime/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uwsgi-vassal/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-varnish/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-xentop/lib"
)

func runPlugin(plug string) error {
	switch plug {
	case "accesslog":
		mpaccesslog.Do()
	case "apache2":
		mpapache2.Do()
	case "aws-cloudfront":
		mpawscloudfront.Do()
	case "aws-dynamodb":
		mpawsdynamodb.Do()
	case "aws-ec2-cpucredit":
		mpawsec2cpucredit.Do()
	case "aws-ec2-ebs":
		mpawsec2ebs.Do()
	case "aws-elasticache":
		mpawselasticache.Do()
	case "aws-elasticsearch":
		mpawselasticsearch.Do()
	case "aws-elb":
		mpawselb.Do()
	case "aws-kinesis-streams":
		mpawskinesisstreams.Do()
	case "aws-lambda":
		mpawslambda.Do()
	case "aws-rds":
		mpawsrds.Do()
	case "aws-ses":
		mpawsses.Do()
	case "conntrack":
		mpconntrack.Do()
	case "docker":
		mpdocker.Do()
	case "elasticsearch":
		mpelasticsearch.Do()
	case "fluentd":
		mpfluentd.Do()
	case "flume":
		mpflume.Do()
	case "gostats":
		mpgostats.Do()
	case "graphite":
		mpgraphite.Do()
	case "h2o":
		mph2o.Do()
	case "haproxy":
		mphaproxy.Do()
	case "inode":
		mpinode.Do()
	case "jmx-jolokia":
		mpjmxjolokia.Do()
	case "jvm":
		mpjvm.Do()
	case "linux":
		mplinux.Do()
	case "mailq":
		mpmailq.Do()
	case "memcached":
		mpmemcached.Do()
	case "mongodb":
		mpmongodb.Do()
	case "multicore":
		mpmulticore.Do()
	case "munin":
		mpmunin.Do()
	case "mysql":
		mpmysql.Do()
	case "nginx":
		mpnginx.Do()
	case "nvidia-smi":
		mpnvidiasmi.Do()
	case "openldap":
		mpopenldap.Do()
	case "php-apc":
		mpphpapc.Do()
	case "php-fpm":
		mpphpfpm.Do()
	case "php-opcache":
		mpphpopcache.Do()
	case "plack":
		mpplack.Do()
	case "postgres":
		mppostgres.Do()
	case "proc-fd":
		mpprocfd.Do()
	case "rabbitmq":
		mprabbitmq.Do()
	case "redis":
		mpredis.Do()
	case "sidekiq":
		mpsidekiq.Do()
	case "snmp":
		mpsnmp.Do()
	case "solr":
		mpsolr.Do()
	case "squid":
		mpsquid.Do()
	case "td-table-count":
		mptdtablecount.Do()
	case "trafficserver":
		mptrafficserver.Do()
	case "twemproxy":
		mptwemproxy.Do()
	case "unicorn":
		mpunicorn.Do()
	case "uptime":
		mpuptime.Do()
	case "uwsgi-vassal":
		mpuwsgivassal.Do()
	case "varnish":
		mpvarnish.Do()
	case "xentop":
		mpxentop.Do()
	default:
		return fmt.Errorf("unknown plugin: %q", plug)
	}
	return nil
}

var plugins = []string{
	"accesslog",
	"apache2",
	"aws-cloudfront",
	"aws-dynamodb",
	"aws-ec2-cpucredit",
	"aws-ec2-ebs",
	"aws-elasticache",
	"aws-elasticsearch",
	"aws-elb",
	"aws-kinesis-streams",
	"aws-lambda",
	"aws-rds",
	"aws-ses",
	"conntrack",
	"docker",
	"elasticsearch",
	"fluentd",
	"flume",
	"gostats",
	"graphite",
	"h2o",
	"haproxy",
	"inode",
	"jmx-jolokia",
	"jvm",
	"linux",
	"mailq",
	"memcached",
	"mongodb",
	"multicore",
	"munin",
	"mysql",
	"nginx",
	"nvidia-smi",
	"openldap",
	"php-apc",
	"php-fpm",
	"php-opcache",
	"plack",
	"postgres",
	"proc-fd",
	"rabbitmq",
	"redis",
	"sidekiq",
	"snmp",
	"solr",
	"squid",
	"td-table-count",
	"trafficserver",
	"twemproxy",
	"unicorn",
	"uptime",
	"uwsgi-vassal",
	"varnish",
	"xentop",
}
<|endoftext|>


<commit_before>// Code generated by "tool/gen_mackerel_plugin.pl"; DO NOT EDIT
package main

import (
	"fmt"

	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-accesslog/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-apache2/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-cloudfront/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-dynamodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-cpucredit/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-ebs/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-kinesis-streams/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-lambda/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-rds/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ses/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-conntrack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-docker/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-fluentd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-flume/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-gostats/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-graphite/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-h2o/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-haproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-inode/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jmx-jolokia/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jvm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-linux/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mailq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-memcached/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mongodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-multicore/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-munin/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mysql/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nginx/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nvidia-smi/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-openldap/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-apc/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-fpm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-opcache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-plack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-postgres/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-proc-fd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-rabbitmq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-redis/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-sidekiq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-snmp/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-solr/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-squid/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-td-table-count/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-trafficserver/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-twemproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-unicorn/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uptime/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uwsgi-vassal/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-varnish/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-xentop/lib"
)

func runPlugin(plug string) error {
	switch plug {
	case "accesslog":
		mpaccesslog.Do()
	case "apache2":
		mpapache2.Do()
	case "aws-cloudfront":
		mpawscloudfront.Do()
	case "aws-dynamodb":
		mpawsdynamodb.Do()
	case "aws-ec2-cpucredit":
		mpawsec2cpucredit.Do()
	case "aws-ec2-ebs":
		mpawsec2ebs.Do()
	case "aws-elasticache":
		mpawselasticache.Do()
	case "aws-elasticsearch":
		mpawselasticsearch.Do()
	case "aws-elb":
		mpawselb.Do()
	case "aws-kinesis-streams":
		mpawskinesisstreams.Do()
	case "aws-lambda":
		mpawslambda.Do()
	case "aws-rds":
		mpawsrds.Do()
	case "aws-ses":
		mpawsses.Do()
	case "conntrack":
		mpconntrack.Do()
	case "docker":
		mpdocker.Do()
	case "elasticsearch":
		mpelasticsearch.Do()
	case "fluentd":
		mpfluentd.Do()
	case "flume":
		mpflume.Do()
	case "gostats":
		mpgostats.Do()
	case "graphite":
		mpgraphite.Do()
	case "h2o":
		mph2o.Do()
	case "haproxy":
		mphaproxy.Do()
	case "inode":
		mpinode.Do()
	case "jmx-jolokia":
		mpjmxjolokia.Do()
	case "jvm":
		mpjvm.Do()
	case "linux":
		mplinux.Do()
	case "mailq":
		mpmailq.Do()
	case "memcached":
		mpmemcached.Do()
	case "mongodb":
		mpmongodb.Do()
	case "multicore":
		mpmulticore.Do()
	case "munin":
		mpmunin.Do()
	case "mysql":
		mpmysql.Do()
	case "nginx":
		mpnginx.Do()
	case "nvidia-smi":
		mpnvidiasmi.Do()
	case "openldap":
		mpopenldap.Do()
	case "php-apc":
		mpphpapc.Do()
	case "php-fpm":
		mpphpfpm.Do()
	case "php-opcache":
		mpphpopcache.Do()
	case "plack":
		mpplack.Do()
	case "postgres":
		mppostgres.Do()
	case "proc-fd":
		mpprocfd.Do()
	case "rabbitmq":
		mprabbitmq.Do()
	case "redis":
		mpredis.Do()
	case "sidekiq":
		mpsidekiq.Do()
	case "snmp":
		mpsnmp.Do()
	case "solr":
		mpsolr.Do()
	case "squid":
		mpsquid.Do()
	case "td-table-count":
		mptdtablecount.Do()
	case "trafficserver":
		mptrafficserver.Do()
	case "twemproxy":
		mptwemproxy.Do()
	case "unicorn":
		mpunicorn.Do()
	case "uptime":
		mpuptime.Do()
	case "uwsgi-vassal":
		mpuwsgivassal.Do()
	case "varnish":
		mpvarnish.Do()
	case "xentop":
		mpxentop.Do()
	default:
		return fmt.Errorf("unknown plugin: %q", plug)
	}
	return nil
}

var plugins = []string{
	"accesslog",
	"apache2",
	"aws-cloudfront",
	"aws-dynamodb",
	"aws-ec2-cpucredit",
	"aws-ec2-ebs",
	"aws-elasticache",
	"aws-elasticsearch",
	"aws-elb",
	"aws-kinesis-streams",
	"aws-lambda",
	"aws-rds",
	"aws-ses",
	"conntrack",
	"docker",
	"elasticsearch",
	"fluentd",
	"flume",
	"gostats",
	"graphite",
	"h2o",
	"haproxy",
	"inode",
	"jmx-jolokia",
	"jvm",
	"linux",
	"mailq",
	"memcached",
	"mongodb",
	"multicore",
	"munin",
	"mysql",
	"nginx",
	"nvidia-smi",
	"openldap",
	"php-apc",
	"php-fpm",
	"php-opcache",
	"plack",
	"postgres",
	"proc-fd",
	"rabbitmq",
	"redis",
	"sidekiq",
	"snmp",
	"solr",
	"squid",
	"td-table-count",
	"trafficserver",
	"twemproxy",
	"unicorn",
	"uptime",
	"uwsgi-vassal",
	"varnish",
	"xentop",
}
<commit_msg>go generate<commit_after>// Code generated by "tool/gen_mackerel_plugin.pl"; DO NOT EDIT
package main

import (
	"fmt"

	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-accesslog/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-apache2/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-cloudfront/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-dynamodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-cpucredit/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ec2-ebs/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-elb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-kinesis-streams/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-lambda/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-rds/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-s3-requests/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-aws-ses/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-conntrack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-docker/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-elasticsearch/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-fluentd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-flume/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-gostats/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-graphite/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-h2o/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-haproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-inode/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jmx-jolokia/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-jvm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-linux/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mailq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-memcached/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mongodb/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-multicore/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-munin/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-mysql/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nginx/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-nvidia-smi/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-openldap/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-apc/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-fpm/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-php-opcache/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-plack/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-postgres/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-proc-fd/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-rabbitmq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-redis/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-sidekiq/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-snmp/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-solr/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-squid/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-td-table-count/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-trafficserver/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-twemproxy/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-unicorn/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uptime/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-uwsgi-vassal/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-varnish/lib"
	"github.com/mackerelio/mackerel-agent-plugins/mackerel-plugin-xentop/lib"
)

func runPlugin(plug string) error {
	switch plug {
	case "accesslog":
		mpaccesslog.Do()
	case "apache2":
		mpapache2.Do()
	case "aws-cloudfront":
		mpawscloudfront.Do()
	case "aws-dynamodb":
		mpawsdynamodb.Do()
	case "aws-ec2-cpucredit":
		mpawsec2cpucredit.Do()
	case "aws-ec2-ebs":
		mpawsec2ebs.Do()
	case "aws-elasticache":
		mpawselasticache.Do()
	case "aws-elasticsearch":
		mpawselasticsearch.Do()
	case "aws-elb":
		mpawselb.Do()
	case "aws-kinesis-streams":
		mpawskinesisstreams.Do()
	case "aws-lambda":
		mpawslambda.Do()
	case "aws-rds":
		mpawsrds.Do()
	case "aws-s3-requests":
		mpawss3requests.Do()
	case "aws-ses":
		mpawsses.Do()
	case "conntrack":
		mpconntrack.Do()
	case "docker":
		mpdocker.Do()
	case "elasticsearch":
		mpelasticsearch.Do()
	case "fluentd":
		mpfluentd.Do()
	case "flume":
		mpflume.Do()
	case "gostats":
		mpgostats.Do()
	case "graphite":
		mpgraphite.Do()
	case "h2o":
		mph2o.Do()
	case "haproxy":
		mphaproxy.Do()
	case "inode":
		mpinode.Do()
	case "jmx-jolokia":
		mpjmxjolokia.Do()
	case "jvm":
		mpjvm.Do()
	case "linux":
		mplinux.Do()
	case "mailq":
		mpmailq.Do()
	case "memcached":
		mpmemcached.Do()
	case "mongodb":
		mpmongodb.Do()
	case "multicore":
		mpmulticore.Do()
	case "munin":
		mpmunin.Do()
	case "mysql":
		mpmysql.Do()
	case "nginx":
		mpnginx.Do()
	case "nvidia-smi":
		mpnvidiasmi.Do()
	case "openldap":
		mpopenldap.Do()
	case "php-apc":
		mpphpapc.Do()
	case "php-fpm":
		mpphpfpm.Do()
	case "php-opcache":
		mpphpopcache.Do()
	case "plack":
		mpplack.Do()
	case "postgres":
		mppostgres.Do()
	case "proc-fd":
		mpprocfd.Do()
	case "rabbitmq":
		mprabbitmq.Do()
	case "redis":
		mpredis.Do()
	case "sidekiq":
		mpsidekiq.Do()
	case "snmp":
		mpsnmp.Do()
	case "solr":
		mpsolr.Do()
	case "squid":
		mpsquid.Do()
	case "td-table-count":
		mptdtablecount.Do()
	case "trafficserver":
		mptrafficserver.Do()
	case "twemproxy":
		mptwemproxy.Do()
	case "unicorn":
		mpunicorn.Do()
	case "uptime":
		mpuptime.Do()
	case "uwsgi-vassal":
		mpuwsgivassal.Do()
	case "varnish":
		mpvarnish.Do()
	case "xentop":
		mpxentop.Do()
	default:
		return fmt.Errorf("unknown plugin: %q", plug)
	}
	return nil
}

var plugins = []string{
	"accesslog",
	"apache2",
	"aws-cloudfront",
	"aws-dynamodb",
	"aws-ec2-cpucredit",
	"aws-ec2-ebs",
	"aws-elasticache",
	"aws-elasticsearch",
	"aws-elb",
	"aws-kinesis-streams",
	"aws-lambda",
	"aws-rds",
	"aws-s3-requests",
	"aws-ses",
	"conntrack",
	"docker",
	"elasticsearch",
	"fluentd",
	"flume",
	"gostats",
	"graphite",
	"h2o",
	"haproxy",
	"inode",
	"jmx-jolokia",
	"jvm",
	"linux",
	"mailq",
	"memcached",
	"mongodb",
	"multicore",
	"munin",
	"mysql",
	"nginx",
	"nvidia-smi",
	"openldap",
	"php-apc",
	"php-fpm",
	"php-opcache",
	"plack",
	"postgres",
	"proc-fd",
	"rabbitmq",
	"redis",
	"sidekiq",
	"snmp",
	"solr",
	"squid",
	"td-table-count",
	"trafficserver",
	"twemproxy",
	"unicorn",
	"uptime",
	"uwsgi-vassal",
	"varnish",
	"xentop",
}
<|endoftext|>


<commit_before>// Package main contains the content-server executable.
package main

import (
	"flag"
	"log"
	"path/filepath"

	"github.com/polyglottis/content_server/database"
	"github.com/polyglottis/content_server/operations"
	"github.com/polyglottis/content_server/server"
	"github.com/polyglottis/rpc"
)

var dbFile = flag.String("db", "content.db", "path to sqlite db file")
var tcpAddr = flag.String("tcp", ":18982", "TCP address of content server")
var operationsAddr = flag.String("op-tcp", ":16485", "TCP address of operations RPC server")

func main() {
	flag.Parse()

	abs, err := filepath.Abs(*dbFile)
	if err != nil {
		log.Fatalln(err)
	}

	db, err := database.Open(abs)
	if err != nil {
		log.Fatalln(err)
	}
	log.Printf("Content server accessing db file %v", abs)

	main := server.New(server.NewServerDB(db), *tcpAddr)
	op := operations.NewOpServer(db, *operationsAddr)
	p := rpc.NewServerPair("Content Server", main, op)

	err = p.RegisterAndListen()
	if err != nil {
		log.Fatalln(err)
	}
	defer p.Close()

	p.Accept()
}
<commit_msg>Use config files<commit_after>// Package main contains the content-server executable.
package main

import (
	"log"

	"github.com/polyglottis/content_server/database"
	"github.com/polyglottis/content_server/operations"
	"github.com/polyglottis/content_server/server"
	"github.com/polyglottis/platform/config"
	"github.com/polyglottis/rpc"
)

func main() {

	c := config.Get()

	db, err := database.Open(c.ContentDB)
	if err != nil {
		log.Fatalln(err)
	}

	main := server.New(server.NewServerDB(db), c.Content)
	op := operations.NewOpServer(db, c.ContentOp)
	p := rpc.NewServerPair("Content Server", main, op)

	err = p.RegisterAndListen()
	if err != nil {
		log.Fatalln(err)
	}
	defer p.Close()

	p.Accept()
}
<|endoftext|>


<commit_before>// Copyright 2019, OpenTelemetry Authors
//
// 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 fileexporter

import (
	"os"

	"go.uber.org/zap"

	"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
	"github.com/open-telemetry/opentelemetry-collector/exporter"
)

const (
	// The value of "type" key in configuration.
	typeStr = "file"
)

// Factory is the factory for logging exporter.
type Factory struct {
}

// Type gets the type of the Exporter config created by this factory.
func (f *Factory) Type() string {
	return typeStr
}

// CreateDefaultConfig creates the default configuration for exporter.
func (f *Factory) CreateDefaultConfig() configmodels.Exporter {
	return &Config{
		ExporterSettings: configmodels.ExporterSettings{
			TypeVal: typeStr,
			NameVal: typeStr,
		},
	}
}

// CreateTraceExporter creates a trace exporter based on this config.
func (f *Factory) CreateTraceExporter(logger *zap.Logger, config configmodels.Exporter) (exporter.TraceExporter, error) {
	return f.createExporter(config)
}

// CreateMetricsExporter creates a metrics exporter based on this config.
func (f *Factory) CreateMetricsExporter(logger *zap.Logger, config configmodels.Exporter) (exporter.MetricsExporter, error) {
	return f.createExporter(config)
}

func (f *Factory) createExporter(config configmodels.Exporter) (*Exporter, error) {
	cfg := config.(*Config)

	// There must be one exporter for both metrics and traces. We maintain a map of
	// exporters per config.

	// Check to see if there is already a exporter for this config.
	exporter, ok := exporters[cfg]

	if !ok {
		file, err := os.OpenFile(cfg.Path, os.O_RDWR|os.O_CREATE, 0755)
		if err != nil {
			return nil, err
		}
		exporter = &Exporter{file: file}

		// Remember the receiver in the map
		exporters[cfg] = exporter
	}
	return exporter, nil
}

// This is the map of already created File exporters for particular configurations.
// We maintain this map because the Factory is asked trace and metric receivers separately
// when it gets CreateTraceReceiver() and CreateMetricsReceiver() but they must not
// create separate objects, they must use one Receiver object per configuration.
var exporters = map[*Config]*Exporter{}
<commit_msg>Ensure file exporter truncates output file when starting (#525)<commit_after>// Copyright 2019, OpenTelemetry Authors
//
// 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 fileexporter

import (
	"os"

	"go.uber.org/zap"

	"github.com/open-telemetry/opentelemetry-collector/config/configmodels"
	"github.com/open-telemetry/opentelemetry-collector/exporter"
)

const (
	// The value of "type" key in configuration.
	typeStr = "file"
)

// Factory is the factory for logging exporter.
type Factory struct {
}

// Type gets the type of the Exporter config created by this factory.
func (f *Factory) Type() string {
	return typeStr
}

// CreateDefaultConfig creates the default configuration for exporter.
func (f *Factory) CreateDefaultConfig() configmodels.Exporter {
	return &Config{
		ExporterSettings: configmodels.ExporterSettings{
			TypeVal: typeStr,
			NameVal: typeStr,
		},
	}
}

// CreateTraceExporter creates a trace exporter based on this config.
func (f *Factory) CreateTraceExporter(logger *zap.Logger, config configmodels.Exporter) (exporter.TraceExporter, error) {
	return f.createExporter(config)
}

// CreateMetricsExporter creates a metrics exporter based on this config.
func (f *Factory) CreateMetricsExporter(logger *zap.Logger, config configmodels.Exporter) (exporter.MetricsExporter, error) {
	return f.createExporter(config)
}

func (f *Factory) createExporter(config configmodels.Exporter) (*Exporter, error) {
	cfg := config.(*Config)

	// There must be one exporter for both metrics and traces. We maintain a map of
	// exporters per config.

	// Check to see if there is already a exporter for this config.
	exporter, ok := exporters[cfg]

	if !ok {
		file, err := os.OpenFile(cfg.Path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
		if err != nil {
			return nil, err
		}
		exporter = &Exporter{file: file}

		// Remember the receiver in the map
		exporters[cfg] = exporter
	}
	return exporter, nil
}

// This is the map of already created File exporters for particular configurations.
// We maintain this map because the Factory is asked trace and metric receivers separately
// when it gets CreateTraceReceiver() and CreateMetricsReceiver() but they must not
// create separate objects, they must use one Receiver object per configuration.
var exporters = map[*Config]*Exporter{}
<|endoftext|>


<commit_before>package message

import (
	"encoding/json"
	"fmt"
	"runtime"

	"github.com/mongodb/grip/level"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/disk"
	"github.com/shirou/gopsutil/mem"
	"github.com/shirou/gopsutil/net"
)

// SystemInfo is a type that implements message.Composer but also
// collects system-wide resource utilization statistics about memory,
// CPU, and network use, along with an optional message.
type SystemInfo struct {
	Message    string                `json:"message,omitempty" bson:"message,omitempty"`
	CPU        cpu.TimesStat         `json:"cpu,omitempty" bson:"cpu,omitempty"`
	NumCPU     int                   `json:"num_cpus,omitempty" bson:"num_cpus,omitempty"`
	VMStat     mem.VirtualMemoryStat `json:"vmstat,omitempty" bson:"vmstat,omitempty"`
	NetStat    net.IOCountersStat    `json:"netstat,omitempty" bson:"netstat,omitempty"`
	Partitions []disk.PartitionStat  `json:"partitions,omitempty" bson:"partitions,omitempty"`
	Usage      []disk.UsageStat      `json:"usage,omitempty" bson:"usage,omitempty"`
	IOStat     []disk.IOCountersStat `json:"iostat,omitempty" bson:"iostat,omitempty"`
	Errors     []string              `json:"errors,omitempty" bson:"errors,omitempty"`
	Base       `json:"metadata,omitempty" bson:"metadata,omitempty"`
	loggable   bool
	rendered   string
}

// CollectSystemInfo returns a populated SystemInfo object,
// without a message.
func CollectSystemInfo() Composer {
	return NewSystemInfo(level.Trace, "")
}

// MakeSystemInfo builds a populated SystemInfo object with the
// specified message.
func MakeSystemInfo(message string) Composer {
	return NewSystemInfo(level.Info, message)
}

// NewSystemInfo returns a fully configured and populated SystemInfo
// object.
func NewSystemInfo(priority level.Priority, message string) Composer {
	var err error
	s := &SystemInfo{
		Message: message,
		NumCPU:  runtime.NumCPU(),
	}

	if err = s.SetPriority(priority); err != nil {
		s.Errors = append(s.Errors, err.Error())
		return s
	}

	s.loggable = true

	times, err := cpu.Times(false)
	s.saveError("cpu_times", err)
	if err == nil && len(times) > 0 {
		// since we're not storing per-core information,
		// there's only one thing we care about in this struct
		s.CPU = times[0]
	}

	vmstat, err := mem.VirtualMemory()
	s.saveError("vmstat", err)
	if err == nil && vmstat != nil {
		s.VMStat = *vmstat
	}

	netstat, err := net.IOCounters(false)
	s.saveError("netstat", err)
	if err == nil && len(netstat) > 0 {
		s.NetStat = netstat[0]
	}

	partitions, err := disk.Partitions(true)
	s.saveError("disk_part", err)

	if err == nil {
		var u *disk.UsageStat
		for _, p := range partitions {
			u, err = disk.Usage(p.Mountpoint)
			s.saveError("partition", err)
			if err != nil {
				continue
			}

			s.Usage = append(s.Usage, *u)
		}

		s.Partitions = partitions
	}

	iostatMap, err := disk.IOCounters()
	s.saveError("iostat", err)
	for _, stat := range iostatMap {
		s.IOStat = append(s.IOStat, stat)
	}

	return s
}

// Loggable returns true when the Processinfo structure has been
// populated.
func (s *SystemInfo) Loggable() bool { return s.loggable }

// Raw always returns the SystemInfo object, however it will call the
// Collect method of the base operation first.
func (s *SystemInfo) Raw() interface{} { _ = s.Collect(); return s }

// String returns a string representation of the message, lazily
// rendering the message, and caching it privately.
func (s *SystemInfo) String() string {
	if s.rendered == "" {
		s.rendered = renderStatsString(s.Message, s)
	}

	return s.rendered
}

func (s *SystemInfo) saveError(stat string, err error) {
	if shouldSaveError(err) {
		s.Errors = append(s.Errors, fmt.Sprintf("%s: %v", stat, err))
	}
}

// helper function
func shouldSaveError(err error) bool {
	return err != nil && err.Error() != "not implemented yet"
}

func renderStatsString(msg string, data interface{}) string {
	out, err := json.Marshal(data)
	if err != nil {
		return msg
	}

	if msg == "" {
		return string(out)
	}

	return fmt.Sprintf("%s:\n%s", msg, string(out))
}
<commit_msg>MAKE-352 Save CPU percent in system info (#20)<commit_after>package message

import (
	"encoding/json"
	"fmt"
	"runtime"

	"github.com/mongodb/grip/level"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/disk"
	"github.com/shirou/gopsutil/mem"
	"github.com/shirou/gopsutil/net"
)

// SystemInfo is a type that implements message.Composer but also
// collects system-wide resource utilization statistics about memory,
// CPU, and network use, along with an optional message.
type SystemInfo struct {
	Message    string                `json:"message,omitempty" bson:"message,omitempty"`
	CPU        cpu.TimesStat         `json:"cpu,omitempty" bson:"cpu,omitempty"`
	CPUPercent float64               `json:"cpu_percent,omitempty" bson:"cpu_percent,omitempty"`
	NumCPU     int                   `json:"num_cpus,omitempty" bson:"num_cpus,omitempty"`
	VMStat     mem.VirtualMemoryStat `json:"vmstat,omitempty" bson:"vmstat,omitempty"`
	NetStat    net.IOCountersStat    `json:"netstat,omitempty" bson:"netstat,omitempty"`
	Partitions []disk.PartitionStat  `json:"partitions,omitempty" bson:"partitions,omitempty"`
	Usage      []disk.UsageStat      `json:"usage,omitempty" bson:"usage,omitempty"`
	IOStat     []disk.IOCountersStat `json:"iostat,omitempty" bson:"iostat,omitempty"`
	Errors     []string              `json:"errors,omitempty" bson:"errors,omitempty"`
	Base       `json:"metadata,omitempty" bson:"metadata,omitempty"`
	loggable   bool
	rendered   string
}

// CollectSystemInfo returns a populated SystemInfo object,
// without a message.
func CollectSystemInfo() Composer {
	return NewSystemInfo(level.Trace, "")
}

// MakeSystemInfo builds a populated SystemInfo object with the
// specified message.
func MakeSystemInfo(message string) Composer {
	return NewSystemInfo(level.Info, message)
}

// NewSystemInfo returns a fully configured and populated SystemInfo
// object.
func NewSystemInfo(priority level.Priority, message string) Composer {
	var err error
	s := &SystemInfo{
		Message: message,
		NumCPU:  runtime.NumCPU(),
	}

	if err = s.SetPriority(priority); err != nil {
		s.Errors = append(s.Errors, err.Error())
		return s
	}

	s.loggable = true

	times, err := cpu.Times(false)
	s.saveError("cpu_times", err)
	if err == nil && len(times) > 0 {
		// since we're not storing per-core information,
		// there's only one thing we care about in this struct
		s.CPU = times[0]
	}

	percent, err := cpu.Percent(0, false)
	if err != nil {
		s.saveError("cpu_times", err)
	} else {
		s.CPUPercent = percent[0]
	}

	vmstat, err := mem.VirtualMemory()
	s.saveError("vmstat", err)
	if err == nil && vmstat != nil {
		s.VMStat = *vmstat
	}

	netstat, err := net.IOCounters(false)
	s.saveError("netstat", err)
	if err == nil && len(netstat) > 0 {
		s.NetStat = netstat[0]
	}

	partitions, err := disk.Partitions(true)
	s.saveError("disk_part", err)

	if err == nil {
		var u *disk.UsageStat
		for _, p := range partitions {
			u, err = disk.Usage(p.Mountpoint)
			s.saveError("partition", err)
			if err != nil {
				continue
			}

			s.Usage = append(s.Usage, *u)
		}

		s.Partitions = partitions
	}

	iostatMap, err := disk.IOCounters()
	s.saveError("iostat", err)
	for _, stat := range iostatMap {
		s.IOStat = append(s.IOStat, stat)
	}

	return s
}

// Loggable returns true when the Processinfo structure has been
// populated.
func (s *SystemInfo) Loggable() bool { return s.loggable }

// Raw always returns the SystemInfo object, however it will call the
// Collect method of the base operation first.
func (s *SystemInfo) Raw() interface{} { _ = s.Collect(); return s }

// String returns a string representation of the message, lazily
// rendering the message, and caching it privately.
func (s *SystemInfo) String() string {
	if s.rendered == "" {
		s.rendered = renderStatsString(s.Message, s)
	}

	return s.rendered
}

func (s *SystemInfo) saveError(stat string, err error) {
	if shouldSaveError(err) {
		s.Errors = append(s.Errors, fmt.Sprintf("%s: %v", stat, err))
	}
}

// helper function
func shouldSaveError(err error) bool {
	return err != nil && err.Error() != "not implemented yet"
}

func renderStatsString(msg string, data interface{}) string {
	out, err := json.Marshal(data)
	if err != nil {
		return msg
	}

	if msg == "" {
		return string(out)
	}

	return fmt.Sprintf("%s:\n%s", msg, string(out))
}
<|endoftext|>