<commit_before>package golib

import (
	"errors"
	"net"
	"sync"
)

// FirstIpAddress tries to get the main public IP of the local host.
// It iterates all available, enabled network interfaces and looks for the first
// non-local IP address.
func FirstIpAddress() (net.IP, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
			// Loopback and disabled interfaces are not interesting
			continue
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range addrs {
			switch v := addr.(type) {
			case *net.IPNet:
				return v.IP, nil
			case *net.IPAddr:
				return v.IP, nil
			}
		}
	}
	return nil, errors.New("No valid network interfaces found")
}

// ==================== TCP listener task ====================

// TCPConnectionHandler is a callback function for TCPListenerTask, which is
// invoked whenever a new TCP connection is successfully accepted.
type TCPConnectionHandler func(wg *sync.WaitGroup, conn *net.TCPConn)

// TCPListenerTask is an implementation of the Task interface that listens
// for incoming TCP connections on a given TCP endpoint. A handler function
// is invoked for every accepted TCP connection, and an optional hook can be
// executed when the TCP socket is closed and the task stops.
type TCPListenerTask struct {
	*LoopTask

	// ListenEndpoint is the TCP endpoint to open a TCP listening socket on.
	ListenEndpoint string

	// Handler is a required callback-function that will be called for every
	// successfully established TCP connection. It is not called in a separate
	// goroutine, so it should fork a new routine for long-running connections.
	// The handler is always executed while the StopChan in the underlying
	// LoopTask is locked.
	Handler TCPConnectionHandler

	// StopHook is an optional callback that is invoked after the task stops and
	// the listening TCP socket is closed. When StopHook is executed, the underlying
	// LoopTask/StopChan is NOT locked, so helpers methods like Execute() must be used
	// if synchronization is required.
	StopHook func()

	listener *net.TCPListener
}

// String implements the Task interface by returning a descriptive string.
func (task *TCPListenerTask) String() string {
	return "TCP listener " + task.ListenEndpoint
}

// Start implements the Task interface. It opens the TCP listen socket and
// starts accepting incoming connections.
func (task *TCPListenerTask) Start(wg *sync.WaitGroup) StopChan {
	return task.ExtendedStart(nil, wg)
}

// ExtendedStart creates the TCP listen socket and starts accepting incoming connections.
// In addition, a hook function can be defined that will be called once after the
// socket has been opened successfully and is passed the resolved address of the TCP endpoint.
func (task *TCPListenerTask) ExtendedStart(start func(addr net.Addr), wg *sync.WaitGroup) StopChan {
	hook := task.StopHook
	defer func() {
		if hook != nil {
			hook()
		}
	}()
	task.LoopTask = task.listen(wg)

	endpoint, err := net.ResolveTCPAddr("tcp", task.ListenEndpoint)
	if err != nil {
		return NewStoppedChan(err)
	}
	task.listener, err = net.ListenTCP("tcp", endpoint)
	if err != nil {
		return NewStoppedChan(err)
	}
	if start != nil {
		start(task.listener.Addr())
	}
	hook = nil
	return task.LoopTask.Start(wg)
}

func (task *TCPListenerTask) listen(wg *sync.WaitGroup) *LoopTask {
	return &LoopTask{
		Description: "tcp listener on " + task.ListenEndpoint,
		StopHook:    task.StopHook,
		Loop: func(stop StopChan) error {
			if listener := task.listener; listener == nil {
				return StopLoopTask
			} else {
				conn, err := listener.AcceptTCP()
				if err != nil {
					if task.listener != nil {
						Log.Errorln("Error accepting connection:", err)
					}
				} else {
					stop.IfElseStopped(func() {
						_ = conn.Close() // Drop error
					}, func() {
						task.Handler(wg, conn)
					})
				}
			}
			return nil
		},
	}
}

// StopErrFunc extends the StopErrFunc() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) StopErrFunc(perform func() error) {
	task.LoopTask.StopErrFunc(func() error {
		task.stop()
		return perform()
	})
}

// StopFunc extends the StopFunc() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) StopFunc(perform func()) {
	task.LoopTask.StopFunc(func() {
		task.stop()
		perform()
	})
}

// StopErr extends the StopErr() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) StopErr(err error) {
	task.LoopTask.StopErrFunc(func() error {
		task.stop()
		return err
	})
}

// Stop extends the Stop() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) Stop() {
	task.LoopTask.StopFunc(func() {
		task.stop()
	})
}

func (task *TCPListenerTask) stop() {
	if listener := task.listener; listener != nil {
		task.listener = nil  // Will be checked when returning from AcceptTCP()
		_ = listener.Close() // Drop error
	}
}
<commit_msg>Added UDPListenerTask<commit_after>package golib

import (
	"errors"
	"net"
	"sync"
)

// FirstIpAddress tries to get the main public IP of the local host.
// It iterates all available, enabled network interfaces and looks for the first
// non-local IP address.
func FirstIpAddress() (net.IP, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
			// Loopback and disabled interfaces are not interesting
			continue
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range addrs {
			switch v := addr.(type) {
			case *net.IPNet:
				return v.IP, nil
			case *net.IPAddr:
				return v.IP, nil
			}
		}
	}
	return nil, errors.New("No valid network interfaces found")
}

// ==================== TCP listener task ====================

// TCPConnectionHandler is a callback function for TCPListenerTask, which is
// invoked whenever a new TCP connection is successfully accepted.
type TCPConnectionHandler func(wg *sync.WaitGroup, conn *net.TCPConn)

// TCPListenerTask is an implementation of the Task interface that listens
// for incoming TCP connections on a given TCP endpoint. A handler function
// is invoked for every accepted TCP connection, and an optional hook can be
// executed when the TCP socket is closed and the task stops.
type TCPListenerTask struct {
	*LoopTask

	// ListenEndpoint is the TCP endpoint to open a TCP listening socket on.
	ListenEndpoint string

	// Handler is a required callback-function that will be called for every
	// successfully established TCP connection. It is not called in a separate
	// goroutine, so it should fork a new routine for long-running connections.
	// The handler is always executed while the StopChan in the underlying
	// LoopTask is locked.
	Handler TCPConnectionHandler

	// StopHook is an optional callback that is invoked after the task stops and
	// the listening TCP socket is closed. When StopHook is executed, the underlying
	// LoopTask/StopChan is NOT locked, so helpers methods like Execute() must be used
	// if synchronization is required.
	StopHook func()

	listener *net.TCPListener
}

// String implements the Task interface by returning a descriptive string.
func (task *TCPListenerTask) String() string {
	return "TCP listener " + task.ListenEndpoint
}

// Start implements the Task interface. It opens the TCP listen socket and
// starts accepting incoming connections.
func (task *TCPListenerTask) Start(wg *sync.WaitGroup) StopChan {
	return task.ExtendedStart(nil, wg)
}

// ExtendedStart creates the TCP listen socket and starts accepting incoming connections.
// In addition, a hook function can be defined that will be called once after the
// socket has been opened successfully and is passed the resolved address of the TCP endpoint.
func (task *TCPListenerTask) ExtendedStart(start func(addr net.Addr), wg *sync.WaitGroup) StopChan {
	hook := task.StopHook
	defer func() {
		if hook != nil {
			hook()
		}
	}()
	task.LoopTask = task.listen(wg)

	endpoint, err := net.ResolveTCPAddr("tcp", task.ListenEndpoint)
	if err != nil {
		return NewStoppedChan(err)
	}
	task.listener, err = net.ListenTCP("tcp", endpoint)
	if err != nil {
		return NewStoppedChan(err)
	}
	if start != nil {
		start(task.listener.Addr())
	}
	hook = nil
	return task.LoopTask.Start(wg)
}

func (task *TCPListenerTask) listen(wg *sync.WaitGroup) *LoopTask {
	return &LoopTask{
		Description: "tcp listener on " + task.ListenEndpoint,
		StopHook:    task.StopHook,
		Loop: func(stop StopChan) error {
			if listener := task.listener; listener == nil {
				return StopLoopTask
			} else {
				conn, err := listener.AcceptTCP()
				if err != nil {
					if task.listener != nil {
						Log.Errorln("Error accepting connection:", err)
					}
				} else {
					stop.IfElseStopped(func() {
						_ = conn.Close() // Drop error
					}, func() {
						task.Handler(wg, conn)
					})
				}
			}
			return nil
		},
	}
}

// StopErrFunc extends the StopErrFunc() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) StopErrFunc(perform func() error) {
	task.LoopTask.StopErrFunc(func() error {
		task.stop()
		return perform()
	})
}

// StopFunc extends the StopFunc() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) StopFunc(perform func()) {
	task.LoopTask.StopFunc(func() {
		task.stop()
		perform()
	})
}

// StopErr extends the StopErr() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) StopErr(err error) {
	task.LoopTask.StopErrFunc(func() error {
		task.stop()
		return err
	})
}

// Stop extends the Stop() function inherited from LoopTask/StopChan and additionally
// closes the TCP listening socket.
func (task *TCPListenerTask) Stop() {
	task.LoopTask.StopFunc(func() {
		task.stop()
	})
}

func (task *TCPListenerTask) stop() {
	if listener := task.listener; listener != nil {
		task.listener = nil  // Will be checked when returning from AcceptTCP()
		_ = listener.Close() // Drop error
	}
}

// ==================== UDP listener task ====================

var DefaultUdpPacketSize = 2048

// UDPConnectionHandler is a callback function for UDPListenerTask, which is
// invoked whenever a new UDP packet is received.
type UDPPacketHandler func(wg *sync.WaitGroup, localAddr net.Addr, remoteAddr *net.UDPAddr, packet []byte)

// UDPListenerTask is an implementation of the Task interface that listens
// for incoming UDP packets on a given UDP endpoint. A handler function
// is invoked for every received UDP packet, and an optional hook can be
// executed when the UDP socket is closed and the task stops.
type UDPListenerTask struct {
	*LoopTask

	// ListenEndpoint is the UDP endpoint to open a UDP listening socket on.
	ListenEndpoint string

	// Handler is a required callback-function that will be called for every
	// received UDP packet. It is not called in a separate
	// goroutine, so it should fork a new routine for long-running operations.
	// The handler is always executed while the StopChan in the underlying
	// LoopTask is locked.
	Handler UDPPacketHandler

	// StopHook is an optional callback that is invoked after the task stops and
	// the listening UDP socket is closed. When StopHook is executed, the underlying
	// LoopTask/StopChan is NOT locked, so helper methods like Execute() must be used
	// if synchronization is required.
	StopHook func()

	// The size of the buffer to receive UDP packets into. If the buffer size is smaller
	// than incoming packets, the UDPPacketHandler might be invoked multiple times with
	// different UDP packet fragments. The value of DefaultUdpPacketSize is used if this is
	// to <=0.
	PacketBufferSize int

	listener *net.UDPConn
}

// String implements the Task interface by returning a descriptive string.
func (task *UDPListenerTask) String() string {
	return "UDP listener " + task.ListenEndpoint
}

