Get plugin building and mostly working
This commit is contained in:
parent
aff02b798a
commit
1221794f0a
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
|||||||
*~
|
*~
|
||||||
bin
|
bin
|
||||||
pkg
|
pkg
|
||||||
|
crash.log
|
||||||
|
packer_cache/*
|
||||||
|
202
Godeps/Godeps.json
generated
202
Godeps/Godeps.json
generated
@ -1,202 +0,0 @@
|
|||||||
{
|
|
||||||
"ImportPath": "github.com/xenserver/packer-builder-xenserver",
|
|
||||||
"GoVersion": "go1.6",
|
|
||||||
"GodepVersion": "v74",
|
|
||||||
"Packages": [
|
|
||||||
"./..."
|
|
||||||
],
|
|
||||||
"Deps": [
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/Sirupsen/logrus",
|
|
||||||
"Comment": "v0.10.0-19-gf3cfb45",
|
|
||||||
"Rev": "f3cfb454f4c209e6668c95216c4744b8fddb2356"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/dylanmei/iso8601",
|
|
||||||
"Comment": "v0.1.0",
|
|
||||||
"Rev": "2075bf119b58e5576c6ed9f867b8f3d17f2e54d4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/dylanmei/winrmtest",
|
|
||||||
"Rev": "025617847eb2cf9bd1d851bc3b22ed28e6245ce5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/errwrap",
|
|
||||||
"Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/go-multierror",
|
|
||||||
"Rev": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/go-version",
|
|
||||||
"Rev": "7e3c02b30806fa5779d3bdfc152ce4c6f40e7b38"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/yamux",
|
|
||||||
"Rev": "df949784da9ed028ee76df44652e42d37a09d7e4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/kr/fs",
|
|
||||||
"Rev": "2788f0dbd16903de03cb8186e5c7d97b69ad387b"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/masterzen/simplexml/dom",
|
|
||||||
"Rev": "95ba30457eb1121fa27753627c774c7cd4e90083"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/masterzen/winrm/soap",
|
|
||||||
"Rev": "54ea5d01478cfc2afccec1504bd0dfcd8c260cfa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/masterzen/winrm/winrm",
|
|
||||||
"Rev": "54ea5d01478cfc2afccec1504bd0dfcd8c260cfa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/masterzen/xmlpath",
|
|
||||||
"Rev": "13f4951698adc0fa9c1dda3e275d489a24201161"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/go-fs",
|
|
||||||
"Rev": "a34c1b9334e86165685a9449b782f20465eb8c69"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/go-fs/fat",
|
|
||||||
"Rev": "a34c1b9334e86165685a9449b782f20465eb8c69"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/iochan",
|
|
||||||
"Rev": "87b45ffd0e9581375c491fef3d32130bb15c5bd7"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/mapstructure",
|
|
||||||
"Rev": "281073eb9eb092240d33ef253c404f1cca550309"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/multistep",
|
|
||||||
"Rev": "162146fc57112954184d90266f4733e900ed05a5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/osext",
|
|
||||||
"Rev": "5e2d6d41470f99c881826dedd8c526728b783c9c"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/common",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/common/ssh",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/common/uuid",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/communicator/none",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/communicator/ssh",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/communicator/winrm",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/helper/communicator",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/helper/config",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/packer",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/packer/plugin",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/packer/rpc",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/template",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/packer/template/interpolate",
|
|
||||||
"Comment": "v0.10.1-135-g63edbd4",
|
|
||||||
"Rev": "63edbd40edc5a55394f8532aa9958bbe257b31b5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/mitchellh/reflectwalk",
|
|
||||||
"Rev": "eecf4c70c626c7cfbb95c90195bc34d386c74ac6"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/nilshell/xmlrpc",
|
|
||||||
"Rev": "41b9444050f7a0494a44cd5644f5048aa8261b17"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/nu7hatch/gouuid",
|
|
||||||
"Rev": "179d4d0c4d8d407a32af483c2354df1d2c91e6c3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/packer-community/winrmcp/winrmcp",
|
|
||||||
"Rev": "f1bcf36a69fa2945e65dd099eee11b560fbd3346"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/pkg/sftp",
|
|
||||||
"Rev": "e84cc8c755ca39b7b64f510fe1fffc1b51f210a5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/satori/go.uuid",
|
|
||||||
"Rev": "d41af8bb6a7704f00bc3b7cba9355ae6a5a80048"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/svanharmelen/gocs",
|
|
||||||
"Comment": "v1.0.0-4-ga53656b",
|
|
||||||
"Rev": "a53656b67c7b6db48362e3b4edb5e335a7162bf0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/ugorji/go/codec",
|
|
||||||
"Rev": "646ae4a518c1c3be0739df898118d9bccf993858"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/xenserver/go-xenserver-client",
|
|
||||||
"Rev": "42dc9035c2e805b844614741d804f308bacb7490"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/crypto/curve25519",
|
|
||||||
"Rev": "1f22c0103821b9390939b6776727195525381532"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/crypto/ssh",
|
|
||||||
"Rev": "1f22c0103821b9390939b6776727195525381532"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/crypto/ssh/agent",
|
|
||||||
"Rev": "1f22c0103821b9390939b6776727195525381532"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/sys/unix",
|
|
||||||
"Rev": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
5
Godeps/Readme
generated
5
Godeps/Readme
generated
@ -1,5 +0,0 @@
|
|||||||
This directory tree is generated automatically by godep.
|
|
||||||
|
|
||||||
Please do not edit.
|
|
||||||
|
|
||||||
See https://github.com/tools/godep for more information.
|
|
4
build.sh
4
build.sh
@ -12,10 +12,10 @@ GOPATH=${GOPATH:-$(go env GOPATH)}
|
|||||||
echo "==> Removing old directory..."
|
echo "==> Removing old directory..."
|
||||||
rm -f bin/*
|
rm -f bin/*
|
||||||
rm -rf pkg/*
|
rm -rf pkg/*
|
||||||
rm -rf $GOPATH/pkg/*
|
# rm -rf $GOPATH/pkg/*
|
||||||
mkdir -p bin/
|
mkdir -p bin/
|
||||||
|
|
||||||
gox \
|
~/go/bin/gox \
|
||||||
-os="${XC_OS}" \
|
-os="${XC_OS}" \
|
||||||
-arch="${XC_ARCH}" \
|
-arch="${XC_ARCH}" \
|
||||||
-output "pkg/{{.OS}}_{{.Arch}}/packer-{{.Dir}}" \
|
-output "pkg/{{.OS}}_{{.Arch}}/packer-{{.Dir}}" \
|
||||||
|
BIN
builder-xenserver-iso
Executable file
BIN
builder-xenserver-iso
Executable file
Binary file not shown.
BIN
builder-xenserver-xva
Executable file
BIN
builder-xenserver-xva
Executable file
Binary file not shown.
@ -4,9 +4,10 @@ import (
|
|||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/nilshell/xmlrpc"
|
|
||||||
"log"
|
"log"
|
||||||
"regexp"
|
|
||||||
|
xmlrpc "github.com/amfranz/go-xmlrpc-client"
|
||||||
|
xenapi "github.com/terra-farm/go-xen-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type XenAPIClient struct {
|
type XenAPIClient struct {
|
||||||
@ -62,9 +63,8 @@ const (
|
|||||||
|
|
||||||
func (c *XenAPIClient) RPCCall(result interface{}, method string, params []interface{}) (err error) {
|
func (c *XenAPIClient) RPCCall(result interface{}, method string, params []interface{}) (err error) {
|
||||||
fmt.Println(params)
|
fmt.Println(params)
|
||||||
p := new(xmlrpc.Params)
|
p := xmlrpc.Params{Params: params}
|
||||||
p.Params = params
|
err = c.RPC.Call(method, p, result)
|
||||||
err = c.RPC.Call(method, *p, result)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,24 +202,6 @@ func (client *XenAPIClient) GetVMByNameLabel(name_label string) (vms []*VM, err
|
|||||||
return vms, nil
|
return vms, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *XenAPIClient) GetSRByNameLabel(name_label string) (srs []*SR, err error) {
|
|
||||||
srs = make([]*SR, 0)
|
|
||||||
result := APIResult{}
|
|
||||||
err = client.APICall(&result, "SR.get_by_name_label", name_label)
|
|
||||||
if err != nil {
|
|
||||||
return srs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, elem := range result.Value.([]interface{}) {
|
|
||||||
sr := new(SR)
|
|
||||||
sr.Ref = elem.(string)
|
|
||||||
sr.Client = client
|
|
||||||
srs = append(srs, sr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return srs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *XenAPIClient) GetNetworkByUuid(network_uuid string) (network *Network, err error) {
|
func (client *XenAPIClient) GetNetworkByUuid(network_uuid string) (network *Network, err error) {
|
||||||
network = new(Network)
|
network = new(Network)
|
||||||
result := APIResult{}
|
result := APIResult{}
|
||||||
@ -268,18 +250,6 @@ func (client *XenAPIClient) GetVdiByNameLabel(name_label string) (vdis []*VDI, e
|
|||||||
return vdis, nil
|
return vdis, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *XenAPIClient) GetSRByUuid(sr_uuid string) (sr *SR, err error) {
|
|
||||||
sr = new(SR)
|
|
||||||
result := APIResult{}
|
|
||||||
err = client.APICall(&result, "SR.get_by_uuid", sr_uuid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sr.Ref = result.Value.(string)
|
|
||||||
sr.Client = client
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *XenAPIClient) GetVdiByUuid(vdi_uuid string) (vdi *VDI, err error) {
|
func (client *XenAPIClient) GetVdiByUuid(vdi_uuid string) (vdi *VDI, err error) {
|
||||||
vdi = new(VDI)
|
vdi = new(VDI)
|
||||||
result := APIResult{}
|
result := APIResult{}
|
||||||
@ -309,20 +279,6 @@ func (client *XenAPIClient) GetPIFs() (pifs []*PIF, err error) {
|
|||||||
return pifs, nil
|
return pifs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *XenAPIClient) CreateTask() (task *Task, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = client.APICall(&result, "task.create", "packer-task", "Packer task")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
task = new(Task)
|
|
||||||
task.Ref = result.Value.(string)
|
|
||||||
task.Client = client
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Host associated functions
|
// Host associated functions
|
||||||
|
|
||||||
func (self *Host) GetSoftwareVersion() (versions map[string]interface{}, err error) {
|
func (self *Host) GetSoftwareVersion() (versions map[string]interface{}, err error) {
|
||||||
@ -400,18 +356,8 @@ func (self *VM) CleanShutdown() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VM) HardShutdown() (err error) {
|
func Unpause(c *Connection, vmRef xenapi.VMRef) (err error) {
|
||||||
result := APIResult{}
|
err = c.client.VM.Unpause(c.session, vmRef)
|
||||||
err = self.Client.APICall(&result, "VM.hard_shutdown", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *VM) Unpause() (err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VM.unpause", self.Ref)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -495,39 +441,22 @@ func (self *VM) GetVBDs() (vbds []VBD, err error) {
|
|||||||
return vbds, nil
|
return vbds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VM) GetVIFs() (vifs []VIF, err error) {
|
func GetDisks(c *Connection, vmRef xenapi.VMRef) (vdis []xenapi.VDIRef, err error) {
|
||||||
vifs = make([]VIF, 0)
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VM.get_VIFs", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return vifs, err
|
|
||||||
}
|
|
||||||
for _, elem := range result.Value.([]interface{}) {
|
|
||||||
vif := VIF{}
|
|
||||||
vif.Ref = elem.(string)
|
|
||||||
vif.Client = self.Client
|
|
||||||
vifs = append(vifs, vif)
|
|
||||||
}
|
|
||||||
|
|
||||||
return vifs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *VM) GetDisks() (vdis []*VDI, err error) {
|
|
||||||
// Return just data disks (non-isos)
|
// Return just data disks (non-isos)
|
||||||
vdis = make([]*VDI, 0)
|
vdis = make([]xenapi.VDIRef, 0)
|
||||||
vbds, err := self.GetVBDs()
|
vbds, err := c.client.VM.GetVBDs(c.session, vmRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, vbd := range vbds {
|
for _, vbd := range vbds {
|
||||||
rec, err := vbd.GetRecord()
|
rec, err := c.client.VBD.GetRecord(c.session, vbd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if rec["type"] == "Disk" {
|
if rec.Type == "Disk" {
|
||||||
|
|
||||||
vdi, err := vbd.GetVDI()
|
vdi, err := c.client.VBD.GetVDI(c.session, vbd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -576,51 +505,53 @@ func (self *VM) SetStaticMemoryRange(min, max uint) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VM) ConnectVdi(vdi *VDI, vdiType VDIType) (err error) {
|
func ConnectVdi(c *Connection, vmRef xenapi.VMRef, vdiRef xenapi.VDIRef, vbdType xenapi.VbdType) (err error) {
|
||||||
|
|
||||||
// 1. Create a VBD
|
var mode xenapi.VbdMode
|
||||||
|
var unpluggable bool
|
||||||
vbd_rec := make(xmlrpc.Struct)
|
var bootable bool
|
||||||
vbd_rec["VM"] = self.Ref
|
var t xenapi.VbdType
|
||||||
vbd_rec["VDI"] = vdi.Ref
|
switch vbdType {
|
||||||
vbd_rec["userdevice"] = "autodetect"
|
case xenapi.VbdTypeCD:
|
||||||
vbd_rec["empty"] = false
|
mode = xenapi.VbdModeRO
|
||||||
vbd_rec["other_config"] = make(xmlrpc.Struct)
|
bootable = true
|
||||||
vbd_rec["qos_algorithm_type"] = ""
|
unpluggable = false
|
||||||
vbd_rec["qos_algorithm_params"] = make(xmlrpc.Struct)
|
t = xenapi.VbdTypeCD
|
||||||
|
case xenapi.VbdTypeDisk:
|
||||||
switch vdiType {
|
mode = xenapi.VbdModeRW
|
||||||
case CD:
|
bootable = false
|
||||||
vbd_rec["mode"] = "RO"
|
unpluggable = false
|
||||||
vbd_rec["bootable"] = true
|
t = xenapi.VbdTypeDisk
|
||||||
vbd_rec["unpluggable"] = false
|
case xenapi.VbdTypeFloppy:
|
||||||
vbd_rec["type"] = "CD"
|
mode = xenapi.VbdModeRW
|
||||||
case Disk:
|
bootable = false
|
||||||
vbd_rec["mode"] = "RW"
|
unpluggable = true
|
||||||
vbd_rec["bootable"] = false
|
t = xenapi.VbdTypeFloppy
|
||||||
vbd_rec["unpluggable"] = false
|
|
||||||
vbd_rec["type"] = "Disk"
|
|
||||||
case Floppy:
|
|
||||||
vbd_rec["mode"] = "RW"
|
|
||||||
vbd_rec["bootable"] = false
|
|
||||||
vbd_rec["unpluggable"] = true
|
|
||||||
vbd_rec["type"] = "Floppy"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result := APIResult{}
|
vbd_ref, err := c.client.VBD.Create(c.session, xenapi.VBDRecord{
|
||||||
err = self.Client.APICall(&result, "VBD.create", vbd_rec)
|
VM: xenapi.VMRef(vmRef),
|
||||||
|
VDI: xenapi.VDIRef(vdiRef),
|
||||||
|
Userdevice: "autodetect",
|
||||||
|
Empty: false,
|
||||||
|
// OtherConfig: map[string]interface{{}},
|
||||||
|
QosAlgorithmType: "",
|
||||||
|
// QosAlgorithmParams: map[string]interface{{}},
|
||||||
|
Mode: mode,
|
||||||
|
Unpluggable: unpluggable,
|
||||||
|
Bootable: bootable,
|
||||||
|
Type: t,
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vbd_ref := result.Value.(string)
|
|
||||||
fmt.Println("VBD Ref:", vbd_ref)
|
fmt.Println("VBD Ref:", vbd_ref)
|
||||||
|
|
||||||
result = APIResult{}
|
uuid, err := c.client.VBD.GetUUID(c.session, vbd_ref)
|
||||||
err = self.Client.APICall(&result, "VBD.get_uuid", vbd_ref)
|
|
||||||
|
|
||||||
fmt.Println("VBD UUID: ", result.Value.(string))
|
fmt.Println("VBD UUID: ", uuid)
|
||||||
/*
|
/*
|
||||||
// 2. Plug VBD (Non need - the VM hasn't booted.
|
// 2. Plug VBD (Non need - the VM hasn't booted.
|
||||||
// @todo - check VM state
|
// @todo - check VM state
|
||||||
@ -634,34 +565,32 @@ func (self *VM) ConnectVdi(vdi *VDI, vdiType VDIType) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VM) DisconnectVdi(vdi *VDI) error {
|
func DisconnectVdi(c *Connection, vmRef xenapi.VMRef, vdi xenapi.VDIRef) error {
|
||||||
vbds, err := self.GetVBDs()
|
vbds, err := c.client.VM.GetVBDs(c.session, vmRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to get VM VBDs: %s", err.Error())
|
return fmt.Errorf("Unable to get VM VBDs: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, vbd := range vbds {
|
for _, vbd := range vbds {
|
||||||
rec, err := vbd.GetRecord()
|
rec, err := c.client.VBD.GetRecord(c.session, vbd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Could not get record for VBD '%s': %s", vbd.Ref, err.Error())
|
return fmt.Errorf("Could not get record for VBD '%s': %s", vbd, err.Error())
|
||||||
}
|
}
|
||||||
|
recVdi := rec.VDI
|
||||||
if recVdi, ok := rec["VDI"].(string); ok {
|
if recVdi == vdi {
|
||||||
if recVdi == vdi.Ref {
|
_ = c.client.VBD.Unplug(c.session, vbd)
|
||||||
_ = vbd.Unplug()
|
err = c.client.VBD.Destroy(c.session, vbd)
|
||||||
err = vbd.Destroy()
|
if err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("Could not destroy VBD '%s': %s", vbd, err.Error())
|
||||||
return fmt.Errorf("Could not destroy VBD '%s': %s", vbd.Ref, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Could not find VDI record in VBD '%s'", vbd.Ref)
|
log.Printf("Could not find VDI record in VBD '%s'", vbd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Could not find VBD for VDI '%s'", vdi.Ref)
|
return fmt.Errorf("Could not find VBD for VDI '%s'", vdi)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VM) SetPlatform(params map[string]string) (err error) {
|
func (self *VM) SetPlatform(params map[string]string) (err error) {
|
||||||
@ -679,31 +608,25 @@ func (self *VM) SetPlatform(params map[string]string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VM) ConnectNetwork(network *Network, device string) (vif *VIF, err error) {
|
func ConnectNetwork(c *Connection, networkRef xenapi.NetworkRef, vmRef xenapi.VMRef, device string) (*xenapi.VIFRef, error) {
|
||||||
// Create the VIF
|
// Create the VIF
|
||||||
|
// vif_rec["other_config"] = make(xmlrpc.Struct)
|
||||||
|
// vif_rec["qos_algorithm_params"] = make(xmlrpc.Struct)
|
||||||
|
|
||||||
vif_rec := make(xmlrpc.Struct)
|
vif, err := c.client.VIF.Create(c.session, xenapi.VIFRecord{
|
||||||
vif_rec["network"] = network.Ref
|
Network: networkRef,
|
||||||
vif_rec["VM"] = self.Ref
|
VM: vmRef,
|
||||||
vif_rec["MAC"] = ""
|
MAC: "",
|
||||||
vif_rec["device"] = device
|
Device: device,
|
||||||
vif_rec["MTU"] = "1504"
|
MTU: 1504,
|
||||||
vif_rec["other_config"] = make(xmlrpc.Struct)
|
QosAlgorithmType: "",
|
||||||
vif_rec["qos_algorithm_type"] = ""
|
})
|
||||||
vif_rec["qos_algorithm_params"] = make(xmlrpc.Struct)
|
|
||||||
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "VIF.create", vif_rec)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vif = new(VIF)
|
return &vif, nil
|
||||||
vif.Ref = result.Value.(string)
|
|
||||||
vif.Client = self.Client
|
|
||||||
|
|
||||||
return vif, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
@ -901,9 +824,9 @@ type TransferRecord struct {
|
|||||||
UrlFull string `xml:"url_full,attr"`
|
UrlFull string `xml:"url_full,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *VDI) Expose(format string) (url string, err error) {
|
func Expose(c *Connection, vdiRef xenapi.VDIRef, format string) (url string, err error) {
|
||||||
|
|
||||||
hosts, err := self.Client.GetHosts()
|
hosts, err := c.client.Host.GetAll(c.session)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.New(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
|
err = errors.New(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
|
||||||
@ -911,33 +834,31 @@ func (self *VDI) Expose(format string) (url string, err error) {
|
|||||||
}
|
}
|
||||||
host := hosts[0]
|
host := hosts[0]
|
||||||
|
|
||||||
disk_uuid, err := self.GetUuid()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.New(fmt.Sprintf("Failed to get VDI uuid for %s: %s", self.Ref, err.Error()))
|
err = errors.New(fmt.Sprintf("Failed to get VDI uuid for %s: %s", vdiRef, err.Error()))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
args := make(map[string]string)
|
args := make(map[string]string)
|
||||||
args["transfer_mode"] = "http"
|
args["transfer_mode"] = "http"
|
||||||
args["vdi_uuid"] = disk_uuid
|
args["vdi_uuid"] = string(vdiRef)
|
||||||
args["expose_vhd"] = "true"
|
args["expose_vhd"] = "true"
|
||||||
args["network_uuid"] = "management"
|
args["network_uuid"] = "management"
|
||||||
args["timeout_minutes"] = "5"
|
args["timeout_minutes"] = "5"
|
||||||
|
|
||||||
handle, err := host.CallPlugin("transfer", "expose", args)
|
handle, err := c.client.Host.CallPlugin(c.session, host, "transfer", "expose", args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.New(fmt.Sprintf("Error whilst exposing VDI %s: %s", disk_uuid, err.Error()))
|
err = errors.New(fmt.Sprintf("Error whilst exposing VDI %s: %s", vdiRef, err.Error()))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
args = make(map[string]string)
|
args = make(map[string]string)
|
||||||
args["record_handle"] = handle
|
args["record_handle"] = handle
|
||||||
record_xml, err := host.CallPlugin("transfer", "get_record", args)
|
record_xml, err := c.client.Host.CallPlugin(c.session, host, "transfer", "get_record", args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.New(fmt.Sprintf("Unable to retrieve transfer record for VDI %s: %s", disk_uuid, err.Error()))
|
err = errors.New(fmt.Sprintf("Unable to retrieve transfer record for VDI %s: %s", vdiRef, err.Error()))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,17 +882,15 @@ func (self *VDI) Expose(format string) (url string, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unexpose a VDI if exposed with a Transfer VM.
|
func Unexpose(c *Connection, vdiRef xenapi.VDIRef) (err error) {
|
||||||
|
|
||||||
func (self *VDI) Unexpose() (err error) {
|
disk_uuid, err := c.client.VDI.GetUUID(c.session, vdiRef)
|
||||||
|
|
||||||
disk_uuid, err := self.GetUuid()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts, err := self.Client.GetHosts()
|
hosts, err := c.client.Host.GetAll(c.session)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.New(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
|
err = errors.New(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
|
||||||
@ -983,7 +902,7 @@ func (self *VDI) Unexpose() (err error) {
|
|||||||
args := make(map[string]string)
|
args := make(map[string]string)
|
||||||
args["vdi_uuid"] = disk_uuid
|
args["vdi_uuid"] = disk_uuid
|
||||||
|
|
||||||
result, err := host.CallPlugin("transfer", "unexpose", args)
|
result, err := c.client.Host.CallPlugin(c.session, host, "transfer", "unexpose", args)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -996,94 +915,65 @@ func (self *VDI) Unexpose() (err error) {
|
|||||||
|
|
||||||
// Task associated functions
|
// Task associated functions
|
||||||
|
|
||||||
func (self *Task) GetStatus() (status TaskStatusType, err error) {
|
// func (self *Task) GetResult() (object *XenAPIObject, err error) {
|
||||||
result := APIResult{}
|
// result := APIResult{}
|
||||||
err = self.Client.APICall(&result, "task.get_status", self.Ref)
|
// err = self.Client.APICall(&result, "task.get_result", self.Ref)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
rawStatus := result.Value.(string)
|
// switch ref := result.Value.(type) {
|
||||||
switch rawStatus {
|
// case string:
|
||||||
case "pending":
|
// // @fixme: xapi currently sends us an xmlrpc-encoded string via xmlrpc.
|
||||||
status = Pending
|
// // This seems to be a bug in xapi. Remove this workaround when it's fixed
|
||||||
case "success":
|
// re := regexp.MustCompile("^<value><array><data><value>([^<]*)</value>.*</data></array></value>$")
|
||||||
status = Success
|
// match := re.FindStringSubmatch(ref)
|
||||||
case "failure":
|
// if match == nil {
|
||||||
status = Failure
|
// object = nil
|
||||||
case "cancelling":
|
// } else {
|
||||||
status = Cancelling
|
// object = &XenAPIObject{
|
||||||
case "cancelled":
|
// Ref: match[1],
|
||||||
status = Cancelled
|
// Client: self.Client,
|
||||||
default:
|
// }
|
||||||
panic(fmt.Sprintf("Task.get_status: Unknown status '%s'", rawStatus))
|
// }
|
||||||
}
|
// case nil:
|
||||||
return
|
// object = nil
|
||||||
}
|
// default:
|
||||||
|
// err = fmt.Errorf("task.get_result: unknown value type %T (expected string or nil)", ref)
|
||||||
func (self *Task) GetProgress() (progress float64, err error) {
|
// }
|
||||||
result := APIResult{}
|
// return
|
||||||
err = self.Client.APICall(&result, "task.get_progress", self.Ref)
|
// }
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
progress = result.Value.(float64)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Task) GetResult() (object *XenAPIObject, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.get_result", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch ref := result.Value.(type) {
|
|
||||||
case string:
|
|
||||||
// @fixme: xapi currently sends us an xmlrpc-encoded string via xmlrpc.
|
|
||||||
// This seems to be a bug in xapi. Remove this workaround when it's fixed
|
|
||||||
re := regexp.MustCompile("^<value><array><data><value>([^<]*)</value>.*</data></array></value>$")
|
|
||||||
match := re.FindStringSubmatch(ref)
|
|
||||||
if match == nil {
|
|
||||||
object = nil
|
|
||||||
} else {
|
|
||||||
object = &XenAPIObject{
|
|
||||||
Ref: match[1],
|
|
||||||
Client: self.Client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case nil:
|
|
||||||
object = nil
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("task.get_result: unknown value type %T (expected string or nil)", ref)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Task) GetErrorInfo() (errorInfo []string, err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.get_error_info", self.Ref)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errorInfo = make([]string, 0)
|
|
||||||
for _, infoRaw := range result.Value.([]interface{}) {
|
|
||||||
errorInfo = append(errorInfo, fmt.Sprintf("%v", infoRaw))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Task) Destroy() (err error) {
|
|
||||||
result := APIResult{}
|
|
||||||
err = self.Client.APICall(&result, "task.destroy", self.Ref)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client Initiator
|
// Client Initiator
|
||||||
|
type Connection struct {
|
||||||
func NewXenAPIClient(host, username, password string) (client XenAPIClient) {
|
client *xenapi.Client
|
||||||
client.Host = host
|
session xenapi.SessionRef
|
||||||
client.Url = "http://" + host
|
Host string
|
||||||
client.Username = username
|
Username string
|
||||||
client.Password = password
|
Password string
|
||||||
client.RPC, _ = xmlrpc.NewClient(client.Url, nil)
|
}
|
||||||
return
|
|
||||||
|
func (c Connection) GetSession() string {
|
||||||
|
return string(c.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewXenAPIClient(host, username, password string) (*Connection, error) {
|
||||||
|
client, err := xenapi.NewClient("https://"+host, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err := client.Session.LoginWithPassword(username, password, "1.0", "packer")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Connection{client, session, host, username, password}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) GetClient() *xenapi.Client {
|
||||||
|
return c.client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) GetSessionRef() xenapi.SessionRef {
|
||||||
|
return c.session
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
commonssh "github.com/mitchellh/packer/common/ssh"
|
commonssh "github.com/mitchellh/packer/common/ssh"
|
||||||
"github.com/mitchellh/packer/template/interpolate"
|
"github.com/mitchellh/packer/template/interpolate"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommonConfig struct {
|
type CommonConfig struct {
|
||||||
@ -221,27 +220,3 @@ func (c CommonConfig) ShouldKeepVM(state multistep.StateBag) bool {
|
|||||||
panic(fmt.Sprintf("Unknown keep_vm value '%s'", c.KeepVM))
|
panic(fmt.Sprintf("Unknown keep_vm value '%s'", c.KeepVM))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config CommonConfig) GetSR(client xsclient.XenAPIClient) (*xsclient.SR, error) {
|
|
||||||
if config.SrName == "" {
|
|
||||||
// Find the default SR
|
|
||||||
return client.GetDefaultSR()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Use the provided name label to find the SR to use
|
|
||||||
srs, err := client.GetSRByNameLabel(config.SrName)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case len(srs) == 0:
|
|
||||||
return nil, fmt.Errorf("Couldn't find a SR with the specified name-label '%s'", config.SrName)
|
|
||||||
case len(srs) > 1:
|
|
||||||
return nil, fmt.Errorf("Found more than one SR with the name '%s'. The name must be unique", config.SrName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return srs[0], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,14 +3,15 @@ package common
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func appendQuery(urlstring, k, v string) (string, error) {
|
func appendQuery(urlstring, k, v string) (string, error) {
|
||||||
@ -24,18 +25,18 @@ func appendQuery(urlstring, k, v string) (string, error) {
|
|||||||
return u.String(), err
|
return u.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (result *xsclient.XenAPIObject, err error) {
|
func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (result string, err error) {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
task, err := client.CreateTask()
|
task, err := c.client.Task.Create(c.session, "packer-task", "Packer task")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Unable to create task: %s", err.Error())
|
err = fmt.Errorf("Unable to create task: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer task.Destroy()
|
defer c.client.Task.Destroy(c.session, task)
|
||||||
|
|
||||||
import_task_url, err := appendQuery(import_url, "task_id", task.Ref)
|
import_task_url, err := appendQuery(import_url, "task_id", string(task))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -75,13 +76,13 @@ func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (resul
|
|||||||
logIteration := 0
|
logIteration := 0
|
||||||
err = InterruptibleWait{
|
err = InterruptibleWait{
|
||||||
Predicate: func() (bool, error) {
|
Predicate: func() (bool, error) {
|
||||||
status, err := task.GetStatus()
|
status, err := c.client.Task.GetStatus(c.session, task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("Failed to get task status: %s", err.Error())
|
return false, fmt.Errorf("Failed to get task status: %s", err.Error())
|
||||||
}
|
}
|
||||||
switch status {
|
switch status {
|
||||||
case xsclient.Pending:
|
case xsclient.TaskStatusTypePending:
|
||||||
progress, err := task.GetProgress()
|
progress, err := c.client.Task.GetProgress(c.session, task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("Failed to get progress: %s", err.Error())
|
return false, fmt.Errorf("Failed to get progress: %s", err.Error())
|
||||||
}
|
}
|
||||||
@ -90,15 +91,15 @@ func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (resul
|
|||||||
log.Printf("Upload %.0f%% complete", progress*100)
|
log.Printf("Upload %.0f%% complete", progress*100)
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
case xsclient.Success:
|
case xsclient.TaskStatusTypeSuccess:
|
||||||
return true, nil
|
return true, nil
|
||||||
case xsclient.Failure:
|
case xsclient.TaskStatusTypeFailure:
|
||||||
errorInfo, err := task.GetErrorInfo()
|
errorInfo, err := c.client.Task.GetErrorInfo(c.session, task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorInfo = []string{fmt.Sprintf("furthermore, failed to get error info: %s", err.Error())}
|
errorInfo = []string{fmt.Sprintf("furthermore, failed to get error info: %s", err.Error())}
|
||||||
}
|
}
|
||||||
return false, fmt.Errorf("Task failed: %s", errorInfo)
|
return false, fmt.Errorf("Task failed: %s", errorInfo)
|
||||||
case xsclient.Cancelling, xsclient.Cancelled:
|
case xsclient.TaskStatusTypeCancelling, xsclient.TaskStatusTypeCancelled:
|
||||||
return false, fmt.Errorf("Task cancelled")
|
return false, fmt.Errorf("Task cancelled")
|
||||||
default:
|
default:
|
||||||
return false, fmt.Errorf("Unknown task status %v", status)
|
return false, fmt.Errorf("Unknown task status %v", status)
|
||||||
@ -115,7 +116,7 @@ func HTTPUpload(import_url string, fh *os.File, state multistep.StateBag) (resul
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err = task.GetResult()
|
result, err = c.client.Task.GetResult(c.session, task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Error getting result: %s", err.Error())
|
err = fmt.Errorf("Error getting result: %s", err.Error())
|
||||||
return
|
return
|
||||||
|
@ -2,22 +2,23 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepAttachVdi struct {
|
type StepAttachVdi struct {
|
||||||
VdiUuidKey string
|
VdiUuidKey string
|
||||||
VdiType xsclient.VDIType
|
VdiType xsclient.VbdType
|
||||||
|
|
||||||
vdi *xsclient.VDI
|
vdi xsclient.VDIRef
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
var vdiUuid string
|
var vdiUuid string
|
||||||
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
||||||
@ -28,20 +29,20 @@ func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
self.vdi, err = client.GetVdiByUuid(vdiUuid)
|
self.vdi, err = c.client.VDI.GetByUUID(c.session, vdiUuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.ConnectVdi(self.vdi, self.VdiType, "")
|
err = ConnectVdi(c, instance, self.vdi, self.VdiType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error attaching VDI '%s': '%s'", vdiUuid, err.Error()))
|
ui.Error(fmt.Sprintf("Error attaching VDI '%s': '%s'", vdiUuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -54,17 +55,18 @@ func (self *StepAttachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
func (self *StepAttachVdi) Cleanup(state multistep.StateBag) {
|
func (self *StepAttachVdi) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
if config.ShouldKeepVM(state) {
|
if config.ShouldKeepVM(state) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.vdi == nil {
|
// TODO: What the fuck does this mean?
|
||||||
|
if self.vdi == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
vmRef, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to get VM from UUID '%s': %s", uuid, err.Error())
|
log.Printf("Unable to get VM from UUID '%s': %s", uuid, err.Error())
|
||||||
return
|
return
|
||||||
@ -72,7 +74,7 @@ func (self *StepAttachVdi) Cleanup(state multistep.StateBag) {
|
|||||||
|
|
||||||
vdiUuid := state.Get(self.VdiUuidKey).(string)
|
vdiUuid := state.Get(self.VdiUuidKey).(string)
|
||||||
|
|
||||||
err = instance.DisconnectVdi(self.vdi)
|
err = DisconnectVdi(c, vmRef, self.vdi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to disconnect VDI '%s': %s", vdiUuid, err.Error())
|
log.Printf("Unable to disconnect VDI '%s': %s", vdiUuid, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -2,21 +2,21 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepBootWait struct{}
|
type StepBootWait struct{}
|
||||||
|
|
||||||
func (self *StepBootWait) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepBootWait) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
instance, _ := client.GetVMByUuid(state.Get("instance_uuid").(string))
|
instance, _ := c.client.VM.GetByUUID(c.session, state.Get("instance_uuid").(string))
|
||||||
ui.Say("Unpausing VM " + state.Get("instance_uuid").(string))
|
ui.Say("Unpausing VM " + state.Get("instance_uuid").(string))
|
||||||
instance.Unpause()
|
Unpause(c, instance)
|
||||||
|
|
||||||
if int64(config.BootWait) > 0 {
|
if int64(config.BootWait) > 0 {
|
||||||
ui.Say(fmt.Sprintf("Waiting %s for boot...", config.BootWait))
|
ui.Say(fmt.Sprintf("Waiting %s for boot...", config.BootWait))
|
||||||
|
@ -2,10 +2,10 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepDetachVdi struct {
|
type StepDetachVdi struct {
|
||||||
@ -14,7 +14,7 @@ type StepDetachVdi struct {
|
|||||||
|
|
||||||
func (self *StepDetachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepDetachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
var vdiUuid string
|
var vdiUuid string
|
||||||
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
if vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey); ok {
|
||||||
@ -24,20 +24,20 @@ func (self *StepDetachVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
vdi, err := client.GetVdiByUuid(vdiUuid)
|
vdi, err := c.client.VDI.GetByUUID(c.session, vdiUuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.DisconnectVdi(vdi)
|
err = DisconnectVdi(c, instance, vdi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to detach VDI '%s': %s", vdiUuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to detach VDI '%s': %s", vdiUuid, err.Error()))
|
||||||
//return multistep.ActionHalt
|
//return multistep.ActionHalt
|
||||||
|
@ -3,13 +3,13 @@ package common
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepExport struct{}
|
type StepExport struct{}
|
||||||
@ -82,33 +82,33 @@ func downloadFile(url, filename string, ui packer.Ui) (err error) {
|
|||||||
func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
instance_uuid := state.Get("instance_uuid").(string)
|
instance_uuid := state.Get("instance_uuid").(string)
|
||||||
suffix := ".vhd"
|
suffix := ".vhd"
|
||||||
extrauri := "&format=vhd"
|
extrauri := "&format=vhd"
|
||||||
|
|
||||||
instance, err := client.GetVMByUuid(instance_uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, instance_uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not get VM with UUID '%s': %s", instance_uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Could not get VM with UUID '%s': %s", instance_uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(config.ExportNetworkNames) > 0 {
|
if len(config.ExportNetworkNames) > 0 {
|
||||||
vifs, err := instance.GetVIFs()
|
vifs, err := c.client.VM.GetVIFs(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error occured getting VIFs: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error occured getting VIFs: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, vif := range vifs {
|
for _, vif := range vifs {
|
||||||
err := vif.Destroy()
|
err := c.client.VIF.Destroy(c.session, vif)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Destroy vif fail: '%s': %s", vif.Ref, err.Error()))
|
ui.Error(fmt.Sprintf("Destroy vif fail: '%s': %s", vif, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, networkNameLabel := range config.ExportNetworkNames {
|
for i, networkNameLabel := range config.ExportNetworkNames {
|
||||||
networks, err := client.GetNetworkByNameLabel(networkNameLabel)
|
networks, err := c.client.Network.GetByNameLabel(c.session, networkNameLabel)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
|
||||||
@ -126,7 +126,7 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
//we need the VIF index string
|
//we need the VIF index string
|
||||||
vifIndexString := fmt.Sprintf("%d", i)
|
vifIndexString := fmt.Sprintf("%d", i)
|
||||||
_, err = instance.ConnectNetwork(networks[0], vifIndexString)
|
_, err = ConnectNetwork(c, networks[0], instance, vifIndexString)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say(err.Error())
|
ui.Say(err.Error())
|
||||||
@ -157,10 +157,10 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
if xe, e := exec.LookPath("xe"); e == nil && use_xe {
|
if xe, e := exec.LookPath("xe"); e == nil && use_xe {
|
||||||
cmd := exec.Command(
|
cmd := exec.Command(
|
||||||
xe,
|
xe,
|
||||||
"-s", client.Host,
|
"-s", c.Host,
|
||||||
"-p", "443",
|
"-p", "443",
|
||||||
"-u", client.Username,
|
"-u", c.Username,
|
||||||
"-pw", client.Password,
|
"-pw", c.Password,
|
||||||
"vm-export",
|
"vm-export",
|
||||||
"vm="+instance_uuid,
|
"vm="+instance_uuid,
|
||||||
compress_option_xe,
|
compress_option_xe,
|
||||||
@ -172,10 +172,10 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
} else {
|
} else {
|
||||||
export_url := fmt.Sprintf("https://%s/export?%suuid=%s&session_id=%s",
|
export_url := fmt.Sprintf("https://%s/export?%suuid=%s&session_id=%s",
|
||||||
client.Host,
|
c.Host,
|
||||||
compress_option_url,
|
compress_option_url,
|
||||||
instance_uuid,
|
instance_uuid,
|
||||||
client.Session.(string),
|
c.GetSession(),
|
||||||
)
|
)
|
||||||
|
|
||||||
ui.Say("Getting XVA " + export_url)
|
ui.Say("Getting XVA " + export_url)
|
||||||
@ -194,28 +194,28 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
case "vdi_vhd":
|
case "vdi_vhd":
|
||||||
// export the disks
|
// export the disks
|
||||||
|
|
||||||
disks, err := instance.GetDisks()
|
disks, err := GetDisks(c, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not get VM disks: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Could not get VM disks: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
for _, disk := range disks {
|
for _, disk := range disks {
|
||||||
disk_uuid, err := disk.GetUuid()
|
disk_uuid, err := c.client.VDI.GetUUID(c.session, disk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not get disk with UUID '%s': %s", disk_uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Could not get disk with UUID '%s': %s", disk_uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work out XenServer version
|
// Work out XenServer version
|
||||||
hosts, err := client.GetHosts()
|
hosts, err := c.client.Host.GetAll(c.session)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
host := hosts[0]
|
host := hosts[0]
|
||||||
host_software_versions, err := host.GetSoftwareVersion()
|
host_software_versions, err := c.client.Host.GetSoftwareVersion(c.session, host)
|
||||||
xs_version := host_software_versions["product_version"].(string)
|
xs_version := host_software_versions["product_version"]
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not get the software version: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Could not get the software version: %s", err.Error()))
|
||||||
@ -228,7 +228,7 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
if xs_version <= "6.5.0" && config.Format == "vdi_vhd" {
|
if xs_version <= "6.5.0" && config.Format == "vdi_vhd" {
|
||||||
// Export the VHD using a Transfer VM
|
// Export the VHD using a Transfer VM
|
||||||
|
|
||||||
disk_export_url, err = disk.Expose("vhd")
|
disk_export_url, err = Expose(c, disk, "vhd")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Failed to expose disk %s: %s", disk_uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Failed to expose disk %s: %s", disk_uuid, err.Error()))
|
||||||
@ -242,9 +242,9 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
// accepted for some reason.
|
// accepted for some reason.
|
||||||
// @todo: raise with XAPI team.
|
// @todo: raise with XAPI team.
|
||||||
disk_export_url = fmt.Sprintf("https://%s:%s@%s/export_raw_vdi?vdi=%s%s",
|
disk_export_url = fmt.Sprintf("https://%s:%s@%s/export_raw_vdi?vdi=%s%s",
|
||||||
client.Username,
|
c.Username,
|
||||||
client.Password,
|
c.Password,
|
||||||
client.Host,
|
c.Host,
|
||||||
disk_uuid,
|
disk_uuid,
|
||||||
extrauri)
|
extrauri)
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
// Call unexpose in case a TVM was used. The call is harmless
|
// Call unexpose in case a TVM was used. The call is harmless
|
||||||
// if that is not the case.
|
// if that is not the case.
|
||||||
disk.Unexpose()
|
Unexpose(c, disk)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepFindVdi struct {
|
type StepFindVdi struct {
|
||||||
@ -15,14 +15,14 @@ type StepFindVdi struct {
|
|||||||
|
|
||||||
func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
// Ignore if VdiName is not specified
|
// Ignore if VdiName is not specified
|
||||||
if self.VdiName == "" {
|
if self.VdiName == "" {
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
vdis, err := client.GetVdiByNameLabel(self.VdiName)
|
vdis, err := c.client.VDI.GetByNameLabel(c.session, self.VdiName)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case len(vdis) == 0:
|
case len(vdis) == 0:
|
||||||
@ -35,7 +35,7 @@ func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
vdi := vdis[0]
|
vdi := vdis[0]
|
||||||
|
|
||||||
vdiUuid, err := vdi.GetUuid()
|
vdiUuid, err := c.client.VDI.GetUUID(c.session, vdi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", self.VdiName, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", self.VdiName, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
@ -2,9 +2,10 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepGetVNCPort struct{}
|
type StepGetVNCPort struct{}
|
||||||
@ -14,8 +15,8 @@ func (self *StepGetVNCPort) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
ui.Say("Step: forward the instances VNC port over SSH")
|
ui.Say("Step: forward the instances VNC port over SSH")
|
||||||
|
|
||||||
domid := state.Get("domid").(string)
|
domid := state.Get("domid").(int)
|
||||||
cmd := fmt.Sprintf("xenstore-read /local/domain/%s/console/vnc-port", domid)
|
cmd := fmt.Sprintf("xenstore-read /local/domain/%d/console/vnc-port", domid)
|
||||||
|
|
||||||
remote_vncport, err := ExecuteHostSSHCmd(state, cmd)
|
remote_vncport, err := ExecuteHostSSHCmd(state, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2,33 +2,33 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepSetVmHostSshAddress struct{}
|
type StepSetVmHostSshAddress struct{}
|
||||||
|
|
||||||
func (self *StepSetVmHostSshAddress) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepSetVmHostSshAddress) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Step: Set SSH address to VM host IP")
|
ui.Say("Step: Set SSH address to VM host IP")
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := instance.GetResidentOn()
|
host, err := c.client.VM.GetResidentOn(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM Host for VM '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM Host for VM '%s': %s", uuid, err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
address, err := host.GetAddress()
|
address, err := c.client.Host.GetAddress(c.session, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get address from VM Host: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get address from VM Host: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
xenapi "github.com/terra-farm/go-xen-api-client"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepShutdown struct{}
|
type StepShutdown struct{}
|
||||||
@ -13,10 +14,10 @@ type StepShutdown struct{}
|
|||||||
func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
instance_uuid := state.Get("instance_uuid").(string)
|
instance_uuid := state.Get("instance_uuid").(string)
|
||||||
|
|
||||||
instance, err := client.GetVMByUuid(instance_uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, instance_uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not get VM with UUID '%s': %s", instance_uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Could not get VM with UUID '%s': %s", instance_uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -39,8 +40,8 @@ func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
err = InterruptibleWait{
|
err = InterruptibleWait{
|
||||||
Predicate: func() (bool, error) {
|
Predicate: func() (bool, error) {
|
||||||
power_state, err := instance.GetPowerState()
|
power_state, err := c.client.VM.GetPowerState(c.session, instance)
|
||||||
return power_state == "Halted", err
|
return power_state == xenapi.VMPowerStateHalted, err
|
||||||
},
|
},
|
||||||
PredicateInterval: 5 * time.Second,
|
PredicateInterval: 5 * time.Second,
|
||||||
Timeout: 300 * time.Second,
|
Timeout: 300 * time.Second,
|
||||||
@ -54,7 +55,7 @@ func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
} else {
|
} else {
|
||||||
ui.Message("Attempting to cleanly shutdown the VM...")
|
ui.Message("Attempting to cleanly shutdown the VM...")
|
||||||
|
|
||||||
err = instance.CleanShutdown()
|
err = c.client.VM.CleanShutdown(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not shut down VM: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Could not shut down VM: %s", err.Error()))
|
||||||
return false
|
return false
|
||||||
@ -66,7 +67,7 @@ func (StepShutdown) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
|
|
||||||
if !success {
|
if !success {
|
||||||
ui.Say("WARNING: Forcing hard shutdown of the VM...")
|
ui.Say("WARNING: Forcing hard shutdown of the VM...")
|
||||||
err = instance.HardShutdown()
|
err = c.client.VM.HardShutdown(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Could not hard shut down VM -- giving up: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Could not hard shut down VM -- giving up: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
@ -2,12 +2,12 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
gossh "golang.org/x/crypto/ssh"
|
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
gossh "golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepStartOnHIMN struct{}
|
type StepStartOnHIMN struct{}
|
||||||
@ -23,19 +23,19 @@ type StepStartOnHIMN struct{}
|
|||||||
func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
ui.Say("Step: Start VM on the Host Internal Mangement Network")
|
ui.Say("Step: Start VM on the Host Internal Mangement Network")
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the HIMN Ref
|
// Find the HIMN Ref
|
||||||
networks, err := client.GetNetworkByNameLabel("Host internal management network")
|
networks, err := c.client.Network.GetByNameLabel(c.session, "Host internal management network")
|
||||||
if err != nil || len(networks) == 0 {
|
if err != nil || len(networks) == 0 {
|
||||||
ui.Error("Unable to find a host internal management network")
|
ui.Error("Unable to find a host internal management network")
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
@ -45,7 +45,7 @@ func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction
|
|||||||
himn := networks[0]
|
himn := networks[0]
|
||||||
|
|
||||||
// Create a VIF for the HIMN
|
// Create a VIF for the HIMN
|
||||||
himn_vif, err := instance.ConnectNetwork(himn, "0")
|
himn_vif, err := ConnectNetwork(c, himn, instance, "0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error("Error creating VIF")
|
ui.Error("Error creating VIF")
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
@ -53,22 +53,22 @@ func (self *StepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start the VM
|
// Start the VM
|
||||||
instance.Start(false, false)
|
c.client.VM.Start(c.session, instance, false, false)
|
||||||
|
|
||||||
var himn_iface_ip string = ""
|
var himn_iface_ip string = ""
|
||||||
|
|
||||||
// Obtain the allocated IP
|
// Obtain the allocated IP
|
||||||
err = InterruptibleWait{
|
err = InterruptibleWait{
|
||||||
Predicate: func() (found bool, err error) {
|
Predicate: func() (found bool, err error) {
|
||||||
ips, err := himn.GetAssignedIPs()
|
ips, err := c.client.Network.GetAssignedIps(c.session, himn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("Can't get assigned IPs: %s", err.Error())
|
return false, fmt.Errorf("Can't get assigned IPs: %s", err.Error())
|
||||||
}
|
}
|
||||||
log.Printf("IPs: %s", ips)
|
log.Printf("IPs: %s", ips)
|
||||||
log.Printf("Ref: %s", instance.Ref)
|
log.Printf("Ref: %s", instance)
|
||||||
|
|
||||||
//Check for instance.Ref in map
|
//Check for instance.Ref in map
|
||||||
if vm_ip, ok := ips[himn_vif.Ref]; ok && vm_ip != "" {
|
if vm_ip, ok := ips[*himn_vif]; ok && vm_ip != "" {
|
||||||
ui.Say("Found the VM's IP: " + vm_ip)
|
ui.Say("Found the VM's IP: " + vm_ip)
|
||||||
himn_iface_ip = vm_ip
|
himn_iface_ip = vm_ip
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -2,42 +2,49 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepStartVmPaused struct{}
|
type StepStartVmPaused struct{}
|
||||||
|
|
||||||
func (self *StepStartVmPaused) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepStartVmPaused) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Step: Start VM Paused")
|
ui.Say("Step: Start VM Paused")
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
// note that here "cd" means boot from hard drive ('c') first, then CDROM ('d')
|
// note that here "cd" means boot from hard drive ('c') first, then CDROM ('d')
|
||||||
err = instance.SetHVMBoot("BIOS order", "cd")
|
err = c.client.VM.SetHVMBootPolicy(c.session, instance, "BIOS order")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to set HVM boot params: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to set HVM boot params: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.Start(true, false)
|
err = c.client.VM.SetHVMBootParams(c.session, instance, map[string]string{"order": "cd"})
|
||||||
|
if err != nil {
|
||||||
|
ui.Error(fmt.Sprintf("Unable to set HVM boot params: %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.client.VM.Start(c.session, instance, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to start VM with UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to start VM with UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
domid, err := instance.GetDomainId()
|
domid, err := c.client.VM.GetDomid(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get domid of VM with UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get domid of VM with UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -49,20 +56,20 @@ func (self *StepStartVmPaused) Run(state multistep.StateBag) multistep.StepActio
|
|||||||
|
|
||||||
func (self *StepStartVmPaused) Cleanup(state multistep.StateBag) {
|
func (self *StepStartVmPaused) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
if config.ShouldKeepVM(state) {
|
if config.ShouldKeepVM(state) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
log.Printf(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.HardShutdown()
|
err = c.client.VM.HardShutdown(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf(fmt.Sprintf("Unable to force shutdown VM '%s': %s", uuid, err.Error()))
|
log.Printf(fmt.Sprintf("Unable to force shutdown VM '%s': %s", uuid, err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,17 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/go-vnc"
|
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
"github.com/mitchellh/packer/template/interpolate"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-vnc"
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"github.com/mitchellh/packer/template/interpolate"
|
||||||
)
|
)
|
||||||
|
|
||||||
const KeyLeftShift uint = 0xFFE1
|
const KeyLeftShift uint = 0xFFE1
|
||||||
@ -195,7 +196,9 @@ func vncSendString(c *vnc.ClientConn, original string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.KeyEvent(keyCode, true)
|
c.KeyEvent(keyCode, true)
|
||||||
|
time.Sleep(time.Second / 10)
|
||||||
c.KeyEvent(keyCode, false)
|
c.KeyEvent(keyCode, false)
|
||||||
|
time.Sleep(time.Second / 10)
|
||||||
|
|
||||||
if keyShift {
|
if keyShift {
|
||||||
c.KeyEvent(uint32(KeyLeftShift), false)
|
c.KeyEvent(uint32(KeyLeftShift), false)
|
||||||
|
@ -2,12 +2,13 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
|
||||||
"github.com/mitchellh/packer/packer"
|
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
xenapi "github.com/terra-farm/go-xen-api-client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepUploadVdi struct {
|
type StepUploadVdi struct {
|
||||||
@ -17,9 +18,8 @@ type StepUploadVdi struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
imagePath := self.ImagePathFunc()
|
imagePath := self.ImagePathFunc()
|
||||||
vdiName := self.VdiNameFunc()
|
vdiName := self.VdiNameFunc()
|
||||||
@ -31,7 +31,12 @@ func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
ui.Say(fmt.Sprintf("Step: Upload VDI '%s'", vdiName))
|
ui.Say(fmt.Sprintf("Step: Upload VDI '%s'", vdiName))
|
||||||
|
|
||||||
// Create VDI for the image
|
// Create VDI for the image
|
||||||
sr, err := config.GetSR(client)
|
srs, err := c.client.SR.GetAll(c.session)
|
||||||
|
ui.Say(fmt.Sprintf("Step: Found SRs '%v'", srs))
|
||||||
|
|
||||||
|
srs, err = c.client.SR.GetByNameLabel(c.session, "LocalISO")
|
||||||
|
sr := srs[0]
|
||||||
|
ui.Say(fmt.Sprintf("Step: Found SRs '%v' Choosing: '%v'", srs, sr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -53,13 +58,24 @@ func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
fileLength := fstat.Size()
|
fileLength := fstat.Size()
|
||||||
|
|
||||||
// Create the VDI
|
// Create the VDI
|
||||||
vdi, err := sr.CreateVdi(vdiName, fileLength)
|
// vdi, err := sr.CreateVdi(vdiName, fileLength)
|
||||||
|
vdi, err := c.client.VDI.Create(c.session, xenapi.VDIRecord{
|
||||||
|
NameLabel: vdiName,
|
||||||
|
VirtualSize: int(fileLength),
|
||||||
|
Type: "user",
|
||||||
|
Sharable: false,
|
||||||
|
ReadOnly: false,
|
||||||
|
SR: sr,
|
||||||
|
OtherConfig: map[string]string{
|
||||||
|
"temp": "temp",
|
||||||
|
},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to create VDI '%s': %s", vdiName, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to create VDI '%s': %s", vdiName, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
vdiUuid, err := vdi.GetUuid()
|
vdiUuid, err := c.client.VDI.GetUUID(c.session, vdi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", vdiName, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", vdiName, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -67,9 +83,9 @@ func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
state.Put(self.VdiUuidKey, vdiUuid)
|
state.Put(self.VdiUuidKey, vdiUuid)
|
||||||
|
|
||||||
_, err = HTTPUpload(fmt.Sprintf("https://%s/import_raw_vdi?vdi=%s&session_id=%s",
|
_, err = HTTPUpload(fmt.Sprintf("https://%s/import_raw_vdi?vdi=%s&session_id=%s",
|
||||||
client.Host,
|
c.Host,
|
||||||
vdi.Ref,
|
vdi,
|
||||||
client.Session.(string),
|
c.GetSession(),
|
||||||
), fh, state)
|
), fh, state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to upload VDI: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to upload VDI: %s", err.Error()))
|
||||||
@ -82,7 +98,7 @@ func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
|
func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
|
|
||||||
vdiName := self.VdiNameFunc()
|
vdiName := self.VdiNameFunc()
|
||||||
|
|
||||||
@ -102,7 +118,7 @@ func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vdi, err := client.GetVdiByUuid(vdiUuid)
|
vdi, err := c.client.VDI.GetByUUID(c.session, vdiUuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Can't get VDI '%s': %s", vdiUuid, err.Error()))
|
ui.Error(fmt.Sprintf("Can't get VDI '%s': %s", vdiUuid, err.Error()))
|
||||||
return
|
return
|
||||||
@ -112,7 +128,7 @@ func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
|
|||||||
// so try several times
|
// so try several times
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
log.Printf("Trying to destroy VDI...")
|
log.Printf("Trying to destroy VDI...")
|
||||||
err = vdi.Destroy()
|
err = c.client.VDI.Destroy(c.session, vdi)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/nilshell/xmlrpc"
|
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepWaitForIP struct {
|
type StepWaitForIP struct {
|
||||||
@ -17,13 +15,13 @@ type StepWaitForIP struct {
|
|||||||
|
|
||||||
func (self *StepWaitForIP) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *StepWaitForIP) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*Connection)
|
||||||
config := state.Get("commonconfig").(CommonConfig)
|
config := state.Get("commonconfig").(CommonConfig)
|
||||||
|
|
||||||
ui.Say("Step: Wait for VM's IP to become known to us.")
|
ui.Say("Step: Wait for VM's IP to become known to us.")
|
||||||
|
|
||||||
uuid := state.Get("instance_uuid").(string)
|
uuid := state.Get("instance_uuid").(string)
|
||||||
instance, err := client.GetVMByUuid(uuid)
|
instance, err := c.client.VM.GetByUUID(c.session, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM from UUID '%s': %s", uuid, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -50,14 +48,18 @@ func (self *StepWaitForIP) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
if config.IPGetter == "auto" || config.IPGetter == "tools" {
|
if config.IPGetter == "auto" || config.IPGetter == "tools" {
|
||||||
|
|
||||||
// Look for PV IP
|
// Look for PV IP
|
||||||
metrics, err := instance.GetGuestMetrics()
|
m, err := c.client.VM.GetGuestMetrics(c.session, instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if metrics != nil {
|
if m != "" {
|
||||||
networks := metrics["networks"].(xmlrpc.Struct)
|
metrics, err := c.client.VMGuestMetrics.GetRecord(c.session, m)
|
||||||
if ipRaw, ok := networks["0/ip"]; ok {
|
if err != nil {
|
||||||
if ip = ipRaw.(string); ip != "" {
|
return false, err
|
||||||
|
}
|
||||||
|
networks := metrics.Networks
|
||||||
|
if ip, ok := networks["0/ip"]; ok {
|
||||||
|
if ip != "" {
|
||||||
ui.Message(fmt.Sprintf("Got IP '%s' from XenServer tools", ip))
|
ui.Message(fmt.Sprintf("Got IP '%s' from XenServer tools", ip))
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
hconfig "github.com/mitchellh/packer/helper/config"
|
hconfig "github.com/mitchellh/packer/helper/config"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/mitchellh/packer/template/interpolate"
|
"github.com/mitchellh/packer/template/interpolate"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
||||||
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -191,21 +191,19 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||||
//Setup XAPI client
|
c, err := xscommon.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
||||||
client := xsclient.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
|
||||||
|
|
||||||
err := client.Login()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.(error)
|
return nil, err
|
||||||
}
|
}
|
||||||
ui.Say("XAPI client session established")
|
ui.Say("XAPI client session established")
|
||||||
|
|
||||||
client.GetHosts()
|
c.GetClient().Host.GetAll(c.GetSessionRef())
|
||||||
|
|
||||||
//Share state between the other steps using a statebag
|
//Share state between the other steps using a statebag
|
||||||
state := new(multistep.BasicStateBag)
|
state := new(multistep.BasicStateBag)
|
||||||
state.Put("cache", cache)
|
state.Put("cache", cache)
|
||||||
state.Put("client", client)
|
state.Put("client", c)
|
||||||
state.Put("config", self.config)
|
state.Put("config", self.config)
|
||||||
state.Put("commonconfig", self.config.CommonConfig)
|
state.Put("commonconfig", self.config.CommonConfig)
|
||||||
state.Put("hook", hook)
|
state.Put("hook", hook)
|
||||||
@ -273,19 +271,19 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
|||||||
new(stepCreateInstance),
|
new(stepCreateInstance),
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "floppy_vdi_uuid",
|
VdiUuidKey: "floppy_vdi_uuid",
|
||||||
VdiType: xsclient.Floppy,
|
VdiType: xsclient.VbdTypeFloppy,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "iso_vdi_uuid",
|
VdiUuidKey: "iso_vdi_uuid",
|
||||||
VdiType: xsclient.CD,
|
VdiType: xsclient.VbdTypeCD,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "isoname_vdi_uuid",
|
VdiUuidKey: "isoname_vdi_uuid",
|
||||||
VdiType: xsclient.CD,
|
VdiType: xsclient.VbdTypeCD,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "tools_vdi_uuid",
|
VdiUuidKey: "tools_vdi_uuid",
|
||||||
VdiType: xsclient.CD,
|
VdiType: xsclient.VbdTypeCD,
|
||||||
},
|
},
|
||||||
new(xscommon.StepStartVmPaused),
|
new(xscommon.StepStartVmPaused),
|
||||||
new(xscommon.StepSetVmHostSshAddress),
|
new(xscommon.StepSetVmHostSshAddress),
|
||||||
|
@ -5,17 +5,19 @@ import (
|
|||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
xenapi "github.com/terra-farm/go-xen-api-client"
|
||||||
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
||||||
|
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepCreateInstance struct {
|
type stepCreateInstance struct {
|
||||||
instance *xsclient.VM
|
instance *xsclient.VMRef
|
||||||
vdi *xsclient.VDI
|
vdi *xsclient.VDIRef
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*xscommon.Connection)
|
||||||
config := state.Get("config").(config)
|
config := state.Get("config").(config)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
|
|
||||||
// Get the template to clone from
|
// Get the template to clone from
|
||||||
|
|
||||||
vms, err := client.GetVMByNameLabel(config.CloneTemplate)
|
vms, err := c.GetClient().VM.GetByNameLabel(c.GetSessionRef(), config.CloneTemplate)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case len(vms) == 0:
|
case len(vms) == 0:
|
||||||
@ -37,51 +39,51 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
template := vms[0]
|
template := vms[0]
|
||||||
|
|
||||||
// Clone that VM template
|
// Clone that VM template
|
||||||
instance, err := template.Clone(config.VMName)
|
instance, err := c.GetClient().VM.Clone(c.GetSessionRef(), template, config.VMName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error cloning VM: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error cloning VM: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
self.instance = instance
|
self.instance = &instance
|
||||||
|
|
||||||
err = instance.SetIsATemplate(false)
|
err = c.GetClient().VM.SetIsATemplate(c.GetSessionRef(), instance, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting is_a_template=false: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error setting is_a_template=false: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.SetVCPUsMax(config.VCPUsMax)
|
err = c.GetClient().VM.SetVCPUsMax(c.GetSessionRef(), instance, int(config.VCPUsMax))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM VCPUs Max=%d: %s", config.VCPUsMax, err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM VCPUs Max=%d: %s", config.VCPUsMax, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.SetVCPUsAtStartup(config.VCPUsAtStartup)
|
err = c.GetClient().VM.SetVCPUsAtStartup(c.GetSessionRef(), instance, int(config.VCPUsAtStartup))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM VCPUs At Startup=%d: %s", config.VCPUsAtStartup, err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM VCPUs At Startup=%d: %s", config.VCPUsAtStartup, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.SetStaticMemoryRange(uint64(config.VMMemory*1024*1024), uint64(config.VMMemory*1024*1024))
|
// err = c.GetClient().VM.SetMemoryStaticRange(c.GetSessionRef(), instance, int(config.VMMemory*1024*1024), int(config.VMMemory*1024*1024))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM memory=%d: %s", config.VMMemory*1024*1024, err.Error()))
|
// ui.Error(fmt.Sprintf("Error setting VM memory=%d: %s", config.VMMemory*1024*1024, err.Error()))
|
||||||
return multistep.ActionHalt
|
// return multistep.ActionHalt
|
||||||
}
|
// }
|
||||||
|
|
||||||
err = instance.SetPlatform(config.PlatformArgs)
|
err = c.GetClient().VM.SetPlatform(c.GetSessionRef(), instance, config.PlatformArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM platform: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM platform: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.SetDescription(config.VMDescription)
|
err = c.GetClient().VM.SetNameDescription(c.GetSessionRef(), instance, config.VMDescription)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM description: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM description: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(config.VMOtherConfig) != 0 {
|
if len(config.VMOtherConfig) != 0 {
|
||||||
vm_other_config, err := instance.GetOtherConfig()
|
vm_other_config, err := c.GetClient().VM.GetOtherConfig(c.GetSessionRef(), instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error getting VM other-config: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error getting VM other-config: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -89,7 +91,7 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
for key, value := range config.VMOtherConfig {
|
for key, value := range config.VMOtherConfig {
|
||||||
vm_other_config[key] = value
|
vm_other_config[key] = value
|
||||||
}
|
}
|
||||||
err = instance.SetOtherConfig(vm_other_config)
|
err = c.GetClient().VM.SetOtherConfig(c.GetSessionRef(), instance, vm_other_config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM other-config: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM other-config: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -98,20 +100,31 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
|
|
||||||
// Create VDI for the instance
|
// Create VDI for the instance
|
||||||
|
|
||||||
sr, err := config.GetSR(client)
|
srs, err := c.GetClient().SR.GetByNameLabel(c.GetSessionRef(), "Local storage")
|
||||||
|
sr := srs[0]
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
vdi, err := sr.CreateVdi("Packer-disk", int64(config.DiskSize*1024*1024))
|
vdi, err := c.GetClient().VDI.Create(c.GetSessionRef(), xenapi.VDIRecord{
|
||||||
|
NameLabel: "Packer-disk",
|
||||||
|
VirtualSize: int(config.DiskSize * 1024 * 1024),
|
||||||
|
Type: "user",
|
||||||
|
Sharable: false,
|
||||||
|
ReadOnly: false,
|
||||||
|
SR: sr,
|
||||||
|
OtherConfig: map[string]string{
|
||||||
|
"temp": "temp",
|
||||||
|
},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to create packer disk VDI: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to create packer disk VDI: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
self.vdi = vdi
|
self.vdi = &vdi
|
||||||
|
|
||||||
err = instance.ConnectVdi(vdi, xsclient.Disk, "")
|
err = xscommon.ConnectVdi(c, instance, vdi, xsclient.VbdTypeDisk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to connect packer disk VDI: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to connect packer disk VDI: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -119,15 +132,11 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
|
|
||||||
// Connect Network
|
// Connect Network
|
||||||
|
|
||||||
var network *xsclient.Network
|
var network xsclient.NetworkRef
|
||||||
|
|
||||||
if len(config.NetworkNames) == 0 {
|
if len(config.NetworkNames) == 0 {
|
||||||
// No network has be specified. Use the management interface
|
// No network has be specified. Use the management interface
|
||||||
network = new(xsclient.Network)
|
pifs, err := c.GetClient().PIF.GetAll(c.GetSessionRef())
|
||||||
network.Ref = ""
|
|
||||||
network.Client = &client
|
|
||||||
|
|
||||||
pifs, err := client.GetPIFs()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error getting PIFs: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error getting PIFs: %s", err.Error()))
|
||||||
@ -135,25 +144,25 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, pif := range pifs {
|
for _, pif := range pifs {
|
||||||
pif_rec, err := pif.GetRecord()
|
pif_rec, err := c.GetClient().PIF.GetRecord(c.GetSessionRef(), pif)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error getting PIF record: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error getting PIF record: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
if pif_rec["management"].(bool) {
|
if pif_rec.Management {
|
||||||
network.Ref = pif_rec["network"].(string)
|
network = pif_rec.Network
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if network.Ref == "" {
|
if string(network) == "" {
|
||||||
ui.Error("Error: couldn't find management network. Aborting.")
|
ui.Error("Error: couldn't find management network. Aborting.")
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = instance.ConnectNetwork(network, "0")
|
_, err = xscommon.ConnectNetwork(c, network, instance, "0")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say(err.Error())
|
ui.Say(err.Error())
|
||||||
@ -162,7 +171,7 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
} else {
|
} else {
|
||||||
// Look up each network by it's name label
|
// Look up each network by it's name label
|
||||||
for i, networkNameLabel := range config.NetworkNames {
|
for i, networkNameLabel := range config.NetworkNames {
|
||||||
networks, err := client.GetNetworkByNameLabel(networkNameLabel)
|
networks, err := c.GetClient().Network.GetByNameLabel(c.GetSessionRef(), networkNameLabel)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
|
||||||
@ -180,15 +189,15 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
|
|
||||||
//we need the VIF index string
|
//we need the VIF index string
|
||||||
vifIndexString := fmt.Sprintf("%d", i)
|
vifIndexString := fmt.Sprintf("%d", i)
|
||||||
_, err = instance.ConnectNetwork(networks[0], vifIndexString)
|
_, err = xscommon.ConnectNetwork(c, networks[0], instance, vifIndexString)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say(err.Error())
|
ui.Say(fmt.Sprintf("Failed to connect VIF with error: %v", err.Error()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceId, err := instance.GetUuid()
|
instanceId, err := c.GetClient().VM.GetUUID(c.GetSessionRef(), instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM UUID: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM UUID: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -207,11 +216,12 @@ func (self *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
c := state.Get("client").(*xscommon.Connection)
|
||||||
|
|
||||||
if self.instance != nil {
|
if self.instance != nil {
|
||||||
ui.Say("Destroying VM")
|
ui.Say("Destroying VM")
|
||||||
_ = self.instance.HardShutdown() // redundant, just in case
|
_ = c.GetClient().VM.HardShutdown(c.GetSessionRef(), *self.instance) // redundant, just in case
|
||||||
err := self.instance.Destroy()
|
err := c.GetClient().VM.Destroy(c.GetSessionRef(), *self.instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
}
|
}
|
||||||
@ -219,7 +229,7 @@ func (self *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
|||||||
|
|
||||||
if self.vdi != nil {
|
if self.vdi != nil {
|
||||||
ui.Say("Destroying VDI")
|
ui.Say("Destroying VDI")
|
||||||
err := self.vdi.Destroy()
|
err := c.GetClient().VDI.Destroy(c.GetSessionRef(), *self.vdi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
hconfig "github.com/mitchellh/packer/helper/config"
|
hconfig "github.com/mitchellh/packer/helper/config"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/mitchellh/packer/template/interpolate"
|
"github.com/mitchellh/packer/template/interpolate"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
||||||
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,10 +20,10 @@ type config struct {
|
|||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
xscommon.CommonConfig `mapstructure:",squash"`
|
xscommon.CommonConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
SourcePath string `mapstructure:"source_path"`
|
SourcePath string `mapstructure:"source_path"`
|
||||||
VCPUsMax uint `mapstructure:"vcpus_max"`
|
VCPUsMax uint `mapstructure:"vcpus_max"`
|
||||||
VCPUsAtStartup uint `mapstructure:"vcpus_atstartup"`
|
VCPUsAtStartup uint `mapstructure:"vcpus_atstartup"`
|
||||||
VMMemory uint `mapstructure:"vm_memory"`
|
VMMemory uint `mapstructure:"vm_memory"`
|
||||||
|
|
||||||
PlatformArgs map[string]string `mapstructure:"platform_args"`
|
PlatformArgs map[string]string `mapstructure:"platform_args"`
|
||||||
|
|
||||||
@ -99,21 +99,21 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
|
|
||||||
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||||
//Setup XAPI client
|
//Setup XAPI client
|
||||||
client := xsclient.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
c, err := xscommon.NewXenAPIClient(self.config.HostIp, self.config.Username, self.config.Password)
|
||||||
|
|
||||||
err := client.Login()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err.(error)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("XAPI client session established")
|
ui.Say("XAPI client session established")
|
||||||
|
|
||||||
client.GetHosts()
|
c.GetClient().Host.GetAll(c.GetSessionRef())
|
||||||
|
|
||||||
//Share state between the other steps using a statebag
|
//Share state between the other steps using a statebag
|
||||||
state := new(multistep.BasicStateBag)
|
state := new(multistep.BasicStateBag)
|
||||||
state.Put("cache", cache)
|
state.Put("cache", cache)
|
||||||
state.Put("client", client)
|
state.Put("client", c)
|
||||||
state.Put("config", self.config)
|
// state.Put("config", self.config)
|
||||||
state.Put("commonconfig", self.config.CommonConfig)
|
state.Put("commonconfig", self.config.CommonConfig)
|
||||||
state.Put("hook", hook)
|
state.Put("hook", hook)
|
||||||
state.Put("ui", ui)
|
state.Put("ui", ui)
|
||||||
@ -149,11 +149,11 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
|||||||
new(stepImportInstance),
|
new(stepImportInstance),
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "floppy_vdi_uuid",
|
VdiUuidKey: "floppy_vdi_uuid",
|
||||||
VdiType: xsclient.Floppy,
|
VdiType: xsclient.VbdTypeFloppy,
|
||||||
},
|
},
|
||||||
&xscommon.StepAttachVdi{
|
&xscommon.StepAttachVdi{
|
||||||
VdiUuidKey: "tools_vdi_uuid",
|
VdiUuidKey: "tools_vdi_uuid",
|
||||||
VdiType: xsclient.CD,
|
VdiType: xsclient.VbdTypeCD,
|
||||||
},
|
},
|
||||||
new(xscommon.StepStartVmPaused),
|
new(xscommon.StepStartVmPaused),
|
||||||
new(xscommon.StepSetVmHostSshAddress),
|
new(xscommon.StepSetVmHostSshAddress),
|
||||||
|
@ -6,25 +6,26 @@ import (
|
|||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
xsclient "github.com/xenserver/go-xenserver-client"
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
||||||
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepImportInstance struct {
|
type stepImportInstance struct {
|
||||||
instance *xsclient.VM
|
instance xsclient.VMRef
|
||||||
vdi *xsclient.VDI
|
vdi xsclient.VDIRef
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *stepImportInstance) Run(state multistep.StateBag) multistep.StepAction {
|
func (self *stepImportInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
||||||
client := state.Get("client").(xsclient.XenAPIClient)
|
c := state.Get("client").(*xscommon.Connection)
|
||||||
config := state.Get("config").(config)
|
config := state.Get("config").(config)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Step: Import Instance")
|
ui.Say("Step: Import Instance")
|
||||||
|
|
||||||
// find the SR
|
// find the SR
|
||||||
sr, err := config.GetSR(client)
|
srs, err := c.GetClient().SR.GetAll(c.GetSessionRef())
|
||||||
|
sr := srs[0]
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
@ -38,41 +39,41 @@ func (self *stepImportInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
result, err := xscommon.HTTPUpload(fmt.Sprintf("https://%s/import?session_id=%s&sr_id=%s",
|
result, err := xscommon.HTTPUpload(fmt.Sprintf("https://%s/import?session_id=%s&sr_id=%s",
|
||||||
client.Host,
|
c.Host,
|
||||||
client.Session.(string),
|
c.GetSession(),
|
||||||
sr.Ref,
|
sr,
|
||||||
), fh, state)
|
), fh, state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to upload VDI: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to upload VDI: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
if result == nil {
|
if result == "" {
|
||||||
ui.Error("XAPI did not reply with an instance reference")
|
ui.Error("XAPI did not reply with an instance reference")
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
instance := xsclient.VM(*result)
|
instance := xsclient.VMRef(result)
|
||||||
|
|
||||||
instanceId, err := instance.GetUuid()
|
instanceId, err := c.GetClient().VM.GetUUID(c.GetSessionRef(), instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to get VM UUID: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to get VM UUID: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
state.Put("instance_uuid", instanceId)
|
state.Put("instance_uuid", instanceId)
|
||||||
|
|
||||||
err = instance.SetVCPUsMax(config.VCPUsMax)
|
err = c.GetClient().VM.SetVCPUsMax(c.GetSessionRef(), instance, int(config.VCPUsMax))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM VCPUs Max=%d: %s", config.VCPUsMax, err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM VCPUs Max=%d: %s", config.VCPUsMax, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
err = instance.SetVCPUsAtStartup(config.VCPUsAtStartup)
|
err = c.GetClient().VM.SetVCPUsAtStartup(c.GetSessionRef(), instance, int(config.VCPUsAtStartup))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM VCPUs At Startup=%d: %s", config.VCPUsAtStartup, err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM VCPUs At Startup=%d: %s", config.VCPUsAtStartup, err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.SetDescription(config.VMDescription)
|
err = c.GetClient().VM.SetNameDescription(c.GetSessionRef(), instance, config.VMDescription)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error setting VM description: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Error setting VM description: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
199
examples/http/ks-1804-minimalvm.cfg
Normal file
199
examples/http/ks-1804-minimalvm.cfg
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
#
|
||||||
|
#Kickstart template for Ubuntu
|
||||||
|
#Platform: x86-64
|
||||||
|
#
|
||||||
|
# Customized for Server 18.04 minimal vm install
|
||||||
|
#
|
||||||
|
# See README.mkd for usage
|
||||||
|
|
||||||
|
# Load the minimal server preseed off cdrom
|
||||||
|
preseed preseed/file string /cdrom/preseed/ubuntu-server-minimalvm.seed
|
||||||
|
|
||||||
|
# OPTIONAL: Change hostname from default 'preseed'
|
||||||
|
# If your DHCP hands out a hostname that will take precedence over this
|
||||||
|
# see: https://bugs.launchpad.net/ubuntu/+source/preseed/+bug/1452202
|
||||||
|
#preseed netcfg/hostname string minimal-vm
|
||||||
|
|
||||||
|
# Use local proxy
|
||||||
|
# Setup a server with apt-cacher-ng and enter that hostname here
|
||||||
|
#preseed mirror/http/proxy string http://my-local-cache:3142/
|
||||||
|
|
||||||
|
#System language
|
||||||
|
lang en_US
|
||||||
|
|
||||||
|
#Language modules to install
|
||||||
|
langsupport en_US
|
||||||
|
|
||||||
|
#System keyboard
|
||||||
|
keyboard us
|
||||||
|
|
||||||
|
#System mouse
|
||||||
|
mouse
|
||||||
|
|
||||||
|
#System timezone
|
||||||
|
timezone America/New_York
|
||||||
|
|
||||||
|
#Root password
|
||||||
|
rootpw --disabled
|
||||||
|
|
||||||
|
#Initial user (user with sudo capabilities)
|
||||||
|
user ubuntu --fullname "Ubuntu" --password ChangeMe
|
||||||
|
|
||||||
|
#Reboot after installation
|
||||||
|
reboot
|
||||||
|
|
||||||
|
#Use text mode install
|
||||||
|
text
|
||||||
|
|
||||||
|
#Install OS instead of upgrade
|
||||||
|
install
|
||||||
|
|
||||||
|
#Installation media
|
||||||
|
cdrom
|
||||||
|
|
||||||
|
#Change console size to 1024x768x24
|
||||||
|
preseed debian-installer/add-kernel-opts string "vga=792"
|
||||||
|
|
||||||
|
#System bootloader configuration
|
||||||
|
bootloader --location=mbr
|
||||||
|
|
||||||
|
#Clear the Master Boot Record
|
||||||
|
zerombr yes
|
||||||
|
|
||||||
|
#Partition clearing information
|
||||||
|
# `--all` will give message in install log about only clearing first drive but
|
||||||
|
# this is still needed
|
||||||
|
clearpart --all --initlabel
|
||||||
|
|
||||||
|
#Advanced partition
|
||||||
|
# The last lv specified will take up the remaining space of the vg. To get
|
||||||
|
# around that add up all your disk sizes and set this value. It appears to
|
||||||
|
# factor in the size of non lvm partitions as well
|
||||||
|
preseed partman-auto-lvm/guided_size string 8192MB
|
||||||
|
part /boot --fstype=ext4 --size=512 --asprimary
|
||||||
|
part pv.1 --grow --size=1 --asprimary
|
||||||
|
volgroup vg0 pv.1
|
||||||
|
logvol / --fstype=ext4 --name=root --vgname=vg0 --size=1024
|
||||||
|
logvol /usr --fstype=ext4 --name=usr --vgname=vg0 --size=2048
|
||||||
|
logvol /var --fstype=ext4 --name=var --vgname=vg0 --size=1536
|
||||||
|
logvol /var/log --fstype=ext4 --name=var_log --vgname=vg0 --size=512
|
||||||
|
logvol swap --name=swap --vgname=vg0 --size=2048 --maxsize=2048
|
||||||
|
logvol /home --fstype=ext4 --name=home --vgname=vg0 --size=512
|
||||||
|
|
||||||
|
# Don't install recommended items by default
|
||||||
|
# This will also be set for built system at
|
||||||
|
# /etc/apt/apt.conf.d/00InstallRecommends
|
||||||
|
preseed base-installer/install-recommends boolean false
|
||||||
|
|
||||||
|
#System authorization infomation
|
||||||
|
auth --useshadow
|
||||||
|
|
||||||
|
#Network information
|
||||||
|
# If the system has a single interface the '--device' option isn't needed. If
|
||||||
|
# you do use it remember that in 18.04 the device names are different. For
|
||||||
|
# example I was seeing enp0s3 as the interface name. I haven't tested this
|
||||||
|
# but you should be able to specify 'interface=enp0s3' as a boot paramater and
|
||||||
|
# it will be passed through to installer. I have tested setting the device to
|
||||||
|
# 'auto' will have it automatically pick the first active interface
|
||||||
|
#network --bootproto=dhcp --device=enp0s3
|
||||||
|
network --bootproto=dhcp --device=auto
|
||||||
|
|
||||||
|
#Firewall configuration
|
||||||
|
# Not supported by ubuntu
|
||||||
|
#firewall --disabled --trust=eth0 --ssh
|
||||||
|
|
||||||
|
|
||||||
|
# Policy for applying updates. May be "none" (no automatic updates),
|
||||||
|
# "unattended-upgrades" (install security updates automatically), or
|
||||||
|
# "landscape" (manage system with Landscape).
|
||||||
|
preseed pkgsel/update-policy select unattended-upgrades
|
||||||
|
|
||||||
|
#Do not configure the X Window System
|
||||||
|
skipx
|
||||||
|
|
||||||
|
# Additional packages to install
|
||||||
|
# - Most of these would have installed if it wasn't for turning off
|
||||||
|
# install-recommends
|
||||||
|
# - software-properties-common provides add-apt-repository which is needed for
|
||||||
|
# adding additional PPAs. You can remove that if you don't plan on
|
||||||
|
# installing anything. The %post script needs it for adding git
|
||||||
|
# - Starting in 16.04 Ubuntu no longer installs python v2.7 by default.
|
||||||
|
# Instead the default version of python is v3.x. If you still need v2.7
|
||||||
|
# then add the `python` package to this list
|
||||||
|
# - Uncomment the open-vm-tools line if this is going to run in vmware and are
|
||||||
|
# not going to use vmware-tools that's distributed with it. Don't think the
|
||||||
|
# --no-install-recommends is needed to not install desktop tools but doesn't
|
||||||
|
# hurt anything
|
||||||
|
%packages
|
||||||
|
# -- required for %post --
|
||||||
|
vim
|
||||||
|
software-properties-common
|
||||||
|
# -- pretty much required --
|
||||||
|
gpg-agent # apt-key needs this when piping certs in through stdin
|
||||||
|
curl
|
||||||
|
openssh-server
|
||||||
|
net-tools # this includes commands like ifconfig and netstat
|
||||||
|
wget
|
||||||
|
man
|
||||||
|
# -- additional packages you'll likely want --
|
||||||
|
#open-vm-tools --no-install-recommends # only needed on vmware vms
|
||||||
|
#bash-completion # personally I always install it but not everyone uses bash
|
||||||
|
#chrony # default time server in 18.04. systemd will manage time if this doesn't
|
||||||
|
#haveged # helps keep entropy pool full on VMs
|
||||||
|
|
||||||
|
|
||||||
|
%post
|
||||||
|
# -- begin security hardening --
|
||||||
|
# Change default umask from 022 to 027 (not world readable)
|
||||||
|
sed -i -e 's/^\(UMASK\W*\)[0-9]\+$/\1027/' /etc/login.defs
|
||||||
|
|
||||||
|
# Add noatime to /
|
||||||
|
sed -i -e 's/\(errors=remount-ro\)/noatime,\1/' /etc/fstab
|
||||||
|
# Add noatime and nodev to everything else
|
||||||
|
sed -i -e 's/\(boot.*defaults\)/\1,noatime,nodev/' /etc/fstab
|
||||||
|
sed -i -e 's/\(home.*defaults\)/\1,noatime,nodev/' /etc/fstab
|
||||||
|
sed -i -e 's/\(usr.*defaults\)/\1,noatime,nodev/' /etc/fstab
|
||||||
|
# Remove nodev from this one if it causes issues for you
|
||||||
|
sed -i -e 's/\(var .*defaults\)/\1,noatime,nodev/' /etc/fstab
|
||||||
|
# Add noatime, nodev, and noexec to /var/log
|
||||||
|
sed -i -e 's/\(var\/log .*defaults\)/\1,noatime,nodev,noexec/' /etc/fstab
|
||||||
|
# Add line to enable noexec on /dev/shm
|
||||||
|
echo "none /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0" >>/etc/fstab
|
||||||
|
# -- end security hardening --
|
||||||
|
|
||||||
|
# Set some defaults for apt to keep things tidy
|
||||||
|
cat > /etc/apt/apt.conf.d/90local <<"_EOF_"
|
||||||
|
APT::Periodic::Update-Package-Lists "1";
|
||||||
|
APT::Periodic::Unattended-Upgrade "1";
|
||||||
|
APT::Periodic::AutocleanInterval "1";
|
||||||
|
APT::Periodic::MaxSize "200";
|
||||||
|
Unattended-Upgrade::Remove-Unused-Dependencies "true";
|
||||||
|
#Acquire::http::Proxy "http://my-local-cache:3142";
|
||||||
|
_EOF_
|
||||||
|
|
||||||
|
# -- begin vim package customizations --
|
||||||
|
echo "set background=dark" >>/etc/vim/vimrc.local
|
||||||
|
# -- end vim package customizations --
|
||||||
|
|
||||||
|
# -- begin install git from 'Ubuntu Git Maintainers' PPA --
|
||||||
|
add-apt-repository -y ppa:git-core/ppa
|
||||||
|
apt-get -qq -y update
|
||||||
|
apt-get -qq -y install git
|
||||||
|
# -- end install git from 'Ubuntu Git Maintainers' PPA --
|
||||||
|
|
||||||
|
# -- begin set xdg base directories --
|
||||||
|
cat > /etc/profile.d/xdg_basedir.sh <<"_EOF_"
|
||||||
|
# Set XDG base directory global variables
|
||||||
|
# XDG_RUNTIME_HOME is set on user login
|
||||||
|
export XDG_DATA_HOME="${XDG_DATA_HOME:-"${HOME}/.local/share"}"
|
||||||
|
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-"${HOME}/.config"}"
|
||||||
|
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-"${HOME}/.cache"}"
|
||||||
|
_EOF_
|
||||||
|
chmod 0644 /etc/profile.d/xdg_basedir.sh
|
||||||
|
# -- end set xdg base directories --
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
apt-get -qq -y autoremove
|
||||||
|
apt-get clean
|
||||||
|
rm -f /var/cache/apt/*cache.bin
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
@ -2,19 +2,20 @@
|
|||||||
"builders": [
|
"builders": [
|
||||||
{
|
{
|
||||||
"type": "xenserver-iso",
|
"type": "xenserver-iso",
|
||||||
"remote_host": "your-server.example.com",
|
"tools_iso_name": "guest-tools.iso",
|
||||||
|
"remote_host": "",
|
||||||
"remote_username": "root",
|
"remote_username": "root",
|
||||||
"remote_password": "password",
|
"remote_password": "",
|
||||||
|
|
||||||
"boot_command": [
|
"boot_command": [
|
||||||
"<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter><wait>"
|
"<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks-1804-minimalvm.cfg<enter><wait>"
|
||||||
],
|
],
|
||||||
"boot_wait": "10s",
|
"boot_wait": "10s",
|
||||||
"disk_size": 40960,
|
"disk_size": 40960,
|
||||||
"http_directory": "http",
|
"http_directory": "examples/http",
|
||||||
"iso_checksum": "4ed6c56d365bd3ab12cd88b8a480f4a62e7c66d2",
|
"iso_checksum": "443511f6bf12402c12503733059269a2e10dec602916c0a75263e5d990f6bb93",
|
||||||
"iso_checksum_type": "sha1",
|
"iso_checksum_type": "sha256",
|
||||||
"iso_url": "{{user `mirror`}}/6.6/isos/x86_64/CentOS-6.6-x86_64-minimal.iso",
|
"iso_url": "https://releases.ubuntu.com/20.04.1/ubuntu-20.04.1-live-server-amd64.iso",
|
||||||
"vm_other_config": {
|
"vm_other_config": {
|
||||||
"conversionvm":"true"
|
"conversionvm":"true"
|
||||||
},
|
},
|
||||||
@ -28,7 +29,10 @@
|
|||||||
"ssh_password": "vmpassword",
|
"ssh_password": "vmpassword",
|
||||||
"ssh_wait_timeout": "10000s",
|
"ssh_wait_timeout": "10000s",
|
||||||
"vm_name": "packer-centos-6.6-x86_64",
|
"vm_name": "packer-centos-6.6-x86_64",
|
||||||
"vm_description": "Build time: {{isotime}}"
|
"vm_description": "Build time: {{isotime}}",
|
||||||
|
"clone_template": "Ubuntu Bionic Beaver 18.04",
|
||||||
|
"disk_size": "20000",
|
||||||
|
"vm_memory": "2048"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
38
go.mod
Normal file
38
go.mod
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
module github.com/xenserver/packer-builder-xenserver
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Sirupsen/logrus v0.10.1-0.20160601113210-f3cfb454f4c2 // indirect
|
||||||
|
github.com/dylanmei/iso8601 v0.1.0 // indirect
|
||||||
|
github.com/dylanmei/winrmtest v0.0.0-20151226195028-025617847eb2 // indirect
|
||||||
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect
|
||||||
|
github.com/hashicorp/go-multierror v0.0.0-20150916205742-d30f09973e19 // indirect
|
||||||
|
github.com/hashicorp/go-version v0.0.0-20160119211326-7e3c02b30806 // indirect
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20151129044643-df949784da9e // indirect
|
||||||
|
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b
|
||||||
|
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 // indirect
|
||||||
|
github.com/masterzen/simplexml v0.0.0-20140219194429-95ba30457eb1 // indirect
|
||||||
|
github.com/masterzen/winrm v0.0.0-20151214220635-54ea5d01478c // indirect
|
||||||
|
github.com/masterzen/xmlpath v0.0.0-20140218185901-13f4951698ad // indirect
|
||||||
|
github.com/mitchellh/go-fs v0.0.0-20150611040906-a34c1b9334e8 // indirect
|
||||||
|
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed
|
||||||
|
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20150717051158-281073eb9eb0 // indirect
|
||||||
|
github.com/mitchellh/multistep v0.0.0-20140407010115-162146fc5711
|
||||||
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f // indirect
|
||||||
|
github.com/mitchellh/packer v0.10.2-0.20160629004225-63edbd40edc5
|
||||||
|
github.com/mitchellh/reflectwalk v0.0.0-20150527153153-eecf4c70c626 // indirect
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
|
github.com/packer-community/winrmcp v0.0.0-20160310040704-f1bcf36a69fa // indirect
|
||||||
|
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca // indirect
|
||||||
|
github.com/satori/go.uuid v0.0.0-20151028231719-d41af8bb6a77 // indirect
|
||||||
|
github.com/stretchr/testify v1.6.1 // indirect
|
||||||
|
github.com/terra-farm/go-xen-api-client v0.0.1
|
||||||
|
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20160126184038-1f22c0103821
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
|
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect
|
||||||
|
launchpad.net/xmlpath v0.0.0-20130614043138-000000000004 // indirect
|
||||||
|
)
|
85
go.sum
Normal file
85
go.sum
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
github.com/Sirupsen/logrus v0.10.1-0.20160601113210-f3cfb454f4c2 h1:3BYvDlSNPyoYk6lr17s9IueNAabOBur3f3uVULjbhTA=
|
||||||
|
github.com/Sirupsen/logrus v0.10.1-0.20160601113210-f3cfb454f4c2/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U=
|
||||||
|
github.com/amfranz/go-xmlrpc-client v0.0.0-20190612172737-76858463955d h1:39lR6Kg+GsvDpLMD2Mb7gkjXmmLexqfr7SPy4iQWDTE=
|
||||||
|
github.com/amfranz/go-xmlrpc-client v0.0.0-20190612172737-76858463955d/go.mod h1:2NlXXRCkTbr/vZtUjcHKhbrESE4a3CDqVrgOROB16dg=
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=
|
||||||
|
github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
|
||||||
|
github.com/dylanmei/winrmtest v0.0.0-20151226195028-025617847eb2 h1:J29UzyZ34t5zmOLtGgjoSMpbCYCFooaNWlP/j+dX2Go=
|
||||||
|
github.com/dylanmei/winrmtest v0.0.0-20151226195028-025617847eb2/go.mod h1:VBVDFSBXCIW8JaHQpI8lldSKfYaLMzP9oyq6IJ4fhzY=
|
||||||
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4=
|
||||||
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v0.0.0-20150916205742-d30f09973e19 h1:gb61U/o4ZJ6TRYvZqJUKYidIhJOEAvNyVMesryROxAY=
|
||||||
|
github.com/hashicorp/go-multierror v0.0.0-20150916205742-d30f09973e19/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||||
|
github.com/hashicorp/go-version v0.0.0-20160119211326-7e3c02b30806 h1:0MKTKHll8VOZ0ciR+yTIEJ8JrT0UUiRDsgtujJT7a8U=
|
||||||
|
github.com/hashicorp/go-version v0.0.0-20160119211326-7e3c02b30806/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20151129044643-df949784da9e h1:R35YxgX/iWqsDjzoNO/7uFf8vjcgBIc02rvaV/Vr15c=
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20151129044643-df949784da9e/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||||
|
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b h1:DzHy0GlWeF0KAglaTMY7Q+khIFoG8toHP+wLFBVBQJc=
|
||||||
|
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q=
|
||||||
|
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169/go.mod h1:glhvuHOU9Hy7/8PwwdtnarXqLagOX0b/TbZx2zLMqEg=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/masterzen/simplexml v0.0.0-20140219194429-95ba30457eb1 h1:cLEbk5d4t8CDqmQtCMc2lk91cflxOrj31k9LTIabPoA=
|
||||||
|
github.com/masterzen/simplexml v0.0.0-20140219194429-95ba30457eb1/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
|
||||||
|
github.com/masterzen/winrm v0.0.0-20151214220635-54ea5d01478c h1:qhyvK0cWkEirK1O/Kz1NLY1PUnOLONqvbdLaFjOYj+A=
|
||||||
|
github.com/masterzen/winrm v0.0.0-20151214220635-54ea5d01478c/go.mod h1:CfZSN7zwz5gJiFhZJz49Uzk7mEBHIceWmbFmYx7Hf7E=
|
||||||
|
github.com/masterzen/xmlpath v0.0.0-20140218185901-13f4951698ad h1:x50MyJNOPLsHR1euYRIaBx3Z2wlE0UPfZOHSYD+Flo0=
|
||||||
|
github.com/masterzen/xmlpath v0.0.0-20140218185901-13f4951698ad/go.mod h1:A0zPC53iKKKcXYxr4ROjpQRQ5FgJXtelNdSmHHuq/tY=
|
||||||
|
github.com/mitchellh/go-fs v0.0.0-20150611040906-a34c1b9334e8 h1:UCZ0aWSjQ9BAqutuze9boB7V75PRtZrBdNQ2FNgr3cg=
|
||||||
|
github.com/mitchellh/go-fs v0.0.0-20150611040906-a34c1b9334e8/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU=
|
||||||
|
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed h1:FI2NIv6fpef6BQl2u3IZX/Cj20tfypRF4yd+uaHOMtI=
|
||||||
|
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
|
||||||
|
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95 h1:aHWVygBsLb+Kls/35B3tevL1hvDxZ0UklPA0BmhqTEk=
|
||||||
|
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20150717051158-281073eb9eb0 h1:6VeKv8nNMVKA6qmZLYnPTx0tJ//NbDj1SbubWIikJ9k=
|
||||||
|
github.com/mitchellh/mapstructure v0.0.0-20150717051158-281073eb9eb0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/multistep v0.0.0-20140407010115-162146fc5711 h1:wYK+RW7LV1GJQf1XzS7gL8zVBa+3C963Dsy2Hduzse0=
|
||||||
|
github.com/mitchellh/multistep v0.0.0-20140407010115-162146fc5711/go.mod h1:tZVWRY9V2OVYseuyNEjh0rb7qkeCMl+kRSGLqUEhFNg=
|
||||||
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
|
github.com/mitchellh/packer v0.10.2-0.20160629004225-63edbd40edc5 h1:s+nOB41LJjSQe7yeqNVEJll6IY/cViGUckFFoqP6whw=
|
||||||
|
github.com/mitchellh/packer v0.10.2-0.20160629004225-63edbd40edc5/go.mod h1:3TnGTkplC/koV8K6bCfCN1NB34Tye7lmUzo55/X5wqw=
|
||||||
|
github.com/mitchellh/reflectwalk v0.0.0-20150527153153-eecf4c70c626 h1:88u9H4mNODBcQUwlNpl6+jBhdoYT3WSi0w4hpYaYZ/o=
|
||||||
|
github.com/mitchellh/reflectwalk v0.0.0-20150527153153-eecf4c70c626/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||||
|
github.com/packer-community/winrmcp v0.0.0-20160310040704-f1bcf36a69fa h1:ePOmpdPK/UHhi2SKiOxFiC76BZXaG3FMOzxKxIH/kAE=
|
||||||
|
github.com/packer-community/winrmcp v0.0.0-20160310040704-f1bcf36a69fa/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
|
||||||
|
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca h1:k8gsErq3rkcbAyCnpOycQsbw88NjCHk7L3KfBZKhQDQ=
|
||||||
|
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/satori/go.uuid v0.0.0-20151028231719-d41af8bb6a77 h1:X4eLA68fCmv+kFpUBFXIhv5wD5IFVB+oWUxjmpyl02c=
|
||||||
|
github.com/satori/go.uuid v0.0.0-20151028231719-d41af8bb6a77/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/terra-farm/go-xen-api-client v0.0.1 h1:EigkWRuAwSktqwFwX1DV64RDWTZTTC0uwmP9W3xlLjE=
|
||||||
|
github.com/terra-farm/go-xen-api-client v0.0.1/go.mod h1:DDTy4ADe11t55X7nHKZ92rsU6fGHDjLbGmn3+ZqvZ2w=
|
||||||
|
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1 h1:U6ufy3mLDgg9RYupntOvAF7xCmNNquyKaYaaVHo1Nnk=
|
||||||
|
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||||
|
github.com/xenserver/go-xenserver-client v0.0.0-20150518141242-42dc9035c2e8 h1:5VQ4LGdVcauqxTlnAfwZY8KTn1XlJMxEHOIJqthKJtM=
|
||||||
|
github.com/xenserver/go-xenserver-client v0.0.0-20150518141242-42dc9035c2e8/go.mod h1:1ItwtwM/tObrp073TdWdvA+4lzAeWCDMJZ7fmntbJUc=
|
||||||
|
golang.org/x/crypto v0.0.0-20160126184038-1f22c0103821 h1:Ufz3iUGlZbo8uCQ3IddvmNoW0T2XwdZqjVpOrdtyO0c=
|
||||||
|
golang.org/x/crypto v0.0.0-20160126184038-1f22c0103821/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/sys v0.0.0-20160204225817-50c6bc5e4292 h1:FrW0lbpMBPKe4sGJsd3V/eCGzsC2ksMAG+LlbO74+VQ=
|
||||||
|
golang.org/x/sys v0.0.0-20160204225817-50c6bc5e4292/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54=
|
||||||
|
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
|
||||||
|
launchpad.net/xmlpath v0.0.0-20130614043138-000000000004 h1:B8nNZBUrx8YufDCAJjvO/lVs4GxXMQHyrjwJdJzXMFg=
|
||||||
|
launchpad.net/xmlpath v0.0.0-20130614043138-000000000004/go.mod h1:vqyExLOM3qBx7mvYRkoxjSCF945s0mbe7YynlKYXtsA=
|
6
packer.json
Normal file
6
packer.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"builders": [{
|
||||||
|
"type": "xenserver-iso",
|
||||||
|
"tools_iso_name": "guest-tools.iso"
|
||||||
|
}]
|
||||||
|
}
|
1
vendor/github.com/Sirupsen/logrus/.gitignore
generated
vendored
1
vendor/github.com/Sirupsen/logrus/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
logrus
|
|
10
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
10
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.3
|
|
||||||
- 1.4
|
|
||||||
- 1.5
|
|
||||||
- 1.6
|
|
||||||
- tip
|
|
||||||
install:
|
|
||||||
- go get -t ./...
|
|
||||||
script: GOMAXPROCS=4 GORACE="halt_on_error=1" go test -race -v ./...
|
|
66
vendor/github.com/Sirupsen/logrus/CHANGELOG.md
generated
vendored
66
vendor/github.com/Sirupsen/logrus/CHANGELOG.md
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
# 0.10.0
|
|
||||||
|
|
||||||
* feature: Add a test hook (#180)
|
|
||||||
* feature: `ParseLevel` is now case-insensitive (#326)
|
|
||||||
* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308)
|
|
||||||
* performance: avoid re-allocations on `WithFields` (#335)
|
|
||||||
|
|
||||||
# 0.9.0
|
|
||||||
|
|
||||||
* logrus/text_formatter: don't emit empty msg
|
|
||||||
* logrus/hooks/airbrake: move out of main repository
|
|
||||||
* logrus/hooks/sentry: move out of main repository
|
|
||||||
* logrus/hooks/papertrail: move out of main repository
|
|
||||||
* logrus/hooks/bugsnag: move out of main repository
|
|
||||||
* logrus/core: run tests with `-race`
|
|
||||||
* logrus/core: detect TTY based on `stderr`
|
|
||||||
* logrus/core: support `WithError` on logger
|
|
||||||
* logrus/core: Solaris support
|
|
||||||
|
|
||||||
# 0.8.7
|
|
||||||
|
|
||||||
* logrus/core: fix possible race (#216)
|
|
||||||
* logrus/doc: small typo fixes and doc improvements
|
|
||||||
|
|
||||||
|
|
||||||
# 0.8.6
|
|
||||||
|
|
||||||
* hooks/raven: allow passing an initialized client
|
|
||||||
|
|
||||||
# 0.8.5
|
|
||||||
|
|
||||||
* logrus/core: revert #208
|
|
||||||
|
|
||||||
# 0.8.4
|
|
||||||
|
|
||||||
* formatter/text: fix data race (#218)
|
|
||||||
|
|
||||||
# 0.8.3
|
|
||||||
|
|
||||||
* logrus/core: fix entry log level (#208)
|
|
||||||
* logrus/core: improve performance of text formatter by 40%
|
|
||||||
* logrus/core: expose `LevelHooks` type
|
|
||||||
* logrus/core: add support for DragonflyBSD and NetBSD
|
|
||||||
* formatter/text: print structs more verbosely
|
|
||||||
|
|
||||||
# 0.8.2
|
|
||||||
|
|
||||||
* logrus: fix more Fatal family functions
|
|
||||||
|
|
||||||
# 0.8.1
|
|
||||||
|
|
||||||
* logrus: fix not exiting on `Fatalf` and `Fatalln`
|
|
||||||
|
|
||||||
# 0.8.0
|
|
||||||
|
|
||||||
* logrus: defaults to stderr instead of stdout
|
|
||||||
* hooks/sentry: add special field for `*http.Request`
|
|
||||||
* formatter/text: ignore Windows for colors
|
|
||||||
|
|
||||||
# 0.7.3
|
|
||||||
|
|
||||||
* formatter/\*: allow configuration of timestamp layout
|
|
||||||
|
|
||||||
# 0.7.2
|
|
||||||
|
|
||||||
* formatter/text: Add configuration option for time format (#158)
|
|
390
vendor/github.com/Sirupsen/logrus/README.md
generated
vendored
390
vendor/github.com/Sirupsen/logrus/README.md
generated
vendored
@ -1,390 +0,0 @@
|
|||||||
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/> [](https://travis-ci.org/Sirupsen/logrus) [](https://godoc.org/github.com/Sirupsen/logrus)
|
|
||||||
|
|
||||||
Logrus is a structured logger for Go (golang), completely API compatible with
|
|
||||||
the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
|
|
||||||
yet stable (pre 1.0). Logrus itself is completely stable and has been used in
|
|
||||||
many large deployments. The core API is unlikely to change much but please
|
|
||||||
version control your Logrus to make sure you aren't fetching latest `master` on
|
|
||||||
every build.**
|
|
||||||
|
|
||||||
Nicely color-coded in development (when a TTY is attached, otherwise just
|
|
||||||
plain text):
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash
|
|
||||||
or Splunk:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
|
|
||||||
ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
|
|
||||||
|
|
||||||
{"level":"warning","msg":"The group's number increased tremendously!",
|
|
||||||
"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
|
|
||||||
|
|
||||||
{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
|
|
||||||
"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
|
|
||||||
|
|
||||||
{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
|
|
||||||
"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
|
|
||||||
|
|
||||||
{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
|
|
||||||
"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
|
|
||||||
```
|
|
||||||
|
|
||||||
With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not
|
|
||||||
attached, the output is compatible with the
|
|
||||||
[logfmt](http://godoc.org/github.com/kr/logfmt) format:
|
|
||||||
|
|
||||||
```text
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
|
|
||||||
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
|
|
||||||
exit status 1
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
The simplest way to use Logrus is simply the package-level exported logger:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
}).Info("A walrus appears")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that it's completely api-compatible with the stdlib logger, so you can
|
|
||||||
replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
|
|
||||||
and you'll now have the flexibility of Logrus. You can customize it all you
|
|
||||||
want:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Log as JSON instead of the default ASCII formatter.
|
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
|
||||||
|
|
||||||
// Output to stderr instead of stdout, could also be a file.
|
|
||||||
log.SetOutput(os.Stderr)
|
|
||||||
|
|
||||||
// Only log the warning severity or above.
|
|
||||||
log.SetLevel(log.WarnLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
"size": 10,
|
|
||||||
}).Info("A group of walrus emerges from the ocean")
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"omg": true,
|
|
||||||
"number": 122,
|
|
||||||
}).Warn("The group's number increased tremendously!")
|
|
||||||
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"omg": true,
|
|
||||||
"number": 100,
|
|
||||||
}).Fatal("The ice breaks!")
|
|
||||||
|
|
||||||
// A common pattern is to re-use fields between logging statements by re-using
|
|
||||||
// the logrus.Entry returned from WithFields()
|
|
||||||
contextLogger := log.WithFields(log.Fields{
|
|
||||||
"common": "this is a common field",
|
|
||||||
"other": "I also should be logged always",
|
|
||||||
})
|
|
||||||
|
|
||||||
contextLogger.Info("I'll be logged with common and other field")
|
|
||||||
contextLogger.Info("Me too")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more advanced usage such as logging to multiple locations from the same
|
|
||||||
application, you can also create an instance of the `logrus` Logger:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create a new instance of the logger. You can have any number of instances.
|
|
||||||
var log = logrus.New()
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// The API for setting attributes is a little different than the package level
|
|
||||||
// exported logger. See Godoc.
|
|
||||||
log.Out = os.Stderr
|
|
||||||
|
|
||||||
log.WithFields(logrus.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
"size": 10,
|
|
||||||
}).Info("A group of walrus emerges from the ocean")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Fields
|
|
||||||
|
|
||||||
Logrus encourages careful, structured logging though logging fields instead of
|
|
||||||
long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
|
|
||||||
to send event %s to topic %s with key %d")`, you should log the much more
|
|
||||||
discoverable:
|
|
||||||
|
|
||||||
```go
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"event": event,
|
|
||||||
"topic": topic,
|
|
||||||
"key": key,
|
|
||||||
}).Fatal("Failed to send event")
|
|
||||||
```
|
|
||||||
|
|
||||||
We've found this API forces you to think about logging in a way that produces
|
|
||||||
much more useful logging messages. We've been in countless situations where just
|
|
||||||
a single added field to a log statement that was already there would've saved us
|
|
||||||
hours. The `WithFields` call is optional.
|
|
||||||
|
|
||||||
In general, with Logrus using any of the `printf`-family functions should be
|
|
||||||
seen as a hint you should add a field, however, you can still use the
|
|
||||||
`printf`-family functions with Logrus.
|
|
||||||
|
|
||||||
#### Hooks
|
|
||||||
|
|
||||||
You can add hooks for logging levels. For example to send errors to an exception
|
|
||||||
tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
|
|
||||||
multiple places simultaneously, e.g. syslog.
|
|
||||||
|
|
||||||
Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
|
|
||||||
`init`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
|
|
||||||
logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
|
|
||||||
"log/syslog"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
// Use the Airbrake hook to report errors that have Error severity or above to
|
|
||||||
// an exception tracker. You can create custom hooks, see the Hooks section.
|
|
||||||
log.AddHook(airbrake.NewHook(123, "xyz", "production"))
|
|
||||||
|
|
||||||
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Unable to connect to local syslog daemon")
|
|
||||||
} else {
|
|
||||||
log.AddHook(hook)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
|
|
||||||
|
|
||||||
| Hook | Description |
|
|
||||||
| ----- | ----------- |
|
|
||||||
| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
|
|
||||||
| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
|
|
||||||
| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
|
|
||||||
| [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
|
|
||||||
| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
|
|
||||||
| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
|
|
||||||
| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
|
|
||||||
| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
|
|
||||||
| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
|
|
||||||
| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
|
|
||||||
| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
|
|
||||||
| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
|
|
||||||
| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
|
|
||||||
| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
|
|
||||||
| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
|
|
||||||
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
|
|
||||||
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
|
|
||||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
|
|
||||||
| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) |
|
|
||||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
|
||||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
|
||||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
|
||||||
| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
|
|
||||||
| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
|
|
||||||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
|
|
||||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
|
||||||
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
|
|
||||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
|
||||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
|
|
||||||
|
|
||||||
#### Level logging
|
|
||||||
|
|
||||||
Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
|
|
||||||
|
|
||||||
```go
|
|
||||||
log.Debug("Useful debugging information.")
|
|
||||||
log.Info("Something noteworthy happened!")
|
|
||||||
log.Warn("You should probably take a look at this.")
|
|
||||||
log.Error("Something failed but I'm not quitting.")
|
|
||||||
// Calls os.Exit(1) after logging
|
|
||||||
log.Fatal("Bye.")
|
|
||||||
// Calls panic() after logging
|
|
||||||
log.Panic("I'm bailing.")
|
|
||||||
```
|
|
||||||
|
|
||||||
You can set the logging level on a `Logger`, then it will only log entries with
|
|
||||||
that severity or anything above it:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Will log anything that is info or above (warn, error, fatal, panic). Default.
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
```
|
|
||||||
|
|
||||||
It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
|
|
||||||
environment if your application has that.
|
|
||||||
|
|
||||||
#### Entries
|
|
||||||
|
|
||||||
Besides the fields added with `WithField` or `WithFields` some fields are
|
|
||||||
automatically added to all logging events:
|
|
||||||
|
|
||||||
1. `time`. The timestamp when the entry was created.
|
|
||||||
2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
|
|
||||||
the `AddFields` call. E.g. `Failed to send event.`
|
|
||||||
3. `level`. The logging level. E.g. `info`.
|
|
||||||
|
|
||||||
#### Environments
|
|
||||||
|
|
||||||
Logrus has no notion of environment.
|
|
||||||
|
|
||||||
If you wish for hooks and formatters to only be used in specific environments,
|
|
||||||
you should handle that yourself. For example, if your application has a global
|
|
||||||
variable `Environment`, which is a string representation of the environment you
|
|
||||||
could do:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
init() {
|
|
||||||
// do something here to set environment depending on an environment variable
|
|
||||||
// or command-line flag
|
|
||||||
if Environment == "production" {
|
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
|
||||||
} else {
|
|
||||||
// The TextFormatter is default, you don't actually have to do this.
|
|
||||||
log.SetFormatter(&log.TextFormatter{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This configuration is how `logrus` was intended to be used, but JSON in
|
|
||||||
production is mostly only useful if you do log aggregation with tools like
|
|
||||||
Splunk or Logstash.
|
|
||||||
|
|
||||||
#### Formatters
|
|
||||||
|
|
||||||
The built-in logging formatters are:
|
|
||||||
|
|
||||||
* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
|
|
||||||
without colors.
|
|
||||||
* *Note:* to force colored output when there is no TTY, set the `ForceColors`
|
|
||||||
field to `true`. To force no colored output even if there is a TTY set the
|
|
||||||
`DisableColors` field to `true`
|
|
||||||
* `logrus.JSONFormatter`. Logs fields as JSON.
|
|
||||||
* `logrus/formatters/logstash.LogstashFormatter`. Logs fields as [Logstash](http://logstash.net) Events.
|
|
||||||
|
|
||||||
```go
|
|
||||||
logrus.SetFormatter(&logstash.LogstashFormatter{Type: "application_name"})
|
|
||||||
```
|
|
||||||
|
|
||||||
Third party logging formatters:
|
|
||||||
|
|
||||||
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
|
|
||||||
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
|
|
||||||
|
|
||||||
You can define your formatter by implementing the `Formatter` interface,
|
|
||||||
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
|
|
||||||
`Fields` type (`map[string]interface{}`) with all your fields as well as the
|
|
||||||
default ones (see Entries section above):
|
|
||||||
|
|
||||||
```go
|
|
||||||
type MyJSONFormatter struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SetFormatter(new(MyJSONFormatter))
|
|
||||||
|
|
||||||
func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|
||||||
// Note this doesn't include Time, Level and Message which are available on
|
|
||||||
// the Entry. Consult `godoc` on information about those fields or read the
|
|
||||||
// source of the official loggers.
|
|
||||||
serialized, err := json.Marshal(entry.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
|
||||||
}
|
|
||||||
return append(serialized, '\n'), nil
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Logger as an `io.Writer`
|
|
||||||
|
|
||||||
Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it.
|
|
||||||
|
|
||||||
```go
|
|
||||||
w := logger.Writer()
|
|
||||||
defer w.Close()
|
|
||||||
|
|
||||||
srv := http.Server{
|
|
||||||
// create a stdlib log.Logger that writes to
|
|
||||||
// logrus.Logger.
|
|
||||||
ErrorLog: log.New(w, "", 0),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Each line written to that writer will be printed the usual way, using formatters
|
|
||||||
and hooks. The level for those entries is `info`.
|
|
||||||
|
|
||||||
#### Rotation
|
|
||||||
|
|
||||||
Log rotation is not provided with Logrus. Log rotation should be done by an
|
|
||||||
external program (like `logrotate(8)`) that can compress and delete old log
|
|
||||||
entries. It should not be a feature of the application-level logger.
|
|
||||||
|
|
||||||
#### Tools
|
|
||||||
|
|
||||||
| Tool | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.|
|
|
||||||
|
|
||||||
#### Testing
|
|
||||||
|
|
||||||
Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides:
|
|
||||||
|
|
||||||
* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook
|
|
||||||
* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any):
|
|
||||||
|
|
||||||
```go
|
|
||||||
logger, hook := NewNullLogger()
|
|
||||||
logger.Error("Hello error")
|
|
||||||
|
|
||||||
assert.Equal(1, len(hook.Entries))
|
|
||||||
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
|
|
||||||
assert.Equal("Hello error", hook.LastEntry().Message)
|
|
||||||
|
|
||||||
hook.Reset()
|
|
||||||
assert.Nil(hook.LastEntry())
|
|
||||||
```
|
|
26
vendor/github.com/Sirupsen/logrus/doc.go
generated
vendored
26
vendor/github.com/Sirupsen/logrus/doc.go
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
Package logrus is a structured logger for Go, completely API compatible with the standard library logger.
|
|
||||||
|
|
||||||
|
|
||||||
The simplest way to use Logrus is simply the package-level exported logger:
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"animal": "walrus",
|
|
||||||
"number": 1,
|
|
||||||
"size": 10,
|
|
||||||
}).Info("A walrus appears")
|
|
||||||
}
|
|
||||||
|
|
||||||
Output:
|
|
||||||
time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10
|
|
||||||
|
|
||||||
For a full guide visit https://github.com/Sirupsen/logrus
|
|
||||||
*/
|
|
||||||
package logrus
|
|
264
vendor/github.com/Sirupsen/logrus/entry.go
generated
vendored
264
vendor/github.com/Sirupsen/logrus/entry.go
generated
vendored
@ -1,264 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Defines the key when adding errors using WithError.
|
|
||||||
var ErrorKey = "error"
|
|
||||||
|
|
||||||
// An entry is the final or intermediate Logrus logging entry. It contains all
|
|
||||||
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
|
|
||||||
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
|
|
||||||
// passed around as much as you wish to avoid field duplication.
|
|
||||||
type Entry struct {
|
|
||||||
Logger *Logger
|
|
||||||
|
|
||||||
// Contains all the fields set by the user.
|
|
||||||
Data Fields
|
|
||||||
|
|
||||||
// Time at which the log entry was created
|
|
||||||
Time time.Time
|
|
||||||
|
|
||||||
// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
|
|
||||||
Level Level
|
|
||||||
|
|
||||||
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEntry(logger *Logger) *Entry {
|
|
||||||
return &Entry{
|
|
||||||
Logger: logger,
|
|
||||||
// Default is three fields, give a little extra room
|
|
||||||
Data: make(Fields, 5),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a reader for the entry, which is a proxy to the formatter.
|
|
||||||
func (entry *Entry) Reader() (*bytes.Buffer, error) {
|
|
||||||
serialized, err := entry.Logger.Formatter.Format(entry)
|
|
||||||
return bytes.NewBuffer(serialized), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the string representation from the reader and ultimately the
|
|
||||||
// formatter.
|
|
||||||
func (entry *Entry) String() (string, error) {
|
|
||||||
reader, err := entry.Reader()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return reader.String(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add an error as single field (using the key defined in ErrorKey) to the Entry.
|
|
||||||
func (entry *Entry) WithError(err error) *Entry {
|
|
||||||
return entry.WithField(ErrorKey, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a single field to the Entry.
|
|
||||||
func (entry *Entry) WithField(key string, value interface{}) *Entry {
|
|
||||||
return entry.WithFields(Fields{key: value})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a map of fields to the Entry.
|
|
||||||
func (entry *Entry) WithFields(fields Fields) *Entry {
|
|
||||||
data := make(Fields, len(entry.Data)+len(fields))
|
|
||||||
for k, v := range entry.Data {
|
|
||||||
data[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range fields {
|
|
||||||
data[k] = v
|
|
||||||
}
|
|
||||||
return &Entry{Logger: entry.Logger, Data: data}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is not declared with a pointer value because otherwise
|
|
||||||
// race conditions will occur when using multiple goroutines
|
|
||||||
func (entry Entry) log(level Level, msg string) {
|
|
||||||
entry.Time = time.Now()
|
|
||||||
entry.Level = level
|
|
||||||
entry.Message = msg
|
|
||||||
|
|
||||||
if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
|
||||||
entry.Logger.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
reader, err := entry.Reader()
|
|
||||||
if err != nil {
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
|
|
||||||
entry.Logger.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.Logger.mu.Lock()
|
|
||||||
defer entry.Logger.mu.Unlock()
|
|
||||||
|
|
||||||
_, err = io.Copy(entry.Logger.Out, reader)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// To avoid Entry#log() returning a value that only would make sense for
|
|
||||||
// panic() to use in Entry#Panic(), we avoid the allocation by checking
|
|
||||||
// directly here.
|
|
||||||
if level <= PanicLevel {
|
|
||||||
panic(&entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Debug(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= DebugLevel {
|
|
||||||
entry.log(DebugLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Print(args ...interface{}) {
|
|
||||||
entry.Info(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Info(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= InfoLevel {
|
|
||||||
entry.log(InfoLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warn(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= WarnLevel {
|
|
||||||
entry.log(WarnLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warning(args ...interface{}) {
|
|
||||||
entry.Warn(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Error(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= ErrorLevel {
|
|
||||||
entry.log(ErrorLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Fatal(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= FatalLevel {
|
|
||||||
entry.log(FatalLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Panic(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= PanicLevel {
|
|
||||||
entry.log(PanicLevel, fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
panic(fmt.Sprint(args...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry Printf family functions
|
|
||||||
|
|
||||||
func (entry *Entry) Debugf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= DebugLevel {
|
|
||||||
entry.Debug(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Infof(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= InfoLevel {
|
|
||||||
entry.Info(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Printf(format string, args ...interface{}) {
|
|
||||||
entry.Infof(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warnf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= WarnLevel {
|
|
||||||
entry.Warn(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warningf(format string, args ...interface{}) {
|
|
||||||
entry.Warnf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Errorf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= ErrorLevel {
|
|
||||||
entry.Error(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Fatalf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= FatalLevel {
|
|
||||||
entry.Fatal(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Panicf(format string, args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= PanicLevel {
|
|
||||||
entry.Panic(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry Println family functions
|
|
||||||
|
|
||||||
func (entry *Entry) Debugln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= DebugLevel {
|
|
||||||
entry.Debug(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Infoln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= InfoLevel {
|
|
||||||
entry.Info(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Println(args ...interface{}) {
|
|
||||||
entry.Infoln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warnln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= WarnLevel {
|
|
||||||
entry.Warn(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Warningln(args ...interface{}) {
|
|
||||||
entry.Warnln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Errorln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= ErrorLevel {
|
|
||||||
entry.Error(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Fatalln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= FatalLevel {
|
|
||||||
entry.Fatal(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) Panicln(args ...interface{}) {
|
|
||||||
if entry.Logger.Level >= PanicLevel {
|
|
||||||
entry.Panic(entry.sprintlnn(args...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sprintlnn => Sprint no newline. This is to get the behavior of how
|
|
||||||
// fmt.Sprintln where spaces are always added between operands, regardless of
|
|
||||||
// their type. Instead of vendoring the Sprintln implementation to spare a
|
|
||||||
// string allocation, we do the simplest thing.
|
|
||||||
func (entry *Entry) sprintlnn(args ...interface{}) string {
|
|
||||||
msg := fmt.Sprintln(args...)
|
|
||||||
return msg[:len(msg)-1]
|
|
||||||
}
|
|
193
vendor/github.com/Sirupsen/logrus/exported.go
generated
vendored
193
vendor/github.com/Sirupsen/logrus/exported.go
generated
vendored
@ -1,193 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// std is the name of the standard logger in stdlib `log`
|
|
||||||
std = New()
|
|
||||||
)
|
|
||||||
|
|
||||||
func StandardLogger() *Logger {
|
|
||||||
return std
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOutput sets the standard logger output.
|
|
||||||
func SetOutput(out io.Writer) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Out = out
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFormatter sets the standard logger formatter.
|
|
||||||
func SetFormatter(formatter Formatter) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Formatter = formatter
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLevel sets the standard logger level.
|
|
||||||
func SetLevel(level Level) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Level = level
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLevel returns the standard logger level.
|
|
||||||
func GetLevel() Level {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
return std.Level
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHook adds a hook to the standard logger hooks.
|
|
||||||
func AddHook(hook Hook) {
|
|
||||||
std.mu.Lock()
|
|
||||||
defer std.mu.Unlock()
|
|
||||||
std.Hooks.Add(hook)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
|
|
||||||
func WithError(err error) *Entry {
|
|
||||||
return std.WithField(ErrorKey, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithField creates an entry from the standard logger and adds a field to
|
|
||||||
// it. If you want multiple fields, use `WithFields`.
|
|
||||||
//
|
|
||||||
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
|
|
||||||
// or Panic on the Entry it returns.
|
|
||||||
func WithField(key string, value interface{}) *Entry {
|
|
||||||
return std.WithField(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithFields creates an entry from the standard logger and adds multiple
|
|
||||||
// fields to it. This is simply a helper for `WithField`, invoking it
|
|
||||||
// once for each field.
|
|
||||||
//
|
|
||||||
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
|
|
||||||
// or Panic on the Entry it returns.
|
|
||||||
func WithFields(fields Fields) *Entry {
|
|
||||||
return std.WithFields(fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug logs a message at level Debug on the standard logger.
|
|
||||||
func Debug(args ...interface{}) {
|
|
||||||
std.Debug(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print logs a message at level Info on the standard logger.
|
|
||||||
func Print(args ...interface{}) {
|
|
||||||
std.Print(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info logs a message at level Info on the standard logger.
|
|
||||||
func Info(args ...interface{}) {
|
|
||||||
std.Info(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn logs a message at level Warn on the standard logger.
|
|
||||||
func Warn(args ...interface{}) {
|
|
||||||
std.Warn(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warning logs a message at level Warn on the standard logger.
|
|
||||||
func Warning(args ...interface{}) {
|
|
||||||
std.Warning(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error logs a message at level Error on the standard logger.
|
|
||||||
func Error(args ...interface{}) {
|
|
||||||
std.Error(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic logs a message at level Panic on the standard logger.
|
|
||||||
func Panic(args ...interface{}) {
|
|
||||||
std.Panic(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatal logs a message at level Fatal on the standard logger.
|
|
||||||
func Fatal(args ...interface{}) {
|
|
||||||
std.Fatal(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugf logs a message at level Debug on the standard logger.
|
|
||||||
func Debugf(format string, args ...interface{}) {
|
|
||||||
std.Debugf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Printf logs a message at level Info on the standard logger.
|
|
||||||
func Printf(format string, args ...interface{}) {
|
|
||||||
std.Printf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infof logs a message at level Info on the standard logger.
|
|
||||||
func Infof(format string, args ...interface{}) {
|
|
||||||
std.Infof(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warnf logs a message at level Warn on the standard logger.
|
|
||||||
func Warnf(format string, args ...interface{}) {
|
|
||||||
std.Warnf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warningf logs a message at level Warn on the standard logger.
|
|
||||||
func Warningf(format string, args ...interface{}) {
|
|
||||||
std.Warningf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf logs a message at level Error on the standard logger.
|
|
||||||
func Errorf(format string, args ...interface{}) {
|
|
||||||
std.Errorf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panicf logs a message at level Panic on the standard logger.
|
|
||||||
func Panicf(format string, args ...interface{}) {
|
|
||||||
std.Panicf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatalf logs a message at level Fatal on the standard logger.
|
|
||||||
func Fatalf(format string, args ...interface{}) {
|
|
||||||
std.Fatalf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugln logs a message at level Debug on the standard logger.
|
|
||||||
func Debugln(args ...interface{}) {
|
|
||||||
std.Debugln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Println logs a message at level Info on the standard logger.
|
|
||||||
func Println(args ...interface{}) {
|
|
||||||
std.Println(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infoln logs a message at level Info on the standard logger.
|
|
||||||
func Infoln(args ...interface{}) {
|
|
||||||
std.Infoln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warnln logs a message at level Warn on the standard logger.
|
|
||||||
func Warnln(args ...interface{}) {
|
|
||||||
std.Warnln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warningln logs a message at level Warn on the standard logger.
|
|
||||||
func Warningln(args ...interface{}) {
|
|
||||||
std.Warningln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorln logs a message at level Error on the standard logger.
|
|
||||||
func Errorln(args ...interface{}) {
|
|
||||||
std.Errorln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panicln logs a message at level Panic on the standard logger.
|
|
||||||
func Panicln(args ...interface{}) {
|
|
||||||
std.Panicln(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fatalln logs a message at level Fatal on the standard logger.
|
|
||||||
func Fatalln(args ...interface{}) {
|
|
||||||
std.Fatalln(args...)
|
|
||||||
}
|
|
45
vendor/github.com/Sirupsen/logrus/formatter.go
generated
vendored
45
vendor/github.com/Sirupsen/logrus/formatter.go
generated
vendored
@ -1,45 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
const DefaultTimestampFormat = time.RFC3339
|
|
||||||
|
|
||||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
|
||||||
// `Entry`. It exposes all the fields, including the default ones:
|
|
||||||
//
|
|
||||||
// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
|
|
||||||
// * `entry.Data["time"]`. The timestamp.
|
|
||||||
// * `entry.Data["level"]. The level the entry was logged at.
|
|
||||||
//
|
|
||||||
// Any additional fields added with `WithField` or `WithFields` are also in
|
|
||||||
// `entry.Data`. Format is expected to return an array of bytes which are then
|
|
||||||
// logged to `logger.Out`.
|
|
||||||
type Formatter interface {
|
|
||||||
Format(*Entry) ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is to not silently overwrite `time`, `msg` and `level` fields when
|
|
||||||
// dumping it. If this code wasn't there doing:
|
|
||||||
//
|
|
||||||
// logrus.WithField("level", 1).Info("hello")
|
|
||||||
//
|
|
||||||
// Would just silently drop the user provided level. Instead with this code
|
|
||||||
// it'll logged as:
|
|
||||||
//
|
|
||||||
// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
|
|
||||||
//
|
|
||||||
// It's not exported because it's still using Data in an opinionated way. It's to
|
|
||||||
// avoid code duplication between the two default formatters.
|
|
||||||
func prefixFieldClashes(data Fields) {
|
|
||||||
if t, ok := data["time"]; ok {
|
|
||||||
data["fields.time"] = t
|
|
||||||
}
|
|
||||||
|
|
||||||
if m, ok := data["msg"]; ok {
|
|
||||||
data["fields.msg"] = m
|
|
||||||
}
|
|
||||||
|
|
||||||
if l, ok := data["level"]; ok {
|
|
||||||
data["fields.level"] = l
|
|
||||||
}
|
|
||||||
}
|
|
34
vendor/github.com/Sirupsen/logrus/hooks.go
generated
vendored
34
vendor/github.com/Sirupsen/logrus/hooks.go
generated
vendored
@ -1,34 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
// A hook to be fired when logging on the logging levels returned from
|
|
||||||
// `Levels()` on your implementation of the interface. Note that this is not
|
|
||||||
// fired in a goroutine or a channel with workers, you should handle such
|
|
||||||
// functionality yourself if your call is non-blocking and you don't wish for
|
|
||||||
// the logging calls for levels returned from `Levels()` to block.
|
|
||||||
type Hook interface {
|
|
||||||
Levels() []Level
|
|
||||||
Fire(*Entry) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal type for storing the hooks on a logger instance.
|
|
||||||
type LevelHooks map[Level][]Hook
|
|
||||||
|
|
||||||
// Add a hook to an instance of logger. This is called with
|
|
||||||
// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
|
|
||||||
func (hooks LevelHooks) Add(hook Hook) {
|
|
||||||
for _, level := range hook.Levels() {
|
|
||||||
hooks[level] = append(hooks[level], hook)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire all the hooks for the passed level. Used by `entry.log` to fire
|
|
||||||
// appropriate hooks for a log entry.
|
|
||||||
func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
|
|
||||||
for _, hook := range hooks[level] {
|
|
||||||
if err := hook.Fire(entry); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
41
vendor/github.com/Sirupsen/logrus/json_formatter.go
generated
vendored
41
vendor/github.com/Sirupsen/logrus/json_formatter.go
generated
vendored
@ -1,41 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type JSONFormatter struct {
|
|
||||||
// TimestampFormat sets the format used for marshaling timestamps.
|
|
||||||
TimestampFormat string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
|
|
||||||
data := make(Fields, len(entry.Data)+3)
|
|
||||||
for k, v := range entry.Data {
|
|
||||||
switch v := v.(type) {
|
|
||||||
case error:
|
|
||||||
// Otherwise errors are ignored by `encoding/json`
|
|
||||||
// https://github.com/Sirupsen/logrus/issues/137
|
|
||||||
data[k] = v.Error()
|
|
||||||
default:
|
|
||||||
data[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prefixFieldClashes(data)
|
|
||||||
|
|
||||||
timestampFormat := f.TimestampFormat
|
|
||||||
if timestampFormat == "" {
|
|
||||||
timestampFormat = DefaultTimestampFormat
|
|
||||||
}
|
|
||||||
|
|
||||||
data["time"] = entry.Time.Format(timestampFormat)
|
|
||||||
data["msg"] = entry.Message
|
|
||||||
data["level"] = entry.Level.String()
|
|
||||||
|
|
||||||
serialized, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
|
|
||||||
}
|
|
||||||
return append(serialized, '\n'), nil
|
|
||||||
}
|
|
212
vendor/github.com/Sirupsen/logrus/logger.go
generated
vendored
212
vendor/github.com/Sirupsen/logrus/logger.go
generated
vendored
@ -1,212 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Logger struct {
|
|
||||||
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
|
|
||||||
// file, or leave it default which is `os.Stderr`. You can also set this to
|
|
||||||
// something more adventorous, such as logging to Kafka.
|
|
||||||
Out io.Writer
|
|
||||||
// Hooks for the logger instance. These allow firing events based on logging
|
|
||||||
// levels and log entries. For example, to send errors to an error tracking
|
|
||||||
// service, log to StatsD or dump the core on fatal errors.
|
|
||||||
Hooks LevelHooks
|
|
||||||
// All log entries pass through the formatter before logged to Out. The
|
|
||||||
// included formatters are `TextFormatter` and `JSONFormatter` for which
|
|
||||||
// TextFormatter is the default. In development (when a TTY is attached) it
|
|
||||||
// logs with colors, but to a file it wouldn't. You can easily implement your
|
|
||||||
// own that implements the `Formatter` interface, see the `README` or included
|
|
||||||
// formatters for examples.
|
|
||||||
Formatter Formatter
|
|
||||||
// The logging level the logger should log at. This is typically (and defaults
|
|
||||||
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
|
|
||||||
// logged. `logrus.Debug` is useful in
|
|
||||||
Level Level
|
|
||||||
// Used to sync writing to the log.
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new logger. Configuration should be set by changing `Formatter`,
|
|
||||||
// `Out` and `Hooks` directly on the default logger instance. You can also just
|
|
||||||
// instantiate your own:
|
|
||||||
//
|
|
||||||
// var log = &Logger{
|
|
||||||
// Out: os.Stderr,
|
|
||||||
// Formatter: new(JSONFormatter),
|
|
||||||
// Hooks: make(LevelHooks),
|
|
||||||
// Level: logrus.DebugLevel,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// It's recommended to make this a global instance called `log`.
|
|
||||||
func New() *Logger {
|
|
||||||
return &Logger{
|
|
||||||
Out: os.Stderr,
|
|
||||||
Formatter: new(TextFormatter),
|
|
||||||
Hooks: make(LevelHooks),
|
|
||||||
Level: InfoLevel,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a field to the log entry, note that you it doesn't log until you call
|
|
||||||
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
|
|
||||||
// If you want multiple fields, use `WithFields`.
|
|
||||||
func (logger *Logger) WithField(key string, value interface{}) *Entry {
|
|
||||||
return NewEntry(logger).WithField(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds a struct of fields to the log entry. All it does is call `WithField` for
|
|
||||||
// each `Field`.
|
|
||||||
func (logger *Logger) WithFields(fields Fields) *Entry {
|
|
||||||
return NewEntry(logger).WithFields(fields)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add an error as single field to the log entry. All it does is call
|
|
||||||
// `WithError` for the given `error`.
|
|
||||||
func (logger *Logger) WithError(err error) *Entry {
|
|
||||||
return NewEntry(logger).WithError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debugf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= DebugLevel {
|
|
||||||
NewEntry(logger).Debugf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Infof(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= InfoLevel {
|
|
||||||
NewEntry(logger).Infof(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Printf(format string, args ...interface{}) {
|
|
||||||
NewEntry(logger).Printf(format, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warnf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
NewEntry(logger).Warnf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warningf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
NewEntry(logger).Warnf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Errorf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= ErrorLevel {
|
|
||||||
NewEntry(logger).Errorf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatalf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= FatalLevel {
|
|
||||||
NewEntry(logger).Fatalf(format, args...)
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Panicf(format string, args ...interface{}) {
|
|
||||||
if logger.Level >= PanicLevel {
|
|
||||||
NewEntry(logger).Panicf(format, args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debug(args ...interface{}) {
|
|
||||||
if logger.Level >= DebugLevel {
|
|
||||||
NewEntry(logger).Debug(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Info(args ...interface{}) {
|
|
||||||
if logger.Level >= InfoLevel {
|
|
||||||
NewEntry(logger).Info(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Print(args ...interface{}) {
|
|
||||||
NewEntry(logger).Info(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warn(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
NewEntry(logger).Warn(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warning(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
NewEntry(logger).Warn(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Error(args ...interface{}) {
|
|
||||||
if logger.Level >= ErrorLevel {
|
|
||||||
NewEntry(logger).Error(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatal(args ...interface{}) {
|
|
||||||
if logger.Level >= FatalLevel {
|
|
||||||
NewEntry(logger).Fatal(args...)
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Panic(args ...interface{}) {
|
|
||||||
if logger.Level >= PanicLevel {
|
|
||||||
NewEntry(logger).Panic(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Debugln(args ...interface{}) {
|
|
||||||
if logger.Level >= DebugLevel {
|
|
||||||
NewEntry(logger).Debugln(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Infoln(args ...interface{}) {
|
|
||||||
if logger.Level >= InfoLevel {
|
|
||||||
NewEntry(logger).Infoln(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Println(args ...interface{}) {
|
|
||||||
NewEntry(logger).Println(args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warnln(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
NewEntry(logger).Warnln(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Warningln(args ...interface{}) {
|
|
||||||
if logger.Level >= WarnLevel {
|
|
||||||
NewEntry(logger).Warnln(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Errorln(args ...interface{}) {
|
|
||||||
if logger.Level >= ErrorLevel {
|
|
||||||
NewEntry(logger).Errorln(args...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Fatalln(args ...interface{}) {
|
|
||||||
if logger.Level >= FatalLevel {
|
|
||||||
NewEntry(logger).Fatalln(args...)
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) Panicln(args ...interface{}) {
|
|
||||||
if logger.Level >= PanicLevel {
|
|
||||||
NewEntry(logger).Panicln(args...)
|
|
||||||
}
|
|
||||||
}
|
|
143
vendor/github.com/Sirupsen/logrus/logrus.go
generated
vendored
143
vendor/github.com/Sirupsen/logrus/logrus.go
generated
vendored
@ -1,143 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fields type, used to pass to `WithFields`.
|
|
||||||
type Fields map[string]interface{}
|
|
||||||
|
|
||||||
// Level type
|
|
||||||
type Level uint8
|
|
||||||
|
|
||||||
// Convert the Level to a string. E.g. PanicLevel becomes "panic".
|
|
||||||
func (level Level) String() string {
|
|
||||||
switch level {
|
|
||||||
case DebugLevel:
|
|
||||||
return "debug"
|
|
||||||
case InfoLevel:
|
|
||||||
return "info"
|
|
||||||
case WarnLevel:
|
|
||||||
return "warning"
|
|
||||||
case ErrorLevel:
|
|
||||||
return "error"
|
|
||||||
case FatalLevel:
|
|
||||||
return "fatal"
|
|
||||||
case PanicLevel:
|
|
||||||
return "panic"
|
|
||||||
}
|
|
||||||
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseLevel takes a string level and returns the Logrus log level constant.
|
|
||||||
func ParseLevel(lvl string) (Level, error) {
|
|
||||||
switch strings.ToLower(lvl) {
|
|
||||||
case "panic":
|
|
||||||
return PanicLevel, nil
|
|
||||||
case "fatal":
|
|
||||||
return FatalLevel, nil
|
|
||||||
case "error":
|
|
||||||
return ErrorLevel, nil
|
|
||||||
case "warn", "warning":
|
|
||||||
return WarnLevel, nil
|
|
||||||
case "info":
|
|
||||||
return InfoLevel, nil
|
|
||||||
case "debug":
|
|
||||||
return DebugLevel, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var l Level
|
|
||||||
return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A constant exposing all logging levels
|
|
||||||
var AllLevels = []Level{
|
|
||||||
PanicLevel,
|
|
||||||
FatalLevel,
|
|
||||||
ErrorLevel,
|
|
||||||
WarnLevel,
|
|
||||||
InfoLevel,
|
|
||||||
DebugLevel,
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are the different logging levels. You can set the logging level to log
|
|
||||||
// on your instance of logger, obtained with `logrus.New()`.
|
|
||||||
const (
|
|
||||||
// PanicLevel level, highest level of severity. Logs and then calls panic with the
|
|
||||||
// message passed to Debug, Info, ...
|
|
||||||
PanicLevel Level = iota
|
|
||||||
// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
|
|
||||||
// logging level is set to Panic.
|
|
||||||
FatalLevel
|
|
||||||
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
|
||||||
// Commonly used for hooks to send errors to an error tracking service.
|
|
||||||
ErrorLevel
|
|
||||||
// WarnLevel level. Non-critical entries that deserve eyes.
|
|
||||||
WarnLevel
|
|
||||||
// InfoLevel level. General operational entries about what's going on inside the
|
|
||||||
// application.
|
|
||||||
InfoLevel
|
|
||||||
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
|
||||||
DebugLevel
|
|
||||||
)
|
|
||||||
|
|
||||||
// Won't compile if StdLogger can't be realized by a log.Logger
|
|
||||||
var (
|
|
||||||
_ StdLogger = &log.Logger{}
|
|
||||||
_ StdLogger = &Entry{}
|
|
||||||
_ StdLogger = &Logger{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// StdLogger is what your logrus-enabled library should take, that way
|
|
||||||
// it'll accept a stdlib logger and a logrus logger. There's no standard
|
|
||||||
// interface, this is the closest we get, unfortunately.
|
|
||||||
type StdLogger interface {
|
|
||||||
Print(...interface{})
|
|
||||||
Printf(string, ...interface{})
|
|
||||||
Println(...interface{})
|
|
||||||
|
|
||||||
Fatal(...interface{})
|
|
||||||
Fatalf(string, ...interface{})
|
|
||||||
Fatalln(...interface{})
|
|
||||||
|
|
||||||
Panic(...interface{})
|
|
||||||
Panicf(string, ...interface{})
|
|
||||||
Panicln(...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// The FieldLogger interface generalizes the Entry and Logger types
|
|
||||||
type FieldLogger interface {
|
|
||||||
WithField(key string, value interface{}) *Entry
|
|
||||||
WithFields(fields Fields) *Entry
|
|
||||||
WithError(err error) *Entry
|
|
||||||
|
|
||||||
Debugf(format string, args ...interface{})
|
|
||||||
Infof(format string, args ...interface{})
|
|
||||||
Printf(format string, args ...interface{})
|
|
||||||
Warnf(format string, args ...interface{})
|
|
||||||
Warningf(format string, args ...interface{})
|
|
||||||
Errorf(format string, args ...interface{})
|
|
||||||
Fatalf(format string, args ...interface{})
|
|
||||||
Panicf(format string, args ...interface{})
|
|
||||||
|
|
||||||
Debug(args ...interface{})
|
|
||||||
Info(args ...interface{})
|
|
||||||
Print(args ...interface{})
|
|
||||||
Warn(args ...interface{})
|
|
||||||
Warning(args ...interface{})
|
|
||||||
Error(args ...interface{})
|
|
||||||
Fatal(args ...interface{})
|
|
||||||
Panic(args ...interface{})
|
|
||||||
|
|
||||||
Debugln(args ...interface{})
|
|
||||||
Infoln(args ...interface{})
|
|
||||||
Println(args ...interface{})
|
|
||||||
Warnln(args ...interface{})
|
|
||||||
Warningln(args ...interface{})
|
|
||||||
Errorln(args ...interface{})
|
|
||||||
Fatalln(args ...interface{})
|
|
||||||
Panicln(args ...interface{})
|
|
||||||
}
|
|
9
vendor/github.com/Sirupsen/logrus/terminal_bsd.go
generated
vendored
9
vendor/github.com/Sirupsen/logrus/terminal_bsd.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
// +build darwin freebsd openbsd netbsd dragonfly
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TIOCGETA
|
|
||||||
|
|
||||||
type Termios syscall.Termios
|
|
12
vendor/github.com/Sirupsen/logrus/terminal_linux.go
generated
vendored
12
vendor/github.com/Sirupsen/logrus/terminal_linux.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
// Based on ssh/terminal:
|
|
||||||
// Copyright 2013 The Go 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 logrus
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
const ioctlReadTermios = syscall.TCGETS
|
|
||||||
|
|
||||||
type Termios syscall.Termios
|
|
21
vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
generated
vendored
21
vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
// Based on ssh/terminal:
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build linux darwin freebsd openbsd netbsd dragonfly
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
fd := syscall.Stderr
|
|
||||||
var termios Termios
|
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
|
|
||||||
return err == 0
|
|
||||||
}
|
|
15
vendor/github.com/Sirupsen/logrus/terminal_solaris.go
generated
vendored
15
vendor/github.com/Sirupsen/logrus/terminal_solaris.go
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
// +build solaris
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
_, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
27
vendor/github.com/Sirupsen/logrus/terminal_windows.go
generated
vendored
27
vendor/github.com/Sirupsen/logrus/terminal_windows.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
// Based on ssh/terminal:
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
|
|
||||||
var (
|
|
||||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTerminal returns true if stderr's file descriptor is a terminal.
|
|
||||||
func IsTerminal() bool {
|
|
||||||
fd := syscall.Stderr
|
|
||||||
var st uint32
|
|
||||||
r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
|
|
||||||
return r != 0 && e == 0
|
|
||||||
}
|
|
161
vendor/github.com/Sirupsen/logrus/text_formatter.go
generated
vendored
161
vendor/github.com/Sirupsen/logrus/text_formatter.go
generated
vendored
@ -1,161 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
nocolor = 0
|
|
||||||
red = 31
|
|
||||||
green = 32
|
|
||||||
yellow = 33
|
|
||||||
blue = 34
|
|
||||||
gray = 37
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
baseTimestamp time.Time
|
|
||||||
isTerminal bool
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
baseTimestamp = time.Now()
|
|
||||||
isTerminal = IsTerminal()
|
|
||||||
}
|
|
||||||
|
|
||||||
func miniTS() int {
|
|
||||||
return int(time.Since(baseTimestamp) / time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
type TextFormatter struct {
|
|
||||||
// Set to true to bypass checking for a TTY before outputting colors.
|
|
||||||
ForceColors bool
|
|
||||||
|
|
||||||
// Force disabling colors.
|
|
||||||
DisableColors bool
|
|
||||||
|
|
||||||
// Disable timestamp logging. useful when output is redirected to logging
|
|
||||||
// system that already adds timestamps.
|
|
||||||
DisableTimestamp bool
|
|
||||||
|
|
||||||
// Enable logging the full timestamp when a TTY is attached instead of just
|
|
||||||
// the time passed since beginning of execution.
|
|
||||||
FullTimestamp bool
|
|
||||||
|
|
||||||
// TimestampFormat to use for display when a full timestamp is printed
|
|
||||||
TimestampFormat string
|
|
||||||
|
|
||||||
// The fields are sorted by default for a consistent output. For applications
|
|
||||||
// that log extremely frequently and don't use the JSON formatter this may not
|
|
||||||
// be desired.
|
|
||||||
DisableSorting bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
|
|
||||||
var keys []string = make([]string, 0, len(entry.Data))
|
|
||||||
for k := range entry.Data {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !f.DisableSorting {
|
|
||||||
sort.Strings(keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := &bytes.Buffer{}
|
|
||||||
|
|
||||||
prefixFieldClashes(entry.Data)
|
|
||||||
|
|
||||||
isColorTerminal := isTerminal && (runtime.GOOS != "windows")
|
|
||||||
isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors
|
|
||||||
|
|
||||||
timestampFormat := f.TimestampFormat
|
|
||||||
if timestampFormat == "" {
|
|
||||||
timestampFormat = DefaultTimestampFormat
|
|
||||||
}
|
|
||||||
if isColored {
|
|
||||||
f.printColored(b, entry, keys, timestampFormat)
|
|
||||||
} else {
|
|
||||||
if !f.DisableTimestamp {
|
|
||||||
f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
|
|
||||||
}
|
|
||||||
f.appendKeyValue(b, "level", entry.Level.String())
|
|
||||||
if entry.Message != "" {
|
|
||||||
f.appendKeyValue(b, "msg", entry.Message)
|
|
||||||
}
|
|
||||||
for _, key := range keys {
|
|
||||||
f.appendKeyValue(b, key, entry.Data[key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteByte('\n')
|
|
||||||
return b.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) {
|
|
||||||
var levelColor int
|
|
||||||
switch entry.Level {
|
|
||||||
case DebugLevel:
|
|
||||||
levelColor = gray
|
|
||||||
case WarnLevel:
|
|
||||||
levelColor = yellow
|
|
||||||
case ErrorLevel, FatalLevel, PanicLevel:
|
|
||||||
levelColor = red
|
|
||||||
default:
|
|
||||||
levelColor = blue
|
|
||||||
}
|
|
||||||
|
|
||||||
levelText := strings.ToUpper(entry.Level.String())[0:4]
|
|
||||||
|
|
||||||
if !f.FullTimestamp {
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message)
|
|
||||||
}
|
|
||||||
for _, k := range keys {
|
|
||||||
v := entry.Data[k]
|
|
||||||
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func needsQuoting(text string) bool {
|
|
||||||
for _, ch := range text {
|
|
||||||
if !((ch >= 'a' && ch <= 'z') ||
|
|
||||||
(ch >= 'A' && ch <= 'Z') ||
|
|
||||||
(ch >= '0' && ch <= '9') ||
|
|
||||||
ch == '-' || ch == '.') {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
|
|
||||||
|
|
||||||
b.WriteString(key)
|
|
||||||
b.WriteByte('=')
|
|
||||||
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
if !needsQuoting(value) {
|
|
||||||
b.WriteString(value)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "%q", value)
|
|
||||||
}
|
|
||||||
case error:
|
|
||||||
errmsg := value.Error()
|
|
||||||
if !needsQuoting(errmsg) {
|
|
||||||
b.WriteString(errmsg)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(b, "%q", value)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Fprint(b, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.WriteByte(' ')
|
|
||||||
}
|
|
53
vendor/github.com/Sirupsen/logrus/writer.go
generated
vendored
53
vendor/github.com/Sirupsen/logrus/writer.go
generated
vendored
@ -1,53 +0,0 @@
|
|||||||
package logrus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (logger *Logger) Writer() *io.PipeWriter {
|
|
||||||
return logger.WriterLevel(InfoLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
|
|
||||||
reader, writer := io.Pipe()
|
|
||||||
|
|
||||||
var printFunc func(args ...interface{})
|
|
||||||
switch level {
|
|
||||||
case DebugLevel:
|
|
||||||
printFunc = logger.Debug
|
|
||||||
case InfoLevel:
|
|
||||||
printFunc = logger.Info
|
|
||||||
case WarnLevel:
|
|
||||||
printFunc = logger.Warn
|
|
||||||
case ErrorLevel:
|
|
||||||
printFunc = logger.Error
|
|
||||||
case FatalLevel:
|
|
||||||
printFunc = logger.Fatal
|
|
||||||
case PanicLevel:
|
|
||||||
printFunc = logger.Panic
|
|
||||||
default:
|
|
||||||
printFunc = logger.Print
|
|
||||||
}
|
|
||||||
|
|
||||||
go logger.writerScanner(reader, printFunc)
|
|
||||||
runtime.SetFinalizer(writer, writerFinalizer)
|
|
||||||
|
|
||||||
return writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
|
|
||||||
scanner := bufio.NewScanner(reader)
|
|
||||||
for scanner.Scan() {
|
|
||||||
printFunc(scanner.Text())
|
|
||||||
}
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
logger.Errorf("Error while reading from Writer: %s", err)
|
|
||||||
}
|
|
||||||
reader.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func writerFinalizer(writer *io.PipeWriter) {
|
|
||||||
writer.Close()
|
|
||||||
}
|
|
26
vendor/github.com/amfranz/go-xmlrpc-client/error.go
generated
vendored
Normal file
26
vendor/github.com/amfranz/go-xmlrpc-client/error.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error represents errors returned on xmlrpc request.
|
||||||
|
type Error struct {
|
||||||
|
code string
|
||||||
|
message string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error() method implements Error interface
|
||||||
|
func (e *Error) Error() string {
|
||||||
|
return fmt.Sprintf("Error: \"%s\" Code: %s", e.message, e.code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code ...
|
||||||
|
func (e *Error) Code() string {
|
||||||
|
return e.code
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message ...
|
||||||
|
func (e *Error) Message() string {
|
||||||
|
return e.message
|
||||||
|
}
|
@ -34,7 +34,7 @@ func parseFailedResponse(response []byte) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &(xmlrpcError{
|
return &(Error{
|
||||||
code: fmt.Sprintf("%v", faultDetails["faultCode"]),
|
code: fmt.Sprintf("%v", faultDetails["faultCode"]),
|
||||||
message: faultDetails["faultString"].(string),
|
message: faultDetails["faultString"].(string),
|
||||||
})
|
})
|
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
// TIME_LAYOUT defines time template defined by iso8601, used to encode/decode time values.
|
// TIME_LAYOUT defines time template defined by iso8601, used to encode/decode time values.
|
||||||
const TIME_LAYOUT = "20060102T15:04:05"
|
const TIME_LAYOUT = "20060102T15:04:05"
|
||||||
|
const TIME_LAYOUT_iso8601Z = "20060102T15:04:05Z07:00"
|
||||||
|
|
||||||
func parseValue(valueXml []byte) (result interface{}, err error) {
|
func parseValue(valueXml []byte) (result interface{}, err error) {
|
||||||
parser := xml.NewDecoder(bytes.NewReader(valueXml))
|
parser := xml.NewDecoder(bytes.NewReader(valueXml))
|
||||||
@ -90,7 +91,9 @@ func getDateValue(parser *xml.Decoder) (result interface{}, err error) {
|
|||||||
var value string
|
var value string
|
||||||
value, err = getElementValue(parser)
|
value, err = getElementValue(parser)
|
||||||
result, err = time.Parse(TIME_LAYOUT, value)
|
result, err = time.Parse(TIME_LAYOUT, value)
|
||||||
|
if err != nil {
|
||||||
|
result, err = time.Parse(TIME_LAYOUT_iso8601Z, value)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
12
vendor/github.com/amfranz/go-xmlrpc-client/xmlrpc.go
generated
vendored
Normal file
12
vendor/github.com/amfranz/go-xmlrpc-client/xmlrpc.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
// Struct presents hash type used in xmlprc requests and responses.
|
||||||
|
type Struct map[string]interface{}
|
||||||
|
|
||||||
|
// Base64 represents base64 data
|
||||||
|
type Base64 string
|
||||||
|
|
||||||
|
// Params represents a list of parameters to a method.
|
||||||
|
type Params struct {
|
||||||
|
Params []interface{}
|
||||||
|
}
|
2
vendor/github.com/hashicorp/go-version/constraint.go
generated
vendored
2
vendor/github.com/hashicorp/go-version/constraint.go
generated
vendored
@ -37,7 +37,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ops := make([]string, 0, len(constraintOperators))
|
ops := make([]string, 0, len(constraintOperators))
|
||||||
for k := range constraintOperators {
|
for k, _ := range constraintOperators {
|
||||||
ops = append(ops, regexp.QuoteMeta(k))
|
ops = append(ops, regexp.QuoteMeta(k))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
vendor/github.com/kolo/xmlrpc/LICENSE
generated
vendored
Normal file
19
vendor/github.com/kolo/xmlrpc/LICENSE
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (C) 2012 Dmitry Maksimov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
90
vendor/github.com/kolo/xmlrpc/README.md
generated
vendored
Normal file
90
vendor/github.com/kolo/xmlrpc/README.md
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
[](https://godoc.org/github.com/kolo/xmlrpc)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
xmlrpc is an implementation of client side part of XMLRPC protocol in Go language.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
This project is in minimal maintenance mode with no further development. Bug fixes
|
||||||
|
are accepted, but it might take some time until they will be merged.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
To install xmlrpc package run `go get github.com/kolo/xmlrpc`. To use
|
||||||
|
it in application add `"github.com/kolo/xmlrpc"` string to `import`
|
||||||
|
statement.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
client, _ := xmlrpc.NewClient("https://bugzilla.mozilla.org/xmlrpc.cgi", nil)
|
||||||
|
result := struct{
|
||||||
|
Version string `xmlrpc:"version"`
|
||||||
|
}{}
|
||||||
|
client.Call("Bugzilla.version", nil, &result)
|
||||||
|
fmt.Printf("Version: %s\n", result.Version) // Version: 4.2.7+
|
||||||
|
|
||||||
|
Second argument of NewClient function is an object that implements
|
||||||
|
[http.RoundTripper](http://golang.org/pkg/net/http/#RoundTripper)
|
||||||
|
interface, it can be used to get more control over connection options.
|
||||||
|
By default it initialized by http.DefaultTransport object.
|
||||||
|
|
||||||
|
### Arguments encoding
|
||||||
|
|
||||||
|
xmlrpc package supports encoding of native Go data types to method
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
Data types encoding rules:
|
||||||
|
|
||||||
|
* int, int8, int16, int32, int64 encoded to int;
|
||||||
|
* float32, float64 encoded to double;
|
||||||
|
* bool encoded to boolean;
|
||||||
|
* string encoded to string;
|
||||||
|
* time.Time encoded to datetime.iso8601;
|
||||||
|
* xmlrpc.Base64 encoded to base64;
|
||||||
|
* slice encoded to array;
|
||||||
|
|
||||||
|
Structs encoded to struct by following rules:
|
||||||
|
|
||||||
|
* all public field become struct members;
|
||||||
|
* field name become member name;
|
||||||
|
* if field has xmlrpc tag, its value become member name.
|
||||||
|
* for fields tagged with `",omitempty"`, empty values are omitted;
|
||||||
|
|
||||||
|
Server method can accept few arguments, to handle this case there is
|
||||||
|
special approach to handle slice of empty interfaces (`[]interface{}`).
|
||||||
|
Each value of such slice encoded as separate argument.
|
||||||
|
|
||||||
|
### Result decoding
|
||||||
|
|
||||||
|
Result of remote function is decoded to native Go data type.
|
||||||
|
|
||||||
|
Data types decoding rules:
|
||||||
|
|
||||||
|
* int, i4 decoded to int, int8, int16, int32, int64;
|
||||||
|
* double decoded to float32, float64;
|
||||||
|
* boolean decoded to bool;
|
||||||
|
* string decoded to string;
|
||||||
|
* array decoded to slice;
|
||||||
|
* structs decoded following the rules described in previous section;
|
||||||
|
* datetime.iso8601 decoded as time.Time data type;
|
||||||
|
* base64 decoded to string.
|
||||||
|
|
||||||
|
## Implementation details
|
||||||
|
|
||||||
|
xmlrpc package contains clientCodec type, that implements [rpc.ClientCodec](http://golang.org/pkg/net/rpc/#ClientCodec)
|
||||||
|
interface of [net/rpc](http://golang.org/pkg/net/rpc) package.
|
||||||
|
|
||||||
|
xmlrpc package works over HTTP protocol, but some internal functions
|
||||||
|
and data type were made public to make it easier to create another
|
||||||
|
implementation of xmlrpc that works over another protocol. To encode
|
||||||
|
request body there is EncodeMethodCall function. To decode server
|
||||||
|
response Response data type can be used.
|
||||||
|
|
||||||
|
## Contribution
|
||||||
|
|
||||||
|
See [project status](#status).
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
Dmitry Maksimov (dmtmax@gmail.com)
|
161
vendor/github.com/kolo/xmlrpc/client.go
generated
vendored
Normal file
161
vendor/github.com/kolo/xmlrpc/client.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"net/rpc"
|
||||||
|
"net/url"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
*rpc.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// clientCodec is rpc.ClientCodec interface implementation.
|
||||||
|
type clientCodec struct {
|
||||||
|
// url presents url of xmlrpc service
|
||||||
|
url *url.URL
|
||||||
|
|
||||||
|
// httpClient works with HTTP protocol
|
||||||
|
httpClient *http.Client
|
||||||
|
|
||||||
|
// cookies stores cookies received on last request
|
||||||
|
cookies http.CookieJar
|
||||||
|
|
||||||
|
// responses presents map of active requests. It is required to return request id, that
|
||||||
|
// rpc.Client can mark them as done.
|
||||||
|
responses map[uint64]*http.Response
|
||||||
|
mutex sync.Mutex
|
||||||
|
|
||||||
|
response Response
|
||||||
|
|
||||||
|
// ready presents channel, that is used to link request and it`s response.
|
||||||
|
ready chan uint64
|
||||||
|
|
||||||
|
// close notifies codec is closed.
|
||||||
|
close chan uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *clientCodec) WriteRequest(request *rpc.Request, args interface{}) (err error) {
|
||||||
|
httpRequest, err := NewRequest(codec.url.String(), request.ServiceMethod, args)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if codec.cookies != nil {
|
||||||
|
for _, cookie := range codec.cookies.Cookies(codec.url) {
|
||||||
|
httpRequest.AddCookie(cookie)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpResponse *http.Response
|
||||||
|
httpResponse, err = codec.httpClient.Do(httpRequest)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if codec.cookies != nil {
|
||||||
|
codec.cookies.SetCookies(codec.url, httpResponse.Cookies())
|
||||||
|
}
|
||||||
|
|
||||||
|
codec.mutex.Lock()
|
||||||
|
codec.responses[request.Seq] = httpResponse
|
||||||
|
codec.mutex.Unlock()
|
||||||
|
|
||||||
|
codec.ready <- request.Seq
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *clientCodec) ReadResponseHeader(response *rpc.Response) (err error) {
|
||||||
|
var seq uint64
|
||||||
|
select {
|
||||||
|
case seq = <-codec.ready:
|
||||||
|
case <-codec.close:
|
||||||
|
return errors.New("codec is closed")
|
||||||
|
}
|
||||||
|
response.Seq = seq
|
||||||
|
|
||||||
|
codec.mutex.Lock()
|
||||||
|
httpResponse := codec.responses[seq]
|
||||||
|
delete(codec.responses, seq)
|
||||||
|
codec.mutex.Unlock()
|
||||||
|
|
||||||
|
defer httpResponse.Body.Close()
|
||||||
|
|
||||||
|
if httpResponse.StatusCode < 200 || httpResponse.StatusCode >= 300 {
|
||||||
|
response.Error = fmt.Sprintf("request error: bad status code - %d", httpResponse.StatusCode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(httpResponse.Body)
|
||||||
|
if err != nil {
|
||||||
|
response.Error = err.Error()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := Response(body)
|
||||||
|
if err := resp.Err(); err != nil {
|
||||||
|
response.Error = err.Error()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
codec.response = resp
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *clientCodec) ReadResponseBody(v interface{}) (err error) {
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return codec.response.Unmarshal(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (codec *clientCodec) Close() error {
|
||||||
|
if transport, ok := codec.httpClient.Transport.(*http.Transport); ok {
|
||||||
|
transport.CloseIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
|
close(codec.close)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns instance of rpc.Client object, that is used to send request to xmlrpc service.
|
||||||
|
func NewClient(requrl string, transport http.RoundTripper) (*Client, error) {
|
||||||
|
if transport == nil {
|
||||||
|
transport = http.DefaultTransport
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := &http.Client{Transport: transport}
|
||||||
|
|
||||||
|
jar, err := cookiejar.New(nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(requrl)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
codec := clientCodec{
|
||||||
|
url: u,
|
||||||
|
httpClient: httpClient,
|
||||||
|
close: make(chan uint64),
|
||||||
|
ready: make(chan uint64),
|
||||||
|
responses: make(map[uint64]*http.Response),
|
||||||
|
cookies: jar,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Client{rpc.NewClientWithCodec(&codec)}, nil
|
||||||
|
}
|
473
vendor/github.com/kolo/xmlrpc/decoder.go
generated
vendored
Normal file
473
vendor/github.com/kolo/xmlrpc/decoder.go
generated
vendored
Normal file
@ -0,0 +1,473 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
iso8601 = "20060102T15:04:05"
|
||||||
|
iso8601Z = "20060102T15:04:05Z07:00"
|
||||||
|
iso8601Hyphen = "2006-01-02T15:04:05"
|
||||||
|
iso8601HyphenZ = "2006-01-02T15:04:05Z07:00"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// CharsetReader is a function to generate reader which converts a non UTF-8
|
||||||
|
// charset into UTF-8.
|
||||||
|
CharsetReader func(string, io.Reader) (io.Reader, error)
|
||||||
|
|
||||||
|
timeLayouts = []string{iso8601, iso8601Z, iso8601Hyphen, iso8601HyphenZ}
|
||||||
|
invalidXmlError = errors.New("invalid xml")
|
||||||
|
)
|
||||||
|
|
||||||
|
type TypeMismatchError string
|
||||||
|
|
||||||
|
func (e TypeMismatchError) Error() string { return string(e) }
|
||||||
|
|
||||||
|
type decoder struct {
|
||||||
|
*xml.Decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshal(data []byte, v interface{}) (err error) {
|
||||||
|
dec := &decoder{xml.NewDecoder(bytes.NewBuffer(data))}
|
||||||
|
|
||||||
|
if CharsetReader != nil {
|
||||||
|
dec.CharsetReader = CharsetReader
|
||||||
|
}
|
||||||
|
|
||||||
|
var tok xml.Token
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := tok.(xml.StartElement); ok {
|
||||||
|
if t.Name.Local == "value" {
|
||||||
|
val := reflect.ValueOf(v)
|
||||||
|
if val.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("non-pointer value passed to unmarshal")
|
||||||
|
}
|
||||||
|
if err = dec.decodeValue(val.Elem()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read until end of document
|
||||||
|
err = dec.Skip()
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *decoder) decodeValue(val reflect.Value) error {
|
||||||
|
var tok xml.Token
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if val.Kind() == reflect.Ptr {
|
||||||
|
if val.IsNil() {
|
||||||
|
val.Set(reflect.New(val.Type().Elem()))
|
||||||
|
}
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeName string
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := tok.(xml.EndElement); ok {
|
||||||
|
if t.Name.Local == "value" {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return invalidXmlError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := tok.(xml.StartElement); ok {
|
||||||
|
typeName = t.Name.Local
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Treat value data without type identifier as string
|
||||||
|
if t, ok := tok.(xml.CharData); ok {
|
||||||
|
if value := strings.TrimSpace(string(t)); value != "" {
|
||||||
|
if err = checkType(val, reflect.String); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
val.SetString(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typeName {
|
||||||
|
case "struct":
|
||||||
|
ismap := false
|
||||||
|
pmap := val
|
||||||
|
valType := val.Type()
|
||||||
|
|
||||||
|
if err = checkType(val, reflect.Struct); err != nil {
|
||||||
|
if checkType(val, reflect.Map) == nil {
|
||||||
|
if valType.Key().Kind() != reflect.String {
|
||||||
|
return fmt.Errorf("only maps with string key type can be unmarshalled")
|
||||||
|
}
|
||||||
|
ismap = true
|
||||||
|
} else if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
var dummy map[string]interface{}
|
||||||
|
valType = reflect.TypeOf(dummy)
|
||||||
|
pmap = reflect.New(valType).Elem()
|
||||||
|
val.Set(pmap)
|
||||||
|
ismap = true
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fields map[string]reflect.Value
|
||||||
|
|
||||||
|
if !ismap {
|
||||||
|
fields = make(map[string]reflect.Value)
|
||||||
|
|
||||||
|
for i := 0; i < valType.NumField(); i++ {
|
||||||
|
field := valType.Field(i)
|
||||||
|
fieldVal := val.FieldByName(field.Name)
|
||||||
|
|
||||||
|
if fieldVal.CanSet() {
|
||||||
|
if fn := field.Tag.Get("xmlrpc"); fn != "" {
|
||||||
|
fields[fn] = fieldVal
|
||||||
|
} else {
|
||||||
|
fields[field.Name] = fieldVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create initial empty map
|
||||||
|
pmap.Set(reflect.MakeMap(valType))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process struct members.
|
||||||
|
StructLoop:
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch t := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
if t.Name.Local != "member" {
|
||||||
|
return invalidXmlError
|
||||||
|
}
|
||||||
|
|
||||||
|
tagName, fieldName, err := dec.readTag()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if tagName != "name" {
|
||||||
|
return invalidXmlError
|
||||||
|
}
|
||||||
|
|
||||||
|
var fv reflect.Value
|
||||||
|
ok := true
|
||||||
|
|
||||||
|
if !ismap {
|
||||||
|
fv, ok = fields[string(fieldName)]
|
||||||
|
} else {
|
||||||
|
fv = reflect.New(valType.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if t, ok := tok.(xml.StartElement); ok && t.Name.Local == "value" {
|
||||||
|
if err = dec.decodeValue(fv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// </value>
|
||||||
|
if err = dec.Skip(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// </member>
|
||||||
|
if err = dec.Skip(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ismap {
|
||||||
|
pmap.SetMapIndex(reflect.ValueOf(string(fieldName)), reflect.Indirect(fv))
|
||||||
|
val.Set(pmap)
|
||||||
|
}
|
||||||
|
case xml.EndElement:
|
||||||
|
break StructLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "array":
|
||||||
|
slice := val
|
||||||
|
if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
slice = reflect.ValueOf([]interface{}{})
|
||||||
|
} else if err = checkType(val, reflect.Slice); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayLoop:
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
var index int
|
||||||
|
if t.Name.Local != "data" {
|
||||||
|
return invalidXmlError
|
||||||
|
}
|
||||||
|
DataLoop:
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tt := tok.(type) {
|
||||||
|
case xml.StartElement:
|
||||||
|
if tt.Name.Local != "value" {
|
||||||
|
return invalidXmlError
|
||||||
|
}
|
||||||
|
|
||||||
|
if index < slice.Len() {
|
||||||
|
v := slice.Index(index)
|
||||||
|
if v.Kind() == reflect.Interface {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
if v.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("error: cannot write to non-pointer array element")
|
||||||
|
}
|
||||||
|
if err = dec.decodeValue(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v := reflect.New(slice.Type().Elem())
|
||||||
|
if err = dec.decodeValue(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
slice = reflect.Append(slice, v.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
// </value>
|
||||||
|
if err = dec.Skip(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
case xml.EndElement:
|
||||||
|
val.Set(slice)
|
||||||
|
break DataLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case xml.EndElement:
|
||||||
|
break ArrayLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
|
||||||
|
switch t := tok.(type) {
|
||||||
|
case xml.EndElement:
|
||||||
|
return nil
|
||||||
|
case xml.CharData:
|
||||||
|
data = []byte(t.Copy())
|
||||||
|
default:
|
||||||
|
return invalidXmlError
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typeName {
|
||||||
|
case "int", "i4", "i8":
|
||||||
|
if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
i, err := strconv.ParseInt(string(data), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pi := reflect.New(reflect.TypeOf(i)).Elem()
|
||||||
|
pi.SetInt(i)
|
||||||
|
val.Set(pi)
|
||||||
|
} else if err = checkType(val, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
i, err := strconv.ParseInt(string(data), 10, val.Type().Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
val.SetInt(i)
|
||||||
|
}
|
||||||
|
case "string", "base64":
|
||||||
|
str := string(data)
|
||||||
|
if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
pstr := reflect.New(reflect.TypeOf(str)).Elem()
|
||||||
|
pstr.SetString(str)
|
||||||
|
val.Set(pstr)
|
||||||
|
} else if err = checkType(val, reflect.String); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
val.SetString(str)
|
||||||
|
}
|
||||||
|
case "dateTime.iso8601":
|
||||||
|
var t time.Time
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for _, layout := range timeLayouts {
|
||||||
|
t, err = time.Parse(layout, string(data))
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
ptime := reflect.New(reflect.TypeOf(t)).Elem()
|
||||||
|
ptime.Set(reflect.ValueOf(t))
|
||||||
|
val.Set(ptime)
|
||||||
|
} else if _, ok := val.Interface().(time.Time); !ok {
|
||||||
|
return TypeMismatchError(fmt.Sprintf("error: type mismatch error - can't decode %v to time", val.Kind()))
|
||||||
|
} else {
|
||||||
|
val.Set(reflect.ValueOf(t))
|
||||||
|
}
|
||||||
|
case "boolean":
|
||||||
|
v, err := strconv.ParseBool(string(data))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
pv := reflect.New(reflect.TypeOf(v)).Elem()
|
||||||
|
pv.SetBool(v)
|
||||||
|
val.Set(pv)
|
||||||
|
} else if err = checkType(val, reflect.Bool); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
val.SetBool(v)
|
||||||
|
}
|
||||||
|
case "double":
|
||||||
|
if checkType(val, reflect.Interface) == nil && val.IsNil() {
|
||||||
|
i, err := strconv.ParseFloat(string(data), 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pdouble := reflect.New(reflect.TypeOf(i)).Elem()
|
||||||
|
pdouble.SetFloat(i)
|
||||||
|
val.Set(pdouble)
|
||||||
|
} else if err = checkType(val, reflect.Float32, reflect.Float64); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
i, err := strconv.ParseFloat(string(data), val.Type().Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
val.SetFloat(i)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return errors.New("unsupported type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// </type>
|
||||||
|
if err = dec.Skip(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *decoder) readTag() (string, []byte, error) {
|
||||||
|
var tok xml.Token
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var name string
|
||||||
|
for {
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := tok.(xml.StartElement); ok {
|
||||||
|
name = t.Name.Local
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := dec.readCharData()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return name, value, dec.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *decoder) readCharData() ([]byte, error) {
|
||||||
|
var tok xml.Token
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if tok, err = dec.Token(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := tok.(xml.CharData); ok {
|
||||||
|
return []byte(t.Copy()), nil
|
||||||
|
} else {
|
||||||
|
return nil, invalidXmlError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkType(val reflect.Value, kinds ...reflect.Kind) error {
|
||||||
|
if len(kinds) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if val.Kind() == reflect.Ptr {
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
match := false
|
||||||
|
|
||||||
|
for _, kind := range kinds {
|
||||||
|
if val.Kind() == kind {
|
||||||
|
match = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !match {
|
||||||
|
return TypeMismatchError(fmt.Sprintf("error: type mismatch - can't unmarshal %v to %v",
|
||||||
|
val.Kind(), kinds[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
181
vendor/github.com/kolo/xmlrpc/encoder.go
generated
vendored
Normal file
181
vendor/github.com/kolo/xmlrpc/encoder.go
generated
vendored
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Base64 represents value in base64 encoding
|
||||||
|
type Base64 string
|
||||||
|
|
||||||
|
type encodeFunc func(reflect.Value) ([]byte, error)
|
||||||
|
|
||||||
|
func marshal(v interface{}) ([]byte, error) {
|
||||||
|
if v == nil {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
val := reflect.ValueOf(v)
|
||||||
|
return encodeValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeValue(val reflect.Value) ([]byte, error) {
|
||||||
|
var b []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface {
|
||||||
|
if val.IsNil() {
|
||||||
|
return []byte("<value/>"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
switch val.Interface().(type) {
|
||||||
|
case time.Time:
|
||||||
|
t := val.Interface().(time.Time)
|
||||||
|
b = []byte(fmt.Sprintf("<dateTime.iso8601>%s</dateTime.iso8601>", t.Format(iso8601)))
|
||||||
|
default:
|
||||||
|
b, err = encodeStruct(val)
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
b, err = encodeMap(val)
|
||||||
|
case reflect.Slice:
|
||||||
|
b, err = encodeSlice(val)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
b = []byte(fmt.Sprintf("<int>%s</int>", strconv.FormatInt(val.Int(), 10)))
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
b = []byte(fmt.Sprintf("<i4>%s</i4>", strconv.FormatUint(val.Uint(), 10)))
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
b = []byte(fmt.Sprintf("<double>%s</double>",
|
||||||
|
strconv.FormatFloat(val.Float(), 'f', -1, val.Type().Bits())))
|
||||||
|
case reflect.Bool:
|
||||||
|
if val.Bool() {
|
||||||
|
b = []byte("<boolean>1</boolean>")
|
||||||
|
} else {
|
||||||
|
b = []byte("<boolean>0</boolean>")
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
xml.Escape(&buf, []byte(val.String()))
|
||||||
|
|
||||||
|
if _, ok := val.Interface().(Base64); ok {
|
||||||
|
b = []byte(fmt.Sprintf("<base64>%s</base64>", buf.String()))
|
||||||
|
} else {
|
||||||
|
b = []byte(fmt.Sprintf("<string>%s</string>", buf.String()))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("xmlrpc encode error: unsupported type")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(fmt.Sprintf("<value>%s</value>", string(b))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeStruct(structVal reflect.Value) ([]byte, error) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
b.WriteString("<struct>")
|
||||||
|
|
||||||
|
structType := structVal.Type()
|
||||||
|
for i := 0; i < structType.NumField(); i++ {
|
||||||
|
fieldVal := structVal.Field(i)
|
||||||
|
fieldType := structType.Field(i)
|
||||||
|
|
||||||
|
name := fieldType.Tag.Get("xmlrpc")
|
||||||
|
// if the tag has the omitempty property, skip it
|
||||||
|
if strings.HasSuffix(name, ",omitempty") && isZero(fieldVal) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name = strings.TrimSuffix(name, ",omitempty")
|
||||||
|
if name == "" {
|
||||||
|
name = fieldType.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := encodeValue(fieldVal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("<member>")
|
||||||
|
b.WriteString(fmt.Sprintf("<name>%s</name>", name))
|
||||||
|
b.Write(p)
|
||||||
|
b.WriteString("</member>")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("</struct>")
|
||||||
|
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var sortMapKeys bool
|
||||||
|
|
||||||
|
func encodeMap(val reflect.Value) ([]byte, error) {
|
||||||
|
var t = val.Type()
|
||||||
|
|
||||||
|
if t.Key().Kind() != reflect.String {
|
||||||
|
return nil, fmt.Errorf("xmlrpc encode error: only maps with string keys are supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
b.WriteString("<struct>")
|
||||||
|
|
||||||
|
keys := val.MapKeys()
|
||||||
|
|
||||||
|
if sortMapKeys {
|
||||||
|
sort.Slice(keys, func(i, j int) bool { return keys[i].String() < keys[j].String() })
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < val.Len(); i++ {
|
||||||
|
key := keys[i]
|
||||||
|
kval := val.MapIndex(key)
|
||||||
|
|
||||||
|
b.WriteString("<member>")
|
||||||
|
b.WriteString(fmt.Sprintf("<name>%s</name>", key.String()))
|
||||||
|
|
||||||
|
p, err := encodeValue(kval)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Write(p)
|
||||||
|
b.WriteString("</member>")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("</struct>")
|
||||||
|
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeSlice(val reflect.Value) ([]byte, error) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
b.WriteString("<array><data>")
|
||||||
|
|
||||||
|
for i := 0; i < val.Len(); i++ {
|
||||||
|
p, err := encodeValue(val.Index(i))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("</data></array>")
|
||||||
|
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
44
vendor/github.com/kolo/xmlrpc/is_zero.go
generated
vendored
Normal file
44
vendor/github.com/kolo/xmlrpc/is_zero.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
. "reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isZero(v Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case Bool:
|
||||||
|
return !v.Bool()
|
||||||
|
case Int, Int8, Int16, Int32, Int64:
|
||||||
|
return v.Int() == 0
|
||||||
|
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||||
|
return v.Uint() == 0
|
||||||
|
case Float32, Float64:
|
||||||
|
return math.Float64bits(v.Float()) == 0
|
||||||
|
case Complex64, Complex128:
|
||||||
|
c := v.Complex()
|
||||||
|
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
|
||||||
|
case Array:
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
if !isZero(v.Index(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer:
|
||||||
|
return v.IsNil()
|
||||||
|
case String:
|
||||||
|
return v.Len() == 0
|
||||||
|
case Struct:
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
if !isZero(v.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
// This should never happens, but will act as a safeguard for
|
||||||
|
// later, as a default value doesn't makes sense here.
|
||||||
|
panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
|
||||||
|
}
|
||||||
|
}
|
57
vendor/github.com/kolo/xmlrpc/request.go
generated
vendored
Normal file
57
vendor/github.com/kolo/xmlrpc/request.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRequest(url string, method string, args interface{}) (*http.Request, error) {
|
||||||
|
var t []interface{}
|
||||||
|
var ok bool
|
||||||
|
if t, ok = args.([]interface{}); !ok {
|
||||||
|
if args != nil {
|
||||||
|
t = []interface{}{args}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := EncodeMethodCall(method, t...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
request, err := http.NewRequest("POST", url, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Header.Set("Content-Type", "text/xml")
|
||||||
|
request.Header.Set("Content-Length", fmt.Sprintf("%d", len(body)))
|
||||||
|
|
||||||
|
return request, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeMethodCall(method string, args ...interface{}) ([]byte, error) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
b.WriteString(`<?xml version="1.0" encoding="UTF-8"?>`)
|
||||||
|
b.WriteString(fmt.Sprintf("<methodCall><methodName>%s</methodName>", method))
|
||||||
|
|
||||||
|
if args != nil {
|
||||||
|
b.WriteString("<params>")
|
||||||
|
|
||||||
|
for _, arg := range args {
|
||||||
|
p, err := marshal(arg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString(fmt.Sprintf("<param>%s</param>", string(p)))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("</params>")
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("</methodCall>")
|
||||||
|
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
42
vendor/github.com/kolo/xmlrpc/response.go
generated
vendored
Normal file
42
vendor/github.com/kolo/xmlrpc/response.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package xmlrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
faultRx = regexp.MustCompile(`<fault>(\s|\S)+</fault>`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// FaultError is returned from the server when an invalid call is made
|
||||||
|
type FaultError struct {
|
||||||
|
Code int `xmlrpc:"faultCode"`
|
||||||
|
String string `xmlrpc:"faultString"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface
|
||||||
|
func (e FaultError) Error() string {
|
||||||
|
return fmt.Sprintf("Fault(%d): %s", e.Code, e.String)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response []byte
|
||||||
|
|
||||||
|
func (r Response) Err() error {
|
||||||
|
if !faultRx.Match(r) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var fault FaultError
|
||||||
|
if err := unmarshal(r, &fault); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fault
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Response) Unmarshal(v interface{}) error {
|
||||||
|
if err := unmarshal(r, v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
25
vendor/github.com/kolo/xmlrpc/test_server.rb
generated
vendored
Normal file
25
vendor/github.com/kolo/xmlrpc/test_server.rb
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
require "xmlrpc/server"
|
||||||
|
|
||||||
|
class Service
|
||||||
|
def time
|
||||||
|
Time.now
|
||||||
|
end
|
||||||
|
|
||||||
|
def upcase(s)
|
||||||
|
s.upcase
|
||||||
|
end
|
||||||
|
|
||||||
|
def sum(x, y)
|
||||||
|
x + y
|
||||||
|
end
|
||||||
|
|
||||||
|
def error
|
||||||
|
raise XMLRPC::FaultException.new(500, "Server error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
server = XMLRPC::Server.new 5001, 'localhost'
|
||||||
|
server.add_handler "service", Service.new
|
||||||
|
server.serve
|
6
vendor/github.com/masterzen/simplexml/dom/document.go
generated
vendored
6
vendor/github.com/masterzen/simplexml/dom/document.go
generated
vendored
@ -6,14 +6,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Document struct {
|
type Document struct {
|
||||||
root *Element
|
root *Element
|
||||||
PrettyPrint bool
|
PrettyPrint bool
|
||||||
Indentation string
|
Indentation string
|
||||||
DocType bool
|
DocType bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateDocument() *Document {
|
func CreateDocument() *Document {
|
||||||
return &Document{PrettyPrint: false, Indentation: " ", DocType: true}
|
return &Document{ PrettyPrint: false, Indentation: " ", DocType: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (doc *Document) SetRoot(node *Element) {
|
func (doc *Document) SetRoot(node *Element) {
|
||||||
|
33
vendor/github.com/masterzen/simplexml/dom/element.go
generated
vendored
33
vendor/github.com/masterzen/simplexml/dom/element.go
generated
vendored
@ -1,9 +1,9 @@
|
|||||||
package dom
|
package dom
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Attr struct {
|
type Attr struct {
|
||||||
@ -12,20 +12,20 @@ type Attr struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Element struct {
|
type Element struct {
|
||||||
name xml.Name
|
name xml.Name
|
||||||
children []*Element
|
children []*Element
|
||||||
parent *Element
|
parent *Element
|
||||||
content string
|
content string
|
||||||
attributes []*Attr
|
attributes []*Attr
|
||||||
namespaces []*Namespace
|
namespaces []*Namespace
|
||||||
document *Document
|
document *Document
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateElement(n string) *Element {
|
func CreateElement(n string) *Element {
|
||||||
element := &Element{name: xml.Name{Local: n}}
|
element := &Element { name: xml.Name { Local: n } }
|
||||||
element.children = make([]*Element, 0, 5)
|
element.children = make([]*Element, 0, 5)
|
||||||
element.attributes = make([]*Attr, 0, 10)
|
element.attributes = make([]*Attr, 0, 10)
|
||||||
element.namespaces = make([]*Namespace, 0, 10)
|
element.namespaces = make([]*Namespace, 0, 10)
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ func (node *Element) RemoveChild(child *Element) *Element {
|
|||||||
|
|
||||||
func (node *Element) SetAttr(name string, value string) *Element {
|
func (node *Element) SetAttr(name string, value string) *Element {
|
||||||
// namespaces?
|
// namespaces?
|
||||||
attr := &Attr{Name: xml.Name{Local: name}, Value: value}
|
attr := &Attr{ Name: xml.Name { Local: name }, Value: value }
|
||||||
node.attributes = append(node.attributes, attr)
|
node.attributes = append(node.attributes, attr)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ func (node *Element) SetContent(content string) *Element {
|
|||||||
func (node *Element) DeclareNamespace(ns Namespace) *Element {
|
func (node *Element) DeclareNamespace(ns Namespace) *Element {
|
||||||
// check if we already have it
|
// check if we already have it
|
||||||
prefix := node.namespacePrefix(ns.Uri)
|
prefix := node.namespacePrefix(ns.Uri)
|
||||||
if prefix == ns.Prefix {
|
if prefix == ns.Prefix {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
// add it
|
// add it
|
||||||
@ -94,7 +94,7 @@ func (node *Element) SetNamespace(prefix string, uri string) {
|
|||||||
resolved := node.namespacePrefix(uri)
|
resolved := node.namespacePrefix(uri)
|
||||||
if resolved == "" {
|
if resolved == "" {
|
||||||
// we couldn't find the namespace, let's declare it at this node
|
// we couldn't find the namespace, let's declare it at this node
|
||||||
node.namespaces = append(node.namespaces, &Namespace{Prefix: prefix, Uri: uri})
|
node.namespaces = append(node.namespaces, &Namespace { Prefix: prefix, Uri: uri })
|
||||||
}
|
}
|
||||||
node.name.Space = uri
|
node.name.Space = uri
|
||||||
}
|
}
|
||||||
@ -102,16 +102,16 @@ func (node *Element) SetNamespace(prefix string, uri string) {
|
|||||||
func (node *Element) Bytes(out *bytes.Buffer, indent bool, indentType string, level int) {
|
func (node *Element) Bytes(out *bytes.Buffer, indent bool, indentType string, level int) {
|
||||||
empty := len(node.children) == 0 && node.content == ""
|
empty := len(node.children) == 0 && node.content == ""
|
||||||
content := node.content != ""
|
content := node.content != ""
|
||||||
// children := len(node.children) > 0
|
// children := len(node.children) > 0
|
||||||
// ns := len(node.namespaces) > 0
|
// ns := len(node.namespaces) > 0
|
||||||
// attrs := len(node.attributes) > 0
|
// attrs := len(node.attributes) > 0
|
||||||
|
|
||||||
indentStr := ""
|
indentStr := ""
|
||||||
nextLine := ""
|
nextLine := ""
|
||||||
if indent {
|
if indent {
|
||||||
nextLine = "\n"
|
nextLine = "\n"
|
||||||
for i := 0; i < level; i++ {
|
for i := 0; i < level; i++ {
|
||||||
indentStr += indentType
|
indentStr += indentType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ func (node *Element) Bytes(out *bytes.Buffer, indent bool, indentType string, le
|
|||||||
|
|
||||||
if len(node.children) > 0 {
|
if len(node.children) > 0 {
|
||||||
for _, child := range node.children {
|
for _, child := range node.children {
|
||||||
child.Bytes(out, indent, indentType, level+1)
|
child.Bytes(out, indent, indentType, level + 1)
|
||||||
}
|
}
|
||||||
} else if node.content != "" {
|
} else if node.content != "" {
|
||||||
//val := []byte(node.content)
|
//val := []byte(node.content)
|
||||||
@ -192,6 +192,7 @@ func (node *Element) namespacePrefix(uri string) string {
|
|||||||
return node.parent.namespacePrefix(uri)
|
return node.parent.namespacePrefix(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (node *Element) String() string {
|
func (node *Element) String() string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
node.Bytes(&b, false, "", 0)
|
node.Bytes(&b, false, "", 0)
|
||||||
|
14
vendor/github.com/masterzen/xmlpath/path.go
generated
vendored
14
vendor/github.com/masterzen/xmlpath/path.go
generated
vendored
@ -372,7 +372,7 @@ func MustCompile(path string) *Path {
|
|||||||
|
|
||||||
// Compile returns the compiled path.
|
// Compile returns the compiled path.
|
||||||
func Compile(path string) (*Path, error) {
|
func Compile(path string) (*Path, error) {
|
||||||
c := pathCompiler{path, 0, []Namespace{}}
|
c := pathCompiler{path, 0, []Namespace{} }
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return nil, c.errorf("empty path")
|
return nil, c.errorf("empty path")
|
||||||
}
|
}
|
||||||
@ -397,9 +397,9 @@ func CompileWithNamespace(path string, ns []Namespace) (*Path, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type pathCompiler struct {
|
type pathCompiler struct {
|
||||||
path string
|
path string
|
||||||
i int
|
i int
|
||||||
ns []Namespace
|
ns []Namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *pathCompiler) errorf(format string, args ...interface{}) error {
|
func (c *pathCompiler) errorf(format string, args ...interface{}) error {
|
||||||
@ -575,14 +575,14 @@ func (c *pathCompiler) parseLiteral() (string, error) {
|
|||||||
if !c.skipByteFind('"') {
|
if !c.skipByteFind('"') {
|
||||||
return "", fmt.Errorf(`missing '"'`)
|
return "", fmt.Errorf(`missing '"'`)
|
||||||
}
|
}
|
||||||
return c.path[mark : c.i-1], nil
|
return c.path[mark:c.i-1], nil
|
||||||
}
|
}
|
||||||
if c.skipByte('\'') {
|
if c.skipByte('\'') {
|
||||||
mark := c.i
|
mark := c.i
|
||||||
if !c.skipByteFind('\'') {
|
if !c.skipByteFind('\'') {
|
||||||
return "", fmt.Errorf(`missing "'"`)
|
return "", fmt.Errorf(`missing "'"`)
|
||||||
}
|
}
|
||||||
return c.path[mark : c.i-1], nil
|
return c.path[mark:c.i-1], nil
|
||||||
}
|
}
|
||||||
return "", errNoLiteral
|
return "", errNoLiteral
|
||||||
}
|
}
|
||||||
@ -611,7 +611,7 @@ func (c *pathCompiler) skipByte(b byte) bool {
|
|||||||
func (c *pathCompiler) skipByteFind(b byte) bool {
|
func (c *pathCompiler) skipByteFind(b byte) bool {
|
||||||
for i := c.i; i < len(c.path); i++ {
|
for i := c.i; i < len(c.path); i++ {
|
||||||
if c.path[i] == b {
|
if c.path[i] == b {
|
||||||
c.i = i + 1
|
c.i = i+1
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/mitchellh/go-fs/fat/directory_cluster.go
generated
vendored
8
vendor/github.com/mitchellh/go-fs/fat/directory_cluster.go
generated
vendored
@ -125,7 +125,7 @@ func NewDirectoryCluster(start uint32, parent uint32, t time.Time) *DirectoryClu
|
|||||||
|
|
||||||
// Create the "." and ".." entries
|
// Create the "." and ".." entries
|
||||||
cluster.entries = []*DirectoryClusterEntry{
|
cluster.entries = []*DirectoryClusterEntry{
|
||||||
{
|
&DirectoryClusterEntry{
|
||||||
accessTime: t,
|
accessTime: t,
|
||||||
attr: AttrDirectory,
|
attr: AttrDirectory,
|
||||||
cluster: start,
|
cluster: start,
|
||||||
@ -133,7 +133,7 @@ func NewDirectoryCluster(start uint32, parent uint32, t time.Time) *DirectoryClu
|
|||||||
name: ".",
|
name: ".",
|
||||||
writeTime: t,
|
writeTime: t,
|
||||||
},
|
},
|
||||||
{
|
&DirectoryClusterEntry{
|
||||||
accessTime: t,
|
accessTime: t,
|
||||||
attr: AttrDirectory,
|
attr: AttrDirectory,
|
||||||
cluster: parent,
|
cluster: parent,
|
||||||
@ -159,8 +159,8 @@ func NewFat16RootDirectoryCluster(bs *BootSectorCommon, label string) (*Director
|
|||||||
|
|
||||||
// Create the volume ID entry
|
// Create the volume ID entry
|
||||||
result.entries[0] = &DirectoryClusterEntry{
|
result.entries[0] = &DirectoryClusterEntry{
|
||||||
attr: AttrVolumeId,
|
attr: AttrVolumeId,
|
||||||
name: label,
|
name: label,
|
||||||
cluster: 0,
|
cluster: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/github.com/mitchellh/go-fs/fat/short_name.go
generated
vendored
4
vendor/github.com/mitchellh/go-fs/fat/short_name.go
generated
vendored
@ -30,11 +30,11 @@ func generateShortName(longName string, used []string) (string, error) {
|
|||||||
if dotIdx == -1 {
|
if dotIdx == -1 {
|
||||||
dotIdx = len(longName)
|
dotIdx = len(longName)
|
||||||
} else {
|
} else {
|
||||||
ext = longName[dotIdx+1:]
|
ext = longName[dotIdx+1 : len(longName)]
|
||||||
}
|
}
|
||||||
|
|
||||||
ext = cleanShortString(ext)
|
ext = cleanShortString(ext)
|
||||||
ext = ext[0:]
|
ext = ext[0:len(ext)]
|
||||||
rawName := longName[0:dotIdx]
|
rawName := longName[0:dotIdx]
|
||||||
name := cleanShortString(rawName)
|
name := cleanShortString(rawName)
|
||||||
simpleName := fmt.Sprintf("%s.%s", name, ext)
|
simpleName := fmt.Sprintf("%s.%s", name, ext)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2014 Simon Eskildsen
|
Copyright (c) 2013 Mitchell Hashimoto
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
16
vendor/github.com/mitchellh/go-vnc/README.md
generated
vendored
Normal file
16
vendor/github.com/mitchellh/go-vnc/README.md
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# VNC Library for Go
|
||||||
|
|
||||||
|
go-vnc is a VNC library for Go, initially supporting VNC clients but
|
||||||
|
with the goal of eventually implementing a VNC server.
|
||||||
|
|
||||||
|
This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143).
|
||||||
|
|
||||||
|
## Usage & Installation
|
||||||
|
|
||||||
|
The library is installable via standard `go get`. The package name is `vnc`.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get github.com/mitchellh/go-vnc
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation is available on GoDoc: http://godoc.org/github.com/mitchellh/go-vnc
|
482
vendor/github.com/mitchellh/go-vnc/client.go
generated
vendored
Normal file
482
vendor/github.com/mitchellh/go-vnc/client.go
generated
vendored
Normal file
@ -0,0 +1,482 @@
|
|||||||
|
// Package vnc implements a VNC client.
|
||||||
|
//
|
||||||
|
// References:
|
||||||
|
// [PROTOCOL]: http://tools.ietf.org/html/rfc6143
|
||||||
|
package vnc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientConn struct {
|
||||||
|
c net.Conn
|
||||||
|
config *ClientConfig
|
||||||
|
|
||||||
|
// If the pixel format uses a color map, then this is the color
|
||||||
|
// map that is used. This should not be modified directly, since
|
||||||
|
// the data comes from the server.
|
||||||
|
ColorMap [256]Color
|
||||||
|
|
||||||
|
// Encodings supported by the client. This should not be modified
|
||||||
|
// directly. Instead, SetEncodings should be used.
|
||||||
|
Encs []Encoding
|
||||||
|
|
||||||
|
// Width of the frame buffer in pixels, sent from the server.
|
||||||
|
FrameBufferWidth uint16
|
||||||
|
|
||||||
|
// Height of the frame buffer in pixels, sent from the server.
|
||||||
|
FrameBufferHeight uint16
|
||||||
|
|
||||||
|
// Name associated with the desktop, sent from the server.
|
||||||
|
DesktopName string
|
||||||
|
|
||||||
|
// The pixel format associated with the connection. This shouldn't
|
||||||
|
// be modified. If you wish to set a new pixel format, use the
|
||||||
|
// SetPixelFormat method.
|
||||||
|
PixelFormat PixelFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ClientConfig structure is used to configure a ClientConn. After
|
||||||
|
// one has been passed to initialize a connection, it must not be modified.
|
||||||
|
type ClientConfig struct {
|
||||||
|
// A slice of ClientAuth methods. Only the first instance that is
|
||||||
|
// suitable by the server will be used to authenticate.
|
||||||
|
Auth []ClientAuth
|
||||||
|
|
||||||
|
// Exclusive determines whether the connection is shared with other
|
||||||
|
// clients. If true, then all other clients connected will be
|
||||||
|
// disconnected when a connection is established to the VNC server.
|
||||||
|
Exclusive bool
|
||||||
|
|
||||||
|
// The channel that all messages received from the server will be
|
||||||
|
// sent on. If the channel blocks, then the goroutine reading data
|
||||||
|
// from the VNC server may block indefinitely. It is up to the user
|
||||||
|
// of the library to ensure that this channel is properly read.
|
||||||
|
// If this is not set, then all messages will be discarded.
|
||||||
|
ServerMessageCh chan<- ServerMessage
|
||||||
|
|
||||||
|
// A slice of supported messages that can be read from the server.
|
||||||
|
// This only needs to contain NEW server messages, and doesn't
|
||||||
|
// need to explicitly contain the RFC-required messages.
|
||||||
|
ServerMessages []ServerMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func Client(c net.Conn, cfg *ClientConfig) (*ClientConn, error) {
|
||||||
|
conn := &ClientConn{
|
||||||
|
c: c,
|
||||||
|
config: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := conn.handshake(); err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go conn.mainLoop()
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientConn) Close() error {
|
||||||
|
return c.c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CutText tells the server that the client has new text in its cut buffer.
|
||||||
|
// The text string MUST only contain Latin-1 characters. This encoding
|
||||||
|
// is compatible with Go's native string format, but can only use up to
|
||||||
|
// unicode.MaxLatin values.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.5.6
|
||||||
|
func (c *ClientConn) CutText(text string) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
// This is the fixed size data we'll send
|
||||||
|
fixedData := []interface{}{
|
||||||
|
uint8(6),
|
||||||
|
uint8(0),
|
||||||
|
uint8(0),
|
||||||
|
uint8(0),
|
||||||
|
uint32(len(text)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range fixedData {
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, char := range text {
|
||||||
|
if char > unicode.MaxLatin1 {
|
||||||
|
return fmt.Errorf("Character '%s' is not valid Latin-1", char)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, uint8(char)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataLength := 8 + len(text)
|
||||||
|
if _, err := c.c.Write(buf.Bytes()[0:dataLength]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requests a framebuffer update from the server. There may be an indefinite
|
||||||
|
// time between the request and the actual framebuffer update being
|
||||||
|
// received.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.5.3
|
||||||
|
func (c *ClientConn) FramebufferUpdateRequest(incremental bool, x, y, width, height uint16) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
var incrementalByte uint8 = 0
|
||||||
|
|
||||||
|
if incremental {
|
||||||
|
incrementalByte = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
data := []interface{}{
|
||||||
|
uint8(3),
|
||||||
|
incrementalByte,
|
||||||
|
x, y, width, height,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range data {
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := c.c.Write(buf.Bytes()[0:10]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyEvent indiciates a key press or release and sends it to the server.
|
||||||
|
// The key is indicated using the X Window System "keysym" value. Use
|
||||||
|
// Google to find a reference of these values. To simulate a key press,
|
||||||
|
// you must send a key with both a down event, and a non-down event.
|
||||||
|
//
|
||||||
|
// See 7.5.4.
|
||||||
|
func (c *ClientConn) KeyEvent(keysym uint32, down bool) error {
|
||||||
|
var downFlag uint8 = 0
|
||||||
|
if down {
|
||||||
|
downFlag = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
data := []interface{}{
|
||||||
|
uint8(4),
|
||||||
|
downFlag,
|
||||||
|
uint8(0),
|
||||||
|
uint8(0),
|
||||||
|
keysym,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range data {
|
||||||
|
if err := binary.Write(c.c, binary.BigEndian, val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointerEvent indicates that pointer movement or a pointer button
|
||||||
|
// press or release.
|
||||||
|
//
|
||||||
|
// The mask is a bitwise mask of various ButtonMask values. When a button
|
||||||
|
// is set, it is pressed, when it is unset, it is released.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.5.5
|
||||||
|
func (c *ClientConn) PointerEvent(mask ButtonMask, x, y uint16) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
data := []interface{}{
|
||||||
|
uint8(5),
|
||||||
|
uint8(mask),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range data {
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := c.c.Write(buf.Bytes()[0:6]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEncodings sets the encoding types in which the pixel data can
|
||||||
|
// be sent from the server. After calling this method, the encs slice
|
||||||
|
// given should not be modified.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.5.2
|
||||||
|
func (c *ClientConn) SetEncodings(encs []Encoding) error {
|
||||||
|
data := make([]interface{}, 3+len(encs))
|
||||||
|
data[0] = uint8(2)
|
||||||
|
data[1] = uint8(0)
|
||||||
|
data[2] = uint16(len(encs))
|
||||||
|
|
||||||
|
for i, enc := range encs {
|
||||||
|
data[3+i] = int32(enc.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, val := range data {
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataLength := 4 + (4 * len(encs))
|
||||||
|
if _, err := c.c.Write(buf.Bytes()[0:dataLength]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Encs = encs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPixelFormat sets the format in which pixel values should be sent
|
||||||
|
// in FramebufferUpdate messages from the server.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.5.1
|
||||||
|
func (c *ClientConn) SetPixelFormat(format *PixelFormat) error {
|
||||||
|
var keyEvent [20]byte
|
||||||
|
keyEvent[0] = 0
|
||||||
|
|
||||||
|
pfBytes, err := writePixelFormat(format)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the pixel format bytes into the proper slice location
|
||||||
|
copy(keyEvent[4:], pfBytes)
|
||||||
|
|
||||||
|
// Send the data down the connection
|
||||||
|
if _, err := c.c.Write(keyEvent[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the color map as according to RFC.
|
||||||
|
var newColorMap [256]Color
|
||||||
|
c.ColorMap = newColorMap
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const pvLen = 12 // ProtocolVersion message length.
|
||||||
|
|
||||||
|
func parseProtocolVersion(pv []byte) (uint, uint, error) {
|
||||||
|
var major, minor uint
|
||||||
|
|
||||||
|
if len(pv) < pvLen {
|
||||||
|
return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), pvLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor)
|
||||||
|
if l != 2 {
|
||||||
|
return 0, 0, fmt.Errorf("error parsing ProtocolVersion.")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return major, minor, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientConn) handshake() error {
|
||||||
|
var protocolVersion [pvLen]byte
|
||||||
|
|
||||||
|
// 7.1.1, read the ProtocolVersion message sent by the server.
|
||||||
|
if _, err := io.ReadFull(c.c, protocolVersion[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
maxMajor, maxMinor, err := parseProtocolVersion(protocolVersion[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maxMajor < 3 {
|
||||||
|
return fmt.Errorf("unsupported major version, less than 3: %d", maxMajor)
|
||||||
|
}
|
||||||
|
if maxMinor < 8 {
|
||||||
|
return fmt.Errorf("unsupported minor version, less than 8: %d", maxMinor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Respond with the version we will support
|
||||||
|
if _, err = c.c.Write([]byte("RFB 003.008\n")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7.1.2 Security Handshake from server
|
||||||
|
var numSecurityTypes uint8
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &numSecurityTypes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if numSecurityTypes == 0 {
|
||||||
|
return fmt.Errorf("no security types: %s", c.readErrorReason())
|
||||||
|
}
|
||||||
|
|
||||||
|
securityTypes := make([]uint8, numSecurityTypes)
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &securityTypes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
clientSecurityTypes := c.config.Auth
|
||||||
|
if clientSecurityTypes == nil {
|
||||||
|
clientSecurityTypes = []ClientAuth{new(ClientAuthNone)}
|
||||||
|
}
|
||||||
|
|
||||||
|
var auth ClientAuth
|
||||||
|
FindAuth:
|
||||||
|
for _, curAuth := range clientSecurityTypes {
|
||||||
|
for _, securityType := range securityTypes {
|
||||||
|
if curAuth.SecurityType() == securityType {
|
||||||
|
// We use the first matching supported authentication
|
||||||
|
auth = curAuth
|
||||||
|
break FindAuth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if auth == nil {
|
||||||
|
return fmt.Errorf("no suitable auth schemes found. server supported: %#v", securityTypes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Respond back with the security type we'll use
|
||||||
|
if err = binary.Write(c.c, binary.BigEndian, auth.SecurityType()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = auth.Handshake(c.c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7.1.3 SecurityResult Handshake
|
||||||
|
var securityResult uint32
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &securityResult); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if securityResult == 1 {
|
||||||
|
return fmt.Errorf("security handshake failed: %s", c.readErrorReason())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7.3.1 ClientInit
|
||||||
|
var sharedFlag uint8 = 1
|
||||||
|
if c.config.Exclusive {
|
||||||
|
sharedFlag = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = binary.Write(c.c, binary.BigEndian, sharedFlag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7.3.2 ServerInit
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &c.FrameBufferWidth); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &c.FrameBufferHeight); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the pixel format
|
||||||
|
if err = readPixelFormat(c.c, &c.PixelFormat); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameLength uint32
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &nameLength); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nameBytes := make([]uint8, nameLength)
|
||||||
|
if err = binary.Read(c.c, binary.BigEndian, &nameBytes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.DesktopName = string(nameBytes)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mainLoop reads messages sent from the server and routes them to the
|
||||||
|
// proper channels for users of the client to read.
|
||||||
|
func (c *ClientConn) mainLoop() {
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
// Build the map of available server messages
|
||||||
|
typeMap := make(map[uint8]ServerMessage)
|
||||||
|
|
||||||
|
defaultMessages := []ServerMessage{
|
||||||
|
new(FramebufferUpdateMessage),
|
||||||
|
new(SetColorMapEntriesMessage),
|
||||||
|
new(BellMessage),
|
||||||
|
new(ServerCutTextMessage),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, msg := range defaultMessages {
|
||||||
|
typeMap[msg.Type()] = msg
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.ServerMessages != nil {
|
||||||
|
for _, msg := range c.config.ServerMessages {
|
||||||
|
typeMap[msg.Type()] = msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
var messageType uint8
|
||||||
|
if err := binary.Read(c.c, binary.BigEndian, &messageType); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, ok := typeMap[messageType]
|
||||||
|
if !ok {
|
||||||
|
// Unsupported message type! Bad!
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedMsg, err := msg.Read(c, c.c)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.ServerMessageCh == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c.config.ServerMessageCh <- parsedMsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientConn) readErrorReason() string {
|
||||||
|
var reasonLen uint32
|
||||||
|
if err := binary.Read(c.c, binary.BigEndian, &reasonLen); err != nil {
|
||||||
|
return "<error>"
|
||||||
|
}
|
||||||
|
|
||||||
|
reason := make([]uint8, reasonLen)
|
||||||
|
if err := binary.Read(c.c, binary.BigEndian, &reason); err != nil {
|
||||||
|
return "<error>"
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(reason)
|
||||||
|
}
|
124
vendor/github.com/mitchellh/go-vnc/client_auth.go
generated
vendored
Normal file
124
vendor/github.com/mitchellh/go-vnc/client_auth.go
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package vnc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"crypto/des"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ClientAuth implements a method of authenticating with a remote server.
|
||||||
|
type ClientAuth interface {
|
||||||
|
// SecurityType returns the byte identifier sent by the server to
|
||||||
|
// identify this authentication scheme.
|
||||||
|
SecurityType() uint8
|
||||||
|
|
||||||
|
// Handshake is called when the authentication handshake should be
|
||||||
|
// performed, as part of the general RFB handshake. (see 7.2.1)
|
||||||
|
Handshake(net.Conn) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientAuthNone is the "none" authentication. See 7.2.1
|
||||||
|
type ClientAuthNone byte
|
||||||
|
|
||||||
|
func (*ClientAuthNone) SecurityType() uint8 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ClientAuthNone) Handshake(net.Conn) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PasswordAuth is VNC authentication, 7.2.2
|
||||||
|
type PasswordAuth struct {
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PasswordAuth) SecurityType() uint8 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PasswordAuth) Handshake(c net.Conn) error {
|
||||||
|
randomValue := make([]uint8, 16)
|
||||||
|
if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
crypted, err := p.encrypt(p.Password, randomValue)
|
||||||
|
|
||||||
|
if (err != nil) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(c, binary.BigEndian, &crypted); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PasswordAuth) reverseBits(b byte) byte {
|
||||||
|
var reverse = [256]int{
|
||||||
|
0, 128, 64, 192, 32, 160, 96, 224,
|
||||||
|
16, 144, 80, 208, 48, 176, 112, 240,
|
||||||
|
8, 136, 72, 200, 40, 168, 104, 232,
|
||||||
|
24, 152, 88, 216, 56, 184, 120, 248,
|
||||||
|
4, 132, 68, 196, 36, 164, 100, 228,
|
||||||
|
20, 148, 84, 212, 52, 180, 116, 244,
|
||||||
|
12, 140, 76, 204, 44, 172, 108, 236,
|
||||||
|
28, 156, 92, 220, 60, 188, 124, 252,
|
||||||
|
2, 130, 66, 194, 34, 162, 98, 226,
|
||||||
|
18, 146, 82, 210, 50, 178, 114, 242,
|
||||||
|
10, 138, 74, 202, 42, 170, 106, 234,
|
||||||
|
26, 154, 90, 218, 58, 186, 122, 250,
|
||||||
|
6, 134, 70, 198, 38, 166, 102, 230,
|
||||||
|
22, 150, 86, 214, 54, 182, 118, 246,
|
||||||
|
14, 142, 78, 206, 46, 174, 110, 238,
|
||||||
|
30, 158, 94, 222, 62, 190, 126, 254,
|
||||||
|
1, 129, 65, 193, 33, 161, 97, 225,
|
||||||
|
17, 145, 81, 209, 49, 177, 113, 241,
|
||||||
|
9, 137, 73, 201, 41, 169, 105, 233,
|
||||||
|
25, 153, 89, 217, 57, 185, 121, 249,
|
||||||
|
5, 133, 69, 197, 37, 165, 101, 229,
|
||||||
|
21, 149, 85, 213, 53, 181, 117, 245,
|
||||||
|
13, 141, 77, 205, 45, 173, 109, 237,
|
||||||
|
29, 157, 93, 221, 61, 189, 125, 253,
|
||||||
|
3, 131, 67, 195, 35, 163, 99, 227,
|
||||||
|
19, 147, 83, 211, 51, 179, 115, 243,
|
||||||
|
11, 139, 75, 203, 43, 171, 107, 235,
|
||||||
|
27, 155, 91, 219, 59, 187, 123, 251,
|
||||||
|
7, 135, 71, 199, 39, 167, 103, 231,
|
||||||
|
23, 151, 87, 215, 55, 183, 119, 247,
|
||||||
|
15, 143, 79, 207, 47, 175, 111, 239,
|
||||||
|
31, 159, 95, 223, 63, 191, 127, 255,
|
||||||
|
}
|
||||||
|
|
||||||
|
return byte(reverse[int(b)])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) {
|
||||||
|
keyBytes := []byte{0,0,0,0,0,0,0,0}
|
||||||
|
|
||||||
|
if len(key) > 8 {
|
||||||
|
key = key[:8]
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(key); i++ {
|
||||||
|
keyBytes[i] = p.reverseBits(key[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
block, err := des.NewCipher(keyBytes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result1 := make([]byte, 8)
|
||||||
|
block.Encrypt(result1, bytes)
|
||||||
|
result2 := make([]byte, 8)
|
||||||
|
block.Encrypt(result2, bytes[8:])
|
||||||
|
|
||||||
|
crypted := append(result1, result2...)
|
||||||
|
|
||||||
|
return crypted, nil
|
||||||
|
}
|
6
vendor/github.com/mitchellh/go-vnc/color.go
generated
vendored
Normal file
6
vendor/github.com/mitchellh/go-vnc/color.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package vnc
|
||||||
|
|
||||||
|
// Color represents a single color in a color map.
|
||||||
|
type Color struct {
|
||||||
|
R, G, B uint16
|
||||||
|
}
|
69
vendor/github.com/mitchellh/go-vnc/encoding.go
generated
vendored
Normal file
69
vendor/github.com/mitchellh/go-vnc/encoding.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package vnc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Encoding implements a method for encoding pixel data that is
|
||||||
|
// sent by the server to the client.
|
||||||
|
type Encoding interface {
|
||||||
|
// The number that uniquely identifies this encoding type.
|
||||||
|
Type() int32
|
||||||
|
|
||||||
|
// Read reads the contents of the encoded pixel data from the reader.
|
||||||
|
// This should return a new Encoding implementation that contains
|
||||||
|
// the proper data.
|
||||||
|
Read(*ClientConn, *Rectangle, io.Reader) (Encoding, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawEncoding is raw pixel data sent by the server.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.7.1
|
||||||
|
type RawEncoding struct {
|
||||||
|
Colors []Color
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RawEncoding) Type() int32 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) {
|
||||||
|
bytesPerPixel := c.PixelFormat.BPP / 8
|
||||||
|
pixelBytes := make([]uint8, bytesPerPixel)
|
||||||
|
|
||||||
|
var byteOrder binary.ByteOrder = binary.LittleEndian
|
||||||
|
if c.PixelFormat.BigEndian {
|
||||||
|
byteOrder = binary.BigEndian
|
||||||
|
}
|
||||||
|
|
||||||
|
colors := make([]Color, int(rect.Height)*int(rect.Width))
|
||||||
|
|
||||||
|
for y := uint16(0); y < rect.Height; y++ {
|
||||||
|
for x := uint16(0); x < rect.Width; x++ {
|
||||||
|
if _, err := io.ReadFull(r, pixelBytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawPixel uint32
|
||||||
|
if c.PixelFormat.BPP == 8 {
|
||||||
|
rawPixel = uint32(pixelBytes[0])
|
||||||
|
} else if c.PixelFormat.BPP == 16 {
|
||||||
|
rawPixel = uint32(byteOrder.Uint16(pixelBytes))
|
||||||
|
} else if c.PixelFormat.BPP == 32 {
|
||||||
|
rawPixel = byteOrder.Uint32(pixelBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
color := &colors[int(y)*int(rect.Width)+int(x)]
|
||||||
|
if c.PixelFormat.TrueColor {
|
||||||
|
color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax))
|
||||||
|
color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax))
|
||||||
|
color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax))
|
||||||
|
} else {
|
||||||
|
*color = c.ColorMap[rawPixel]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &RawEncoding{colors}, nil
|
||||||
|
}
|
151
vendor/github.com/mitchellh/go-vnc/pixel_format.go
generated
vendored
Normal file
151
vendor/github.com/mitchellh/go-vnc/pixel_format.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package vnc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PixelFormat describes the way a pixel is formatted for a VNC connection.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.4 for information on each of the fields.
|
||||||
|
type PixelFormat struct {
|
||||||
|
BPP uint8
|
||||||
|
Depth uint8
|
||||||
|
BigEndian bool
|
||||||
|
TrueColor bool
|
||||||
|
RedMax uint16
|
||||||
|
GreenMax uint16
|
||||||
|
BlueMax uint16
|
||||||
|
RedShift uint8
|
||||||
|
GreenShift uint8
|
||||||
|
BlueShift uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func readPixelFormat(r io.Reader, result *PixelFormat) error {
|
||||||
|
var rawPixelFormat [16]byte
|
||||||
|
if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pfBoolByte uint8
|
||||||
|
brPF := bytes.NewReader(rawPixelFormat[:])
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pfBoolByte != 0 {
|
||||||
|
// Big endian is true
|
||||||
|
result.BigEndian = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pfBoolByte != 0 {
|
||||||
|
// True Color is true. So we also have to read all the color max & shifts.
|
||||||
|
result.TrueColor = true
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePixelFormat(format *PixelFormat) ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
// Byte 1
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte 2
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var boolByte byte
|
||||||
|
if format.BigEndian {
|
||||||
|
boolByte = 1
|
||||||
|
} else {
|
||||||
|
boolByte = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte 3 (BigEndian)
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if format.TrueColor {
|
||||||
|
boolByte = 1
|
||||||
|
} else {
|
||||||
|
boolByte = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte 4 (TrueColor)
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have true color enabled then we have to fill in the rest of the
|
||||||
|
// structure with the color values.
|
||||||
|
if format.TrueColor {
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes()[0:16], nil
|
||||||
|
}
|
16
vendor/github.com/mitchellh/go-vnc/pointer.go
generated
vendored
Normal file
16
vendor/github.com/mitchellh/go-vnc/pointer.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package vnc
|
||||||
|
|
||||||
|
// ButtonMask represents a mask of pointer presses/releases.
|
||||||
|
type ButtonMask uint8
|
||||||
|
|
||||||
|
// All available button mask components.
|
||||||
|
const (
|
||||||
|
ButtonLeft ButtonMask = 1 << iota
|
||||||
|
ButtonMiddle
|
||||||
|
ButtonRight
|
||||||
|
Button4
|
||||||
|
Button5
|
||||||
|
Button6
|
||||||
|
Button7
|
||||||
|
Button8
|
||||||
|
)
|
192
vendor/github.com/mitchellh/go-vnc/server_messages.go
generated
vendored
Normal file
192
vendor/github.com/mitchellh/go-vnc/server_messages.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package vnc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ServerMessage implements a message sent from the server to the client.
|
||||||
|
type ServerMessage interface {
|
||||||
|
// The type of the message that is sent down on the wire.
|
||||||
|
Type() uint8
|
||||||
|
|
||||||
|
// Read reads the contents of the message from the reader. At the point
|
||||||
|
// this is called, the message type has already been read from the reader.
|
||||||
|
// This should return a new ServerMessage that is the appropriate type.
|
||||||
|
Read(*ClientConn, io.Reader) (ServerMessage, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FramebufferUpdateMessage consists of a sequence of rectangles of
|
||||||
|
// pixel data that the client should put into its framebuffer.
|
||||||
|
type FramebufferUpdateMessage struct {
|
||||||
|
Rectangles []Rectangle
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rectangle represents a rectangle of pixel data.
|
||||||
|
type Rectangle struct {
|
||||||
|
X uint16
|
||||||
|
Y uint16
|
||||||
|
Width uint16
|
||||||
|
Height uint16
|
||||||
|
Enc Encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FramebufferUpdateMessage) Type() uint8 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) {
|
||||||
|
// Read off the padding
|
||||||
|
var padding [1]byte
|
||||||
|
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var numRects uint16
|
||||||
|
if err := binary.Read(r, binary.BigEndian, &numRects); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the map of encodings supported
|
||||||
|
encMap := make(map[int32]Encoding)
|
||||||
|
for _, enc := range c.Encs {
|
||||||
|
encMap[enc.Type()] = enc
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must always support the raw encoding
|
||||||
|
rawEnc := new(RawEncoding)
|
||||||
|
encMap[rawEnc.Type()] = rawEnc
|
||||||
|
|
||||||
|
rects := make([]Rectangle, numRects)
|
||||||
|
for i := uint16(0); i < numRects; i++ {
|
||||||
|
var encodingType int32
|
||||||
|
|
||||||
|
rect := &rects[i]
|
||||||
|
data := []interface{}{
|
||||||
|
&rect.X,
|
||||||
|
&rect.Y,
|
||||||
|
&rect.Width,
|
||||||
|
&rect.Height,
|
||||||
|
&encodingType,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range data {
|
||||||
|
if err := binary.Read(r, binary.BigEndian, val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enc, ok := encMap[encodingType]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unsupported encoding type: %d", encodingType)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
rect.Enc, err = enc.Read(c, rect, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FramebufferUpdateMessage{rects}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetColorMapEntriesMessage is sent by the server to set values into
|
||||||
|
// the color map. This message will automatically update the color map
|
||||||
|
// for the associated connection, but contains the color change data
|
||||||
|
// if the consumer wants to read it.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.6.2
|
||||||
|
type SetColorMapEntriesMessage struct {
|
||||||
|
FirstColor uint16
|
||||||
|
Colors []Color
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SetColorMapEntriesMessage) Type() uint8 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SetColorMapEntriesMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) {
|
||||||
|
// Read off the padding
|
||||||
|
var padding [1]byte
|
||||||
|
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result SetColorMapEntriesMessage
|
||||||
|
if err := binary.Read(r, binary.BigEndian, &result.FirstColor); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var numColors uint16
|
||||||
|
if err := binary.Read(r, binary.BigEndian, &numColors); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Colors = make([]Color, numColors)
|
||||||
|
for i := uint16(0); i < numColors; i++ {
|
||||||
|
|
||||||
|
color := &result.Colors[i]
|
||||||
|
data := []interface{}{
|
||||||
|
&color.R,
|
||||||
|
&color.G,
|
||||||
|
&color.B,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range data {
|
||||||
|
if err := binary.Read(r, binary.BigEndian, val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the connection's color map
|
||||||
|
c.ColorMap[result.FirstColor+i] = *color
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bell signals that an audible bell should be made on the client.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.6.3
|
||||||
|
type BellMessage byte
|
||||||
|
|
||||||
|
func (*BellMessage) Type() uint8 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*BellMessage) Read(*ClientConn, io.Reader) (ServerMessage, error) {
|
||||||
|
return new(BellMessage), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerCutTextMessage indicates the server has new text in the cut buffer.
|
||||||
|
//
|
||||||
|
// See RFC 6143 Section 7.6.4
|
||||||
|
type ServerCutTextMessage struct {
|
||||||
|
Text string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ServerCutTextMessage) Type() uint8 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ServerCutTextMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) {
|
||||||
|
// Read off the padding
|
||||||
|
var padding [1]byte
|
||||||
|
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var textLength uint32
|
||||||
|
if err := binary.Read(r, binary.BigEndian, &textLength); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
textBytes := make([]uint8, textLength)
|
||||||
|
if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ServerCutTextMessage{string(textBytes)}, nil
|
||||||
|
}
|
6
vendor/github.com/mitchellh/mapstructure/mapstructure.go
generated
vendored
6
vendor/github.com/mitchellh/mapstructure/mapstructure.go
generated
vendored
@ -653,7 +653,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||||||
if !rawMapVal.IsValid() {
|
if !rawMapVal.IsValid() {
|
||||||
// Do a slower search by iterating over each key and
|
// Do a slower search by iterating over each key and
|
||||||
// doing case-insensitive search.
|
// doing case-insensitive search.
|
||||||
for dataValKey := range dataValKeys {
|
for dataValKey, _ := range dataValKeys {
|
||||||
mK, ok := dataValKey.Interface().(string)
|
mK, ok := dataValKey.Interface().(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
// Not a string key
|
// Not a string key
|
||||||
@ -701,7 +701,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||||||
|
|
||||||
if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
|
if d.config.ErrorUnused && len(dataValKeysUnused) > 0 {
|
||||||
keys := make([]string, 0, len(dataValKeysUnused))
|
keys := make([]string, 0, len(dataValKeysUnused))
|
||||||
for rawKey := range dataValKeysUnused {
|
for rawKey, _ := range dataValKeysUnused {
|
||||||
keys = append(keys, rawKey.(string))
|
keys = append(keys, rawKey.(string))
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
@ -716,7 +716,7 @@ func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value)
|
|||||||
|
|
||||||
// Add the unused keys to the list of unused keys if we're tracking metadata
|
// Add the unused keys to the list of unused keys if we're tracking metadata
|
||||||
if d.config.Metadata != nil {
|
if d.config.Metadata != nil {
|
||||||
for rawKey := range dataValKeysUnused {
|
for rawKey, _ := range dataValKeysUnused {
|
||||||
key := rawKey.(string)
|
key := rawKey.(string)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
key = fmt.Sprintf("%s.%s", name, key)
|
key = fmt.Sprintf("%s.%s", name, key)
|
||||||
|
20
vendor/github.com/mitchellh/osext/LICENSE
generated
vendored
20
vendor/github.com/mitchellh/osext/LICENSE
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
Copyright (c) 2012 Daniel Theophanes
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
|
||||||
warranty. In no event will the authors be held liable for any damages
|
|
||||||
arising from the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software
|
|
||||||
in a product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source
|
|
||||||
distribution.
|
|
3
vendor/github.com/mitchellh/osext/README.md
generated
vendored
3
vendor/github.com/mitchellh/osext/README.md
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# osext
|
|
||||||
|
|
||||||
**Don't use this anymore! Use the official library at: https://github.com/kardianos/osext**
|
|
32
vendor/github.com/mitchellh/osext/osext.go
generated
vendored
32
vendor/github.com/mitchellh/osext/osext.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Extensions to the standard "os" package.
|
|
||||||
package osext
|
|
||||||
|
|
||||||
import "path/filepath"
|
|
||||||
|
|
||||||
// Executable returns an absolute path that can be used to
|
|
||||||
// re-invoke the current program.
|
|
||||||
// It may not be valid after the current program exits.
|
|
||||||
func Executable() (string, error) {
|
|
||||||
p, err := executable()
|
|
||||||
return filepath.Clean(p), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns same path as Executable, returns just the folder
|
|
||||||
// path. Excludes the executable name.
|
|
||||||
func ExecutableFolder() (string, error) {
|
|
||||||
p, err := Executable()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
folder, _ := filepath.Split(p)
|
|
||||||
return folder, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Depricated. Same as Executable().
|
|
||||||
func GetExePath() (exePath string, err error) {
|
|
||||||
return Executable()
|
|
||||||
}
|
|
16
vendor/github.com/mitchellh/osext/osext_plan9.go
generated
vendored
16
vendor/github.com/mitchellh/osext/osext_plan9.go
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
// Copyright 2012 The Go 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 osext
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func executable() (string, error) {
|
|
||||||
f, err := Open("/proc/" + itoa(Getpid()) + "/text")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
return syscall.Fd2path(int(f.Fd()))
|
|
||||||
}
|
|
25
vendor/github.com/mitchellh/osext/osext_procfs.go
generated
vendored
25
vendor/github.com/mitchellh/osext/osext_procfs.go
generated
vendored
@ -1,25 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build linux netbsd openbsd
|
|
||||||
|
|
||||||
package osext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func executable() (string, error) {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "linux":
|
|
||||||
return os.Readlink("/proc/self/exe")
|
|
||||||
case "netbsd":
|
|
||||||
return os.Readlink("/proc/curproc/exe")
|
|
||||||
case "openbsd":
|
|
||||||
return os.Readlink("/proc/curproc/file")
|
|
||||||
}
|
|
||||||
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
|
|
||||||
}
|
|
64
vendor/github.com/mitchellh/osext/osext_sysctl.go
generated
vendored
64
vendor/github.com/mitchellh/osext/osext_sysctl.go
generated
vendored
@ -1,64 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build darwin freebsd
|
|
||||||
|
|
||||||
package osext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var startUpcwd, getwdError = os.Getwd()
|
|
||||||
|
|
||||||
func executable() (string, error) {
|
|
||||||
var mib [4]int32
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "freebsd":
|
|
||||||
mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
|
|
||||||
case "darwin":
|
|
||||||
mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
|
|
||||||
}
|
|
||||||
|
|
||||||
n := uintptr(0)
|
|
||||||
// get length
|
|
||||||
_, _, err := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
|
||||||
if err != 0 {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if n == 0 { // shouldn't happen
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
buf := make([]byte, n)
|
|
||||||
_, _, err = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
|
|
||||||
if err != 0 {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if n == 0 { // shouldn't happen
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
for i, v := range buf {
|
|
||||||
if v == 0 {
|
|
||||||
buf = buf[:i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if buf[0] != '/' {
|
|
||||||
if getwdError != nil {
|
|
||||||
return string(buf), getwdError
|
|
||||||
} else {
|
|
||||||
if buf[0] == '.' {
|
|
||||||
buf = buf[1:]
|
|
||||||
}
|
|
||||||
if startUpcwd[len(startUpcwd)-1] != '/' {
|
|
||||||
return startUpcwd + "/" + string(buf), nil
|
|
||||||
}
|
|
||||||
return startUpcwd + string(buf), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
34
vendor/github.com/mitchellh/osext/osext_windows.go
generated
vendored
34
vendor/github.com/mitchellh/osext/osext_windows.go
generated
vendored
@ -1,34 +0,0 @@
|
|||||||
// Copyright 2012 The Go 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 osext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unicode/utf16"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
kernel = syscall.MustLoadDLL("kernel32.dll")
|
|
||||||
getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetModuleFileName() with hModule = NULL
|
|
||||||
func executable() (exePath string, err error) {
|
|
||||||
return getModuleFileName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getModuleFileName() (string, error) {
|
|
||||||
var n uint32
|
|
||||||
b := make([]uint16, syscall.MAX_PATH)
|
|
||||||
size := uint32(len(b))
|
|
||||||
|
|
||||||
r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
|
|
||||||
n = uint32(r0)
|
|
||||||
if n == 0 {
|
|
||||||
return "", e1
|
|
||||||
}
|
|
||||||
return string(utf16.Decode(b[0:n])), nil
|
|
||||||
}
|
|
2
vendor/github.com/mitchellh/packer/common/download.go
generated
vendored
2
vendor/github.com/mitchellh/packer/common/download.go
generated
vendored
@ -124,7 +124,7 @@ func (d *DownloadClient) Get() (string, error) {
|
|||||||
|
|
||||||
// Remove forward slash on absolute Windows file URLs before processing
|
// Remove forward slash on absolute Windows file URLs before processing
|
||||||
if runtime.GOOS == "windows" && len(finalPath) > 0 && finalPath[0] == '/' {
|
if runtime.GOOS == "windows" && len(finalPath) > 0 && finalPath[0] == '/' {
|
||||||
finalPath = finalPath[1:]
|
finalPath = finalPath[1:len(finalPath)]
|
||||||
}
|
}
|
||||||
// Keep track of the source so we can make sure not to delete this later
|
// Keep track of the source so we can make sure not to delete this later
|
||||||
sourcePath = finalPath
|
sourcePath = finalPath
|
||||||
|
4
vendor/github.com/mitchellh/packer/communicator/ssh/communicator.go
generated
vendored
4
vendor/github.com/mitchellh/packer/communicator/ssh/communicator.go
generated
vendored
@ -175,7 +175,7 @@ func (c *comm) DownloadDir(src string, dst string, excl []string) error {
|
|||||||
|
|
||||||
switch fi[0] {
|
switch fi[0] {
|
||||||
case '\x01', '\x02':
|
case '\x01', '\x02':
|
||||||
return fmt.Errorf("%s", fi[1:])
|
return fmt.Errorf("%s", fi[1:len(fi)])
|
||||||
case 'C', 'D':
|
case 'C', 'D':
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -591,7 +591,7 @@ func (c *comm) scpDownloadSession(path string, output io.Writer) error {
|
|||||||
|
|
||||||
switch fi[0] {
|
switch fi[0] {
|
||||||
case '\x01', '\x02':
|
case '\x01', '\x02':
|
||||||
return fmt.Errorf("%s", fi[1:])
|
return fmt.Errorf("%s", fi[1:len(fi)])
|
||||||
case 'C':
|
case 'C':
|
||||||
case 'D':
|
case 'D':
|
||||||
return fmt.Errorf("remote file is directory")
|
return fmt.Errorf("remote file is directory")
|
||||||
|
2
vendor/github.com/mitchellh/packer/communicator/ssh/password.go
generated
vendored
2
vendor/github.com/mitchellh/packer/communicator/ssh/password.go
generated
vendored
@ -18,7 +18,7 @@ func PasswordKeyboardInteractive(password string) ssh.KeyboardInteractiveChallen
|
|||||||
|
|
||||||
// Just send the password back for all questions
|
// Just send the password back for all questions
|
||||||
answers := make([]string, len(questions))
|
answers := make([]string, len(questions))
|
||||||
for i := range answers {
|
for i, _ := range answers {
|
||||||
answers[i] = string(password)
|
answers[i] = string(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/mitchellh/packer/packer/core.go
generated
vendored
2
vendor/github.com/mitchellh/packer/packer/core.go
generated
vendored
@ -87,7 +87,7 @@ func NewCore(c *CoreConfig) (*Core, error) {
|
|||||||
// BuildNames returns the builds that are available in this configured core.
|
// BuildNames returns the builds that are available in this configured core.
|
||||||
func (c *Core) BuildNames() []string {
|
func (c *Core) BuildNames() []string {
|
||||||
r := make([]string, 0, len(c.builds))
|
r := make([]string, 0, len(c.builds))
|
||||||
for n := range c.builds {
|
for n, _ := range c.builds {
|
||||||
r = append(r, n)
|
r = append(r, n)
|
||||||
}
|
}
|
||||||
sort.Strings(r)
|
sort.Strings(r)
|
||||||
|
2
vendor/github.com/mitchellh/packer/packer/plugin/client.go
generated
vendored
2
vendor/github.com/mitchellh/packer/packer/plugin/client.go
generated
vendored
@ -291,7 +291,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
|
|||||||
// so they dont' block since it is an io.Pipe
|
// so they dont' block since it is an io.Pipe
|
||||||
defer func() {
|
defer func() {
|
||||||
go func() {
|
go func() {
|
||||||
for range linesCh {
|
for _ = range linesCh {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}()
|
}()
|
||||||
|
2
vendor/github.com/mitchellh/packer/template/template.go
generated
vendored
2
vendor/github.com/mitchellh/packer/template/template.go
generated
vendored
@ -107,7 +107,7 @@ func (t *Template) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate overrides
|
// Validate overrides
|
||||||
for name := range p.Override {
|
for name, _ := range p.Override {
|
||||||
if _, ok := t.Builders[name]; !ok {
|
if _, ok := t.Builders[name]; !ok {
|
||||||
err = multierror.Append(err, fmt.Errorf(
|
err = multierror.Append(err, fmt.Errorf(
|
||||||
"provisioner %d: override '%s' doesn't exist",
|
"provisioner %d: override '%s' doesn't exist",
|
||||||
|
27
vendor/github.com/nilshell/xmlrpc/xmlrpc.go
generated
vendored
27
vendor/github.com/nilshell/xmlrpc/xmlrpc.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
package xmlrpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Struct presents hash type used in xmlprc requests and responses.
|
|
||||||
type Struct map[string]interface{}
|
|
||||||
|
|
||||||
// Base64 represents base64 data
|
|
||||||
type Base64 string
|
|
||||||
|
|
||||||
// Params represents a list of parameters to a method.
|
|
||||||
type Params struct {
|
|
||||||
Params []interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// xmlrpcError represents errors returned on xmlrpc request.
|
|
||||||
type xmlrpcError struct {
|
|
||||||
code string
|
|
||||||
message string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error() method implements Error interface
|
|
||||||
func (e *xmlrpcError) Error() string {
|
|
||||||
return fmt.Sprintf("Error: \"%s\" Code: %s", e.message, e.code)
|
|
||||||
}
|
|
4
vendor/github.com/packer-community/winrmcp/winrmcp/psobject.go
generated
vendored
4
vendor/github.com/packer-community/winrmcp/winrmcp/psobject.go
generated
vendored
@ -6,10 +6,12 @@ type pslist struct {
|
|||||||
|
|
||||||
type psobject struct {
|
type psobject struct {
|
||||||
Properties []psproperty `xml:"Property"`
|
Properties []psproperty `xml:"Property"`
|
||||||
Value string `xml:",innerxml"`
|
Value string `xml:",innerxml"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type psproperty struct {
|
type psproperty struct {
|
||||||
Name string `xml:"Name,attr"`
|
Name string `xml:"Name,attr"`
|
||||||
Value string `xml:",innerxml"`
|
Value string `xml:",innerxml"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
24
vendor/github.com/pkg/errors/.gitignore
generated
vendored
24
vendor/github.com/pkg/errors/.gitignore
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
||||||
*.prof
|
|
10
vendor/github.com/pkg/errors/.travis.yml
generated
vendored
10
vendor/github.com/pkg/errors/.travis.yml
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
language: go
|
|
||||||
go_import_path: github.com/pkg/errors
|
|
||||||
go:
|
|
||||||
- 1.4.3
|
|
||||||
- 1.5.4
|
|
||||||
- 1.6.2
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v ./...
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user