// Start implements the Task interface. It opens the UDP listen socket and
// starts accepting incoming packets.
func (task *UDPListenerTask) Start(wg *sync.WaitGroup) StopChan {
	return task.ExtendedStart(nil, wg)
}

// ExtendedStart creates the UDP listen socket and starts receiving incoming packets.
// In addition, a hook function can be defined that will be called once after the
// socket has been opened successfully and is passed the resolved address of the UDP endpoint.
func (task *UDPListenerTask) ExtendedStart(start func(addr net.Addr), wg *sync.WaitGroup) StopChan {
	hook := task.StopHook
	defer func() {
		if hook != nil {
			hook()
		}
	}()
	task.LoopTask = task.listen(wg)

	endpoint, err := net.ResolveUDPAddr("udp", task.ListenEndpoint)
	if err != nil {
		return NewStoppedChan(err)
	}
	task.listener, err = net.ListenUDP("udp", endpoint)
	if err != nil {
		return NewStoppedChan(err)
	}
	if start != nil {
		start(task.listener.LocalAddr())
	}
	hook = nil
	return task.LoopTask.Start(wg)
}

func (task *UDPListenerTask) listen(wg *sync.WaitGroup) *LoopTask {
	return &LoopTask{
		Description: "udp listener on " + task.ListenEndpoint,
		StopHook:    task.StopHook,
		Loop: func(stop StopChan) error {
			if listener := task.listener; listener == nil {
				return StopLoopTask
			} else {
				// TODO recycle these buffers for performance
				bufLen := task.PacketBufferSize
				if bufLen <= 0 {
					bufLen = DefaultUdpPacketSize
				}
				buf := make([]byte, bufLen)
				num, remoteAddr, err := listener.ReadFromUDP(buf)
				buf = buf[:num]
				if err != nil {
					if task.listener != nil {
						Log.Errorln("Error accepting UDP packet:", err)
					}
				} else {
					stop.IfNotStopped(func() {
						task.Handler(wg, listener.LocalAddr(), remoteAddr, buf)
					})
				}
			}
			return nil
		},
	}
}

// StopErrFunc extends the StopErrFunc() function inherited from LoopTask/StopChan and additionally
// closes the UDP listening socket.
func (task *UDPListenerTask) StopErrFunc(perform func() error) {
	task.LoopTask.StopErrFunc(func() error {
		task.stop()
		return perform()
	})
}

// StopFunc extends the StopFunc() function inherited from LoopTask/StopChan and additionally
// closes the UDP listening socket.
func (task *UDPListenerTask) StopFunc(perform func()) {
	task.LoopTask.StopFunc(func() {
		task.stop()
		perform()
	})
}

// StopErr extends the StopErr() function inherited from LoopTask/StopChan and additionally
// closes the UDP listening socket.
func (task *UDPListenerTask) StopErr(err error) {
	task.LoopTask.StopErrFunc(func() error {
		task.stop()
		return err
	})
}

// Stop extends the Stop() function inherited from LoopTask/StopChan and additionally
// closes the UDP listening socket.
func (task *UDPListenerTask) Stop() {
	task.LoopTask.StopFunc(func() {
		task.stop()
	})
}

func (task *UDPListenerTask) stop() {
	if listener := task.listener; listener != nil {
		task.listener = nil  // Will be checked when returning from AcceptTCP()
		_ = listener.Close() // Drop error
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Che Wei, Lin
//
// 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 tinynet

import (
	"fmt"

	log "github.com/sirupsen/logrus"
)

// HostConfig is a host network configuration
type HostConfig struct {
	name      string
	address   string
	docker    bool
	ifaceName string
	imageRef  string
	mtu       int
}

// NewHostConfig is a constructor to initial host network configuration.
func NewHostConfig(name, addr, ifaceName string, mtu int, docker bool, imageRef string) HostConfig {
	hostConfig := HostConfig{}
	if name == "" {
		panic("Host name is required")
	}
	if addr == "" {
		panic("Host address is required")
	}
	hostConfig.name = name
	hostConfig.address = addr
	hostConfig.docker = docker
	hostConfig.ifaceName = ifaceName
	if ifaceName == "" {
		hostConfig.ifaceName = "eth1"
	}
	hostConfig.imageRef = imageRef
	if imageRef == "" {
		hostConfig.imageRef = "library/busybox"
	}
	hostConfig.mtu = mtu
	if mtu == 0 {
		hostConfig.mtu = 1500
	}
	return hostConfig
}

// AddHostWithConf will add a host to topology.
func AddHostWithConf(hc hostConfig) (*Host, error) {
	var h *Host
	var err error
	if hc.docker {
		// Create a docker container
		h, err = NewContainer(hc.name, hc.imageRef)
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(hc.name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth(hc.ifaceName, hc.mtu)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(hc.address)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddHost will add a host to topology. set docker to true can enable docker container as a host
func AddHost(name string, addr string, docker bool) (*Host, error) {
	log.Warnf("Will be deprecated: use AddHostWithConf instead")
	var h *Host
	var err error
	if docker {
		// Create a docker container
		h, err = NewContainer(name, "library/busybox")
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth("eth2", 1500)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(addr)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddSwitch will add a switch to topology.
func AddSwitch(params ...string) (*OVSSwitch, error) {
	// params[0] for brName
	// params[1] for controller remote IP and port
	// Create a Open vSwitch bridge
	sw, err := NewOVSSwitch(params[0])
	if err != nil {
		log.Fatal("failed to NewOVSSwitch: ", err)
	}
	if len(params) == 2 {
		if err := sw.SetCtrl(params[1]); err != nil {
			log.Warnf("failed to SetCtrl for %s: %v", sw.BridgeName, err)
			return nil, err
		}
	} else if len(params) > 2 {
		return nil, fmt.Errorf("Too many arguments")
	}
	return sw, nil
}

// AddLink will add a link between switch to switch or host to switch.
func AddLink(n1, n2 interface{}) error {
	// log.Info(n1.(*OVSSwitch).nodeType)
	// log.Info(n2.(*Host).nodeType)
	var err error
	switch n1.(type) {
	case *OVSSwitch:
		switch n2.(type) {
		case *OVSSwitch:
			tap0, tap1, err := makeVethPair("tap0", "tap1")
			if err != nil {
				log.Fatalf("failed to makeVethPair: %v", err)
			}
			err = n1.(*OVSSwitch).addPort(tap0.Name)
			if err != nil {
				log.Fatalf("failed to addPortswitch - switch: %v", err)
			}
			err = n2.(*OVSSwitch).addPort(tap1.Name)
			if err != nil {
				log.Fatalf("failed to addPort switch - switch: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*OVSSwitch).BridgeName)
		case *Host:
			err = n1.(*OVSSwitch).addPort(n2.(*Host).vethName)
			if err != nil {
				log.Fatalf("failed to addPort switch - host: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*Host).Name)
		default:
			log.Fatalf("Type Error")
		}
	case *Host:
		switch n2.(type) {
		case *OVSSwitch:
			err = n2.(*OVSSwitch).addPort(n1.(*Host).vethName)
			if err != nil {
				log.Fatalf("failed to addPort host - switch : %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*Host).Name, n2.(*OVSSwitch).BridgeName)
		case *Host:
			log.Fatalf("Type Error: host can not connect to host")
		default:
			log.Fatalf("Type Error")
		}
	default:
		log.Fatalf("Type Error")
	}
	return nil
}

// GetIPs will get IP address from a CIDR notation
// Return an array with IP address. negative num for getting all IP addresses
// (network address and broadcast address are not included)
func GetIPs(cidr string, num int) ([]string, error) {
	ips, err := getAllIPsfromCIDR(cidr)
	if err != nil {
		return nil, err
	}
	if num < 0 {
		return ips, nil
	}
	return ips[0:num], nil
}
<commit_msg>fixed variable name<commit_after>// Copyright (c) 2017 Che Wei, Lin
//
// 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 tinynet

import (
	"fmt"

	log "github.com/sirupsen/logrus"
)

// HostConfig is a host network configuration
type HostConfig struct {
	name      string
	address   string
	docker    bool
	ifaceName string
	imageRef  string
	mtu       int
}

// NewHostConfig is a constructor to initial host network configuration.
func NewHostConfig(name, addr, ifaceName string, mtu int, docker bool, imageRef string) HostConfig {
	hostConfig := HostConfig{}
	if name == "" {
		panic("Host name is required")
	}
	if addr == "" {
		panic("Host address is required")
	}
	hostConfig.name = name
	hostConfig.address = addr
	hostConfig.docker = docker
	hostConfig.ifaceName = ifaceName
	if ifaceName == "" {
		hostConfig.ifaceName = "eth1"
	}
	hostConfig.imageRef = imageRef
	if imageRef == "" {
		hostConfig.imageRef = "library/busybox"
	}
	hostConfig.mtu = mtu
	if mtu == 0 {
		hostConfig.mtu = 1500
	}
	return hostConfig
}

// AddHostWithConf will add a host to topology.
func AddHostWithConf(hc hostConfig) (*Host, error) {
	var h *Host
	var err error
	if hc.docker {
		// Create a docker container
		h, err = NewContainer(hc.name, hc.imageRef)
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(hc.name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth(hc.ifaceName, hc.mtu)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(hc.address)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddHost will add a host to topology. set docker to true can enable docker container as a host
func AddHost(name string, addr string, docker bool) (*Host, error) {
	log.Warnf("Will be deprecated: use AddHostWithConf instead")
	var h *Host
	var err error
	if docker {
		// Create a docker container
		h, err = NewContainer(name, "library/busybox")
		if err != nil {
			log.Fatal("failed to NewContainer: ", err)
		}
	} else {
		// Create a network namespace
		h, err = NewHost(name)
		if err != nil {
			log.Fatal("failed to NewHost: ", err)
		}
	}
	// setup a veth pair
	_, err = h.setupVeth("eth2", 1500)
	if err != nil {
		log.Fatal("failed to setup veth pair: ", err)
	}
	// setup a IP for host
	h.setIfaceIP(addr)
	if err != nil {
		log.Fatalf("failed to setIfaceIP for %s: %v", h.Name, err)
		return nil, err
	}
	return h, nil
}

// AddSwitch will add a switch to topology.
func AddSwitch(params ...string) (*OVSSwitch, error) {
	// params[0] for brName
	// params[1] for controller remote IP and port
	// Create a Open vSwitch bridge
	sw, err := NewOVSSwitch(params[0])
	if err != nil {
		log.Fatal("failed to NewOVSSwitch: ", err)
	}
	if len(params) == 2 {
		if err := sw.SetCtrl(params[1]); err != nil {
			log.Warnf("failed to SetCtrl for %s: %v", sw.BridgeName, err)
			return nil, err
		}
	} else if len(params) > 2 {
		return nil, fmt.Errorf("Too many arguments")
	}
	return sw, nil
}

// AddLink will add a link between switch to switch or host to switch.
func AddLink(n1, n2 interface{}) error {
	// log.Info(n1.(*OVSSwitch).nodeType)
	// log.Info(n2.(*Host).nodeType)
	var err error
	switch n1.(type) {
	case *OVSSwitch:
		switch n2.(type) {
		case *OVSSwitch:
			tap0, tap1, err := makeVethPair("tap0", "tap1")
			if err != nil {
				log.Fatalf("failed to makeVethPair: %v", err)
			}
			err = n1.(*OVSSwitch).addPort(tap0.Name)
			if err != nil {
				log.Fatalf("failed to addPortswitch - switch: %v", err)
			}
			err = n2.(*OVSSwitch).addPort(tap1.Name)
			if err != nil {
				log.Fatalf("failed to addPort switch - switch: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*OVSSwitch).BridgeName)
		case *Host:
			err = n1.(*OVSSwitch).addPort(n2.(*Host).VethName)
			if err != nil {
				log.Fatalf("failed to addPort switch - host: %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*OVSSwitch).BridgeName, n2.(*Host).Name)
		default:
			log.Fatalf("Type Error")
		}
	case *Host:
		switch n2.(type) {
		case *OVSSwitch:
			err = n2.(*OVSSwitch).addPort(n1.(*Host).VethName)
			if err != nil {
				log.Fatalf("failed to addPort host - switch : %v", err)
			}
			log.Infof("Adding a link: (%s, %s)", n1.(*Host).Name, n2.(*OVSSwitch).BridgeName)
		case *Host:
			log.Fatalf("Type Error: host can not connect to host")
		default:
			log.Fatalf("Type Error")
		}
	default:
		log.Fatalf("Type Error")
	}
	return nil
}

// GetIPs will get IP address from a CIDR notation
// Return an array with IP address. negative num for getting all IP addresses
// (network address and broadcast address are not included)
func GetIPs(cidr string, num int) ([]string, error) {
	ips, err := getAllIPsfromCIDR(cidr)
	if err != nil {
		return nil, err
	}
	if num < 0 {
		return ips, nil
	}
	return ips[0:num], nil
}
<|endoftext|>


<commit_before>/*
Serve is a very simple static file server in go
Usage:
	-p="8100": port to serve on
	-d=".":    the directory of static files to host

Navigating to http://localhost:8100 will display the index.html or directory
listing file.
*/
package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
)

const videoPath string = "/home/kestein/Videos"

func play(w http.ResponseWriter, req *http.Request) {
	if len(req.URL.Path) == 1 {
		dir, err := os.Open(videoPath)
		if err != nil {
			log.Fatal("WRONG %s", err)
		}
		files, err := dir.Readdir(0)
		if err != nil {
			log.Fatal("WRONG %s", err)
		}
		for i := 0; i < len(files); i++ {
			vid := fmt.Sprintf("%s", files[i].Name())
			url := fmt.Sprintf("%s\n", url.QueryEscape(vid), vid)
			io.WriteString(w, url)
		}
	} else {
		// Take everything after the '/' and play it in VLC
		rawVideo := string(req.URL.Path[1:])
		video, err := url.QueryUnescape(rawVideo)
		if err != nil {
			fmt.Println("WRONG")
		}
		cartoon := exec.Command("vlc", "-f", fmt.Sprintf("%s/%s", videoPath, video))
		err = cartoon.Start()
		if err != nil {
			log.Fatal("WRONG")
		}
	}
}

func main() {
	port := flag.String("p", "8100", "port to serve on")
	directory := flag.String("d", ".", "the directory of static file to host")
	flag.Parse()

	http.HandleFunc("/", play)

	log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
	log.Fatal(http.ListenAndServe("localhost:"+*port, nil))
}
<commit_msg>Make REST api<commit_after>/*
Serve is a very simple static file server in go
Usage:
	-p="8100": port to serve on
	-d=".":    the directory of static files to host

Navigating to http://localhost:8100 will display the index.html or directory
listing file.
*/
package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	//"os/exec"
)

const videoPath string = "/home/kestein/Videos"

func list(w http.ResponseWriter, req *http.Request) {
	dir, err := os.Open(videoPath)
	if err != nil {
		log.Fatal("Unable to open video path %s", err)
	}
	files, err := dir.Readdir(0)
	if err != nil {
		log.Fatal("Unable to read dir %s", err)
	}
	io.WriteString(w, "
\n")
	for i := 0; i < len(files); i++ {
		vid := fmt.Sprintf("%s", files[i].Name())
		url := fmt.Sprintf("
%s
\n", url.QueryEscape(vid), vid)
		io.WriteString(w, url)
	}
	io.WriteString(w, "
\n")
}

func play(w http.ResponseWriter, req *http.Request) {
	// Take everything after the '/' and play it in VLC
	/*rawVideo := string(req.URL.Path[1:])
	video, err := url.QueryUnescape(rawVideo)
	if err != nil {
		fmt.Println("WRONG")
	}
	cartoon := exec.Command("vlc", "-f", fmt.Sprintf("%s/%s", videoPath, video))
	err = cartoon.Start()
	if err != nil {
		log.Fatal("WRONG")
	}*/
	fmt.Println("asdf")
}

func main() {
	port := flag.String("p", "8100", "port to serve on")
	directory := flag.String("d", ".", "the directory of static file to host")
	flag.Parse()

	http.Handle("/", http.StripPrefix("/", http.HandlerFunc(list)))
	http.Handle("/list/", http.StripPrefix("/list/", http.HandlerFunc(list)))
	http.Handle("/play/", http.StripPrefix("/play/", http.HandlerFunc(play)))

	log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
	log.Fatal(http.ListenAndServe("localhost:"+*port, nil))
}
<|endoftext|>


<commit_before>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gltext

import (
	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
)

var fontVertexShaderSource string = `
#version 330

uniform mat4 scale_matrix;
uniform mat4 orthographic_matrix;
uniform vec2 final_position;

in vec4 centered_position;
in vec2 uv;

out vec2 fragment_uv;

// The orthographic projection uses a lower left-hand point of (0,0)
// 1) We center the text on screen.
// 2) We perform othographic transformation and then scaling.
// 3) We move the text to its final resting place.
// This is all pretty standard I would imagine, but it took me a bit to sort out what has to happen :P

void main() {
  fragment_uv = uv;
  vec4 scaled = scale_matrix * orthographic_matrix * centered_position;
  gl_Position = vec4(scaled.x + final_position.x, scaled.y + final_position.y, scaled.z, scaled.w);
}
` + "\x00"

var fontFragmentShaderSource string = `
#version 330

uniform sampler2D fragment_texture;
uniform float text_lowerbound;
uniform vec4 fragment_color_adjustment;

in vec2 fragment_uv;
out vec4 fragment_color;

void main() {
  vec4 color     = texture(fragment_texture, fragment_uv);
  color.xyz      = fragment_color_adjustment.xyz;
  fragment_color = color;
}
` + "\x00"

type Font struct {
	Config         *FontConfig // Character set for this font.
	textureID      uint32      // Holds the glyph texture id.
	maxGlyphWidth  int         // Largest glyph width.
	maxGlyphHeight int         // Largest glyph height.
	program        uint32      // program compiled from shaders

	// attributes
	centeredPosition uint32 // vertex centered_position required for scaling around the orthographic projections center
	uv               uint32 // texture position

	// The final screen position post-scaling
	finalPositionUniform int32

	// Position of the shaders fragment texture variable
	fragmentTextureUniform int32

	// The desired color of the text
	colorUniform int32

	// View matrix
	orthographicMatrixUniform int32
	OrthographicMatrix        mgl32.Mat4

	// Scale the resulting text
	scaleMatrixUniform int32

	textureWidth  float32
	textureHeight float32
	WindowWidth   float32
	WindowHeight  float32
}

func NewFont(config *FontConfig) (f *Font, err error) {
	f = &Font{}
	f.Config = config

	// Resize image to next power-of-two.
	// config.Image = Pow2Image(config.Image).(*image.RGBA)
	ib := config.Image.Bounds()

	f.textureWidth = float32(ib.Dx())
	f.textureHeight = float32(ib.Dy())

	for _, glyph := range config.Glyphs {
		if glyph.Width > f.maxGlyphWidth {
			f.maxGlyphWidth = glyph.Width
		}
		if glyph.Height > f.maxGlyphHeight {
			f.maxGlyphHeight = glyph.Height
		}
	}

	// save to disk for testing
	if IsDebug {
		err = SaveImage(".", config.Image)
		if err != nil {
			return f, err
		}
	}

	// generate texture
	gl.GenTextures(1, &f.textureID)
	gl.BindTexture(gl.TEXTURE_2D, f.textureID)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0,
		gl.RGBA,
		int32(ib.Dx()),
		int32(ib.Dy()),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(config.Image.Pix),
	)
	gl.BindTexture(gl.TEXTURE_2D, 0)

	// create shader program and define attributes and uniforms
	f.program, err = NewProgram(fontVertexShaderSource, fontFragmentShaderSource)
	if err != nil {
		return f, err
	}

	// attributes
	f.centeredPosition = uint32(gl.GetAttribLocation(f.program, gl.Str("centered_position\x00")))
	f.uv = uint32(gl.GetAttribLocation(f.program, gl.Str("uv\x00")))

	// uniforms
	f.finalPositionUniform = gl.GetUniformLocation(f.program, gl.Str("final_position\x00"))
	f.orthographicMatrixUniform = gl.GetUniformLocation(f.program, gl.Str("orthographic_matrix\x00"))
	f.scaleMatrixUniform = gl.GetUniformLocation(f.program, gl.Str("scale_matrix\x00"))
	f.fragmentTextureUniform = gl.GetUniformLocation(f.program, gl.Str("fragment_texture\x00"))
	f.colorUniform = gl.GetUniformLocation(f.program, gl.Str("fragment_color_adjustment\x00"))

	return f, nil
}

func (f *Font) ResizeWindow(width float32, height float32) {
	f.WindowWidth = width
	f.WindowHeight = height
	f.OrthographicMatrix = mgl32.Ortho2D(-f.WindowWidth/2, f.WindowWidth/2, -f.WindowHeight/2, f.WindowHeight/2)
}

func (f *Font) Release() {
	gl.DeleteTextures(1, &f.textureID)
}
<commit_msg>Not sure if this is really necessary.  Need to look into why power of 2 sizing is best.<commit_after>// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gltext

import (
	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
	"image"
)

var fontVertexShaderSource string = `
#version 330

uniform mat4 scale_matrix;
uniform mat4 orthographic_matrix;
uniform vec2 final_position;

in vec4 centered_position;
in vec2 uv;

out vec2 fragment_uv;

// The orthographic projection uses a lower left-hand point of (0,0)
// 1) We center the text on screen.
// 2) We perform othographic transformation and then scaling.
// 3) We move the text to its final resting place.
// This is all pretty standard I would imagine, but it took me a bit to sort out what has to happen :P

void main() {
  fragment_uv = uv;
  vec4 scaled = scale_matrix * orthographic_matrix * centered_position;
  gl_Position = vec4(scaled.x + final_position.x, scaled.y + final_position.y, scaled.z, scaled.w);
}
` + "\x00"

var fontFragmentShaderSource string = `
#version 330

uniform sampler2D fragment_texture;
uniform float text_lowerbound;
uniform vec4 fragment_color_adjustment;

in vec2 fragment_uv;
out vec4 fragment_color;

void main() {
  vec4 color     = texture(fragment_texture, fragment_uv);
  color.xyz      = fragment_color_adjustment.xyz;
  fragment_color = color;
}
` + "\x00"

type Font struct {
	Config         *FontConfig // Character set for this font.
	textureID      uint32      // Holds the glyph texture id.
	maxGlyphWidth  int         // Largest glyph width.
	maxGlyphHeight int         // Largest glyph height.
	program        uint32      // program compiled from shaders

	// attributes
	centeredPosition uint32 // vertex centered_position required for scaling around the orthographic projections center
	uv               uint32 // texture position

	// The final screen position post-scaling
	finalPositionUniform int32

	// Position of the shaders fragment texture variable
	fragmentTextureUniform int32

	// The desired color of the text
	colorUniform int32

	// View matrix
	orthographicMatrixUniform int32
	OrthographicMatrix        mgl32.Mat4

	// Scale the resulting text
	scaleMatrixUniform int32

	textureWidth  float32
	textureHeight float32
	WindowWidth   float32
	WindowHeight  float32
}

func NewFont(config *FontConfig) (f *Font, err error) {
	f = &Font{}
	f.Config = config

	// Resize image to next power-of-two.
	config.Image = Pow2Image(config.Image).(*image.NRGBA)
	ib := config.Image.Bounds()

	f.textureWidth = float32(ib.Dx())
	f.textureHeight = float32(ib.Dy())

	for _, glyph := range config.Glyphs {
		if glyph.Width > f.maxGlyphWidth {
			f.maxGlyphWidth = glyph.Width
		}
		if glyph.Height > f.maxGlyphHeight {
			f.maxGlyphHeight = glyph.Height
		}
	}

	// save to disk for testing
	if IsDebug {
		err = SaveImage(".", config.Image)
		if err != nil {
			return f, err
		}
	}

	// generate texture
	gl.GenTextures(1, &f.textureID)
	gl.BindTexture(gl.TEXTURE_2D, f.textureID)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexImage2D(
		gl.TEXTURE_2D,
		0,
		gl.RGBA,
		int32(ib.Dx()),
		int32(ib.Dy()),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(config.Image.Pix),
	)
	gl.BindTexture(gl.TEXTURE_2D, 0)

	// create shader program and define attributes and uniforms
	f.program, err = NewProgram(fontVertexShaderSource, fontFragmentShaderSource)
	if err != nil {
		return f, err
	}

	// attributes
	f.centeredPosition = uint32(gl.GetAttribLocation(f.program, gl.Str("centered_position\x00")))
	f.uv = uint32(gl.GetAttribLocation(f.program, gl.Str("uv\x00")))

	// uniforms
	f.finalPositionUniform = gl.GetUniformLocation(f.program, gl.Str("final_position\x00"))
	f.orthographicMatrixUniform = gl.GetUniformLocation(f.program, gl.Str("orthographic_matrix\x00"))
	f.scaleMatrixUniform = gl.GetUniformLocation(f.program, gl.Str("scale_matrix\x00"))
	f.fragmentTextureUniform = gl.GetUniformLocation(f.program, gl.Str("fragment_texture\x00"))
	f.colorUniform = gl.GetUniformLocation(f.program, gl.Str("fragment_color_adjustment\x00"))

	return f, nil
}

func (f *Font) ResizeWindow(width float32, height float32) {
	f.WindowWidth = width
	f.WindowHeight = height
	f.OrthographicMatrix = mgl32.Ortho2D(-f.WindowWidth/2, f.WindowWidth/2, -f.WindowHeight/2, f.WindowHeight/2)
}

func (f *Font) Release() {
	gl.DeleteTextures(1, &f.textureID)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

var (
	LSBLK_CMD = `lsblk -f -a -p --pairs -n -b -o NAME,FSTYPE,MOUNTPOINT,LABEL,UUID,PARTLABEL,PARTUUID,SIZE,TYPE`
	LSBLK_RX  = regexp.MustCompile(`(\w+)=(?:"(.*?)")`)
)

const (
	_             = iota
	KBYTE float64 = 1 << (10 * iota)
	MBYTE
	GBYTE
	TBYTE
)

type Disk struct {
	Name    string
	Size    string
	SizeH   string
	Volumes Volumes
	HasLUKS bool
}

type Volume struct {
	Name       string
	Fstype     string
	IsLUKS     bool
	Mountpoint string
	IsMounted  bool
	Label      string
	Uuid       string
	Partlabel  string
	Partuuid   string
	Size       string
	SizeH      string
	Type       string
}

type Volumes []Volume

func lsdsk() []Disk {
	disks := make([]Disk, 0)

	var disk Disk
	for _, volume := range lsblk() {
		if volume.Type == "disk" {
			// add new disk
			disk = Disk{
				Name:    volume.Name,
				Size:    volume.Size,
				SizeH:   volume.SizeH,
				Volumes: make([]Volume, 0),
			}
			disks = append(disks, disk)
		} else {
			// add volume to disk
			if volume.Fstype == "crypto_LUKS" {
				disks[len(disks)-1].HasLUKS = true
				volume.IsLUKS = true
			}
			disks[len(disks)-1].Volumes = append(disks[len(disks)-1].Volumes, volume)
		}
	}

	return disks
}

func lsblk() (volumes Volumes) {
	for _, line := range strings.Split(system(LSBLK_CMD), "\n") {
		line = strings.Trim(line, "\t\n\r ")
		if line == "" {
			continue
		}

		volume := Volume{}
		vol := reflect.ValueOf(&volume).Elem()

		pairs := LSBLK_RX.FindAllStringSubmatch(line, -1)
		for _, pair := range pairs {
			if len(pair) != 3 {
				continue
			}

			key, value := strings.Title(strings.ToLower(pair[1])), pair[2]
			field := vol.FieldByName(key)
			if field.IsValid() {
				field.SetString(value)
				if key == "Size" {
					if size, err := formatByteSize(value); err == nil {
						volume.SizeH = size
					}
				}
			}
		}

		volume.IsMounted = volume.Mountpoint != "" // TODO: this is not correct for LUKS encrypted volumes! BUG: fix this!
		volumes = append(volumes, volume)
	}

	return
}

func formatByteSize(value string) (string, error) {
	size, err := strconv.ParseFloat(value, 64)
	if err != nil {
		return "", err
	}

	switch {
	case size >= TBYTE:
		return fmt.Sprintf("%.1fT", size/TBYTE), nil
	case size >= GBYTE:
		return fmt.Sprintf("%.1fG", size/GBYTE), nil
	case size >= MBYTE:
		return fmt.Sprintf("%.1fM", size/MBYTE), nil
	case size >= KBYTE:
		return fmt.Sprintf("%.1fK", size/KBYTE), nil
	}

	return fmt.Sprintf("%.1fB", size), nil
}

func (volumes *Volumes) filter(predicate func(Volume) bool) *Volumes {
	var newVolumes Volumes
	for _, volume := range *volumes {
		if predicate(volume) {
			newVolumes = append(newVolumes, volume)
		}
	}
	return &newVolumes
}

func (volumes *Volumes) luksOnly() *Volumes {
	return volumes.filter(func(v Volume) bool {
		return v.IsLUKS
	})
}

func (volumes *Volumes) mounted() *Volumes {
	return volumes.filter(func(v Volume) bool {
		return v.IsMounted
	})
}

func (volumes *Volumes) unmounted() *Volumes {
	return volumes.filter(func(v Volume) bool {
		return !v.IsMounted
	})
}
<commit_msg>wip, fix LUKS listing<commit_after>package main

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"
	"strings"
)

var (
	LSBLK_CMD = `lsblk -f -a -p --pairs -n -b -o NAME,FSTYPE,MOUNTPOINT,LABEL,UUID,PARTLABEL,PARTUUID,SIZE,TYPE`
	LSBLK_RX  = regexp.MustCompile(`(\w+)=(?:"(.*?)")`)
)

const (
	_             = iota
	KBYTE float64 = 1 << (10 * iota)
	MBYTE
	GBYTE
	TBYTE
)

type Disk struct {
	Name    string
	Size    string
	SizeH   string
	Volumes Volumes
	HasLUKS bool
}

type Volume struct {
	Name       string
	Fstype     string
	IsLUKS     bool
	Mountpoint string
	IsMounted  bool
	Label      string
	Uuid       string
	Partlabel  string
	Partuuid   string
	Size       string
	SizeH      string
	Type       string
}

type Volumes []Volume

func lsdsk() []Disk {
	disks := make([]Disk, 0)

	var disk Disk
	for _, volume := range lsblk() {
		if volume.Type == "disk" {
			// add new disk
			disk = Disk{
				Name:    volume.Name,
				Size:    volume.Size,
				SizeH:   volume.SizeH,
				Volumes: make([]Volume, 0),
			}
			disks = append(disks, disk)
		} else {
			// add volume to disk
			// TODO: if crypto_LUKS, then check the volume that follows if it is type "crypt" and was mounted from this one (/dev/mapper/*)
			if volume.Fstype == "crypto_LUKS" || volume.Type == "crypt" {
				disks[len(disks)-1].HasLUKS = true
				volume.IsLUKS = true
			}
			disks[len(disks)-1].Volumes = append(disks[len(disks)-1].Volumes, volume)
		}
	}

	return disks
}

func lsblk() (volumes Volumes) {
	for _, line := range strings.Split(system(LSBLK_CMD), "\n") {
		line = strings.Trim(line, "\t\n\r ")
		if line == "" {
			continue
		}

		volume := Volume{}
		vol := reflect.ValueOf(&volume).Elem()

		pairs := LSBLK_RX.FindAllStringSubmatch(line, -1)
		for _, pair := range pairs {
			if len(pair) != 3 {
				continue
			}

			key, value := strings.Title(strings.ToLower(pair[1])), pair[2]
			field := vol.FieldByName(key)
			if field.IsValid() {
				field.SetString(value)
				if key == "Size" {
					if size, err := formatByteSize(value); err == nil {
						volume.SizeH = size
					}
				}
			}
		}

		volume.IsMounted = volume.Mountpoint != ""
		volumes = append(volumes, volume)
	}

	return
}

func formatByteSize(value string) (string, error) {
	size, err := strconv.ParseFloat(value, 64)
	if err != nil {
		return "", err
	}

	switch {
	case size >= TBYTE:
		return fmt.Sprintf("%.1fT", size/TBYTE), nil
	case size >= GBYTE:
		return fmt.Sprintf("%.1fG", size/GBYTE), nil
	case size >= MBYTE:
		return fmt.Sprintf("%.1fM", size/MBYTE), nil
	case size >= KBYTE:
		return fmt.Sprintf("%.1fK", size/KBYTE), nil
	}

	return fmt.Sprintf("%.1fB", size), nil
}

func (volumes *Volumes) filter(predicate func(Volume) bool) *Volumes {
	var newVolumes Volumes
	for _, volume := range *volumes {
		if predicate(volume) {
			newVolumes = append(newVolumes, volume)
		}
	}
	return &newVolumes
}

func (volumes *Volumes) luksOnly() *Volumes {
	return volumes.filter(func(v Volume) bool {
		return v.IsLUKS
	})
}

func (volumes *Volumes) mounted() *Volumes {
	return volumes.filter(func(v Volume) bool {
		return v.IsMounted
	})
}

func (volumes *Volumes) unmounted() *Volumes {
	return volumes.filter(func(v Volume) bool {
		return !v.IsMounted
	})
}
<|endoftext|>


<commit_before>package server

import (
	"errors"
	"github.com/Comcast/webpa-common/concurrent"
	"github.com/Comcast/webpa-common/health"
	"github.com/Comcast/webpa-common/logging"
	"github.com/Comcast/webpa-common/logging/golog"
	"net/http"
	"sync"
	"time"
)

var (
	// ErrorNoPrimaryAddress is the error returned when no primary address is specified in a WebPA instance
	ErrorNoPrimaryAddress = errors.New("No primary address configured")
)

// executor is an internal type used to start an HTTP server.  *http.Server implements
// this interface.  It can be mocked for testing.
type executor interface {
	ListenAndServe() error
	ListenAndServeTLS(certificateFile, keyFile string) error
}

// Secure exposes the optional certificate information to be used when starting an HTTP server.
type Secure interface {
	// Certificate returns the certificate information associated with this Secure instance.
	// BOTH the returned file paths must be non-empty if a TLS server is desired.
	Certificate() (certificateFile, keyFile string)
}

// ListenAndServe invokes the appropriate server method based on the secure information.
// If Secure.Certificate() returns both a certificateFile and a keyFile, e.ListenAndServeTLS()
// is called to start the server.  Otherwise, e.ListenAndServe() is used.
func ListenAndServe(logger logging.Logger, s Secure, e executor) {
	certificateFile, keyFile := s.Certificate()
	if len(certificateFile) > 0 && len(keyFile) > 0 {
		go func() {
			logger.Error(
				e.ListenAndServeTLS(certificateFile, keyFile),
			)
		}()
	} else {
		go func() {
			logger.Error(
				e.ListenAndServe(),
			)
		}()
	}
}

// Basic describes a simple HTTP server.  Typically, this struct has its values
// injected via Viper.  See the New function in this package.
type Basic struct {
	Name               string
	Address            string
	CertificateFile    string
	KeyFile            string
	LogConnectionState bool
}

func (b *Basic) Certificate() (certificateFile, keyFile string) {
	return b.CertificateFile, b.KeyFile
}

// New creates an http.Server using this instance's configuration.  The given logger is required,
// but the handler may be nil.  If the handler is nil, http.DefaultServeMux is used, which matches
// the behavior of http.Server.
//
// This method returns nil if the configured address is empty, effectively disabling
// this server from startup.
func (b *Basic) New(logger logging.Logger, handler http.Handler) *http.Server {
	if len(b.Address) == 0 {
		return nil
	}

	server := &http.Server{
		Addr:     b.Address,
		Handler:  handler,
		ErrorLog: NewErrorLog(b.Name, logger),
	}

	if b.LogConnectionState {
		server.ConnState = NewConnectionStateLogger(b.Name, logger)
	}

	return server
}

// Health represents a configurable factory for a Health server.
//
// Due to a limitation of Viper, this struct does not use an embedded Basic
// instance.  Rather, it duplicates the fields so that Viper can inject them.
type Health struct {
	Name               string
	Address            string
	CertificateFile    string
	KeyFile            string
	LogConnectionState bool
	LogInterval        time.Duration
	Options            []string
}

func (h *Health) Certificate() (certificateFile, keyFile string) {
	return h.CertificateFile, h.KeyFile
}

// New creates both a health.Health monitor (which is also an HTTP handler) and an HTTP server
// which services health requests.
//
// This method returns nils if the configured Address is empty, which effectively disables
// the health server.
func (h *Health) New(logger logging.Logger) (handler *health.Health, server *http.Server) {
	if len(h.Address) == 0 {
		return
	}

	options := make([]health.Option, 0, len(h.Options))
	for _, value := range h.Options {
		options = append(options, health.Stat(value))
	}

	handler = health.New(
		h.LogInterval,
		logger,
		options...,
	)

	mux := http.NewServeMux()
	mux.Handle("/health", handler)

	server = &http.Server{
		Addr:     h.Address,
		Handler:  mux,
//		Handler:  handler,
		ErrorLog: NewErrorLog(h.Name, logger),
	}

	if h.LogConnectionState {
		server.ConnState = NewConnectionStateLogger(h.Name, logger)
	}

	return
}

// WebPA represents a server component within the WebPA cluster.  It is used for both
// primary servers (e.g. petasos) and supporting, embedded servers such as pprof.
type WebPA struct {
	// Primary is the main server for this application, e.g. petasos.
	Primary Basic

	// Alternate is an alternate server which serves the primary application logic.
	// Used to have the same API served on more than one port and possibly more than
	// one protocol, e.g. HTTP and HTTPS.
	Alternate Basic

	// Health describes the health server for this application.  Note that if the Address
	// is empty, no health server is started.
	Health Health

	// Pprof describes the pprof server for this application.  Note that if the Address
	// is empty, no pprof server is started.
	Pprof Basic

	// Log is the logging configuration for this application.
	Log golog.LoggerFactory
}

// Prepare gets a WebPA server ready for execution.  This method does not return errors, but the returned
// Runnable may return an error.  The supplied logger will usually come from the New function, but the
// WebPA.Log object can be used to create a different logger if desired.
//
// The supplied http.Handler is used for the primary server.  If the alternate server has an address,
// it will also be used for that server.  The health server uses an internally create handler, while the pprof
// server uses http.DefaultServeMux.  The health Monitor created from configuration is returned so that other
// infrastructure can make use of it.
func (w *WebPA) Prepare(logger logging.Logger, primaryHandler http.Handler) (health.Monitor, concurrent.Runnable) {
	healthHandler, healthServer := w.Health.New(logger)
	return healthHandler, concurrent.RunnableFunc(func(waitGroup *sync.WaitGroup, shutdown <-chan struct{}) error {
		if healthHandler != nil && healthServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Health.Name, w.Health.Address)
			ListenAndServe(logger, &w.Health, healthServer)
			healthHandler.Run(waitGroup, shutdown)

			// wrap the primary handler in the RequestTracker decorator
			primaryHandler = healthHandler.RequestTracker(primaryHandler)
		}

		if pprofServer := w.Pprof.New(logger, nil); pprofServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Pprof.Name, w.Pprof.Address)
			ListenAndServe(logger, &w.Pprof, pprofServer)
		}

		if primaryServer := w.Primary.New(logger, primaryHandler); primaryServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Primary.Name, w.Primary.Address)
			ListenAndServe(logger, &w.Primary, primaryServer)
		} else {
			return ErrorNoPrimaryAddress
		}

		if alternateServer := w.Alternate.New(logger, primaryHandler); alternateServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Alternate.Name, w.Alternate.Address)
			ListenAndServe(logger, &w.Alternate, alternateServer)
		}

		return nil
	})
}
<commit_msg>Fixed the commented out handler<commit_after>package server

import (
	"errors"
	"net/http"
	"sync"
	"time"

	"github.com/Comcast/webpa-common/concurrent"
	"github.com/Comcast/webpa-common/health"
	"github.com/Comcast/webpa-common/logging"
	"github.com/Comcast/webpa-common/logging/golog"
)

var (
	// ErrorNoPrimaryAddress is the error returned when no primary address is specified in a WebPA instance
	ErrorNoPrimaryAddress = errors.New("No primary address configured")
)

// executor is an internal type used to start an HTTP server.  *http.Server implements
// this interface.  It can be mocked for testing.
type executor interface {
	ListenAndServe() error
	ListenAndServeTLS(certificateFile, keyFile string) error
}

// Secure exposes the optional certificate information to be used when starting an HTTP server.
type Secure interface {
	// Certificate returns the certificate information associated with this Secure instance.
	// BOTH the returned file paths must be non-empty if a TLS server is desired.
	Certificate() (certificateFile, keyFile string)
}

// ListenAndServe invokes the appropriate server method based on the secure information.
// If Secure.Certificate() returns both a certificateFile and a keyFile, e.ListenAndServeTLS()
// is called to start the server.  Otherwise, e.ListenAndServe() is used.
func ListenAndServe(logger logging.Logger, s Secure, e executor) {
	certificateFile, keyFile := s.Certificate()
	if len(certificateFile) > 0 && len(keyFile) > 0 {
		go func() {
			logger.Error(
				e.ListenAndServeTLS(certificateFile, keyFile),
			)
		}()
	} else {
		go func() {
			logger.Error(
				e.ListenAndServe(),
			)
		}()
	}
}

// Basic describes a simple HTTP server.  Typically, this struct has its values
// injected via Viper.  See the New function in this package.
type Basic struct {
	Name               string
	Address            string
	CertificateFile    string
	KeyFile            string
	LogConnectionState bool
}

func (b *Basic) Certificate() (certificateFile, keyFile string) {
	return b.CertificateFile, b.KeyFile
}

// New creates an http.Server using this instance's configuration.  The given logger is required,
// but the handler may be nil.  If the handler is nil, http.DefaultServeMux is used, which matches
// the behavior of http.Server.
//
// This method returns nil if the configured address is empty, effectively disabling
// this server from startup.
func (b *Basic) New(logger logging.Logger, handler http.Handler) *http.Server {
	if len(b.Address) == 0 {
		return nil
	}

	server := &http.Server{
		Addr:     b.Address,
		Handler:  handler,
		ErrorLog: NewErrorLog(b.Name, logger),
	}

	if b.LogConnectionState {
		server.ConnState = NewConnectionStateLogger(b.Name, logger)
	}

	return server
}

// Health represents a configurable factory for a Health server.
//
// Due to a limitation of Viper, this struct does not use an embedded Basic
// instance.  Rather, it duplicates the fields so that Viper can inject them.
type Health struct {
	Name               string
	Address            string
	CertificateFile    string
	KeyFile            string
	LogConnectionState bool
	LogInterval        time.Duration
	Options            []string
}

func (h *Health) Certificate() (certificateFile, keyFile string) {
	return h.CertificateFile, h.KeyFile
}

// New creates both a health.Health monitor (which is also an HTTP handler) and an HTTP server
// which services health requests.
//
// This method returns nils if the configured Address is empty, which effectively disables
// the health server.
func (h *Health) New(logger logging.Logger) (handler *health.Health, server *http.Server) {
	if len(h.Address) == 0 {
		return
	}

	options := make([]health.Option, 0, len(h.Options))
	for _, value := range h.Options {
		options = append(options, health.Stat(value))
	}

	handler = health.New(
		h.LogInterval,
		logger,
		options...,
	)

	mux := http.NewServeMux()
	mux.Handle("/health", handler)

	server = &http.Server{
		Addr:     h.Address,
		Handler:  mux,
		Handler:  handler,
		ErrorLog: NewErrorLog(h.Name, logger),
	}

	if h.LogConnectionState {
		server.ConnState = NewConnectionStateLogger(h.Name, logger)
	}

	return
}

// WebPA represents a server component within the WebPA cluster.  It is used for both
// primary servers (e.g. petasos) and supporting, embedded servers such as pprof.
type WebPA struct {
	// Primary is the main server for this application, e.g. petasos.
	Primary Basic

	// Alternate is an alternate server which serves the primary application logic.
	// Used to have the same API served on more than one port and possibly more than
	// one protocol, e.g. HTTP and HTTPS.
	Alternate Basic

	// Health describes the health server for this application.  Note that if the Address
	// is empty, no health server is started.
	Health Health

	// Pprof describes the pprof server for this application.  Note that if the Address
	// is empty, no pprof server is started.
	Pprof Basic

	// Log is the logging configuration for this application.
	Log golog.LoggerFactory
}

// Prepare gets a WebPA server ready for execution.  This method does not return errors, but the returned
// Runnable may return an error.  The supplied logger will usually come from the New function, but the
// WebPA.Log object can be used to create a different logger if desired.
//
// The supplied http.Handler is used for the primary server.  If the alternate server has an address,
// it will also be used for that server.  The health server uses an internally create handler, while the pprof
// server uses http.DefaultServeMux.  The health Monitor created from configuration is returned so that other
// infrastructure can make use of it.
func (w *WebPA) Prepare(logger logging.Logger, primaryHandler http.Handler) (health.Monitor, concurrent.Runnable) {
	healthHandler, healthServer := w.Health.New(logger)
	return healthHandler, concurrent.RunnableFunc(func(waitGroup *sync.WaitGroup, shutdown <-chan struct{}) error {
		if healthHandler != nil && healthServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Health.Name, w.Health.Address)
			ListenAndServe(logger, &w.Health, healthServer)
			healthHandler.Run(waitGroup, shutdown)

			// wrap the primary handler in the RequestTracker decorator
			primaryHandler = healthHandler.RequestTracker(primaryHandler)
		}

		if pprofServer := w.Pprof.New(logger, nil); pprofServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Pprof.Name, w.Pprof.Address)
			ListenAndServe(logger, &w.Pprof, pprofServer)
		}

		if primaryServer := w.Primary.New(logger, primaryHandler); primaryServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Primary.Name, w.Primary.Address)
			ListenAndServe(logger, &w.Primary, primaryServer)
		} else {
			return ErrorNoPrimaryAddress
		}

		if alternateServer := w.Alternate.New(logger, primaryHandler); alternateServer != nil {
			logger.Info("Starting [%s] on [%s]", w.Alternate.Name, w.Alternate.Address)
			ListenAndServe(logger, &w.Alternate, alternateServer)
		}

		return nil
	})
}
<|endoftext|>


<commit_before>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

// Package agent implements a service that runs on a serviced node. It is
// responsible for ensuring that a particular node is running the correct services
// and reporting the state and health of those services back to the master
// serviced.

package main

// This is the main entry point for the application. Here we parse command line
// flags and either start a service or execute command line functions.

//svc "github.com/zenoss/serviced/svc"
import (
	"github.com/zenoss/serviced"
	"github.com/zenoss/serviced/dao"
	"github.com/zenoss/serviced/dao/elasticsearch"
	"github.com/zenoss/serviced/isvcs"
	"github.com/zenoss/serviced/shell"
	"github.com/zenoss/serviced/volume"
	_ "github.com/zenoss/serviced/volume/btrfs"
	_ "github.com/zenoss/serviced/volume/rsync"
	"github.com/zenoss/serviced/web"

	"flag"
	"fmt"
	"github.com/zenoss/glog"
	"net"
	"net/http"
	"net/rpc"
	"os"
	"os/signal"
	"os/user"
	"path"
	"time"
)

// Store the command line options
var options struct {
	port           string
	listen         string
	master         bool
	agent          bool
	muxPort        int
	tls            bool
	keyPEMFile     string
	certPEMFile    string
	varPath        string // Directory to store data, eg isvcs & service volumes
	resourcePath   string
	zookeepers     ListOpts
	repstats       bool
	statshost      string
	statsperiod    int
	mcusername     string
	mcpasswd       string
	mount          ListOpts
	resourceperiod int
	vfs            string
}

var agentIP string

// Setup flag options (static block)
func init() {
	var err error
	agentIP, err = serviced.GetIpAddress()
	if err != nil {
		panic(err)
	}

	flag.StringVar(&options.port, "port", agentIP+":4979", "port for remote serviced (example.com:8080)")
	flag.StringVar(&options.listen, "listen", ":4979", "port for local serviced (example.com:8080)")
	flag.BoolVar(&options.master, "master", false, "run in master mode, ie the control plane service")
	flag.BoolVar(&options.agent, "agent", false, "run in agent mode, ie a host in a resource pool")
	flag.IntVar(&options.muxPort, "muxport", 22250, "multiplexing port to use")
	flag.BoolVar(&options.tls, "tls", true, "enable TLS")

	varPathDefault := path.Join(os.TempDir(), "serviced")
	if len(os.Getenv("SERVICED_HOME")) > 0 {
		varPathDefault = path.Join(os.Getenv("SERVICED_HOME"), "var")
	} else {
		if user, err := user.Current(); err == nil {
			varPathDefault = path.Join(os.TempDir(), "serviced-"+user.Username, "var")
		}
	}
	flag.StringVar(&options.varPath, "varPath", varPathDefault, "path to store serviced data")

	flag.StringVar(&options.keyPEMFile, "keyfile", "", "path to private key file (defaults to compiled in private key)")
	flag.StringVar(&options.certPEMFile, "certfile", "", "path to public certificate file (defaults to compiled in public cert)")
	options.zookeepers = make(ListOpts, 0)
	flag.Var(&options.zookeepers, "zk", "Specify a zookeeper instance to connect to (e.g. -zk localhost:2181 )")
	flag.BoolVar(&options.repstats, "reportstats", false, "report container statistics")
	flag.StringVar(&options.statshost, "statshost", "127.0.0.1:8443", "host:port for container statistics")
	flag.IntVar(&options.statsperiod, "statsperiod", 5, "Period (minutes) for container statistics reporting")
	flag.StringVar(&options.mcusername, "mcusername", "scott", "Username for the Zenoss metric consumer")
	flag.StringVar(&options.mcpasswd, "mcpasswd", "tiger", "Password for the Zenoss metric consumer")
	options.mount = make(ListOpts, 0)
	flag.Var(&options.mount, "mount", "bind mount: container_image:host_path:container_path (e.g. -mount zenoss/zenoss5x:/home/zenoss/zenhome/zenoss/Products/:/opt/zenoss/Products/)")
	flag.StringVar(&options.vfs, "vfs", "rsync", "file system for container volumes")

	flag.Usage = func() {
		flag.PrintDefaults()
	}
}

func compareVersion(a, b []int) int {
	astr := ""
	for _, s := range a {
		astr += fmt.Sprintf("%12d", s)
	}
	bstr := ""
	for _, s := range b {
		bstr += fmt.Sprintf("%12d", s)
	}
	if astr > bstr {
		return -1
	}
	if astr < bstr {
		return 1
	}
	return 0
}

// Start the agent or master services on this host.
func startServer() {
	l, err := net.Listen("tcp", options.listen)
	if err != nil {
		glog.Fatalf("Could not bind to port %v. Is another instance running", err)
	}

	isvcs.Init()
	isvcs.Mgr.SetVolumesDir(options.varPath + "/isvcs")

	dockerVersion, err := serviced.GetDockerVersion()
	if err != nil {
		glog.Fatalf("Could not determine docker version: %s", err)
	}

	atLeast := []int{0, 7, 5}
	atMost := []int{0, 7, 6}
	if compareVersion(atLeast, dockerVersion.Client) < 0 || compareVersion(atMost, dockerVersion.Client) > 0 {
		glog.Fatal("serviced needs at least docker >= 0.7.5 or <= 0.7.6")
	}

	if _, ok := volume.Registered(options.vfs); !ok {
		glog.Fatalf("no driver registered for %s", options.vfs)
	}

	if options.master {
		var master dao.ControlPlane
		var err error
		master, err = elasticsearch.NewControlSvc("localhost", 9200, options.zookeepers, options.varPath, options.vfs)

		if err != nil {
			glog.Fatalf("Could not start ControlPlane service: %v", err)
		}
		// register the API
		glog.V(0).Infoln("registering ControlPlane service")
		rpc.RegisterName("LoadBalancer", master)
		rpc.RegisterName("ControlPlane", master)

		// TODO: Make bind port for web server optional?
		cpserver := web.NewServiceConfig(":8787", options.port, options.zookeepers, options.repstats)
		go cpserver.Serve()
	}
	if options.agent {
		mux := serviced.TCPMux{}

		mux.CertPEMFile = options.certPEMFile
		mux.KeyPEMFile = options.keyPEMFile
		mux.Enabled = true
		mux.Port = options.muxPort
		mux.UseTLS = options.tls

		agent, err := serviced.NewHostAgent(options.port, options.varPath, options.mount, options.vfs, options.zookeepers, mux)
		if err != nil {
			glog.Fatalf("Could not start ControlPlane agent: %v", err)
		}
		// register the API
		glog.V(0).Infoln("registering ControlPlaneAgent service")
		rpc.RegisterName("ControlPlaneAgent", agent)

		go func() {
			signalChan := make(chan os.Signal, 10)
			signal.Notify(signalChan, os.Interrupt)
			<-signalChan
			glog.V(0).Info("Shutting down due to interrupt")
			err = agent.Shutdown()
			if err != nil {
				glog.V(1).Infof("Agent shutdown with error: %v", err)
			}
			isvcs.Mgr.Stop()
			os.Exit(0)
		}()

		// TODO: Integrate this server into the rpc server, or something.
		// Currently its only use is for command execution.
		go func() {
			sio := shell.NewProcessExecutorServer(options.port)
			sio.Handle("/", http.FileServer(http.Dir("/home/zenoss/europa/src/golang/src/github.com/zenoss/serviced/serviced/www/")))
			http.ListenAndServe(":50000", sio)
		}()

		resourceDuration := time.Duration(options.resourceperiod) * time.Minute
		go agent.RegisterIPResources(resourceDuration)

	}

	rpc.HandleHTTP()

	if options.repstats {
		statsdest := fmt.Sprintf("http://%s/api/metrics/store", options.statshost)
		sr := StatsReporter{statsdest, options.mcusername, options.mcpasswd}

		glog.V(1).Infoln("Staring container statistics reporter")
		statsduration := time.Duration(options.statsperiod) * time.Minute
		go sr.Report(statsduration)
	}

	glog.V(0).Infof("Listening on %s", l.Addr().String())
	http.Serve(l, nil) // start the server
}

// main entry point of the product
func main() {

	// parse the command line flags
	flag.Parse()

	// are we in server mode
	if (options.master || options.agent) && len(flag.Args()) == 0 {
		startServer()
	} else {
		// we are in command line mode
		if len(flag.Args()) == 0 {
			// no arguments were give, show help
			cli := ServicedCli{}
			cli.CmdHelp(flag.Args()...)
			flag.Usage()
		} else {
			ParseCommands(flag.Args()...)
		}
	}
	glog.Flush()
}
<commit_msg>fixed merge weirdness<commit_after>// Copyright 2014, The Serviced Authors. All rights reserved.
// Use of this source code is governed by a
// license that can be found in the LICENSE file.

// Package agent implements a service that runs on a serviced node. It is
// responsible for ensuring that a particular node is running the correct services
// and reporting the state and health of those services back to the master
// serviced.

package main

// This is the main entry point for the application. Here we parse command line
// flags and either start a service or execute command line functions.

//svc "github.com/zenoss/serviced/svc"
import (
	"github.com/zenoss/serviced"
	"github.com/zenoss/serviced/dao"
	"github.com/zenoss/serviced/dao/elasticsearch"
	"github.com/zenoss/serviced/isvcs"
	"github.com/zenoss/serviced/shell"
	"github.com/zenoss/serviced/volume"
	_ "github.com/zenoss/serviced/volume/btrfs"
	_ "github.com/zenoss/serviced/volume/rsync"
	"github.com/zenoss/serviced/web"

	"flag"
	"fmt"
	"github.com/zenoss/glog"
	"net"
	"net/http"
	"net/rpc"
	"os"
	"os/signal"
	"os/user"
	"path"
	"time"
)

// Store the command line options
var options struct {
	port           string
	listen         string
	master         bool
	agent          bool
	muxPort        int
	tls            bool
	keyPEMFile     string
	certPEMFile    string
	varPath        string // Directory to store data, eg isvcs & service volumes
	resourcePath   string
	zookeepers     ListOpts
	repstats       bool
	statshost      string
	statsperiod    int
	mcusername     string
	mcpasswd       string
	mount          ListOpts
	resourceperiod int
	vfs            string
}

var agentIP string

// Setup flag options (static block)
func init() {
	var err error
	agentIP, err = serviced.GetIpAddress()
	if err != nil {
		panic(err)
	}

	flag.StringVar(&options.port, "port", agentIP+":4979", "port for remote serviced (example.com:8080)")
	flag.StringVar(&options.listen, "listen", ":4979", "port for local serviced (example.com:8080)")
	flag.BoolVar(&options.master, "master", false, "run in master mode, ie the control plane service")
	flag.BoolVar(&options.agent, "agent", false, "run in agent mode, ie a host in a resource pool")
	flag.IntVar(&options.muxPort, "muxport", 22250, "multiplexing port to use")
	flag.BoolVar(&options.tls, "tls", true, "enable TLS")

	varPathDefault := path.Join(os.TempDir(), "serviced")
	if len(os.Getenv("SERVICED_HOME")) > 0 {
		varPathDefault = path.Join(os.Getenv("SERVICED_HOME"), "var")
	} else {
		if user, err := user.Current(); err == nil {
			varPathDefault = path.Join(os.TempDir(), "serviced-"+user.Username, "var")
		}
	}
	flag.StringVar(&options.varPath, "varPath", varPathDefault, "path to store serviced data")

	flag.StringVar(&options.keyPEMFile, "keyfile", "", "path to private key file (defaults to compiled in private key)")
	flag.StringVar(&options.certPEMFile, "certfile", "", "path to public certificate file (defaults to compiled in public cert)")
	options.zookeepers = make(ListOpts, 0)
	flag.Var(&options.zookeepers, "zk", "Specify a zookeeper instance to connect to (e.g. -zk localhost:2181 )")
	flag.BoolVar(&options.repstats, "reportstats", false, "report container statistics")
	flag.StringVar(&options.statshost, "statshost", "127.0.0.1:8443", "host:port for container statistics")
	flag.IntVar(&options.statsperiod, "statsperiod", 5, "Period (minutes) for container statistics reporting")
	flag.StringVar(&options.mcusername, "mcusername", "scott", "Username for the Zenoss metric consumer")
	flag.StringVar(&options.mcpasswd, "mcpasswd", "tiger", "Password for the Zenoss metric consumer")
	options.mount = make(ListOpts, 0)
	flag.Var(&options.mount, "mount", "bind mount: container_image:host_path:container_path (e.g. -mount zenoss/zenoss5x:/home/zenoss/zenhome/zenoss/Products/:/opt/zenoss/Products/)")
	flag.StringVar(&options.vfs, "vfs", "rsync", "file system for container volumes")

	flag.Usage = func() {
		flag.PrintDefaults()
	}
}

func compareVersion(a, b []int) int {
	astr := ""
	for _, s := range a {
		astr += fmt.Sprintf("%12d", s)
	}
	bstr := ""
	for _, s := range b {
		bstr += fmt.Sprintf("%12d", s)
	}
	if astr > bstr {
		return -1
	}
	if astr < bstr {
		return 1
	}
	return 0
}

// Start the agent or master services on this host.
func startServer() {
	l, err := net.Listen("tcp", options.listen)
	if err != nil {
		glog.Fatalf("Could not bind to port %v. Is another instance running", err)
	}

	isvcs.Init()
	isvcs.Mgr.SetVolumesDir(options.varPath + "/isvcs")

	dockerVersion, err := serviced.GetDockerVersion()
	if err != nil {
		glog.Fatalf("Could not determine docker version: %s", err)
	}

	atLeast := []int{0, 7, 5}
	atMost := []int{0, 7, 6}
	if compareVersion(atLeast, dockerVersion.Client) < 0 || compareVersion(atMost, dockerVersion.Client) > 0 {
		glog.Fatal("serviced needs at least docker >= 0.7.5 or <= 0.7.6")
	}

	if _, ok := volume.Registered(options.vfs); !ok {
		glog.Fatalf("no driver registered for %s", options.vfs)
	}

	if options.master {
		var master dao.ControlPlane
		var err error
		master, err = elasticsearch.NewControlSvc("localhost", 9200, options.zookeepers, options.varPath, options.vfs)

		if err != nil {
			glog.Fatalf("Could not start ControlPlane service: %v", err)
		}
		// register the API
		glog.V(0).Infoln("registering ControlPlane service")
		rpc.RegisterName("LoadBalancer", master)
		rpc.RegisterName("ControlPlane", master)

		// TODO: Make bind port for web server optional?
		cpserver := web.NewServiceConfig(":8787", options.port, options.zookeepers, options.repstats)
		go cpserver.Serve()
	}
	if options.agent {
		mux := serviced.TCPMux{}

		mux.CertPEMFile = options.certPEMFile
		mux.KeyPEMFile = options.keyPEMFile
		mux.Enabled = true
		mux.Port = options.muxPort
		mux.UseTLS = options.tls

		agent, err := serviced.NewHostAgent(options.port, options.varPath, options.mount, options.vfs, options.zookeepers, mux)
		if err != nil {
			glog.Fatalf("Could not start ControlPlane agent: %v", err)
		}
		// register the API
		glog.V(0).Infoln("registering ControlPlaneAgent service")
		rpc.RegisterName("ControlPlaneAgent", agent)

		go func() {
			signalChan := make(chan os.Signal, 10)
			signal.Notify(signalChan, os.Interrupt)
			<-signalChan
			glog.V(0).Info("Shutting down due to interrupt")
			err = agent.Shutdown()
			if err != nil {
				glog.V(1).Infof("Agent shutdown with error: %v", err)
			}
			isvcs.Mgr.Stop()
			os.Exit(0)
		}()

		// TODO: Integrate this server into the rpc server, or something.
		// Currently its only use is for command execution.
		go func() {
			sio := shell.NewProcessExecutorServer(options.port)
			sio.Handle("/", http.FileServer(http.Dir("/home/zenoss/europa/src/golang/src/github.com/zenoss/serviced/serviced/www/")))
			http.ListenAndServe(":50000", sio)
		}()
	}

	rpc.HandleHTTP()

	if options.repstats {
		statsdest := fmt.Sprintf("http://%s/api/metrics/store", options.statshost)
		sr := StatsReporter{statsdest, options.mcusername, options.mcpasswd}

		glog.V(1).Infoln("Staring container statistics reporter")
		statsduration := time.Duration(options.statsperiod) * time.Minute
		go sr.Report(statsduration)
	}

	glog.V(0).Infof("Listening on %s", l.Addr().String())
	http.Serve(l, nil) // start the server
}

// main entry point of the product
func main() {

	// parse the command line flags
	flag.Parse()

	// are we in server mode
	if (options.master || options.agent) && len(flag.Args()) == 0 {
		startServer()
	} else {
		// we are in command line mode
		if len(flag.Args()) == 0 {
			// no arguments were give, show help
			cli := ServicedCli{}
			cli.CmdHelp(flag.Args()...)
			flag.Usage()
		} else {
			ParseCommands(flag.Args()...)
		}
	}
	glog.Flush()
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"html/template"
	"net/http"
)

type blogItem struct {
	url   string
	title string
}

func FrontPingCtr(c *gin.Context) {
	c.String(http.StatusOK, "pong")
}
func FrontHomeCtr(c *gin.Context) {
	db, err := sql.Open("mysql", "root:deyilife@tcp(127.0.0.1:3306)/gosense?charset=utf8mb4")
	if err != nil {
		panic(err.Error())
	}
	defer db.Close()

	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}

	var bl [2]blogItem
	bl[0] = blogItem{
		"//www.netroby.com/view.php?id=3833",
		"How To Manually Install Oracle Java on a Debian or Ubuntu VPS",
	}
	bl[1] = blogItem{
		"//www.netroby.com/view.php?id=3832",
		"Linux 4.0 kernel released",
	}
	var blogList string
	for i := 0; i < len(bl); i++ {
		blogList += fmt.Sprintf(
			"
%s
",
			bl[i].url,
			bl[i].title,
		)
	}
	username, err := c.Request.Cookie("username")

	c.HTML(http.StatusOK, "index.html", gin.H{
		"bloglist": template.HTML(blogList),
		"username": username,
	})
}
<commit_msg>Set max connect<commit_after>package main

import (
	"database/sql"
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"html/template"
	"net/http"
)

type blogItem struct {
	url   string
	title string
}

func FrontPingCtr(c *gin.Context) {
	c.String(http.StatusOK, "pong")
}
func FrontHomeCtr(c *gin.Context) {
	db, err := sql.Open("mysql", "root:deyilife@tcp(127.0.0.1:3306)/gosense?charset=utf8mb4")
	if err != nil {
		panic(err.Error())
	}
	db.SetMaxIdleConns(50)
	db.SetMaxOpenConns(100)
	defer db.Close()

	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}

	var bl [2]blogItem
	bl[0] = blogItem{
		"//www.netroby.com/view.php?id=3833",
		"How To Manually Install Oracle Java on a Debian or Ubuntu VPS",
	}
	bl[1] = blogItem{
		"//www.netroby.com/view.php?id=3832",
		"Linux 4.0 kernel released",
	}
	var blogList string
	for i := 0; i < len(bl); i++ {
		blogList += fmt.Sprintf(
			"
%s
",
			bl[i].url,
			bl[i].title,
		)
	}
	username, err := c.Request.Cookie("username")

	c.HTML(http.StatusOK, "index.html", gin.H{
		"bloglist": template.HTML(blogList),
		"username": username,
	})
}
<|endoftext|>


<commit_before>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tag

import (
	"errors"
	"io"
	"os"
)

// ReadOGGTags reads OGG metadata from the io.ReadSeeker, returning the resulting
// metadata in a Metadata implementation, or non-nil error if there was a problem.
// TODO: Needs a more generic return type than "metadataFLAC" and the "FLAC" format is not as obvious as "Vorbis comment"
func ReadOGGTags(r io.ReadSeeker) (Metadata, error) {
	_, err := r.Seek(0, os.SEEK_SET)
	if err != nil {
		return nil, err
	}

	oggs, err := readString(r, 4)
	if err != nil {
		return nil, err
	}
	if oggs != "OggS" {
		return nil, errors.New("expected 'OggS'")
	}

	_, err = r.Seek(22, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	nS, err := readInt(r, 1)
	if err != nil {
		return nil, err
	}

	_, err = r.Seek(int64(nS), os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	idComment, err := readInt(r, 1)
	if err != nil {
		return nil, err
	}
	if idComment != 1 {
		return nil, errors.New("expected 'vorbis' identification type 1")
	}

	_, err = r.Seek(29, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	oggs, err = readString(r, 4)
	if err != nil {
		return nil, err
	}
	if oggs != "OggS" {
		return nil, errors.New("expected 'OggS'")
	}

	_, err = r.Seek(22, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	nS, err = readInt(r, 1)
	if err != nil {
		return nil, err
	}

	_, err = r.Seek(int64(nS), os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	typeComment, err := readInt(r, 1)
	if err != nil {
		return nil, err
	}
	if typeComment != 3 {
		return nil, errors.New("expected 'vorbis' comment type 3")
	}

	_, err = r.Seek(6, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	m := &metadataFLAC{
		c: make(map[string]string),
	}

	err = m.readVorbisComment(r)

	return m, err
}
<commit_msg>Added comments and links to ogg spec. Clarified code with const<commit_after>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tag

import (
	"errors"
	"io"
	"os"
)

const (
	idType      int = 1
	commentType     = 3
)

// ReadOGGTags reads OGG metadata from the io.ReadSeeker, returning the resulting
// metadata in a Metadata implementation, or non-nil error if there was a problem.
// See http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html and http://www.xiph.org/ogg/doc/framing.html for details
// TODO: Needs a more generic return type than "metadataFLAC" and the "FLAC" format is not as obvious as "Vorbis comment"
func ReadOGGTags(r io.ReadSeeker) (Metadata, error) {
	_, err := r.Seek(0, os.SEEK_SET)
	if err != nil {
		return nil, err
	}

	oggs, err := readString(r, 4)
	if err != nil {
		return nil, err
	}
	if oggs != "OggS" {
		return nil, errors.New("expected 'OggS'")
	}

	// Skip 22 bytes of Page header to read page_segments length byte at position 26
	// See http://www.xiph.org/ogg/doc/framing.html
	_, err = r.Seek(22, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	nS, err := readInt(r, 1)
	if err != nil {
		return nil, err
	}

	// Seek and discard the segments
	_, err = r.Seek(int64(nS), os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	// First packet type is identification, type 1
	t, err := readInt(r, 1)
	if err != nil {
		return nil, err
	}
	if t != idType {
		return nil, errors.New("expected 'vorbis' identification type 1")
	}

	// Seek and discard 29 bytes from common and identification header
	// See http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-610004.2
	_, err = r.Seek(29, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	// Beginning of a new page. Comment packet is on a separate page
	// See http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-132000A.2
	oggs, err = readString(r, 4)
	if err != nil {
		return nil, err
	}
	if oggs != "OggS" {
		return nil, errors.New("expected 'OggS'")
	}

	// Skip page 2 header, same as line 30
	_, err = r.Seek(22, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	nS, err = readInt(r, 1)
	if err != nil {
		return nil, err
	}

	_, err = r.Seek(int64(nS), os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	// Packet type is comment, type 3
	t, err = readInt(r, 1)
	if err != nil {
		return nil, err
	}
	if t != commentType {
		return nil, errors.New("expected 'vorbis' comment type 3")
	}

	// Seek and discard 6 bytes from common header
	_, err = r.Seek(6, os.SEEK_CUR)
	if err != nil {
		return nil, err
	}

	m := &metadataFLAC{
		c: make(map[string]string),
	}

	err = m.readVorbisComment(r)

	return m, err
}
<|endoftext|>


<commit_before>package jsoniter

import (
	"io"
	"bytes"
)

// Unmarshal adapts to json/encoding APIs
func Unmarshal(data []byte, v interface{}) error {
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("Unmarshal", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func UnmarshalAny(data []byte) (Any, error) {
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
	}
	return any, iter.Error
}

func lastNotSpacePos(data []byte) int {
	for i := len(data) - 1; i >= 0; i-- {
		if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
			return i + 1
		}
	}
	return 0
}

func UnmarshalFromString(str string, v interface{}) error {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func UnmarshalAnyFromString(str string) (Any, error) {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
	}
	return nil, iter.Error
}

// Marshal is an adapter to json.Marshal
//
// Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API
func Marshal(v interface{}) ([]byte, error) {
	buf := &bytes.Buffer{}
	stream := NewStream(buf, 512)
	stream.WriteVal(v)
	stream.Flush()
	if stream.Error != nil {
		return nil, stream.Error
	}
	return buf.Bytes(), nil
}

// notbeginwithfuncname MarshalToString does not show in doc
func MarshalToString(v interface{}) (string, error) {
	buf, err := Marshal(v)
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

// NewDecoder show in doc
func NewDecoder(reader io.Reader) *AdaptedDecoder {
	iter := Parse(reader, 512)
	return &AdaptedDecoder{iter}
}

type AdaptedDecoder struct {
	iter *Iterator
}

func (adapter *AdaptedDecoder) Decode(obj interface{}) error {
	adapter.iter.ReadVal(obj)
	err := adapter.iter.Error
	if err == io.EOF {
		return nil
	}
	return adapter.iter.Error
}

func (adapter *AdaptedDecoder) More() bool {
	return adapter.iter.head != adapter.iter.tail
}

func (adapter *AdaptedDecoder) Buffered() io.Reader {
	remaining := adapter.iter.buf[adapter.iter.head:adapter.iter.tail]
	return bytes.NewReader(remaining)
}

func NewEncoder(writer io.Writer) *AdaptedEncoder {
	stream := NewStream(writer, 512)
	return &AdaptedEncoder{stream}
}

type AdaptedEncoder struct {
	stream *Stream
}

func (adapter *AdaptedEncoder) Encode(val interface{}) error {
	adapter.stream.WriteVal(val)
	adapter.stream.Flush()
	return adapter.stream.Error
}

func (adapter *AdaptedEncoder) SetIndent(prefix, indent string) {
	// not implemented yet
}<commit_msg>adapter api comment<commit_after>package jsoniter

import (
	"io"
	"bytes"
)

// Unmarshal adapts to json/encoding Unmarshal API
//
// Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.
func Unmarshal(data []byte, v interface{}) error {
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("Unmarshal", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func UnmarshalAny(data []byte) (Any, error) {
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAny", "there are bytes left after unmarshal")
	}
	return any, iter.Error
}

func lastNotSpacePos(data []byte) int {
	for i := len(data) - 1; i >= 0; i-- {
		if data[i] != ' ' && data[i] != '\t' && data[i] != '\r' && data[i] != '\n' {
			return i + 1
		}
	}
	return 0
}

func UnmarshalFromString(str string, v interface{}) error {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	iter.ReadVal(v)
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal")
	}
	return iter.Error
}

func UnmarshalAnyFromString(str string) (Any, error) {
	data := []byte(str)
	data = data[:lastNotSpacePos(data)]
	iter := ParseBytes(data)
	any := iter.ReadAny()
	if iter.head == iter.tail {
		iter.loadMore()
	}
	if iter.Error == io.EOF {
		return any, nil
	}
	if iter.Error == nil {
		iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal")
	}
	return nil, iter.Error
}

// Marshal adapts to json/encoding Marshal API
//
// Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API
func Marshal(v interface{}) ([]byte, error) {
	buf := &bytes.Buffer{}
	stream := NewStream(buf, 512)
	stream.WriteVal(v)
	stream.Flush()
	if stream.Error != nil {
		return nil, stream.Error
	}
	return buf.Bytes(), nil
}

func MarshalToString(v interface{}) (string, error) {
	buf, err := Marshal(v)
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

// NewDecoder adapts to json/stream NewDecoder API.
//
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(reader io.Reader) *AdaptedDecoder {
	iter := Parse(reader, 512)
	return &AdaptedDecoder{iter}
}

type AdaptedDecoder struct {
	iter *Iterator
}

func (adapter *AdaptedDecoder) Decode(obj interface{}) error {
	adapter.iter.ReadVal(obj)
	err := adapter.iter.Error
	if err == io.EOF {
		return nil
	}
	return adapter.iter.Error
}

func (adapter *AdaptedDecoder) More() bool {
	return adapter.iter.head != adapter.iter.tail
}

func (adapter *AdaptedDecoder) Buffered() io.Reader {
	remaining := adapter.iter.buf[adapter.iter.head:adapter.iter.tail]
	return bytes.NewReader(remaining)
}

func NewEncoder(writer io.Writer) *AdaptedEncoder {
	stream := NewStream(writer, 512)
	return &AdaptedEncoder{stream}
}

type AdaptedEncoder struct {
	stream *Stream
}

func (adapter *AdaptedEncoder) Encode(val interface{}) error {
	adapter.stream.WriteVal(val)
	adapter.stream.Flush()
	return adapter.stream.Error
}

func (adapter *AdaptedEncoder) SetIndent(prefix, indent string) {
	// not implemented yet
}<|endoftext|>