Vendoring update for go-discover. (#4412)

* New Providers added and updated vendoring for go-discover

* Vendor.json formatted using make vendorfmt

* Docs/Agent/auto-join: Added documentation for the new providers introduced in this PR

* Updated the golang.org/x/sys/unix in the vendor directory

* Agent: TestGoDiscoverRegistration updated to reflect the addition of new providers

* Deleted terraform.tfstate from vendor.

* Deleted terraform.tfstate.backup

Deleted terraform state file artifacts from unknown runs.

* Updated x/sys/windows vendor for Windows binary compilation
pull/4469/head
Siva Prasad 2018-07-25 19:21:04 -04:00 committed by Jack Pearkes
parent 3959a91e43
commit f4a1c381a5
388 changed files with 156691 additions and 14680 deletions

View File

@ -13,7 +13,7 @@ func TestGoDiscoverRegistration(t *testing.T) {
t.Fatal(err)
}
got := d.Names()
want := []string{"aliyun", "aws", "azure", "digitalocean", "gce", "os", "scaleway", "softlayer", "triton"}
want := []string{"aliyun", "aws", "azure", "digitalocean", "gce", "os", "packet", "scaleway", "softlayer", "triton", "vsphere"}
if !reflect.DeepEqual(got, want) {
t.Fatalf("got go-discover providers %v want %v", got, want)
}

123
vendor/github.com/Sirupsen/logrus/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,123 @@
# 1.0.5
* Fix hooks race (#707)
* Fix panic deadlock (#695)
# 1.0.4
* Fix race when adding hooks (#612)
* Fix terminal check in AppEngine (#635)
# 1.0.3
* Replace example files with testable examples
# 1.0.2
* bug: quote non-string values in text formatter (#583)
* Make (*Logger) SetLevel a public method
# 1.0.1
* bug: fix escaping in text formatter (#575)
# 1.0.0
* Officially changed name to lower-case
* bug: colors on Windows 10 (#541)
* bug: fix race in accessing level (#512)
# 0.11.5
* feature: add writer and writerlevel to entry (#372)
# 0.11.4
* bug: fix undefined variable on solaris (#493)
# 0.11.3
* formatter: configure quoting of empty values (#484)
* formatter: configure quoting character (default is `"`) (#484)
* bug: fix not importing io correctly in non-linux environments (#481)
# 0.11.2
* bug: fix windows terminal detection (#476)
# 0.11.1
* bug: fix tty detection with custom out (#471)
# 0.11.0
* performance: Use bufferpool to allocate (#370)
* terminal: terminal detection for app-engine (#343)
* feature: exit handler (#375)
# 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)

21
vendor/github.com/Sirupsen/logrus/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Simon Eskildsen
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.

461
vendor/github.com/Sirupsen/logrus/README.md generated vendored Normal file
View File

@ -0,0 +1,461 @@
# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus)&nbsp;[![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus)
Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger.
**Seeing weird case-sensitive problems?** It's in the past been possible to
import Logrus as both upper- and lower-case. Due to the Go package environment,
this caused issues in the community and we needed a standard. Some environments
experienced problems with the upper-case variant, so the lower-case was decided.
Everything using `logrus` will need to use the lower-case:
`github.com/sirupsen/logrus`. Any package that isn't, should be changed.
To fix Glide, see [these
comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437).
For an in-depth explanation of the casing issue, see [this
comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276).
**Are you interested in assisting in maintaining Logrus?** Currently I have a
lot of obligations, and I am unable to provide Logrus with the maintainership it
needs. If you'd like to help, please reach out to me at `simon at author's
username dot com`.
Nicely color-coded in development (when a TTY is attached, otherwise just
plain text):
![Colored](http://i.imgur.com/PY7qMwd.png)
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
```
#### Case-sensitivity
The organization's name was changed to lower-case--and this will not be changed
back. If you are getting import conflicts due to case sensitivity, please use
the lower-case import: `github.com/sirupsen/logrus`.
#### 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 stdout instead of the default stderr
// Can be any io.Writer, see below for File example
log.SetOutput(os.Stdout)
// 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 (
"os"
"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.Stdout
// You could set this to any `io.Writer` such as a file
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
// if err == nil {
// log.Out = file
// } else {
// log.Info("Failed to log to file, using default stderr")
// }
log.WithFields(logrus.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
}
```
#### Fields
Logrus encourages careful, structured logging through 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.
#### Default Fields
Often it's helpful to have fields _always_ attached to log statements in an
application or parts of one. For example, you may want to always log the
`request_id` and `user_ip` in the context of a request. Instead of writing
`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on
every line, you can create a `logrus.Entry` to pass around instead:
```go
requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") # will log request_id and user_ip
requestLogger.Warn("something not great happened")
```
#### 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 "airbrake"
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).
A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
#### 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`. For Windows, see
[github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
* When colors are enabled, levels are truncated to 4 characters by default. To disable
truncation set the `DisableLevelTruncation` field to `true`.
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
* `logrus.JSONFormatter`. Logs fields as JSON.
* All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
Third party logging formatters:
* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
* [`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`.
This means that we can override the standard library logger easily:
```go
logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}
// Use logrus for standard log output
// Note that `log` here references stdlib's log
// Not logrus imported under the name `log`.
log.SetOutput(logger.Writer())
```
#### 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.|
|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) |
#### 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
import(
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSomething(t*testing.T){
logger, hook := test.NewNullLogger()
logger.Error("Helloerror")
assert.Equal(t, 1, len(hook.Entries))
assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
assert.Equal(t, "Helloerror", hook.LastEntry().Message)
hook.Reset()
assert.Nil(t, hook.LastEntry())
}
```
#### Fatal handlers
Logrus can register one or more functions that will be called when any `fatal`
level message is logged. The registered handlers will be executed before
logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need
to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted.
```
...
handler := func() {
// gracefully shutdown something...
}
logrus.RegisterExitHandler(handler)
...
```
#### Thread safety
By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs.
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
Situation when locking is not needed includes:
* You have no hooks registered, or hooks calling is already thread-safe.
* Writing to logger.Out is already thread-safe, for example:
1) logger.Out is protected by locks.
2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)
(Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)

64
vendor/github.com/Sirupsen/logrus/alt_exit.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package logrus
// The following code was sourced and modified from the
// https://github.com/tebeka/atexit package governed by the following license:
//
// Copyright (c) 2012 Miki Tebeka <miki.tebeka@gmail.com>.
//
// 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.
import (
"fmt"
"os"
)
var handlers = []func(){}
func runHandler(handler func()) {
defer func() {
if err := recover(); err != nil {
fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err)
}
}()
handler()
}
func runHandlers() {
for _, handler := range handlers {
runHandler(handler)
}
}
// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code)
func Exit(code int) {
runHandlers()
os.Exit(code)
}
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
// all handlers. The handlers will also be invoked when any Fatal log entry is
// made.
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
// closing database connections, or sending a alert that the application is
// closing.
func RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
}

14
vendor/github.com/Sirupsen/logrus/appveyor.yml generated vendored Normal file
View File

@ -0,0 +1,14 @@
version: "{build}"
platform: x64
clone_folder: c:\gopath\src\github.com\sirupsen\logrus
environment:
GOPATH: c:\gopath
branches:
only:
- master
install:
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- go version
build_script:
- go get -t
- go test

26
vendor/github.com/Sirupsen/logrus/doc.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
/*
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

302
vendor/github.com/Sirupsen/logrus/entry.go generated vendored Normal file
View File

@ -0,0 +1,302 @@
package logrus
import (
"bytes"
"fmt"
"os"
"sync"
"time"
)
var bufferPool *sync.Pool
func init() {
bufferPool = &sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
}
// 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
// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
Level Level
// Message passed to Debug, Info, Warn, Error, Fatal or Panic
Message string
// When formatter is called in entry.log(), an Buffer may be set to entry
Buffer *bytes.Buffer
}
func NewEntry(logger *Logger) *Entry {
return &Entry{
Logger: logger,
// Default is five fields, give a little extra room
Data: make(Fields, 5),
}
}
// Returns the string representation from the reader and ultimately the
// formatter.
func (entry *Entry) String() (string, error) {
serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil {
return "", err
}
str := string(serialized)
return str, nil
}
// 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, Time: entry.Time}
}
// Overrides the time of the Entry.
func (entry *Entry) WithTime(t time.Time) *Entry {
return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t}
}
// 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) {
var buffer *bytes.Buffer
// Default to now, but allow users to override if they want.
//
// We don't have to worry about polluting future calls to Entry#log()
// with this assignment because this function is declared with a
// non-pointer receiver.
if entry.Time.IsZero() {
entry.Time = time.Now()
}
entry.Level = level
entry.Message = msg
entry.fireHooks()
buffer = bufferPool.Get().(*bytes.Buffer)
buffer.Reset()
defer bufferPool.Put(buffer)
entry.Buffer = buffer
entry.write()
entry.Buffer = nil
// 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)
}
}
// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
func (entry Entry) fireHooks() {
entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
err := entry.Logger.Hooks.Fire(entry.Level, &entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
}
}
func (entry *Entry) write() {
serialized, err := entry.Logger.Formatter.Format(entry)
entry.Logger.mu.Lock()
defer entry.Logger.mu.Unlock()
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
} else {
_, err = entry.Logger.Out.Write(serialized)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
}
}
}
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...))
}
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...))
}
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...))
}
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]
}

201
vendor/github.com/Sirupsen/logrus/exported.go generated vendored Normal file
View File

@ -0,0 +1,201 @@
package logrus
import (
"io"
"time"
)
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.SetOutput(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.SetLevel(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)
}
// WithTime creats an entry from the standard logger and overrides the time of
// logs generated with it.
//
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
// or Panic on the Entry it returns.
func WithTime(t time.Time) *Entry {
return std.WithTime(t)
}
// 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 then the process will exit with status set to 1.
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 then the process will exit with status set to 1.
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 then the process will exit with status set to 1.
func Fatalln(args ...interface{}) {
std.Fatalln(args...)
}

51
vendor/github.com/Sirupsen/logrus/formatter.go generated vendored Normal file
View File

@ -0,0 +1,51 @@
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, fieldMap FieldMap) {
timeKey := fieldMap.resolve(FieldKeyTime)
if t, ok := data[timeKey]; ok {
data["fields."+timeKey] = t
delete(data, timeKey)
}
msgKey := fieldMap.resolve(FieldKeyMsg)
if m, ok := data[msgKey]; ok {
data["fields."+msgKey] = m
delete(data, msgKey)
}
levelKey := fieldMap.resolve(FieldKeyLevel)
if l, ok := data[levelKey]; ok {
data["fields."+levelKey] = l
delete(data, levelKey)
}
}

34
vendor/github.com/Sirupsen/logrus/hooks.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
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
}

89
vendor/github.com/Sirupsen/logrus/json_formatter.go generated vendored Normal file
View File

@ -0,0 +1,89 @@
package logrus
import (
"encoding/json"
"fmt"
)
type fieldKey string
// FieldMap allows customization of the key names for default fields.
type FieldMap map[fieldKey]string
// Default key names for the default fields
const (
FieldKeyMsg = "msg"
FieldKeyLevel = "level"
FieldKeyTime = "time"
)
func (f FieldMap) resolve(key fieldKey) string {
if k, ok := f[key]; ok {
return k
}
return string(key)
}
// JSONFormatter formats logs into parsable json
type JSONFormatter struct {
// TimestampFormat sets the format used for marshaling timestamps.
TimestampFormat string
// DisableTimestamp allows disabling automatic timestamps in output
DisableTimestamp bool
// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
DataKey string
// FieldMap allows users to customize the names of keys for default fields.
// As an example:
// formatter := &JSONFormatter{
// FieldMap: FieldMap{
// FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
// FieldKeyMsg: "@message",
// },
// }
FieldMap FieldMap
}
// Format renders a single log entry
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
}
}
if f.DataKey != "" {
newData := make(Fields, 4)
newData[f.DataKey] = data
data = newData
}
prefixFieldClashes(data, f.FieldMap)
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
timestampFormat = defaultTimestampFormat
}
if !f.DisableTimestamp {
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat)
}
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
data[f.FieldMap.resolve(FieldKeyLevel)] = 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
}

337
vendor/github.com/Sirupsen/logrus/logger.go generated vendored Normal file
View File

@ -0,0 +1,337 @@
package logrus
import (
"io"
"os"
"sync"
"sync/atomic"
"time"
)
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.
Level Level
// Used to sync writing to the log. Locking is enabled by Default
mu MutexWrap
// Reusable empty entry
entryPool sync.Pool
}
type MutexWrap struct {
lock sync.Mutex
disabled bool
}
func (mw *MutexWrap) Lock() {
if !mw.disabled {
mw.lock.Lock()
}
}
func (mw *MutexWrap) Unlock() {
if !mw.disabled {
mw.lock.Unlock()
}
}
func (mw *MutexWrap) Disable() {
mw.disabled = true
}
// 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,
}
}
func (logger *Logger) newEntry() *Entry {
entry, ok := logger.entryPool.Get().(*Entry)
if ok {
return entry
}
return NewEntry(logger)
}
func (logger *Logger) releaseEntry(entry *Entry) {
logger.entryPool.Put(entry)
}
// Adds a field to the log entry, note that it doesn't log until you call
// Debug, Print, Info, Warn, Error, 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 {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.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 {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.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 {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithError(err)
}
// Overrides the time of the log entry.
func (logger *Logger) WithTime(t time.Time) *Entry {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithTime(t)
}
func (logger *Logger) Debugf(format string, args ...interface{}) {
if logger.level() >= DebugLevel {
entry := logger.newEntry()
entry.Debugf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Infof(format string, args ...interface{}) {
if logger.level() >= InfoLevel {
entry := logger.newEntry()
entry.Infof(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Printf(format string, args ...interface{}) {
entry := logger.newEntry()
entry.Printf(format, args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warnf(format string, args ...interface{}) {
if logger.level() >= WarnLevel {
entry := logger.newEntry()
entry.Warnf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Warningf(format string, args ...interface{}) {
if logger.level() >= WarnLevel {
entry := logger.newEntry()
entry.Warnf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Errorf(format string, args ...interface{}) {
if logger.level() >= ErrorLevel {
entry := logger.newEntry()
entry.Errorf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Fatalf(format string, args ...interface{}) {
if logger.level() >= FatalLevel {
entry := logger.newEntry()
entry.Fatalf(format, args...)
logger.releaseEntry(entry)
}
Exit(1)
}
func (logger *Logger) Panicf(format string, args ...interface{}) {
if logger.level() >= PanicLevel {
entry := logger.newEntry()
entry.Panicf(format, args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Debug(args ...interface{}) {
if logger.level() >= DebugLevel {
entry := logger.newEntry()
entry.Debug(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Info(args ...interface{}) {
if logger.level() >= InfoLevel {
entry := logger.newEntry()
entry.Info(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Print(args ...interface{}) {
entry := logger.newEntry()
entry.Info(args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warn(args ...interface{}) {
if logger.level() >= WarnLevel {
entry := logger.newEntry()
entry.Warn(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Warning(args ...interface{}) {
if logger.level() >= WarnLevel {
entry := logger.newEntry()
entry.Warn(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Error(args ...interface{}) {
if logger.level() >= ErrorLevel {
entry := logger.newEntry()
entry.Error(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Fatal(args ...interface{}) {
if logger.level() >= FatalLevel {
entry := logger.newEntry()
entry.Fatal(args...)
logger.releaseEntry(entry)
}
Exit(1)
}
func (logger *Logger) Panic(args ...interface{}) {
if logger.level() >= PanicLevel {
entry := logger.newEntry()
entry.Panic(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Debugln(args ...interface{}) {
if logger.level() >= DebugLevel {
entry := logger.newEntry()
entry.Debugln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Infoln(args ...interface{}) {
if logger.level() >= InfoLevel {
entry := logger.newEntry()
entry.Infoln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Println(args ...interface{}) {
entry := logger.newEntry()
entry.Println(args...)
logger.releaseEntry(entry)
}
func (logger *Logger) Warnln(args ...interface{}) {
if logger.level() >= WarnLevel {
entry := logger.newEntry()
entry.Warnln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Warningln(args ...interface{}) {
if logger.level() >= WarnLevel {
entry := logger.newEntry()
entry.Warnln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Errorln(args ...interface{}) {
if logger.level() >= ErrorLevel {
entry := logger.newEntry()
entry.Errorln(args...)
logger.releaseEntry(entry)
}
}
func (logger *Logger) Fatalln(args ...interface{}) {
if logger.level() >= FatalLevel {
entry := logger.newEntry()
entry.Fatalln(args...)
logger.releaseEntry(entry)
}
Exit(1)
}
func (logger *Logger) Panicln(args ...interface{}) {
if logger.level() >= PanicLevel {
entry := logger.newEntry()
entry.Panicln(args...)
logger.releaseEntry(entry)
}
}
//When file is opened with appending mode, it's safe to
//write concurrently to a file (within 4k message on Linux).
//In these cases user can choose to disable the lock.
func (logger *Logger) SetNoLock() {
logger.mu.Disable()
}
func (logger *Logger) level() Level {
return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
}
func (logger *Logger) SetLevel(level Level) {
atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
}
func (logger *Logger) SetOutput(out io.Writer) {
logger.mu.Lock()
defer logger.mu.Unlock()
logger.Out = out
}
func (logger *Logger) AddHook(hook Hook) {
logger.mu.Lock()
defer logger.mu.Unlock()
logger.Hooks.Add(hook)
}

143
vendor/github.com/Sirupsen/logrus/logrus.go generated vendored Normal file
View File

@ -0,0 +1,143 @@
package logrus
import (
"fmt"
"log"
"strings"
)
// Fields type, used to pass to `WithFields`.
type Fields map[string]interface{}
// Level type
type Level uint32
// 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{})
}

10
vendor/github.com/Sirupsen/logrus/terminal_bsd.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
// +build darwin freebsd openbsd netbsd dragonfly
// +build !appengine,!gopherjs
package logrus
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TIOCGETA
type Termios unix.Termios

View File

@ -0,0 +1,11 @@
// +build appengine gopherjs
package logrus
import (
"io"
)
func checkIfTerminal(w io.Writer) bool {
return true
}

View File

@ -0,0 +1,19 @@
// +build !appengine,!gopherjs
package logrus
import (
"io"
"os"
"golang.org/x/crypto/ssh/terminal"
)
func checkIfTerminal(w io.Writer) bool {
switch v := w.(type) {
case *os.File:
return terminal.IsTerminal(int(v.Fd()))
default:
return false
}
}

14
vendor/github.com/Sirupsen/logrus/terminal_linux.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// 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.
// +build !appengine,!gopherjs
package logrus
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TCGETS
type Termios unix.Termios

195
vendor/github.com/Sirupsen/logrus/text_formatter.go generated vendored Normal file
View File

@ -0,0 +1,195 @@
package logrus
import (
"bytes"
"fmt"
"sort"
"strings"
"sync"
"time"
)
const (
nocolor = 0
red = 31
green = 32
yellow = 33
blue = 36
gray = 37
)
var (
baseTimestamp time.Time
emptyFieldMap FieldMap
)
func init() {
baseTimestamp = time.Now()
}
// TextFormatter formats logs into text
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
// Disables the truncation of the level text to 4 characters.
DisableLevelTruncation bool
// QuoteEmptyFields will wrap empty fields in quotes if true
QuoteEmptyFields bool
// Whether the logger's out is to a terminal
isTerminal bool
// FieldMap allows users to customize the names of keys for default fields.
// As an example:
// formatter := &TextFormatter{
// FieldMap: FieldMap{
// FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
// FieldKeyMsg: "@message"}}
FieldMap FieldMap
sync.Once
}
func (f *TextFormatter) init(entry *Entry) {
if entry.Logger != nil {
f.isTerminal = checkIfTerminal(entry.Logger.Out)
}
}
// Format renders a single log entry
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
prefixFieldClashes(entry.Data, f.FieldMap)
keys := make([]string, 0, len(entry.Data))
for k := range entry.Data {
keys = append(keys, k)
}
if !f.DisableSorting {
sort.Strings(keys)
}
var b *bytes.Buffer
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
f.Do(func() { f.init(entry) })
isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
timestampFormat := f.TimestampFormat
if timestampFormat == "" {
timestampFormat = defaultTimestampFormat
}
if isColored {
f.printColored(b, entry, keys, timestampFormat)
} else {
if !f.DisableTimestamp {
f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyTime), entry.Time.Format(timestampFormat))
}
f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyLevel), entry.Level.String())
if entry.Message != "" {
f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyMsg), 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())
if !f.DisableLevelTruncation {
levelText = levelText[0:4]
}
if f.DisableTimestamp {
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
} else if !f.FullTimestamp {
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), 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=", levelColor, k)
f.appendValue(b, v)
}
}
func (f *TextFormatter) needsQuoting(text string) bool {
if f.QuoteEmptyFields && len(text) == 0 {
return true
}
for _, ch := range text {
if !((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') {
return true
}
}
return false
}
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
if b.Len() > 0 {
b.WriteByte(' ')
}
b.WriteString(key)
b.WriteByte('=')
f.appendValue(b, value)
}
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
stringVal, ok := value.(string)
if !ok {
stringVal = fmt.Sprint(value)
}
if !f.needsQuoting(stringVal) {
b.WriteString(stringVal)
} else {
b.WriteString(fmt.Sprintf("%q", stringVal))
}
}

62
vendor/github.com/Sirupsen/logrus/writer.go generated vendored Normal file
View File

@ -0,0 +1,62 @@
package logrus
import (
"bufio"
"io"
"runtime"
)
func (logger *Logger) Writer() *io.PipeWriter {
return logger.WriterLevel(InfoLevel)
}
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
return NewEntry(logger).WriterLevel(level)
}
func (entry *Entry) Writer() *io.PipeWriter {
return entry.WriterLevel(InfoLevel)
}
func (entry *Entry) WriterLevel(level Level) *io.PipeWriter {
reader, writer := io.Pipe()
var printFunc func(args ...interface{})
switch level {
case DebugLevel:
printFunc = entry.Debug
case InfoLevel:
printFunc = entry.Info
case WarnLevel:
printFunc = entry.Warn
case ErrorLevel:
printFunc = entry.Error
case FatalLevel:
printFunc = entry.Fatal
case PanicLevel:
printFunc = entry.Panic
default:
printFunc = entry.Print
}
go entry.writerScanner(reader, printFunc)
runtime.SetFinalizer(writer, writerFinalizer)
return writer
}
func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
printFunc(scanner.Text())
}
if err := scanner.Err(); err != nil {
entry.Errorf("Error while reading from Writer: %s", err)
}
reader.Close()
}
func writerFinalizer(writer *io.PipeWriter) {
writer.Close()
}

View File

@ -30,10 +30,12 @@ function.
* Scaleway [Config options](https://github.com/hashicorp/go-discover/blob/master/provider/scaleway/scaleway_discover.go#L14-L22)
* SoftLayer [Config options](https://github.com/hashicorp/go-discover/blob/master/provider/softlayer/softlayer_discover.go#L16-L25)
* Triton [Config options](https://github.com/hashicorp/go-discover/blob/master/provider/triton/triton_discover.go#L17-L27)
* vSphere [Config options](https://github.com/hashicorp/go-discover/blob/master/provider/vsphere/vsphere_discover.go#L148-L155)
* Packet [Config options](https://github.com/hashicorp/go-discover/blob/master/provider/packet/packet_discover.go#L25-L35)
HashiCorp maintains acceptance tests that regularly allocate and run tests with
real resources to verify the behavior of several of these providers. Those
currently are: Amazon AWS, Microsoft Azure, Google Cloud, DigitalOcean, and Triton.
currently are: Amazon AWS, Microsoft Azure, Google Cloud, DigitalOcean, Triton, Scaleway and AliBaba Cloud.
### Config Example
@ -65,6 +67,11 @@ provider=softlayer datacenter=dal06 tag_value=consul username=... api_key=...
# Triton
provider=triton account=testaccount url=https://us-sw-1.api.joyentcloud.com key_id=... tag_key=consul-role tag_value=server
# vSphere
provider=vsphere category_name=consul-role tag_name=consul-server host=... user=... password=... insecure_ssl=[true|false]
# Packet
provider=packet auth_token=token project=uuid url=... address_type=...
```
## Command Line Tool Usage

View File

@ -15,9 +15,11 @@ import (
"github.com/hashicorp/go-discover/provider/digitalocean"
"github.com/hashicorp/go-discover/provider/gce"
"github.com/hashicorp/go-discover/provider/os"
"github.com/hashicorp/go-discover/provider/packet"
"github.com/hashicorp/go-discover/provider/scaleway"
"github.com/hashicorp/go-discover/provider/softlayer"
"github.com/hashicorp/go-discover/provider/triton"
"github.com/hashicorp/go-discover/provider/vsphere"
)
// Provider has lookup functions for meta data in a
@ -49,6 +51,8 @@ var Providers = map[string]Provider{
"scaleway": &scaleway.Provider{},
"softlayer": &softlayer.Provider{},
"triton": &triton.Provider{},
"vsphere": &vsphere.Provider{},
"packet": &packet.Provider{},
}
// Discover looks up metadata in different cloud environments.

View File

@ -0,0 +1,94 @@
package packet
import (
"fmt"
"log"
"os"
"github.com/packethost/packngo"
)
const baseURL = "https://api.packet.net/"
// Provider struct
type Provider struct {
userAgent string
}
// SetUserAgent setter
func (p *Provider) SetUserAgent(s string) {
p.userAgent = s
}
// Help function
func (p *Provider) Help() string {
return `Packet:
provider: "packet"
project: UUID of packet project. Required
auth_token: Packet authentication token. Required
url: Packet REST URL. Optional
address_type: "private_v4", "public_v4" or "public_v6". Defaults to "private_v4". Optional
Variables can also be provided by environmental variables:
export PACKET_PROJECT for project
export PACKET_URL for url
export PACKET_AUTH_TOKEN for auth_token
`
}
// Addrs function
func (p *Provider) Addrs(args map[string]string, l *log.Logger) ([]string, error) {
authToken := argsOrEnv(args, "auth_token", "PACKET_AUTH_TOKEN")
projectID := argsOrEnv(args, "project", "PACKET_PROJECT")
packetURL := argsOrEnv(args, "url", "PACKET_URL")
addressType := args["address_type"]
if addressType != "private_v4" && addressType != "public_v4" && addressType != "public_v6" {
l.Printf("[INFO] discover-packet: Address type %s is not supported. Valid values are {private_v4,public_v4,public_v6}. Falling back to 'private_v4'", addressType)
addressType = "private_v4"
}
c, err := client(p.userAgent, packetURL, authToken)
if err != nil {
return nil, fmt.Errorf("discover-packet: Initializing Packet client failed: %s", err)
}
var devices []packngo.Device
if projectID == "" {
return nil, fmt.Errorf("discover-packet: 'project' parameter must be provider")
}
devices, _, err = c.Devices.List(projectID, nil)
if err != nil {
return nil, fmt.Errorf("discover-packet: Fetching Packet devices failed: %s", err)
}
var addrs []string
for _, d := range devices {
addressFamily := 4
if addressType == "public_v6" {
addressFamily = 6
}
for _, n := range d.Network {
if (n.Public == (addressType == "public_v4" || addressType == "public_v6")) && n.AddressFamily == addressFamily {
addrs = append(addrs, n.Address)
}
}
}
return addrs, nil
}
func client(useragent, url, token string) (*packngo.Client, error) {
if url == "" {
url = baseURL
}
return packngo.NewClientWithBaseURL(useragent, token, nil, url)
}
func argsOrEnv(args map[string]string, key, env string) string {
if value := args[key]; value != "" {
return value
}
return os.Getenv(env)
}

View File

@ -0,0 +1,417 @@
// Package vsphere provides node discovery for VMware vSphere.
//
// The package performs discovery by searching vCenter for all nodes matching a
// certain tag, it then discovers all known IP addresses through VMware tools
// that are not loopback or auto-configuration addresses.
//
// This package requires at least vSphere 6.0 in order to function.
package vsphere
import (
"context"
"fmt"
"io/ioutil"
"log"
"net"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"github.com/vmware/vic/pkg/vsphere/tags"
)
// providerLog is the local provider logger. This should be initialized from
// the provider entry point.
var logger *log.Logger
// setLog sets the logger.
func setLog(l *log.Logger) {
if l != nil {
logger = l
} else {
logger = log.New(ioutil.Discard, "", 0)
}
}
// discoverErr prints out a friendly error heading for the top-level discovery
// errors. It should only be used in the Addrs method.
func discoverErr(format string, a ...interface{}) error {
var s string
if len(a) > 1 {
s = fmt.Sprintf(format, a)
} else {
s = format
}
return fmt.Errorf("discover-vsphere: %s", s)
}
// valueOrEnv provides a way of suppling configuration values through
// environment variables. Defined values always take priority.
func valueOrEnv(config map[string]string, key, env string) string {
if v := config[key]; v != "" {
return v
}
if v := os.Getenv(env); v != "" {
logger.Printf("[DEBUG] Using value of %s for configuration of %s", env, key)
return v
}
return ""
}
// vSphereClient is a client connection manager for the vSphere provider.
type vSphereClient struct {
// The VIM/govmomi client.
VimClient *govmomi.Client
// The specialized tags client SDK imported from vmware/vic.
TagsClient *tags.RestClient
}
// vimURL returns a URL to pass to the VIM SOAP client.
func vimURL(server, user, password string) (*url.URL, error) {
u, err := url.Parse("https://" + server + "/sdk")
if err != nil {
return nil, fmt.Errorf("error parsing url: %s", err)
}
u.User = url.UserPassword(user, password)
return u, nil
}
// newVSphereClient returns a new vSphereClient after setting up the necessary
// connections.
func newVSphereClient(ctx context.Context, host, user, password string, insecure bool) (*vSphereClient, error) {
logger.Println("[DEBUG] Connecting to vSphere client endpoints")
client := new(vSphereClient)
u, err := vimURL(host, user, password)
if err != nil {
return nil, fmt.Errorf("error generating SOAP endpoint url: %s", err)
}
// Set up the VIM/govmomi client connection
client.VimClient, err = newVimSession(ctx, u, insecure)
if err != nil {
return nil, err
}
client.TagsClient, err = newRestSession(ctx, u, insecure)
if err != nil {
return nil, err
}
logger.Println("[DEBUG] All vSphere client endpoints connected successfully")
return client, nil
}
// newVimSession connects the VIM SOAP API client connection.
func newVimSession(ctx context.Context, u *url.URL, insecure bool) (*govmomi.Client, error) {
logger.Printf("[DEBUG] Creating new SOAP API session on endpoint %s", u.Host)
client, err := govmomi.NewClient(ctx, u, insecure)
if err != nil {
return nil, fmt.Errorf("error setting up new vSphere SOAP client: %s", err)
}
logger.Println("[DEBUG] SOAP API session creation successful")
return client, nil
}
// newRestSession connects to the vSphere REST API endpoint, necessary for
// tags.
func newRestSession(ctx context.Context, u *url.URL, insecure bool) (*tags.RestClient, error) {
logger.Printf("[DEBUG] Creating new CIS REST API session on endpoint %s", u.Host)
client := tags.NewClient(u, insecure, "")
if err := client.Login(ctx); err != nil {
return nil, fmt.Errorf("error connecting to CIS REST endpoint: %s", err)
}
logger.Println("[DEBUG] CIS REST API session creation successful")
return client, nil
}
// Provider defines the vSphere discovery provider.
type Provider struct{}
// Help implements the Provider interface for the vsphere package.
func (p *Provider) Help() string {
return `VMware vSphere:
provider: "vsphere"
tag_name: The name of the tag to look up.
category_name: The category of the tag to look up.
host: The host of the vSphere server to connect to.
user: The username to connect as.
password: The password of the user to connect to vSphere as.
insecure_ssl: Whether or not to skip SSL certificate validation.
timeout: Discovery context timeout (default: 10m)
`
}
// Addrs implements the Provider interface for the vsphere package.
func (p *Provider) Addrs(args map[string]string, l *log.Logger) ([]string, error) {
if args["provider"] != "vsphere" {
return nil, discoverErr("invalid provider %s", args["provider"])
}
setLog(l)
tagName := args["tag_name"]
categoryName := args["category_name"]
host := valueOrEnv(args, "host", "VSPHERE_SERVER")
user := valueOrEnv(args, "user", "VSPHERE_USER")
password := valueOrEnv(args, "password", "VSPHERE_PASSWORD")
insecure, err := strconv.ParseBool(valueOrEnv(args, "insecure_ssl", "VSPHERE_ALLOW_UNVERIFIED_SSL"))
if err != nil {
logger.Println("[DEBUG] Non-truthy/falsey value for insecure_ssl, assuming false")
}
timeout, err := time.ParseDuration(args["timeout"])
if err != nil {
logger.Println("[DEBUG] Non-time value given for timeout, assuming 10m")
timeout = time.Minute * 10
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
client, err := newVSphereClient(ctx, host, user, password, insecure)
if err != nil {
return nil, discoverErr(err.Error())
}
if tagName == "" || categoryName == "" {
return nil, discoverErr("both tag_name and category_name must be specified")
}
logger.Printf("[INFO] Locating all virtual machine IP addresses with tag %q in category %q", tagName, categoryName)
tagID, err := tagIDFromName(ctx, client.TagsClient, tagName, categoryName)
if err != nil {
return nil, discoverErr(err.Error())
}
addrs, err := virtualMachineIPsForTag(ctx, client, tagID)
if err != nil {
return nil, discoverErr(err.Error())
}
logger.Printf("[INFO] Final IP address list: %s", strings.Join(addrs, ","))
return addrs, nil
}
// tagIDFromName helps convert the tag and category names into the final ID
// used for discovery.
func tagIDFromName(ctx context.Context, client *tags.RestClient, name, category string) (string, error) {
logger.Printf("[DEBUG] Fetching tag ID for tag name %q and category %q", name, category)
categoryID, err := tagCategoryByName(ctx, client, category)
if err != nil {
return "", err
}
return tagByName(ctx, client, name, categoryID)
}
// tagCategoryByName converts a tag category name into its ID.
func tagCategoryByName(ctx context.Context, client *tags.RestClient, name string) (string, error) {
cats, err := client.GetCategoriesByName(ctx, name)
if err != nil {
return "", fmt.Errorf("could not get category for name %q: %s", name, err)
}
if len(cats) < 1 {
return "", fmt.Errorf("category name %q not found", name)
}
if len(cats) > 1 {
// Although GetCategoriesByName does not seem to think that tag categories
// are unique, empirical observation via the console and API show that they
// are. This error case is handled anyway.
return "", fmt.Errorf("multiple categories with name %q found", name)
}
return cats[0].ID, nil
}
// tagByName converts a tag name into its ID.
func tagByName(ctx context.Context, client *tags.RestClient, name, categoryID string) (string, error) {
tids, err := client.GetTagByNameForCategory(ctx, name, categoryID)
if err != nil {
return "", fmt.Errorf("could not get tag for name %q: %s", name, err)
}
if len(tids) < 1 {
return "", fmt.Errorf("tag name %q not found in category ID %q", name, categoryID)
}
if len(tids) > 1 {
// This situation is very similar to the one in tagCategoryByName. The API
// docs even say that tags need to be unique in categories, yet
// GetTagByNameForCategory still returns multiple results.
return "", fmt.Errorf("multiple tags with name %q found", name)
}
logger.Printf("[DEBUG] Tag ID is %q", tids[0].ID)
return tids[0].ID, nil
}
// virtualMachineIPsForTag is a higher-level wrapper that calls out to
// functions to fetch all of the virtual machines matching a certain tag ID,
// and then gets all of the IP addresses for those virtual machines.
func virtualMachineIPsForTag(ctx context.Context, client *vSphereClient, id string) ([]string, error) {
vms, err := virtualMachinesForTag(ctx, client, id)
if err != nil {
return nil, err
}
return ipAddrsForVirtualMachines(ctx, client, vms)
}
// virtualMachinesForTag discovers all of the virtual machines that match a
// specific tag ID and returns their higher level helper objects.
func virtualMachinesForTag(ctx context.Context, client *vSphereClient, id string) ([]*object.VirtualMachine, error) {
logger.Printf("[DEBUG] Locating all virtual machines under tag ID %q", id)
var vms []*object.VirtualMachine
objs, err := client.TagsClient.ListAttachedObjects(ctx, id)
if err != nil {
return nil, err
}
for i, obj := range objs {
switch {
case obj.Type == nil || obj.ID == nil:
logger.Printf("[WARN] Discovered object at index %d has either no ID or type", i)
continue
case *obj.Type != "VirtualMachine":
logger.Printf("[DEBUG] Discovered object ID %q is not a virutal machine", *obj.ID)
continue
}
vm, err := virtualMachineFromMOID(ctx, client.VimClient, *obj.ID)
if err != nil {
return nil, fmt.Errorf("error locating virtual machine with ID %q: %s", *obj.ID, err)
}
vms = append(vms, vm)
}
logger.Printf("[DEBUG] Discovered virtual machines: %s", virtualMachineNames(vms))
return vms, nil
}
// ipAddrsForVirtualMachines takes a set of virtual machines and returns a
// consolidated list of IP addresses for all of the VMs.
func ipAddrsForVirtualMachines(ctx context.Context, client *vSphereClient, vms []*object.VirtualMachine) ([]string, error) {
var addrs []string
for _, vm := range vms {
as, err := buildAndSelectGuestIPs(ctx, vm)
if err != nil {
return nil, err
}
addrs = append(addrs, as...)
}
return addrs, nil
}
// virtualMachineFromMOID locates a virtual machine by its managed object
// reference ID.
func virtualMachineFromMOID(ctx context.Context, client *govmomi.Client, id string) (*object.VirtualMachine, error) {
logger.Printf("[DEBUG] Locating VM with managed object ID %q", id)
finder := find.NewFinder(client.Client, false)
ref := types.ManagedObjectReference{
Type: "VirtualMachine",
Value: id,
}
vm, err := finder.ObjectReference(ctx, ref)
if err != nil {
return nil, err
}
// Should be safe to return here. If our reference returned here and is not a
// VM, then we have bigger problems and to be honest we should be panicking
// anyway.
return vm.(*object.VirtualMachine), nil
}
// virtualMachineProperties is a convenience method that wraps fetching the
// VirtualMachine MO from its higher-level object.
//
// It takes a list of property keys to fetch. Keeping the property set small
// can sometimes result in significant performance improvements.
func virtualMachineProperties(ctx context.Context, vm *object.VirtualMachine, keys []string) (*mo.VirtualMachine, error) {
logger.Printf("[DEBUG] Fetching properties for VM %q", vm.Name())
var props mo.VirtualMachine
if err := vm.Properties(ctx, vm.Reference(), keys, &props); err != nil {
return nil, err
}
return &props, nil
}
// buildAndSelectGuestIPs builds a list of IP addresses known to VMware tools,
// skipping local and auto-configuration addresses.
//
// The builder is non-discriminate and is only deterministic to the order that
// it discovers addresses in VMware tools.
func buildAndSelectGuestIPs(ctx context.Context, vm *object.VirtualMachine) ([]string, error) {
logger.Printf("[DEBUG] Discovering addresses for virtual machine %q", vm.Name())
var addrs []string
props, err := virtualMachineProperties(ctx, vm, []string{"guest.net"})
if err != nil {
return nil, fmt.Errorf("cannot fetch properties for VM %q: %s", vm.Name(), err)
}
if props.Guest == nil || props.Guest.Net == nil {
logger.Printf("[WARN] No networking stack information available for %q or VMware tools not running", vm.Name())
return nil, nil
}
// Now fetch all IP addresses, checking at the same time to see if the IP
// address is eligible to be a primary IP address.
for _, n := range props.Guest.Net {
if n.IpConfig != nil {
for _, addr := range n.IpConfig.IpAddress {
if skipIPAddr(net.ParseIP(addr.IpAddress)) {
continue
}
addrs = append(addrs, addr.IpAddress)
}
}
}
logger.Printf("[INFO] Discovered IP addresses for virtual machine %q: %s", vm.Name(), strings.Join(addrs, ","))
return addrs, nil
}
// skipIPAddr defines the set of criteria that buildAndSelectGuestIPs uses to
// check to see if it needs to skip an IP address.
func skipIPAddr(ip net.IP) bool {
switch {
case ip.IsLinkLocalMulticast():
fallthrough
case ip.IsLinkLocalUnicast():
fallthrough
case ip.IsLoopback():
fallthrough
case ip.IsMulticast():
return true
}
return false
}
// virtualMachineNames is a helper method that returns all the names for a list
// of virtual machines, comma separated.
func virtualMachineNames(vms []*object.VirtualMachine) string {
var s []string
for _, vm := range vms {
s = append(s, vm.Name())
}
return strings.Join(s, ",")
}

54
vendor/github.com/packethost/packngo/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,54 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
This release contains a bunch of fixes to the package api after some more real
world use. There a few breaks in backwards compatibility, but we are tying to
minimize them and move towards a 1.0 release.
### Added
- "acceptance" tests which run against production api (will incur charges)
- HardwareReservation to Device
- RootPassword to Device
- Spot market support
- Management and Manageable fields to discern between Elastic IPs and device unique IP
- Support for Volume attachments to Device and Volume
- Support for ProvisionEvents
- DoRequest sugar to Client
- Add ListProject function to the SSHKeys interface
- Operations for switching between Network Modes, aka "L2 support"
Support for Organization, Payment Method and Billing address resources
### Fixed
- User.Emails json tag is fixed to match api response
- Single error object api response is now handled correctly
### Changed
- IPService was split to DeviceIPService and ProjectIPService
- Renamed Device.IPXEScriptUrl -> Device.IPXEScriptURL
- Renamed DeviceCreateRequest.HostName -> DeviceCreateRequest.Hostname
- Renamed DeviceCreateRequest.IPXEScriptUrl -> DeviceCreateRequest.IPXEScriptURL
- Renamed DeviceUpdateRequest.HostName -> DeviceUpdateRequest.Hostname
- Renamed DeviceUpdateRequest.IPXEScriptUrl -> DeviceUpdateRequest.IPXEScriptURL
- Sync with packet.net api change to /projects/{id}/ips which no longer returns
the address in CIDR form
- Removed package level exported functions that should have never existed
## [0.1.0] - 2017-08-17
Initial release, supports most of the api for interacting with:
- Plans
- Users
- Emails
- SSH Keys
- Devices
- Projects
- Facilities
- Operating Systems
- IP Reservations
- Volumes

56
vendor/github.com/packethost/packngo/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,56 @@
Copyright (c) 2014 The packngo AUTHORS. All rights reserved.
MIT License
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.
======================
Portions of the client are based on code at:
https://github.com/google/go-github/ and
https://github.com/digitalocean/godo
Copyright (c) 2013 The go-github AUTHORS. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

72
vendor/github.com/packethost/packngo/README.md generated vendored Normal file
View File

@ -0,0 +1,72 @@
# packngo
Packet Go Api Client
![](https://www.packet.net/media/images/xeiw-packettwitterprofilew.png)
Installation
------------
`go get github.com/packethost/packngo`
Usage
-----
To authenticate to the Packet API, you must have your API token exported in env var `PACKET_API_TOKEN`.
This code snippet initializes Packet API client, and lists your Projects:
```go
package main
import (
"log"
"github.com/packethost/packngo"
)
func main() {
c, err := packngo.NewClient()
if err != nil {
log.Fatal(err)
}
ps, _, err := c.Projects.List(nil)
if err != nil {
log.Fatal(err)
}
for _, p := range ps {
log.Println(p.ID, p.Name)
}
}
```
This lib is used by the official [terraform-provider-packet](https://github.com/terraform-providers/terraform-provider-packet).
You can also learn a lot from the `*_test.go` sources. Almost all out tests touch the Packet API, so you can see how auth, querying and POSTing works. For example [devices_test.go](devices_test.go).
Acceptance Tests
----------------
If you want to run tests against the actual Packet API, you must set envvar `PACKET_TEST_ACTUAL_API` to non-empty string for the `go test`. The device tests wait for the device creation, so it's best to run a few in parallel.
To run a particular test, you can do
```
$ PACKNGO_TEST_ACTUAL_API=1 go test -v -run=TestAccDeviceBasic
```
If you want to see HTTP requests, set the `PACKNGO_DEBUG` env var to non-empty string, for example:
```
$ PACKNGO_DEBUG=1 PACKNGO_TEST_ACTUAL_API=1 go test -v -run=TestAccVolumeUpdate
```
Committing
----------
Before committing, it's a good idea to run `gofmt -w *.go`. ([gofmt](https://golang.org/cmd/gofmt/))

View File

@ -0,0 +1,7 @@
package packngo
type BillingAddress struct {
StreetAddress string `json:"street_address,omitempty"`
PostalCode string `json:"postal_code,omitempty"`
CountryCode string `json:"country_code_alpha2,omitempty"`
}

257
vendor/github.com/packethost/packngo/devices.go generated vendored Normal file
View File

@ -0,0 +1,257 @@
package packngo
import (
"fmt"
"strings"
)
const deviceBasePath = "/devices"
// DeviceService interface defines available device methods
type DeviceService interface {
List(ProjectID string, listOpt *ListOptions) ([]Device, *Response, error)
Get(string) (*Device, *Response, error)
GetExtra(deviceID string, includes, excludes []string) (*Device, *Response, error)
Create(*DeviceCreateRequest) (*Device, *Response, error)
Update(string, *DeviceUpdateRequest) (*Device, *Response, error)
Delete(string) (*Response, error)
Reboot(string) (*Response, error)
PowerOff(string) (*Response, error)
PowerOn(string) (*Response, error)
Lock(string) (*Response, error)
Unlock(string) (*Response, error)
}
type devicesRoot struct {
Devices []Device `json:"devices"`
Meta meta `json:"meta"`
}
// Device represents a Packet device
type Device struct {
ID string `json:"id"`
Href string `json:"href,omitempty"`
Hostname string `json:"hostname,omitempty"`
State string `json:"state,omitempty"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
Locked bool `json:"locked,omitempty"`
BillingCycle string `json:"billing_cycle,omitempty"`
Storage map[string]interface{} `json:"storage,omitempty"`
Tags []string `json:"tags,omitempty"`
Network []*IPAddressAssignment `json:"ip_addresses"`
Volumes []*Volume `json:"volumes"`
OS *OS `json:"operating_system,omitempty"`
Plan *Plan `json:"plan,omitempty"`
Facility *Facility `json:"facility,omitempty"`
Project *Project `json:"project,omitempty"`
ProvisionEvents []*ProvisionEvent `json:"provisioning_events,omitempty"`
ProvisionPer float32 `json:"provisioning_percentage,omitempty"`
UserData string `json:"userdata,omitempty"`
RootPassword string `json:"root_password,omitempty"`
IPXEScriptURL string `json:"ipxe_script_url,omitempty"`
AlwaysPXE bool `json:"always_pxe,omitempty"`
HardwareReservation Href `json:"hardware_reservation,omitempty"`
SpotInstance bool `json:"spot_instance,omitempty"`
SpotPriceMax float64 `json:"spot_price_max,omitempty"`
TerminationTime *Timestamp `json:"termination_time,omitempty"`
NetworkPorts []Port `json:"network_ports,omitempty"`
CustomData map[string]interface{} `json:"customdata,omitempty"`
}
type ProvisionEvent struct {
ID string `json:"id"`
Body string `json:"body"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Href string `json:"href"`
Interpolated string `json:"interpolated"`
Relationships []Href `json:"relationships"`
State string `json:"state"`
Type string `json:"type"`
}
func (d Device) String() string {
return Stringify(d)
}
// DeviceCreateRequest type used to create a Packet device
type DeviceCreateRequest struct {
Hostname string `json:"hostname"`
Plan string `json:"plan"`
Facility string `json:"facility"`
OS string `json:"operating_system"`
BillingCycle string `json:"billing_cycle"`
ProjectID string `json:"project_id"`
UserData string `json:"userdata"`
Storage string `json:"storage,omitempty"`
Tags []string `json:"tags"`
IPXEScriptURL string `json:"ipxe_script_url,omitempty"`
PublicIPv4SubnetSize int `json:"public_ipv4_subnet_size,omitempty"`
AlwaysPXE bool `json:"always_pxe,omitempty"`
HardwareReservationID string `json:"hardware_reservation_id,omitempty"`
SpotInstance bool `json:"spot_instance,omitempty"`
SpotPriceMax float64 `json:"spot_price_max,omitempty,string"`
TerminationTime *Timestamp `json:"termination_time,omitempty"`
CustomData string `json:"customdata,omitempty"`
}
// DeviceUpdateRequest type used to update a Packet device
type DeviceUpdateRequest struct {
Hostname *string `json:"hostname,omitempty"`
Description *string `json:"description,omitempty"`
UserData *string `json:"userdata,omitempty"`
Locked *bool `json:"locked,omitempty"`
Tags *[]string `json:"tags,omitempty"`
AlwaysPXE *bool `json:"always_pxe,omitempty"`
IPXEScriptURL *string `json:"ipxe_script_url,omitempty"`
CustomData *string `json:"customdata,omitempty"`
}
func (d DeviceCreateRequest) String() string {
return Stringify(d)
}
// DeviceActionRequest type used to execute actions on devices
type DeviceActionRequest struct {
Type string `json:"type"`
}
func (d DeviceActionRequest) String() string {
return Stringify(d)
}
// DeviceServiceOp implements DeviceService
type DeviceServiceOp struct {
client *Client
}
// List returns devices on a project
func (s *DeviceServiceOp) List(projectID string, listOpt *ListOptions) (devices []Device, resp *Response, err error) {
params := "include=facility"
if listOpt != nil {
params = listOpt.createURL()
}
path := fmt.Sprintf("%s/%s%s?%s", projectBasePath, projectID, deviceBasePath, params)
for {
subset := new(devicesRoot)
resp, err = s.client.DoRequest("GET", path, nil, subset)
if err != nil {
return nil, resp, err
}
devices = append(devices, subset.Devices...)
if subset.Meta.Next != nil && (listOpt == nil || listOpt.Page == 0) {
path = subset.Meta.Next.Href
if params != "" {
path = fmt.Sprintf("%s&%s", path, params)
}
continue
}
return
}
}
// Get returns a device by id
func (s *DeviceServiceOp) Get(deviceID string) (*Device, *Response, error) {
return s.GetExtra(deviceID, []string{"facility"}, nil)
}
// GetExtra returns a device by id. Specifying either includes/excludes provides more or less desired
// detailed information about resources which would otherwise be represented with an href link
func (s *DeviceServiceOp) GetExtra(deviceID string, includes, excludes []string) (*Device, *Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
if includes != nil {
path += fmt.Sprintf("?include=%s", strings.Join(includes, ","))
} else if excludes != nil {
path += fmt.Sprintf("?exclude=%s", strings.Join(excludes, ","))
}
device := new(Device)
resp, err := s.client.DoRequest("GET", path, nil, device)
if err != nil {
return nil, resp, err
}
return device, resp, err
}
// Create creates a new device
func (s *DeviceServiceOp) Create(createRequest *DeviceCreateRequest) (*Device, *Response, error) {
path := fmt.Sprintf("%s/%s%s", projectBasePath, createRequest.ProjectID, deviceBasePath)
device := new(Device)
resp, err := s.client.DoRequest("POST", path, createRequest, device)
if err != nil {
return nil, resp, err
}
return device, resp, err
}
// Update updates an existing device
func (s *DeviceServiceOp) Update(deviceID string, updateRequest *DeviceUpdateRequest) (*Device, *Response, error) {
path := fmt.Sprintf("%s/%s?include=facility", deviceBasePath, deviceID)
device := new(Device)
resp, err := s.client.DoRequest("PUT", path, updateRequest, device)
if err != nil {
return nil, resp, err
}
return device, resp, err
}
// Delete deletes a device
func (s *DeviceServiceOp) Delete(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
return s.client.DoRequest("DELETE", path, nil, nil)
}
// Reboot reboots on a device
func (s *DeviceServiceOp) Reboot(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s/actions", deviceBasePath, deviceID)
action := &DeviceActionRequest{Type: "reboot"}
return s.client.DoRequest("POST", path, action, nil)
}
// PowerOff powers on a device
func (s *DeviceServiceOp) PowerOff(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s/actions", deviceBasePath, deviceID)
action := &DeviceActionRequest{Type: "power_off"}
return s.client.DoRequest("POST", path, action, nil)
}
// PowerOn powers on a device
func (s *DeviceServiceOp) PowerOn(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s/actions", deviceBasePath, deviceID)
action := &DeviceActionRequest{Type: "power_on"}
return s.client.DoRequest("POST", path, action, nil)
}
type lockType struct {
Locked bool `json:"locked"`
}
// Lock sets a device to "locked"
func (s *DeviceServiceOp) Lock(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
action := lockType{Locked: true}
return s.client.DoRequest("PATCH", path, action, nil)
}
// Unlock sets a device to "unlocked"
func (s *DeviceServiceOp) Unlock(deviceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", deviceBasePath, deviceID)
action := lockType{Locked: false}
return s.client.DoRequest("PATCH", path, action, nil)
}

37
vendor/github.com/packethost/packngo/email.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
package packngo
const emailBasePath = "/emails"
// EmailService interface defines available email methods
type EmailService interface {
Get(string) (*Email, *Response, error)
}
// Email represents a user's email address
type Email struct {
ID string `json:"id"`
Address string `json:"address"`
Default bool `json:"default,omitempty"`
URL string `json:"href,omitempty"`
}
func (e Email) String() string {
return Stringify(e)
}
// EmailServiceOp implements EmailService
type EmailServiceOp struct {
client *Client
}
// Get retrieves an email by id
func (s *EmailServiceOp) Get(emailID string) (*Email, *Response, error) {
email := new(Email)
resp, err := s.client.DoRequest("GET", emailBasePath, nil, email)
if err != nil {
return nil, resp, err
}
return email, resp, err
}

52
vendor/github.com/packethost/packngo/facilities.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
package packngo
const facilityBasePath = "/facilities"
// FacilityService interface defines available facility methods
type FacilityService interface {
List() ([]Facility, *Response, error)
}
type facilityRoot struct {
Facilities []Facility `json:"facilities"`
}
// Facility represents a Packet facility
type Facility struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Code string `json:"code,omitempty"`
Features []string `json:"features,omitempty"`
Address *Address `json:"address,omitempty"`
URL string `json:"href,omitempty"`
}
func (f Facility) String() string {
return Stringify(f)
}
// Address - the physical address of the facility
type Address struct {
ID string `json:"id,omitempty"`
}
func (a Address) String() string {
return Stringify(a)
}
// FacilityServiceOp implements FacilityService
type FacilityServiceOp struct {
client *Client
}
// List returns all available Packet facilities
func (s *FacilityServiceOp) List() ([]Facility, *Response, error) {
root := new(facilityRoot)
resp, err := s.client.DoRequest("GET", facilityBasePath, nil, root)
if err != nil {
return nil, resp, err
}
return root.Facilities, resp, err
}

194
vendor/github.com/packethost/packngo/ip.go generated vendored Normal file
View File

@ -0,0 +1,194 @@
package packngo
import (
"fmt"
)
const ipBasePath = "/ips"
// DeviceIPService handles assignment of addresses from reserved blocks to instances in a project.
type DeviceIPService interface {
Assign(deviceID string, assignRequest *AddressStruct) (*IPAddressAssignment, *Response, error)
Unassign(assignmentID string) (*Response, error)
Get(assignmentID string) (*IPAddressAssignment, *Response, error)
}
// ProjectIPService handles reservation of IP address blocks for a project.
type ProjectIPService interface {
Get(reservationID string) (*IPAddressReservation, *Response, error)
List(projectID string) ([]IPAddressReservation, *Response, error)
Request(projectID string, ipReservationReq *IPReservationRequest) (*IPAddressReservation, *Response, error)
Remove(ipReservationID string) (*Response, error)
AvailableAddresses(ipReservationID string, r *AvailableRequest) ([]string, *Response, error)
}
type ipAddressCommon struct {
ID string `json:"id"`
Address string `json:"address"`
Gateway string `json:"gateway"`
Network string `json:"network"`
AddressFamily int `json:"address_family"`
Netmask string `json:"netmask"`
Public bool `json:"public"`
CIDR int `json:"cidr"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
Href string `json:"href"`
Management bool `json:"management"`
Manageable bool `json:"manageable"`
Project Href `json:"project"`
}
// IPAddressReservation is created when user sends IP reservation request for a project (considering it's within quota).
type IPAddressReservation struct {
ipAddressCommon
Assignments []Href `json:"assignments"`
Facility Facility `json:"facility,omitempty"`
Available string `json:"available"`
Addon bool `json:"addon"`
Bill bool `json:"bill"`
}
// AvailableResponse is a type for listing of available addresses from a reserved block.
type AvailableResponse struct {
Available []string `json:"available"`
}
// AvailableRequest is a type for listing available addresses from a reserved block.
type AvailableRequest struct {
CIDR int `json:"cidr"`
}
// IPAddressAssignment is created when an IP address from reservation block is assigned to a device.
type IPAddressAssignment struct {
ipAddressCommon
AssignedTo Href `json:"assigned_to"`
}
// IPReservationRequest represents the body of a reservation request.
type IPReservationRequest struct {
Type string `json:"type"`
Quantity int `json:"quantity"`
Comments string `json:"comments"`
Facility string `json:"facility"`
}
// AddressStruct is a helper type for request/response with dict like {"address": ... }
type AddressStruct struct {
Address string `json:"address"`
}
func deleteFromIP(client *Client, resourceID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", ipBasePath, resourceID)
return client.DoRequest("DELETE", path, nil, nil)
}
func (i IPAddressReservation) String() string {
return Stringify(i)
}
func (i IPAddressAssignment) String() string {
return Stringify(i)
}
// DeviceIPServiceOp is interface for IP-address assignment methods.
type DeviceIPServiceOp struct {
client *Client
}
// Unassign unassigns an IP address from the device to which it is currently assigned.
// This will remove the relationship between an IP and the device and will make the IP
// address available to be assigned to another device.
func (i *DeviceIPServiceOp) Unassign(assignmentID string) (*Response, error) {
return deleteFromIP(i.client, assignmentID)
}
// Assign assigns an IP address to a device.
// The IP address must be in one of the IP ranges assigned to the devices project.
func (i *DeviceIPServiceOp) Assign(deviceID string, assignRequest *AddressStruct) (*IPAddressAssignment, *Response, error) {
path := fmt.Sprintf("%s/%s%s", deviceBasePath, deviceID, ipBasePath)
ipa := new(IPAddressAssignment)
resp, err := i.client.DoRequest("POST", path, assignRequest, ipa)
if err != nil {
return nil, resp, err
}
return ipa, resp, err
}
// Get returns assignment by ID.
func (i *DeviceIPServiceOp) Get(assignmentID string) (*IPAddressAssignment, *Response, error) {
path := fmt.Sprintf("%s/%s", ipBasePath, assignmentID)
ipa := new(IPAddressAssignment)
resp, err := i.client.DoRequest("GET", path, nil, ipa)
if err != nil {
return nil, resp, err
}
return ipa, resp, err
}
// ProjectIPServiceOp is interface for IP assignment methods.
type ProjectIPServiceOp struct {
client *Client
}
// Get returns reservation by ID.
func (i *ProjectIPServiceOp) Get(reservationID string) (*IPAddressReservation, *Response, error) {
path := fmt.Sprintf("%s/%s", ipBasePath, reservationID)
ipr := new(IPAddressReservation)
resp, err := i.client.DoRequest("GET", path, nil, ipr)
if err != nil {
return nil, resp, err
}
return ipr, resp, err
}
// List provides a list of IP resevations for a single project.
func (i *ProjectIPServiceOp) List(projectID string) ([]IPAddressReservation, *Response, error) {
path := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, ipBasePath)
reservations := new(struct {
Reservations []IPAddressReservation `json:"ip_addresses"`
})
resp, err := i.client.DoRequest("GET", path, nil, reservations)
if err != nil {
return nil, resp, err
}
return reservations.Reservations, resp, nil
}
// Request requests more IP space for a project in order to have additional IP addresses to assign to devices.
func (i *ProjectIPServiceOp) Request(projectID string, ipReservationReq *IPReservationRequest) (*IPAddressReservation, *Response, error) {
path := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, ipBasePath)
ipr := new(IPAddressReservation)
resp, err := i.client.DoRequest("POST", path, ipReservationReq, ipr)
if err != nil {
return nil, resp, err
}
return ipr, resp, err
}
// Remove removes an IP reservation from the project.
func (i *ProjectIPServiceOp) Remove(ipReservationID string) (*Response, error) {
return deleteFromIP(i.client, ipReservationID)
}
// AvailableAddresses lists addresses available from a reserved block
func (i *ProjectIPServiceOp) AvailableAddresses(ipReservationID string, r *AvailableRequest) ([]string, *Response, error) {
path := fmt.Sprintf("%s/%s/available?cidr=%d", ipBasePath, ipReservationID, r.CIDR)
ar := new(AvailableResponse)
resp, err := i.client.DoRequest("GET", path, r, ar)
if err != nil {
return nil, resp, err
}
return ar.Available, resp, nil
}

View File

@ -0,0 +1,41 @@
package packngo
const osBasePath = "/operating-systems"
// OSService interface defines available operating_systems methods
type OSService interface {
List() ([]OS, *Response, error)
}
type osRoot struct {
OperatingSystems []OS `json:"operating_systems"`
}
// OS represents a Packet operating system
type OS struct {
Name string `json:"name"`
Slug string `json:"slug"`
Distro string `json:"distro"`
Version string `json:"version"`
}
func (o OS) String() string {
return Stringify(o)
}
// OSServiceOp implements OSService
type OSServiceOp struct {
client *Client
}
// List returns all available operating systems
func (s *OSServiceOp) List() ([]OS, *Response, error) {
root := new(osRoot)
resp, err := s.client.DoRequest("GET", osBasePath, nil, root)
if err != nil {
return nil, resp, err
}
return root.OperatingSystems, resp, err
}

147
vendor/github.com/packethost/packngo/organizations.go generated vendored Normal file
View File

@ -0,0 +1,147 @@
package packngo
import "fmt"
// API documentation https://www.packet.net/developers/api/organizations/
const organizationBasePath = "/organizations"
// OrganizationService interface defines available organization methods
type OrganizationService interface {
List() ([]Organization, *Response, error)
Get(string) (*Organization, *Response, error)
Create(*OrganizationCreateRequest) (*Organization, *Response, error)
Update(string, *OrganizationUpdateRequest) (*Organization, *Response, error)
Delete(string) (*Response, error)
ListPaymentMethods(string) ([]PaymentMethod, *Response, error)
}
type organizationsRoot struct {
Organizations []Organization `json:"organizations"`
}
// Organization represents a Packet organization
type Organization struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Website string `json:"website,omitempty"`
Twitter string `json:"twitter,omitempty"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
Address Address `json:"address,omitempty"`
TaxID string `json:"tax_id,omitempty"`
MainPhone string `json:"main_phone,omitempty"`
BillingPhone string `json:"billing_phone,omitempty"`
CreditAmount float64 `json:"credit_amount,omitempty"`
Logo string `json:"logo,omitempty"`
LogoThumb string `json:"logo_thumb,omitempty"`
Projects []Project `json:"projects,omitempty"`
URL string `json:"href,omitempty"`
Users []User `json:"members,omitempty"`
Owners []User `json:"owners,omitempty"`
}
func (o Organization) String() string {
return Stringify(o)
}
// OrganizationCreateRequest type used to create a Packet organization
type OrganizationCreateRequest struct {
Name string `json:"name"`
Description string `json:"description"`
Website string `json:"website"`
Twitter string `json:"twitter"`
Logo string `json:"logo"`
}
func (o OrganizationCreateRequest) String() string {
return Stringify(o)
}
// OrganizationUpdateRequest type used to update a Packet organization
type OrganizationUpdateRequest struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
Website *string `json:"website,omitempty"`
Twitter *string `json:"twitter,omitempty"`
Logo *string `json:"logo,omitempty"`
}
func (o OrganizationUpdateRequest) String() string {
return Stringify(o)
}
// OrganizationServiceOp implements OrganizationService
type OrganizationServiceOp struct {
client *Client
}
// List returns the user's organizations
func (s *OrganizationServiceOp) List() ([]Organization, *Response, error) {
root := new(organizationsRoot)
resp, err := s.client.DoRequest("GET", organizationBasePath, nil, root)
if err != nil {
return nil, resp, err
}
return root.Organizations, resp, err
}
// Get returns a organization by id
func (s *OrganizationServiceOp) Get(organizationID string) (*Organization, *Response, error) {
path := fmt.Sprintf("%s/%s", organizationBasePath, organizationID)
organization := new(Organization)
resp, err := s.client.DoRequest("GET", path, nil, organization)
if err != nil {
return nil, resp, err
}
return organization, resp, err
}
// Create creates a new organization
func (s *OrganizationServiceOp) Create(createRequest *OrganizationCreateRequest) (*Organization, *Response, error) {
organization := new(Organization)
resp, err := s.client.DoRequest("POST", organizationBasePath, createRequest, organization)
if err != nil {
return nil, resp, err
}
return organization, resp, err
}
// Update updates an organization
func (s *OrganizationServiceOp) Update(id string, updateRequest *OrganizationUpdateRequest) (*Organization, *Response, error) {
path := fmt.Sprintf("%s/%s", organizationBasePath, id)
organization := new(Organization)
resp, err := s.client.DoRequest("PATCH", path, updateRequest, organization)
if err != nil {
return nil, resp, err
}
return organization, resp, err
}
// Delete deletes an organizationID
func (s *OrganizationServiceOp) Delete(organizationID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", organizationBasePath, organizationID)
return s.client.DoRequest("DELETE", path, nil, nil)
}
// ListPaymentMethods returns PaymentMethods for an organization
func (s *OrganizationServiceOp) ListPaymentMethods(organizationID string) ([]PaymentMethod, *Response, error) {
url := fmt.Sprintf("%s/%s%s", organizationBasePath, organizationID, paymentMethodBasePath)
root := new(paymentMethodsRoot)
resp, err := s.client.DoRequest("GET", url, nil, root)
if err != nil {
return nil, resp, err
}
return root.PaymentMethods, resp, err
}

306
vendor/github.com/packethost/packngo/packngo.go generated vendored Normal file
View File

@ -0,0 +1,306 @@
package packngo
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
"time"
)
const (
packetTokenEnvVar = "PACKET_AUTH_TOKEN"
libraryVersion = "0.1.0"
baseURL = "https://api.packet.net/"
userAgent = "packngo/" + libraryVersion
mediaType = "application/json"
debugEnvVar = "PACKNGO_DEBUG"
headerRateLimit = "X-RateLimit-Limit"
headerRateRemaining = "X-RateLimit-Remaining"
headerRateReset = "X-RateLimit-Reset"
)
// ListOptions specifies optional global API parameters
type ListOptions struct {
// for paginated result sets, page of results to retrieve
Page int `url:"page,omitempty"`
// for paginated result sets, the number of results to return per page
PerPage int `url:"per_page,omitempty"`
// specify which resources you want to return as collections instead of references
Includes string
}
func (l *ListOptions) createURL() (url string) {
if l.Includes != "" {
url += fmt.Sprintf("include=%s", l.Includes)
}
if l.Page != 0 {
if url != "" {
url += "&"
}
url += fmt.Sprintf("page=%d", l.Page)
}
if l.PerPage != 0 {
if url != "" {
url += "&"
}
url += fmt.Sprintf("per_page=%d", l.PerPage)
}
return
}
// meta contains pagination information
type meta struct {
Self *Href `json:"self"`
First *Href `json:"first"`
Last *Href `json:"last"`
Previous *Href `json:"previous,omitempty"`
Next *Href `json:"next,omitempty"`
Total int `json:"total"`
CurrentPageNum int `json:"current_page"`
LastPageNum int `json:"last_page"`
}
// Response is the http response from api calls
type Response struct {
*http.Response
Rate
}
// Href is an API link
type Href struct {
Href string `json:"href"`
}
func (r *Response) populateRate() {
// parse the rate limit headers and populate Response.Rate
if limit := r.Header.Get(headerRateLimit); limit != "" {
r.Rate.RequestLimit, _ = strconv.Atoi(limit)
}
if remaining := r.Header.Get(headerRateRemaining); remaining != "" {
r.Rate.RequestsRemaining, _ = strconv.Atoi(remaining)
}
if reset := r.Header.Get(headerRateReset); reset != "" {
if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 {
r.Rate.Reset = Timestamp{time.Unix(v, 0)}
}
}
}
// ErrorResponse is the http response used on errors
type ErrorResponse struct {
Response *http.Response
Errors []string `json:"errors"`
SingleError string `json:"error"`
}
func (r *ErrorResponse) Error() string {
return fmt.Sprintf("%v %v: %d %v %v",
r.Response.Request.Method, r.Response.Request.URL, r.Response.StatusCode, strings.Join(r.Errors, ", "), r.SingleError)
}
// Client is the base API Client
type Client struct {
client *http.Client
debug bool
BaseURL *url.URL
UserAgent string
ConsumerToken string
APIKey string
RateLimit Rate
// Packet Api Objects
Plans PlanService
Users UserService
Emails EmailService
SSHKeys SSHKeyService
Devices DeviceService
Projects ProjectService
Facilities FacilityService
OperatingSystems OSService
DeviceIPs DeviceIPService
DevicePorts DevicePortService
ProjectIPs ProjectIPService
ProjectVirtualNetworks ProjectVirtualNetworkService
Volumes VolumeService
VolumeAttachments VolumeAttachmentService
SpotMarket SpotMarketService
Organizations OrganizationService
}
// NewRequest inits a new http request with the proper headers
func (c *Client) NewRequest(method, path string, body interface{}) (*http.Request, error) {
// relative path to append to the endpoint url, no leading slash please
rel, err := url.Parse(path)
if err != nil {
return nil, err
}
u := c.BaseURL.ResolveReference(rel)
// json encode the request body, if any
buf := new(bytes.Buffer)
if body != nil {
err := json.NewEncoder(buf).Encode(body)
if err != nil {
return nil, err
}
}
req, err := http.NewRequest(method, u.String(), buf)
if err != nil {
return nil, err
}
req.Close = true
req.Header.Add("X-Auth-Token", c.APIKey)
req.Header.Add("X-Consumer-Token", c.ConsumerToken)
req.Header.Add("Content-Type", mediaType)
req.Header.Add("Accept", mediaType)
req.Header.Add("User-Agent", userAgent)
return req, nil
}
// Do executes the http request
func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
response := Response{Response: resp}
response.populateRate()
if c.debug {
o, _ := httputil.DumpResponse(response.Response, true)
log.Printf("\n=======[RESPONSE]============\n%s\n\n", string(o))
}
c.RateLimit = response.Rate
err = checkResponse(resp)
// if the response is an error, return the ErrorResponse
if err != nil {
return &response, err
}
if v != nil {
// if v implements the io.Writer interface, return the raw response
if w, ok := v.(io.Writer); ok {
io.Copy(w, resp.Body)
} else {
err = json.NewDecoder(resp.Body).Decode(v)
if err != nil {
return &response, err
}
}
}
return &response, err
}
// DoRequest is a convenience method, it calls NewRequest followed by Do
// v is the interface to unmarshal the response JSON into
func (c *Client) DoRequest(method, path string, body, v interface{}) (*Response, error) {
req, err := c.NewRequest(method, path, body)
if c.debug {
o, _ := httputil.DumpRequestOut(req, true)
log.Printf("\n=======[REQUEST]=============\n%s\n", string(o))
}
if err != nil {
return nil, err
}
return c.Do(req, v)
}
func NewClient() (*Client, error) {
apiToken := os.Getenv(packetTokenEnvVar)
if apiToken == "" {
return nil, fmt.Errorf("you must export %s.", packetTokenEnvVar)
}
c := NewClientWithAuth("packngo lib", apiToken, nil)
return c, nil
}
// NewClientWithAuth initializes and returns a Client, use this to get an API Client to operate on
// N.B.: Packet's API certificate requires Go 1.5+ to successfully parse. If you are using
// an older version of Go, pass in a custom http.Client with a custom TLS configuration
// that sets "InsecureSkipVerify" to "true"
func NewClientWithAuth(consumerToken string, apiKey string, httpClient *http.Client) *Client {
client, _ := NewClientWithBaseURL(consumerToken, apiKey, httpClient, baseURL)
return client
}
// NewClientWithBaseURL returns a Client pointing to nonstandard API URL, e.g.
// for mocking the remote API
func NewClientWithBaseURL(consumerToken string, apiKey string, httpClient *http.Client, apiBaseURL string) (*Client, error) {
if httpClient == nil {
// Don't fall back on http.DefaultClient as it's not nice to adjust state
// implicitly. If the client wants to use http.DefaultClient, they can
// pass it in explicitly.
httpClient = &http.Client{}
}
u, err := url.Parse(apiBaseURL)
if err != nil {
return nil, err
}
c := &Client{client: httpClient, BaseURL: u, UserAgent: userAgent, ConsumerToken: consumerToken, APIKey: apiKey}
c.debug = os.Getenv(debugEnvVar) != ""
c.Plans = &PlanServiceOp{client: c}
c.Organizations = &OrganizationServiceOp{client: c}
c.Users = &UserServiceOp{client: c}
c.Emails = &EmailServiceOp{client: c}
c.SSHKeys = &SSHKeyServiceOp{client: c}
c.Devices = &DeviceServiceOp{client: c}
c.Projects = &ProjectServiceOp{client: c}
c.Facilities = &FacilityServiceOp{client: c}
c.OperatingSystems = &OSServiceOp{client: c}
c.DeviceIPs = &DeviceIPServiceOp{client: c}
c.DevicePorts = &DevicePortServiceOp{client: c}
c.ProjectVirtualNetworks = &ProjectVirtualNetworkServiceOp{client: c}
c.ProjectIPs = &ProjectIPServiceOp{client: c}
c.Volumes = &VolumeServiceOp{client: c}
c.VolumeAttachments = &VolumeAttachmentServiceOp{client: c}
c.SpotMarket = &SpotMarketServiceOp{client: c}
return c, nil
}
func checkResponse(r *http.Response) error {
// return if http status code is within 200 range
if c := r.StatusCode; c >= 200 && c <= 299 {
// response is good, return
return nil
}
errorResponse := &ErrorResponse{Response: r}
data, err := ioutil.ReadAll(r.Body)
// if the response has a body, populate the message in errorResponse
if err == nil && len(data) > 0 {
json.Unmarshal(data, errorResponse)
}
return errorResponse
}

View File

@ -0,0 +1,72 @@
package packngo
// API documentation https://www.packet.net/developers/api/paymentmethods/
const paymentMethodBasePath = "/payment-methods"
// ProjectService interface defines available project methods
type PaymentMethodService interface {
List() ([]PaymentMethod, *Response, error)
Get(string) (*PaymentMethod, *Response, error)
Create(*PaymentMethodCreateRequest) (*PaymentMethod, *Response, error)
Update(string, *PaymentMethodUpdateRequest) (*PaymentMethod, *Response, error)
Delete(string) (*Response, error)
}
type paymentMethodsRoot struct {
PaymentMethods []PaymentMethod `json:"payment_methods"`
}
// PaymentMethod represents a Packet payment method of an organization
type PaymentMethod struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
Nonce string `json:"nonce,omitempty"`
Default bool `json:"default,omitempty"`
Organization Organization `json:"organization,omitempty"`
Projects []Project `json:"projects,omitempty"`
Type string `json:"type,omitempty"`
CardholderName string `json:"cardholder_name,omitempty"`
ExpMonth string `json:"expiration_month,omitempty"`
ExpYear string `json:"expiration_year,omitempty"`
Last4 string `json:"last_4,omitempty"`
BillingAddress BillingAddress `json:"billing_address,omitempty"`
URL string `json:"href,omitempty"`
}
func (pm PaymentMethod) String() string {
return Stringify(pm)
}
// PaymentMethodCreateRequest type used to create a Packet payment method of an organization
type PaymentMethodCreateRequest struct {
Name string `json:"name"`
Nonce string `json:"name"`
CardholderName string `json:"cardholder_name,omitempty"`
ExpMonth string `json:"expiration_month,omitempty"`
ExpYear string `json:"expiration_year,omitempty"`
BillingAddress string `json:"billing_address,omitempty"`
}
func (pm PaymentMethodCreateRequest) String() string {
return Stringify(pm)
}
// PaymentMethodUpdateRequest type used to update a Packet payment method of an organization
type PaymentMethodUpdateRequest struct {
Name *string `json:"name,omitempty"`
CardholderName *string `json:"cardholder_name,omitempty"`
ExpMonth *string `json:"expiration_month,omitempty"`
ExpYear *string `json:"expiration_year,omitempty"`
BillingAddress *string `json:"billing_address,omitempty"`
}
func (pm PaymentMethodUpdateRequest) String() string {
return Stringify(pm)
}
// PaymentMethodServiceOp implements PaymentMethodService
type PaymentMethodServiceOp struct {
client *Client
}

117
vendor/github.com/packethost/packngo/plans.go generated vendored Normal file
View File

@ -0,0 +1,117 @@
package packngo
const planBasePath = "/plans"
// PlanService interface defines available plan methods
type PlanService interface {
List() ([]Plan, *Response, error)
}
type planRoot struct {
Plans []Plan `json:"plans"`
}
// Plan represents a Packet service plan
type Plan struct {
ID string `json:"id"`
Slug string `json:"slug,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Line string `json:"line,omitempty"`
Specs *Specs `json:"specs,omitempty"`
Pricing *Pricing `json:"pricing,omitempty"`
}
func (p Plan) String() string {
return Stringify(p)
}
// Specs - the server specs for a plan
type Specs struct {
Cpus []*Cpus `json:"cpus,omitempty"`
Memory *Memory `json:"memory,omitempty"`
Drives []*Drives `json:"drives,omitempty"`
Nics []*Nics `json:"nics,omitempty"`
Features *Features `json:"features,omitempty"`
}
func (s Specs) String() string {
return Stringify(s)
}
// Cpus - the CPU config details for specs on a plan
type Cpus struct {
Count int `json:"count,omitempty"`
Type string `json:"type,omitempty"`
}
func (c Cpus) String() string {
return Stringify(c)
}
// Memory - the RAM config details for specs on a plan
type Memory struct {
Total string `json:"total,omitempty"`
}
func (m Memory) String() string {
return Stringify(m)
}
// Drives - the storage config details for specs on a plan
type Drives struct {
Count int `json:"count,omitempty"`
Size string `json:"size,omitempty"`
Type string `json:"type,omitempty"`
}
func (d Drives) String() string {
return Stringify(d)
}
// Nics - the network hardware details for specs on a plan
type Nics struct {
Count int `json:"count,omitempty"`
Type string `json:"type,omitempty"`
}
func (n Nics) String() string {
return Stringify(n)
}
// Features - other features in the specs for a plan
type Features struct {
Raid bool `json:"raid,omitempty"`
Txt bool `json:"txt,omitempty"`
}
func (f Features) String() string {
return Stringify(f)
}
// Pricing - the pricing options on a plan
type Pricing struct {
Hourly float32 `json:"hourly,omitempty"`
Monthly float32 `json:"monthly,omitempty"`
}
func (p Pricing) String() string {
return Stringify(p)
}
// PlanServiceOp implements PlanService
type PlanServiceOp struct {
client *Client
}
// List method returns all available plans
func (s *PlanServiceOp) List() ([]Plan, *Response, error) {
root := new(planRoot)
resp, err := s.client.DoRequest("GET", planBasePath, nil, root)
if err != nil {
return nil, resp, err
}
return root.Plans, resp, err
}

225
vendor/github.com/packethost/packngo/ports.go generated vendored Normal file
View File

@ -0,0 +1,225 @@
package packngo
import (
"fmt"
)
const portBasePath = "/ports"
type NetworkType int
const (
NetworkL3 NetworkType = iota
NetworkHybrid
NetworkL2Bonded
NetworkL2Individual
NetworkUnknown
)
// DevicePortService handles operations on a port which belongs to a particular device
type DevicePortService interface {
Assign(*PortAssignRequest) (*Port, *Response, error)
Unassign(*PortAssignRequest) (*Port, *Response, error)
Bond(*BondRequest) (*Port, *Response, error)
Disbond(*DisbondRequest) (*Port, *Response, error)
PortToLayerTwo(string) (*Port, *Response, error)
PortToLayerThree(string) (*Port, *Response, error)
DeviceToLayerTwo(string) (*Device, error)
DeviceToLayerThree(string) (*Device, error)
DeviceNetworkType(string) (NetworkType, error)
GetBondPort(string) (*Port, error)
GetPortByName(string, string) (*Port, error)
}
type PortData struct {
MAC string `json:"mac"`
Bonded bool `json:"bonded"`
}
type Port struct {
ID string `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Data PortData `json:"data"`
AttachedVirtualNetworks []VirtualNetwork `json:"virtual_networks"`
}
type AddressRequest struct {
AddressFamily int `json:"address_family"`
Public bool `json:"public"`
}
type BackToL3Request struct {
RequestIPs []AddressRequest `json:"request_ips"`
}
type DevicePortServiceOp struct {
client *Client
}
type PortAssignRequest struct {
PortID string `json:"id"`
VirtualNetworkID string `json:"vnid"`
}
type BondRequest struct {
PortID string `json:"id"`
BulkEnable bool `json:"bulk_enable"`
}
type DisbondRequest struct {
PortID string `json:"id"`
BulkDisable bool `json:"bulk_disable"`
}
func (i *DevicePortServiceOp) GetBondPort(deviceID string) (*Port, error) {
device, _, err := i.client.Devices.Get(deviceID)
if err != nil {
return nil, err
}
for _, port := range device.NetworkPorts {
if port.Type == "NetworkBondPort" {
return &port, nil
}
}
return nil, fmt.Errorf("No bonded port found in device %s", deviceID)
}
func (i *DevicePortServiceOp) GetPortByName(deviceID, name string) (*Port, error) {
device, _, err := i.client.Devices.Get(deviceID)
if err != nil {
return nil, err
}
for _, port := range device.NetworkPorts {
if port.Name == name {
return &port, nil
}
}
return nil, fmt.Errorf("Port %s not found in device %s", name, deviceID)
}
func (i *DevicePortServiceOp) Assign(par *PortAssignRequest) (*Port, *Response, error) {
path := fmt.Sprintf("%s/%s/assign", portBasePath, par.PortID)
return i.portAction(path, par)
}
func (i *DevicePortServiceOp) Unassign(par *PortAssignRequest) (*Port, *Response, error) {
path := fmt.Sprintf("%s/%s/unassign", portBasePath, par.PortID)
return i.portAction(path, par)
}
func (i *DevicePortServiceOp) Bond(br *BondRequest) (*Port, *Response, error) {
path := fmt.Sprintf("%s/%s/bond", portBasePath, br.PortID)
return i.portAction(path, br)
}
func (i *DevicePortServiceOp) Disbond(dr *DisbondRequest) (*Port, *Response, error) {
path := fmt.Sprintf("%s/%s/disbond", portBasePath, dr.PortID)
return i.portAction(path, dr)
}
func (i *DevicePortServiceOp) portAction(path string, req interface{}) (*Port, *Response, error) {
port := new(Port)
resp, err := i.client.DoRequest("POST", path, req, port)
if err != nil {
return nil, resp, err
}
return port, resp, err
}
func (i *DevicePortServiceOp) PortToLayerTwo(portID string) (*Port, *Response, error) {
path := fmt.Sprintf("%s/%s/convert/layer-2", portBasePath, portID)
port := new(Port)
resp, err := i.client.DoRequest("POST", path, nil, port)
if err != nil {
return nil, resp, err
}
return port, resp, err
}
func (i *DevicePortServiceOp) PortToLayerThree(portID string) (*Port, *Response, error) {
path := fmt.Sprintf("%s/%s/convert/layer-3", portBasePath, portID)
port := new(Port)
req := BackToL3Request{
RequestIPs: []AddressRequest{
AddressRequest{AddressFamily: 4, Public: true},
AddressRequest{AddressFamily: 4, Public: false},
AddressRequest{AddressFamily: 6, Public: true},
},
}
resp, err := i.client.DoRequest("POST", path, &req, port)
if err != nil {
return nil, resp, err
}
return port, resp, err
}
func (i *DevicePortServiceOp) DeviceNetworkType(deviceID string) (NetworkType, error) {
d, _, err := i.client.Devices.Get(deviceID)
if err != nil {
return NetworkUnknown, err
}
if d.Plan.Slug == "baremetal_0" || d.Plan.Slug == "baremetal_1" {
return NetworkL3, nil
}
if d.Plan.Slug == "baremetal_1e" {
return NetworkHybrid, nil
}
if len(d.NetworkPorts) < 1 {
// really?
return NetworkL2Individual, nil
}
if d.NetworkPorts[0].Data.Bonded {
if d.NetworkPorts[2].Data.Bonded {
for _, ip := range d.Network {
if ip.Management {
return NetworkL3, nil
}
}
return NetworkL2Bonded, nil
} else {
return NetworkHybrid, nil
}
}
return NetworkL2Individual, nil
}
func (i *DevicePortServiceOp) DeviceToLayerThree(deviceID string) (*Device, error) {
// hopefull all the VLANs are unassigned at this point
bond0, err := i.client.DevicePorts.GetBondPort(deviceID)
if err != nil {
return nil, err
}
bond0, _, err = i.client.DevicePorts.PortToLayerThree(bond0.ID)
if err != nil {
return nil, err
}
d, _, err := i.client.Devices.Get(deviceID)
return d, err
}
// DeviceToLayerTwo converts device to L2 networking. Use bond0 to attach VLAN.
func (i *DevicePortServiceOp) DeviceToLayerTwo(deviceID string) (*Device, error) {
bond0, err := i.client.DevicePorts.GetBondPort(deviceID)
if err != nil {
return nil, err
}
bond0, _, err = i.client.DevicePorts.PortToLayerTwo(bond0.ID)
if err != nil {
return nil, err
}
d, _, err := i.client.Devices.Get(deviceID)
return d, err
}

160
vendor/github.com/packethost/packngo/projects.go generated vendored Normal file
View File

@ -0,0 +1,160 @@
package packngo
import (
"fmt"
"strings"
)
const projectBasePath = "/projects"
// ProjectService interface defines available project methods
type ProjectService interface {
List(listOpt *ListOptions) ([]Project, *Response, error)
Get(string) (*Project, *Response, error)
GetExtra(projectID string, includes, excludes []string) (*Project, *Response, error)
Create(*ProjectCreateRequest) (*Project, *Response, error)
Update(string, *ProjectUpdateRequest) (*Project, *Response, error)
Delete(string) (*Response, error)
}
type projectsRoot struct {
Projects []Project `json:"projects"`
Meta meta `json:"meta"`
}
// Project represents a Packet project
type Project struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
Organization Organization `json:"organization,omitempty"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
Users []User `json:"members,omitempty"`
Devices []Device `json:"devices,omitempty"`
SSHKeys []SSHKey `json:"ssh_keys,omitempty"`
URL string `json:"href,omitempty"`
PaymentMethod PaymentMethod `json:"payment_method,omitempty"`
}
func (p Project) String() string {
return Stringify(p)
}
// ProjectCreateRequest type used to create a Packet project
type ProjectCreateRequest struct {
Name string `json:"name"`
PaymentMethodID string `json:"payment_method_id,omitempty"`
OrganizationID string `json:"organization_id,omitempty"`
}
func (p ProjectCreateRequest) String() string {
return Stringify(p)
}
// ProjectUpdateRequest type used to update a Packet project
type ProjectUpdateRequest struct {
Name *string `json:"name,omitempty"`
PaymentMethodID *string `json:"payment_method_id,omitempty"`
}
func (p ProjectUpdateRequest) String() string {
return Stringify(p)
}
// ProjectServiceOp implements ProjectService
type ProjectServiceOp struct {
client *Client
}
// List returns the user's projects
func (s *ProjectServiceOp) List(listOpt *ListOptions) (projects []Project, resp *Response, err error) {
var params string
if listOpt != nil {
params = listOpt.createURL()
}
root := new(projectsRoot)
path := fmt.Sprintf("%s?%s", projectBasePath, params)
for {
resp, err = s.client.DoRequest("GET", path, nil, root)
if err != nil {
return nil, resp, err
}
projects = append(projects, root.Projects...)
if root.Meta.Next != nil && (listOpt == nil || listOpt.Page == 0) {
path = root.Meta.Next.Href
if params != "" {
path = fmt.Sprintf("%s&%s", path, params)
}
continue
}
return
}
}
// GetExtra returns a project by id with extra information
func (s *ProjectServiceOp) GetExtra(projectID string, includes, excludes []string) (*Project, *Response, error) {
path := fmt.Sprintf("%s/%s", projectBasePath, projectID)
if includes != nil {
path += fmt.Sprintf("?include=%s", strings.Join(includes, ","))
} else if excludes != nil {
path += fmt.Sprintf("?exclude=%s", strings.Join(excludes, ","))
}
project := new(Project)
resp, err := s.client.DoRequest("GET", path, nil, project)
if err != nil {
return nil, resp, err
}
return project, resp, err
}
// Get returns a project by id
func (s *ProjectServiceOp) Get(projectID string) (*Project, *Response, error) {
path := fmt.Sprintf("%s/%s", projectBasePath, projectID)
project := new(Project)
resp, err := s.client.DoRequest("GET", path, nil, project)
if err != nil {
return nil, resp, err
}
return project, resp, err
}
// Create creates a new project
func (s *ProjectServiceOp) Create(createRequest *ProjectCreateRequest) (*Project, *Response, error) {
project := new(Project)
resp, err := s.client.DoRequest("POST", projectBasePath, createRequest, project)
if err != nil {
return nil, resp, err
}
return project, resp, err
}
// Update updates a project
func (s *ProjectServiceOp) Update(id string, updateRequest *ProjectUpdateRequest) (*Project, *Response, error) {
path := fmt.Sprintf("%s/%s", projectBasePath, id)
project := new(Project)
resp, err := s.client.DoRequest("PATCH", path, updateRequest, project)
if err != nil {
return nil, resp, err
}
return project, resp, err
}
// Delete deletes a project
func (s *ProjectServiceOp) Delete(projectID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", projectBasePath, projectID)
return s.client.DoRequest("DELETE", path, nil, nil)
}

12
vendor/github.com/packethost/packngo/rate.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
package packngo
// Rate provides the API request rate limit details
type Rate struct {
RequestLimit int `json:"request_limit"`
RequestsRemaining int `json:"requests_remaining"`
Reset Timestamp `json:"rate_reset"`
}
func (r Rate) String() string {
return Stringify(r)
}

39
vendor/github.com/packethost/packngo/spotmarket.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
package packngo
const spotMarketBasePath = "/market/spot/prices"
// SpotMarketService expooses Spot Market methods
type SpotMarketService interface {
Prices() (PriceMap, *Response, error)
}
// SpotMarketServiceOp implements SpotMarketService
type SpotMarketServiceOp struct {
client *Client
}
// PriceMap is a map of [facility][plan]-> float Price
type PriceMap map[string]map[string]float64
// Prices gets current PriceMap from the API
func (s *SpotMarketServiceOp) Prices() (PriceMap, *Response, error) {
root := new(struct {
SMPs map[string]map[string]struct {
Price float64 `json:"price"`
} `json:"spot_market_prices"`
})
resp, err := s.client.DoRequest("GET", spotMarketBasePath, nil, root)
if err != nil {
return nil, resp, err
}
prices := make(PriceMap)
for facility, planMap := range root.SMPs {
prices[facility] = map[string]float64{}
for plan, v := range planMap {
prices[facility][plan] = v.Price
}
}
return prices, resp, err
}

138
vendor/github.com/packethost/packngo/sshkeys.go generated vendored Normal file
View File

@ -0,0 +1,138 @@
package packngo
import "fmt"
const (
sshKeyBasePath = "/ssh-keys"
)
// SSHKeyService interface defines available device methods
type SSHKeyService interface {
List() ([]SSHKey, *Response, error)
ProjectList(string) ([]SSHKey, *Response, error)
Get(string) (*SSHKey, *Response, error)
Create(*SSHKeyCreateRequest) (*SSHKey, *Response, error)
Update(string, *SSHKeyUpdateRequest) (*SSHKey, *Response, error)
Delete(string) (*Response, error)
}
type sshKeyRoot struct {
SSHKeys []SSHKey `json:"ssh_keys"`
}
// SSHKey represents a user's ssh key
type SSHKey struct {
ID string `json:"id"`
Label string `json:"label"`
Key string `json:"key"`
FingerPrint string `json:"fingerprint"`
Created string `json:"created_at"`
Updated string `json:"updated_at"`
User User `json:"user,omitempty"`
URL string `json:"href,omitempty"`
}
func (s SSHKey) String() string {
return Stringify(s)
}
// SSHKeyCreateRequest type used to create an ssh key
type SSHKeyCreateRequest struct {
Label string `json:"label"`
Key string `json:"key"`
ProjectID string `json:"-"`
}
func (s SSHKeyCreateRequest) String() string {
return Stringify(s)
}
// SSHKeyUpdateRequest type used to update an ssh key
type SSHKeyUpdateRequest struct {
Label *string `json:"label,omitempty"`
Key *string `json:"key,omitempty"`
}
func (s SSHKeyUpdateRequest) String() string {
return Stringify(s)
}
// SSHKeyServiceOp implements SSHKeyService
type SSHKeyServiceOp struct {
client *Client
}
func (s *SSHKeyServiceOp) list(url string) ([]SSHKey, *Response, error) {
root := new(sshKeyRoot)
resp, err := s.client.DoRequest("GET", url, nil, root)
if err != nil {
return nil, resp, err
}
return root.SSHKeys, resp, err
}
// ProjectList lists ssh keys of a project
func (s *SSHKeyServiceOp) ProjectList(projectID string) ([]SSHKey, *Response, error) {
return s.list(fmt.Sprintf("%s/%s%s", projectBasePath, projectID, sshKeyBasePath))
}
// List returns a user's ssh keys
func (s *SSHKeyServiceOp) List() ([]SSHKey, *Response, error) {
return s.list(sshKeyBasePath)
}
// Get returns an ssh key by id
func (s *SSHKeyServiceOp) Get(sshKeyID string) (*SSHKey, *Response, error) {
path := fmt.Sprintf("%s/%s", sshKeyBasePath, sshKeyID)
sshKey := new(SSHKey)
resp, err := s.client.DoRequest("GET", path, nil, sshKey)
if err != nil {
return nil, resp, err
}
return sshKey, resp, err
}
// Create creates a new ssh key
func (s *SSHKeyServiceOp) Create(createRequest *SSHKeyCreateRequest) (*SSHKey, *Response, error) {
path := sshKeyBasePath
if createRequest.ProjectID != "" {
path = fmt.Sprintf("%s/%s%s", projectBasePath, createRequest.ProjectID, sshKeyBasePath)
}
sshKey := new(SSHKey)
resp, err := s.client.DoRequest("POST", path, createRequest, sshKey)
if err != nil {
return nil, resp, err
}
return sshKey, resp, err
}
// Update updates an ssh key
func (s *SSHKeyServiceOp) Update(id string, updateRequest *SSHKeyUpdateRequest) (*SSHKey, *Response, error) {
if updateRequest.Label == nil && updateRequest.Key == nil {
return nil, nil, fmt.Errorf("You must set either Label or Key string for SSH Key update")
}
path := fmt.Sprintf("%s/%s", sshKeyBasePath, id)
sshKey := new(SSHKey)
resp, err := s.client.DoRequest("PATCH", path, updateRequest, sshKey)
if err != nil {
return nil, resp, err
}
return sshKey, resp, err
}
// Delete deletes an ssh key
func (s *SSHKeyServiceOp) Delete(sshKeyID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", sshKeyBasePath, sshKeyID)
return s.client.DoRequest("DELETE", path, nil, nil)
}

35
vendor/github.com/packethost/packngo/timestamp.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
package packngo
import (
"strconv"
"time"
)
// Timestamp represents a time that can be unmarshalled from a JSON string
// formatted as either an RFC3339 or Unix timestamp. All
// exported methods of time.Time can be called on Timestamp.
type Timestamp struct {
time.Time
}
func (t Timestamp) String() string {
return t.Time.String()
}
// UnmarshalJSON implements the json.Unmarshaler interface.
// Time is expected in RFC3339 or Unix format.
func (t *Timestamp) UnmarshalJSON(data []byte) (err error) {
str := string(data)
i, err := strconv.ParseInt(str, 10, 64)
if err == nil {
t.Time = time.Unix(i, 0)
} else {
t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str)
}
return
}
// Equal reports whether t and u are equal based on time.Equal
func (t Timestamp) Equal(u Timestamp) bool {
return t.Time.Equal(u.Time)
}

64
vendor/github.com/packethost/packngo/user.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
package packngo
const userBasePath = "/users"
const userPath = "/user"
// UserService interface defines available user methods
type UserService interface {
Get(string) (*User, *Response, error)
Current() (*User, *Response, error)
}
// User represents a Packet user
type User struct {
ID string `json:"id"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
FullName string `json:"full_name,omitempty"`
Email string `json:"email,omitempty"`
TwoFactor string `json:"two_factor_auth,omitempty"`
DefaultOrganizationID string `json:"default_organization_id,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
Facebook string `json:"twitter,omitempty"`
Twitter string `json:"facebook,omitempty"`
LinkedIn string `json:"linkedin,omitempty"`
Created string `json:"created_at,omitempty"`
Updated string `json:"updated_at,omitempty"`
TimeZone string `json:"timezone,omitempty"`
Emails []Email `json:"emails,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
URL string `json:"href,omitempty"`
}
func (u User) String() string {
return Stringify(u)
}
// UserServiceOp implements UserService
type UserServiceOp struct {
client *Client
}
// Get method gets a user by userID
func (s *UserServiceOp) Get(userID string) (*User, *Response, error) {
user := new(User)
resp, err := s.client.DoRequest("GET", userBasePath, nil, user)
if err != nil {
return nil, resp, err
}
return user, resp, err
}
// Returns the user object for the currently logged-in user.
func (s *UserServiceOp) Current() (*User, *Response, error) {
user := new(User)
resp, err := s.client.DoRequest("GET", userPath, nil, user)
if err != nil {
return nil, resp, err
}
return user, resp, err
}

91
vendor/github.com/packethost/packngo/utils.go generated vendored Normal file
View File

@ -0,0 +1,91 @@
package packngo
import (
"bytes"
"fmt"
"io"
"reflect"
)
var timestampType = reflect.TypeOf(Timestamp{})
// Stringify creates a string representation of the provided message
func Stringify(message interface{}) string {
var buf bytes.Buffer
v := reflect.ValueOf(message)
stringifyValue(&buf, v)
return buf.String()
}
// StreamToString converts a reader to a string
func StreamToString(stream io.Reader) string {
buf := new(bytes.Buffer)
buf.ReadFrom(stream)
return buf.String()
}
// stringifyValue was graciously cargoculted from the goprotubuf library
func stringifyValue(w io.Writer, val reflect.Value) {
if val.Kind() == reflect.Ptr && val.IsNil() {
w.Write([]byte("<nil>"))
return
}
v := reflect.Indirect(val)
switch v.Kind() {
case reflect.String:
fmt.Fprintf(w, `"%s"`, v)
case reflect.Slice:
w.Write([]byte{'['})
for i := 0; i < v.Len(); i++ {
if i > 0 {
w.Write([]byte{' '})
}
stringifyValue(w, v.Index(i))
}
w.Write([]byte{']'})
return
case reflect.Struct:
if v.Type().Name() != "" {
w.Write([]byte(v.Type().String()))
}
// special handling of Timestamp values
if v.Type() == timestampType {
fmt.Fprintf(w, "{%s}", v.Interface())
return
}
w.Write([]byte{'{'})
var sep bool
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
if fv.Kind() == reflect.Ptr && fv.IsNil() {
continue
}
if fv.Kind() == reflect.Slice && fv.IsNil() {
continue
}
if sep {
w.Write([]byte(", "))
} else {
sep = true
}
w.Write([]byte(v.Type().Field(i).Name))
w.Write([]byte{':'})
stringifyValue(w, fv)
}
w.Write([]byte{'}'})
default:
if v.CanInterface() {
fmt.Fprint(w, v.Interface())
}
}
}

View File

@ -0,0 +1,81 @@
package packngo
import (
"fmt"
)
const virtualNetworkBasePath = "/virtual-networks"
// DevicePortService handles operations on a port which belongs to a particular device
type ProjectVirtualNetworkService interface {
List(projectID string) (*VirtualNetworkListResponse, *Response, error)
Create(*VirtualNetworkCreateRequest) (*VirtualNetwork, *Response, error)
Delete(virtualNetworkID string) (*Response, error)
}
type VirtualNetwork struct {
ID string `json:"id"`
Description string `json:"description,omitempty"`
VXLAN int `json:"vxlan,omitempty"`
FacilityCode string `json:"facility_code,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
Href string `json:"href"`
}
type ProjectVirtualNetworkServiceOp struct {
client *Client
}
type VirtualNetworkListResponse struct {
VirtualNetworks []VirtualNetwork `json:"virtual_networks"`
}
func (i *ProjectVirtualNetworkServiceOp) List(projectID string) (*VirtualNetworkListResponse, *Response, error) {
path := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, virtualNetworkBasePath)
output := new(VirtualNetworkListResponse)
resp, err := i.client.DoRequest("GET", path, nil, output)
if err != nil {
return nil, nil, err
}
return output, resp, nil
}
type VirtualNetworkCreateRequest struct {
ProjectID string `json:"project_id"`
Description string `json:"description"`
Facility string `json:"facility"`
VXLAN int `json:"vxlan"`
VLAN int `json:"vlan"`
}
type VirtualNetworkCreateResponse struct {
VirtualNetwork VirtualNetwork `json:"virtual_networks"`
}
func (i *ProjectVirtualNetworkServiceOp) Create(input *VirtualNetworkCreateRequest) (*VirtualNetwork, *Response, error) {
// TODO: May need to add timestamp to output from 'post' request
// for the 'created_at' attribute of VirtualNetwork struct since
// API response doesn't include it
path := fmt.Sprintf("%s/%s%s", projectBasePath, input.ProjectID, virtualNetworkBasePath)
output := new(VirtualNetwork)
resp, err := i.client.DoRequest("POST", path, input, output)
if err != nil {
return nil, nil, err
}
return output, resp, nil
}
func (i *ProjectVirtualNetworkServiceOp) Delete(virtualNetworkID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", virtualNetworkBasePath, virtualNetworkID)
resp, err := i.client.DoRequest("DELETE", path, nil, nil)
if err != nil {
return nil, err
}
return resp, nil
}

239
vendor/github.com/packethost/packngo/volumes.go generated vendored Normal file
View File

@ -0,0 +1,239 @@
package packngo
import "fmt"
const (
volumeBasePath = "/storage"
attachmentsBasePath = "/attachments"
)
// VolumeService interface defines available Volume methods
type VolumeService interface {
List(string, *ListOptions) ([]Volume, *Response, error)
Get(string) (*Volume, *Response, error)
Update(string, *VolumeUpdateRequest) (*Volume, *Response, error)
Delete(string) (*Response, error)
Create(*VolumeCreateRequest, string) (*Volume, *Response, error)
Lock(string) (*Response, error)
Unlock(string) (*Response, error)
}
// VolumeAttachmentService defines attachment methdods
type VolumeAttachmentService interface {
Get(string) (*VolumeAttachment, *Response, error)
Create(string, string) (*VolumeAttachment, *Response, error)
Delete(string) (*Response, error)
}
type volumesRoot struct {
Volumes []Volume `json:"volumes"`
Meta meta `json:"meta"`
}
// Volume represents a volume
type Volume struct {
Attachments []*VolumeAttachment `json:"attachments,omitempty"`
BillingCycle string `json:"billing_cycle,omitempty"`
Created string `json:"created_at,omitempty"`
Description string `json:"description,omitempty"`
Facility *Facility `json:"facility,omitempty"`
Href string `json:"href,omitempty"`
ID string `json:"id"`
Locked bool `json:"locked,omitempty"`
Name string `json:"name,omitempty"`
Plan *Plan `json:"plan,omitempty"`
Project *Project `json:"project,omitempty"`
Size int `json:"size,omitempty"`
SnapshotPolicies []*SnapshotPolicy `json:"snapshot_policies,omitempty"`
State string `json:"state,omitempty"`
Updated string `json:"updated_at,omitempty"`
}
// SnapshotPolicy used to execute actions on volume
type SnapshotPolicy struct {
ID string `json:"id"`
Href string `json:"href"`
SnapshotFrequency string `json:"snapshot_frequency,omitempty"`
SnapshotCount int `json:"snapshot_count,omitempty"`
}
func (v Volume) String() string {
return Stringify(v)
}
// VolumeCreateRequest type used to create a Packet volume
type VolumeCreateRequest struct {
BillingCycle string `json:"billing_cycle"`
Description string `json:"description,omitempty"`
Locked bool `json:"locked,omitempty"`
Size int `json:"size"`
PlanID string `json:"plan_id"`
FacilityID string `json:"facility_id"`
SnapshotPolicies []*SnapshotPolicy `json:"snapshot_policies,omitempty"`
}
func (v VolumeCreateRequest) String() string {
return Stringify(v)
}
// VolumeUpdateRequest type used to update a Packet volume
type VolumeUpdateRequest struct {
Description *string `json:"description,omitempty"`
PlanID *string `json:"plan_id,omitempty"`
Size *int `json:"size,omitempty"`
BillingCycle *string `json:"billing_cycle,omitempty"`
}
// VolumeAttachment is a type from Packet API
type VolumeAttachment struct {
Href string `json:"href"`
ID string `json:"id"`
Volume Volume `json:"volume"`
Device Device `json:"device"`
}
func (v VolumeUpdateRequest) String() string {
return Stringify(v)
}
// VolumeAttachmentServiceOp implements VolumeService
type VolumeAttachmentServiceOp struct {
client *Client
}
// VolumeServiceOp implements VolumeService
type VolumeServiceOp struct {
client *Client
}
// List returns the volumes for a project
func (v *VolumeServiceOp) List(projectID string, listOpt *ListOptions) (volumes []Volume, resp *Response, err error) {
url := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, volumeBasePath)
var params string
if listOpt != nil {
params = listOpt.createURL()
if params != "" {
url = fmt.Sprintf("%s?%s", url, params)
}
}
for {
subset := new(volumesRoot)
resp, err = v.client.DoRequest("GET", url, nil, subset)
if err != nil {
return nil, resp, err
}
volumes = append(volumes, subset.Volumes...)
if subset.Meta.Next != nil && (listOpt == nil || listOpt.Page == 0) {
url = subset.Meta.Next.Href
if params != "" {
url = fmt.Sprintf("%s&%s", url, params)
}
continue
}
return
}
}
// Get returns a volume by id
func (v *VolumeServiceOp) Get(volumeID string) (*Volume, *Response, error) {
path := fmt.Sprintf("%s/%s?include=facility,snapshot_policies,attachments.device", volumeBasePath, volumeID)
volume := new(Volume)
resp, err := v.client.DoRequest("GET", path, nil, volume)
if err != nil {
return nil, resp, err
}
return volume, resp, err
}
// Update updates a volume
func (v *VolumeServiceOp) Update(id string, updateRequest *VolumeUpdateRequest) (*Volume, *Response, error) {
path := fmt.Sprintf("%s/%s", volumeBasePath, id)
volume := new(Volume)
resp, err := v.client.DoRequest("PATCH", path, updateRequest, volume)
if err != nil {
return nil, resp, err
}
return volume, resp, err
}
// Delete deletes a volume
func (v *VolumeServiceOp) Delete(volumeID string) (*Response, error) {
path := fmt.Sprintf("%s/%s", volumeBasePath, volumeID)
return v.client.DoRequest("DELETE", path, nil, nil)
}
// Create creates a new volume for a project
func (v *VolumeServiceOp) Create(createRequest *VolumeCreateRequest, projectID string) (*Volume, *Response, error) {
url := fmt.Sprintf("%s/%s%s", projectBasePath, projectID, volumeBasePath)
volume := new(Volume)
resp, err := v.client.DoRequest("POST", url, createRequest, volume)
if err != nil {
return nil, resp, err
}
return volume, resp, err
}
// Attachments
// Create Attachment, i.e. attach volume to a device
func (v *VolumeAttachmentServiceOp) Create(volumeID, deviceID string) (*VolumeAttachment, *Response, error) {
url := fmt.Sprintf("%s/%s%s", volumeBasePath, volumeID, attachmentsBasePath)
volAttachParam := map[string]string{
"device_id": deviceID,
}
volumeAttachment := new(VolumeAttachment)
resp, err := v.client.DoRequest("POST", url, volAttachParam, volumeAttachment)
if err != nil {
return nil, resp, err
}
return volumeAttachment, resp, nil
}
// Get gets attachment by id
func (v *VolumeAttachmentServiceOp) Get(attachmentID string) (*VolumeAttachment, *Response, error) {
path := fmt.Sprintf("%s%s/%s", volumeBasePath, attachmentsBasePath, attachmentID)
volumeAttachment := new(VolumeAttachment)
resp, err := v.client.DoRequest("GET", path, nil, volumeAttachment)
if err != nil {
return nil, resp, err
}
return volumeAttachment, resp, nil
}
// Delete deletes attachment by id
func (v *VolumeAttachmentServiceOp) Delete(attachmentID string) (*Response, error) {
path := fmt.Sprintf("%s%s/%s", volumeBasePath, attachmentsBasePath, attachmentID)
return v.client.DoRequest("DELETE", path, nil, nil)
}
// Lock sets a volume to "locked"
func (s *VolumeServiceOp) Lock(id string) (*Response, error) {
path := fmt.Sprintf("%s/%s", volumeBasePath, id)
action := lockType{Locked: true}
return s.client.DoRequest("PATCH", path, action, nil)
}
// Unlock sets a volume to "unlocked"
func (s *VolumeServiceOp) Unlock(id string) (*Response, error) {
path := fmt.Sprintf("%s/%s", volumeBasePath, id)
action := lockType{Locked: false}
return s.client.DoRequest("PATCH", path, action, nil)
}

317
vendor/github.com/vmware/govmomi/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,317 @@
# changelog
### unreleased
* SetRootCAs on the soap.Client returns an error for invalid certificates
### 0.18.0 (2018-05-24)
* Add VirtualDiskManager wrapper to set UUID
* Add vmxnet2, pcnet32 and sriov to VirtualDeviceList.EthernetCardTypes
* Add new vSphere 6.7 APIs
* Decrease LoginExtensionByCertificate tunnel usage
* SAML token authentication support via SessionManager.LoginByToken
* New SSO admin client for managing users
* New STS client for issuing and renewing SAML tokens
* New Lookup Service client for discovering endpoints such as STS and ssoadmin
* Switch from gvt to go dep for managing dependencies
### 0.17.1 (2018-03-19)
* vcsim: add Destroy method for Folder and Datacenter types
* In progress.Reader emit final report on EOF.
* vcsim: add EventManager.QueryEvents
### 0.17.0 (2018-02-28)
* Add HostStorageSystem.AttachScsiLun method
* Avoid possible panic in Datastore.Stat (#969)
* Destroy event history collectors (#962)
* Add VirtualDiskManager.CreateChildDisk method
### 0.16.0 (2017-11-08)
* Add support for SOAP request operation ID header
* Moved ovf helpers from govc import.ovf command to ovf and nfc packages
* Added guest/toolbox (client) package
* Added toolbox package and toolbox command
* Added simulator package and vcsim command
### 0.15.0 (2017-06-19)
* WaitOptions.MaxWaitSeconds is now optional
* Support removal of ExtraConfig entries
* GuestPosixFileAttributes OwnerId and GroupId fields are now pointers,
rather than omitempty ints to allow chown with root uid:gid
* Updated examples/ using view package
* Add DatastoreFile.TailFunc method
* Export VirtualMachine.FindSnapshot method
* Add AuthorizationManager {Enable,Disable}Methods
* Add PBM client
### 0.14.0 (2017-04-08)
* Add view.ContainerView type and methods
* Add Collector.RetrieveWithFilter method
* Add property.Filter type
* Implement EthernetCardBackingInfo for OpaqueNetwork
* Finder: support changing object root in find mode
* Add VirtualDiskManager.QueryVirtualDiskInfo
* Add performance.Manager APIs
### 0.13.0 (2017-03-02)
* Add DatastoreFileManager API wrapper
* Add HostVsanInternalSystem API wrappers
* Add Container support to view package
* Finder supports Folder recursion without specifying a path
* Add VirtualMachine.QueryConfigTarget method
* Add device option to VirtualMachine.WaitForNetIP
* Remove _Task suffix from vapp methods
### 0.12.1 (2016-12-19)
* Add DiagnosticLog helper
* Add DatastorePath helper
### 0.12.0 (2016-12-01)
* Disable use of service ticket for datastore HTTP access by default
* Attach context to HTTP requests for cancellations
* Update to vim25/6.5 API
### 0.11.4 (2016-11-15)
* Add object.AuthorizationManager methods: RetrieveRolePermissions, RetrieveAllPermissions, AddRole, RemoveRole, UpdateRole
### 0.11.3 (2016-11-08)
* Allow DatastoreFile.Follow reader to drain current body after stopping
### 0.11.2 (2016-11-01)
* Avoid possible NPE in VirtualMachine.Device method
* Add support for OpaqueNetwork type to Finder
* Add HostConfigManager.AccountManager support for ESX 5.5
### 0.11.1 (2016-10-27)
* Add Finder.ResourcePoolListAll method
### 0.11.0 (2016-10-25)
* Add object.DistributedVirtualPortgroup.Reconfigure method
### 0.10.0 (2016-10-20)
* Add option to set soap.Client.UserAgent
* Add service ticket thumbprint validation
* Update use of http.DefaultTransport fields to 1.7
* Set default locale to en_US (override with GOVMOMI_LOCALE env var)
* Add object.HostCertificateInfo (types.HostCertificateManagerCertificateInfo helpers)
* Add object.HostCertificateManager type and HostConfigManager.CertificateManager method
* Add soap.Client SetRootCAs and SetDialTLS methods
### 0.9.0 (2016-09-09)
* Add object.DatastoreFile helpers for streaming and tailing datastore files
* Add object VirtualMachine.Unregister method
* Add object.ListView methods: Add, Remove, Reset
* Update to Go 1.7 - using stdlib's context package
### 0.8.0 (2016-06-30)
* Add session.Manager.AcquireLocalTicket
* Include StoragePod in Finder.FolderList
* Add Finder methods for finding by ManagedObjectReference: Element, ObjectReference
* Add mo.ManagedObjectReference methods: Reference, String, FromString
* Add support using SessionManagerGenericServiceTicket.HostName for Datastore HTTP access
### 0.7.1 (2016-06-03)
* Fix object.ObjectName method
### 0.7.0 (2016-06-02)
* Move InventoryPath field to object.Common
* Add HostDatastoreSystem.CreateLocalDatastore method
* Add DatastoreNamespaceManager methods: CreateDirectory, DeleteDirectory
* Add HostServiceSystem
* Add HostStorageSystem methods: MarkAsSdd, MarkAsNonSdd, MarkAsLocal, MarkAsNonLocal
* Add HostStorageSystem.RescanAllHba method
### 0.6.2 (2016-05-11)
* Get complete file details in Datastore.Stat
* SOAP decoding fixes
* Add VirtualMachine.RemoveAllSnapshot
### 0.6.1 (2016-04-30)
* Fix mo.Entity interface
### 0.6.0 (2016-04-29)
* Add Common.Rename method
* Add mo.Entity interface
* Add OptionManager
* Add Finder.FolderList method
* Add VirtualMachine.WaitForNetIP method
* Add VirtualMachine.RevertToSnapshot method
* Add Datastore.Download method
### 0.5.0 (2016-03-30)
Generated fields using xsd type 'int' change to Go type 'int32'
VirtualDevice.UnitNumber field changed to pointer type
### 0.4.0 (2016-02-26)
* Add method to convert virtual device list to array with virtual device
changes that can be used in the VirtualMachineConfigSpec.
* Make datastore cluster traversable in lister
* Add finder.DatastoreCluster methods (also known as storage pods)
* Add Drone CI check
* Add object.Datastore Type and AttachedClusterHosts methods
* Add finder.*OrDefault methods
### 0.3.0 (2016-01-16)
* Add object.VirtualNicManager wrapper
* Add object.HostVsanSystem wrapper
* Add object.HostSystem methods: EnterMaintenanceMode, ExitMaintenanceMode, Disconnect, Reconnect
* Add finder.Folder method
* Add object.Common.Destroy method
* Add object.ComputeResource.Reconfigure method
* Add license.AssignmentManager wrapper
* Add object.HostFirewallSystem wrapper
* Add object.DiagnosticManager wrapper
* Add LoginExtensionByCertificate support
* Add object.ExtensionManager
...
### 0.2.0 (2015-09-15)
* Update to vim25/6.0 API
* Stop returning children from `ManagedObjectList`
Change the `ManagedObjectList` function in the `find` package to only
return the managed objects specified by the path argument and not their
children. The original behavior was used by govc's `ls` command and is
now available in the newly added function `ManagedObjectListChildren`.
* Add retry functionality to vim25 package
* Change finder functions to no longer take varargs
The `find` package had functions to return a list of objects, given a
variable number of patterns. This makes it impossible to distinguish which
patterns produced results and which ones didn't.
In particular for govc, where multiple arguments can be passed from the
command line, it is useful to let the user know which ones produce results
and which ones don't.
To evaluate multiple patterns, the user should call the find functions
multiple times (either serially or in parallel).
* Make optional boolean fields pointers (`vim25/types`).
False is the zero value of a boolean field, which means they are not serialized
if the field is marked "omitempty". If the field is a pointer instead, the zero
value will be the nil pointer, and both true and false values are serialized.
### 0.1.0 (2015-03-17)
Prior to this version the API of this library was in flux.
Notable changes w.r.t. the state of this library before March 2015 are:
* All functions that may execute a request take a `context.Context` parameter.
* The `vim25` package contains a minimal client implementation.
* The property collector and its convenience functions live in the `property` package.

101
vendor/github.com/vmware/govmomi/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,101 @@
# Contributing to govmomi
## Getting started
First, fork the repository on GitHub to your personal account.
Note that _GOPATH_ can be any directory, the example below uses _$HOME/govmomi_.
Change _$USER_ below to your github username if they are not the same.
``` shell
export GOPATH=$HOME/govmomi
go get github.com/vmware/govmomi
cd $GOPATH/src/github.com/vmware/govmomi
git config push.default nothing # anything to avoid pushing to vmware/govmomi by default
git remote rename origin vmware
git remote add $USER git@github.com:$USER/govmomi.git
git fetch $USER
```
## Installing from source
Compile the govmomi libraries and install govc using:
``` shell
go install -v github.com/vmware/govmomi/govc
```
Note that **govc/build.sh** is only used for building release binaries.
## Contribution flow
This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where you want to base your work.
- Make commits of logical units.
- Make sure your commit messages are in the proper format (see below).
- Update CHANGELOG.md and/or govc/CHANGELOG.md when appropriate.
- Push your changes to a topic branch in your fork of the repository.
- Submit a pull request to vmware/govmomi.
Example:
``` shell
git checkout -b my-new-feature vmware/master
git commit -a
git push $USER my-new-feature
```
### Stay in sync with upstream
When your branch gets out of sync with the vmware/master branch, use the following to update:
``` shell
git checkout my-new-feature
git fetch -a
git rebase vmware/master
git push --force-with-lease $USER my-new-feature
```
### Updating pull requests
If your PR fails to pass CI or needs changes based on code review, you'll most likely want to squash these changes into
existing commits.
If your pull request contains a single commit or your changes are related to the most recent commit, you can simply
amend the commit.
``` shell
git add .
git commit --amend
git push --force-with-lease $USER my-new-feature
```
If you need to squash changes into an earlier commit, you can use:
``` shell
git add .
git commit --fixup <commit>
git rebase -i --autosquash vmware/master
git push --force-with-lease $USER my-new-feature
```
Be sure to add a comment to the PR indicating your new changes are ready to review, as github does not generate a
notification when you git push.
### Code style
The coding style suggested by the Golang community is used in govmomi. See the
[style doc](https://github.com/golang/go/wiki/CodeReviewComments) for details.
Try to limit column width to 120 characters for both code and markdown documents such as this one.
### Format of the Commit Message
We follow the conventions on [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/).
Be sure to include any related GitHub issue references in the commit message.
## Reporting Bugs and Creating Issues
When opening a new issue, try to roughly follow the commit message format conventions above.

83
vendor/github.com/vmware/govmomi/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,83 @@
# People who can (and typically have) contributed to this repository.
#
# This script is generated by contributors.sh
#
Abhijeet Kasurde <akasurde@redhat.com>
abrarshivani <abrarshivani@users.noreply.github.com>
Adam Shannon <adamkshannon@gmail.com>
akutz <sakutz@gmail.com>
Alessandro Cortiana <alessandro.cortiana@gmail.com>
Alex Bozhenko <alexbozhenko@fb.com>
Alvaro Miranda <kikitux@gmail.com>
amandahla <amanda.andrade@serpro.gov.br>
Amanda H. L. de Andrade <amanda.andrade@serpro.gov.br>
Amit Bathla <abathla@.vmware.com>
amit bezalel <amit.bezalel@hpe.com>
Andrew Chin <andrew@andrewtchin.com>
Anfernee Yongkun Gui <agui@vmware.com>
aniketGslab <aniket.shinde@gslab.com>
Arran Walker <arran.walker@zopa.com>
Aryeh Weinreb <aryehweinreb@gmail.com>
Austin Parker <aparker@apprenda.com>
Balu Dontu <bdontu@vmware.com>
bastienbc <bastien.barbe.creuly@gmail.com>
Bob Killen <killen.bob@gmail.com>
Brad Fitzpatrick <bradfitz@golang.org>
Bruce Downs <bruceadowns@gmail.com>
Cédric Blomart <cblomart@gmail.com>
Chris Marchesi <chrism@vancluevertech.com>
Christian Höltje <docwhat@gerf.org>
Clint Greenwood <cgreenwood@vmware.com>
Danny Lockard <danny.lockard@banno.com>
Dave Tucker <dave@dtucker.co.uk>
Davide Agnello <dagnello@hp.com>
David Stark <dave@davidstark.name>
Deric Crago <deric.crago@gmail.com>
Doug MacEachern <dougm@vmware.com>
Eloy Coto <eloy.coto@gmail.com>
Eric Gray <egray@vmware.com>
Eric Yutao <eric.yutao@gmail.com>
Erik Hollensbe <github@hollensbe.org>
Fabio Rapposelli <fabio@vmware.com>
Faiyaz Ahmed <ahmedf@vmware.com>
forkbomber <forkbomber@users.noreply.github.com>
Gavin Gray <gavin@infinio.com>
Gavrie Philipson <gavrie.philipson@elastifile.com>
George Hicken <ghicken@vmware.com>
Gerrit Renker <Gerrit.Renker@ctl.io>
gthombare <gthombare@vmware.com>
Hasan Mahmood <mahmoodh@vmware.com>
Henrik Hodne <henrik@travis-ci.com>
Isaac Rodman <isaac@eyz.us>
Ivan Porto Carrero <icarrero@vmware.com>
Jason Kincl <jkincl@gmail.com>
Jeremy Canady <jcanady@jackhenry.com>
jeremy-clerc <jeremy@clerc.io>
João Pereira <joaodrp@gmail.com>
Jorge Sevilla <jorge.sevilla@rstor.io>
leslie-qiwa <leslie.qiwa@gmail.com>
Louie Jiang <jiangl@vmware.com>
Marc Carmier <mcarmier@gmail.com>
Matthew Cosgrove <matthew.cosgrove@dell.com>
Mevan Samaratunga <mevansam@gmail.com>
Nicolas Lamirault <nicolas.lamirault@gmail.com>
Omar Kohl <omarkohl@gmail.com>
Parham Alvani <parham.alvani@gmail.com>
Pieter Noordhuis <pnoordhuis@vmware.com>
runner.mei <runner.mei@gmail.com>
S.Çağlar Onur <conur@vmware.com>
Sergey Ignatov <sergey.ignatov@jetbrains.com>
Steve Purcell <steve@sanityinc.com>
Takaaki Furukawa <takaaki.frkw@gmail.com>
tanishi <tanishi503@gmail.com>
Ted Zlatanov <tzz@lifelogs.com>
Thibaut Ackermann <thibaut.ackermann@alcatel-lucent.com>
Trevor Dawe <trevor.dawe@gmail.com>
Vadim Egorov <vegorov@vmware.com>
Volodymyr Bobyr <pupsua@gmail.com>
Witold Krecicki <wpk@culm.net>
Yang Yang <yangy@vmware.com>
Yuya Kusakabe <yuya.kusakabe@gmail.com>
Zach Tucker <ztucker@vmware.com>
Zee Yang <zeey@vmware.com>

4
vendor/github.com/vmware/govmomi/Dockerfile generated vendored Normal file
View File

@ -0,0 +1,4 @@
FROM scratch
LABEL maintainer="fabio@vmware.com"
COPY govc /
ENTRYPOINT [ "/govc" ]

44
vendor/github.com/vmware/govmomi/Gopkg.lock generated vendored Normal file
View File

@ -0,0 +1,44 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "improvements"
name = "github.com/davecgh/go-xdr"
packages = ["xdr2"]
revision = "4930550ba2e22f87187498acfd78348b15f4e7a8"
source = "https://github.com/rasky/go-xdr"
[[projects]]
name = "github.com/google/uuid"
packages = ["."]
revision = "6a5e28554805e78ea6141142aba763936c4761c0"
[[projects]]
branch = "govmomi"
name = "github.com/kr/pretty"
packages = ["."]
revision = "2ee9d7453c02ef7fa518a83ae23644eb8872186a"
source = "https://github.com/dougm/pretty"
[[projects]]
branch = "master"
name = "github.com/kr/text"
packages = ["."]
revision = "7cafcd837844e784b526369c9bce262804aebc60"
[[projects]]
branch = "master"
name = "github.com/vmware/vmw-guestinfo"
packages = [
"bdoor",
"message",
"vmcheck"
]
revision = "25eff159a728be87e103a0b8045e08273f4dbec4"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "376638fa6c0621cbd980caf8fc53494d880886f100663da8de47ecb6e596e439"
solver-name = "gps-cdcl"
solver-version = 1

19
vendor/github.com/vmware/govmomi/Gopkg.toml generated vendored Normal file
View File

@ -0,0 +1,19 @@
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# Refer to https://github.com/toml-lang/toml for detailed TOML docs.
[prune]
non-go = true
go-tests = true
unused-packages = true
[[constraint]]
branch = "improvements"
name = "github.com/davecgh/go-xdr"
source = "https://github.com/rasky/go-xdr"
[[constraint]]
branch = "govmomi"
name = "github.com/kr/pretty"
source = "https://github.com/dougm/pretty"

202
vendor/github.com/vmware/govmomi/LICENSE.txt generated vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

29
vendor/github.com/vmware/govmomi/Makefile generated vendored Normal file
View File

@ -0,0 +1,29 @@
.PHONY: test
all: check test
check: goimports govet
goimports:
@echo checking go imports...
@go get golang.org/x/tools/cmd/goimports
@! goimports -d . 2>&1 | egrep -v '^$$'
govet:
@echo checking go vet...
@go tool vet -structtags=false -methods=false $$(find . -mindepth 1 -maxdepth 1 -type d -not -name vendor)
install:
go install -v github.com/vmware/govmomi/govc
go install -v github.com/vmware/govmomi/vcsim
go-test:
go test -race -v $(TEST_OPTS) ./...
govc-test: install
(cd govc/test && ./vendor/github.com/sstephenson/bats/libexec/bats -t .)
test: go-test govc-test
doc: install
./govc/usage.sh > ./govc/USAGE.md

86
vendor/github.com/vmware/govmomi/README.md generated vendored Normal file
View File

@ -0,0 +1,86 @@
[![Build Status](https://travis-ci.org/vmware/govmomi.png?branch=master)](https://travis-ci.org/vmware/govmomi)
[![Go Report Card](https://goreportcard.com/badge/github.com/vmware/govmomi)](https://goreportcard.com/report/github.com/vmware/govmomi)
# govmomi
A Go library for interacting with VMware vSphere APIs (ESXi and/or vCenter).
In addition to the vSphere API client, this repository includes:
* [govc](./govc) - vSphere CLI
* [vcsim](./vcsim) - vSphere API mock framework
* [toolbox](./toolbox) - VM guest tools framework
## Compatibility
This library is built for and tested against ESXi and vCenter 6.0, 6.5 and 6.7.
It may work with versions 5.5 and 5.1, but neither are officially supported.
## Documentation
The APIs exposed by this library very closely follow the API described in the [VMware vSphere API Reference Documentation][apiref].
Refer to this document to become familiar with the upstream API.
The code in the `govmomi` package is a wrapper for the code that is generated from the vSphere API description.
It primarily provides convenience functions for working with the vSphere API.
See [godoc.org][godoc] for documentation.
[apiref]:http://pubs.vmware.com/vsphere-6-5/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
[godoc]:http://godoc.org/github.com/vmware/govmomi
## Installation
```sh
go get -u github.com/vmware/govmomi
```
## Discussion
Contributors and users are encouraged to collaborate using GitHub issues and/or
[Slack](https://vmwarecode.slack.com/messages/govmomi).
Access to Slack requires a [VMware {code} membership](https://code.vmware.com/join/).
## Status
Changes to the API are subject to [semantic versioning](http://semver.org).
Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
## Projects using govmomi
* [Docker Machine](https://github.com/docker/machine/tree/master/drivers/vmwarevsphere)
* [Docker InfraKit](https://github.com/docker/infrakit/tree/master/pkg/provider/vsphere)
* [Docker LinuxKit](https://github.com/linuxkit/linuxkit/tree/master/src/cmd/linuxkit)
* [Kubernetes](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/vsphere)
* [Kubernetes kops](https://github.com/kubernetes/kops/tree/master/upup/pkg/fi/cloudup/vsphere)
* [Terraform](https://github.com/terraform-providers/terraform-provider-vsphere)
* [Packer](https://github.com/jetbrains-infra/packer-builder-vsphere)
* [VMware VIC Engine](https://github.com/vmware/vic)
* [Travis CI](https://github.com/travis-ci/jupiter-brain)
* [collectd-vsphere](https://github.com/travis-ci/collectd-vsphere)
* [Gru](https://github.com/dnaeon/gru)
* [Libretto](https://github.com/apcera/libretto/tree/master/virtualmachine/vsphere)
## Related projects
* [rbvmomi](https://github.com/vmware/rbvmomi)
* [pyvmomi](https://github.com/vmware/pyvmomi)
## License
govmomi is available under the [Apache 2 license](LICENSE).

136
vendor/github.com/vmware/govmomi/client.go generated vendored Normal file
View File

@ -0,0 +1,136 @@
/*
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This package is the root package of the govmomi library.
The library is structured as follows:
Package vim25
The minimal usable functionality is available through the vim25 package.
It contains subpackages that contain generated types, managed objects, and all
available methods. The vim25 package is entirely independent of the other
packages in the govmomi tree -- it has no dependencies on its peers.
The vim25 package itself contains a client structure that is
passed around throughout the entire library. It abstracts a session and its
immutable state. See the vim25 package for more information.
Package session
The session package contains an abstraction for the session manager that allows
a user to login and logout. It also provides access to the current session
(i.e. to determine if the user is in fact logged in)
Package object
The object package contains wrappers for a selection of managed objects. The
constructors of these objects all take a *vim25.Client, which they pass along
to derived objects, if applicable.
Package govc
The govc package contains the govc CLI. The code in this tree is not intended
to be used as a library. Any functionality that govc contains that _could_ be
used as a library function but isn't, _should_ live in a root level package.
Other packages
Other packages, such as "event", "guest", or "license", provide wrappers for
the respective subsystems. They are typically not needed in normal workflows so
are kept outside the object package.
*/
package govmomi
import (
"context"
"net/url"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Client struct {
*vim25.Client
SessionManager *session.Manager
}
// NewClient creates a new client from a URL. The client authenticates with the
// server with username/password before returning if the URL contains user information.
func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error) {
soapClient := soap.NewClient(u, insecure)
vimClient, err := vim25.NewClient(ctx, soapClient)
if err != nil {
return nil, err
}
c := &Client{
Client: vimClient,
SessionManager: session.NewManager(vimClient),
}
// Only login if the URL contains user information.
if u.User != nil {
err = c.Login(ctx, u.User)
if err != nil {
return nil, err
}
}
return c, nil
}
// Login dispatches to the SessionManager.
func (c *Client) Login(ctx context.Context, u *url.Userinfo) error {
return c.SessionManager.Login(ctx, u)
}
// Logout dispatches to the SessionManager.
func (c *Client) Logout(ctx context.Context) error {
// Close any idle connections after logging out.
defer c.Client.CloseIdleConnections()
return c.SessionManager.Logout(ctx)
}
// PropertyCollector returns the session's default property collector.
func (c *Client) PropertyCollector() *property.Collector {
return property.DefaultCollector(c.Client)
}
// RetrieveOne dispatches to the Retrieve function on the default property collector.
func (c *Client) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, p []string, dst interface{}) error {
return c.PropertyCollector().RetrieveOne(ctx, obj, p, dst)
}
// Retrieve dispatches to the Retrieve function on the default property collector.
func (c *Client) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, p []string, dst interface{}) error {
return c.PropertyCollector().Retrieve(ctx, objs, p, dst)
}
// Wait dispatches to property.Wait.
func (c *Client) Wait(ctx context.Context, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error {
return property.Wait(ctx, c.PropertyCollector(), obj, ps, f)
}
// IsVC returns true if we are connected to a vCenter
func (c *Client) IsVC() bool {
return c.Client.IsVC()
}

37
vendor/github.com/vmware/govmomi/find/doc.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package find implements inventory listing and searching.
The Finder is an alternative to the object.SearchIndex FindByInventoryPath() and FindChild() methods.
SearchIndex.FindByInventoryPath requires an absolute path, whereas the Finder also supports relative paths
and patterns via path.Match.
SearchIndex.FindChild requires a parent to find the child, whereas the Finder also supports an ancestor via
recursive object traversal.
The various Finder methods accept a "path" argument, which can absolute or relative to the Folder for the object type.
The Finder supports two modes, "list" and "find". The "list" mode behaves like the "ls" command, only searching within
the immediate path. The "find" mode behaves like the "find" command, with the search starting at the immediate path but
also recursing into sub Folders relative to the Datacenter. The default mode is "list" if the given path contains a "/",
otherwise "find" mode is used.
The exception is to use a "..." wildcard with a path to find all objects recursively underneath any root object.
For example: VirtualMachineList("/DC1/...")
See also: https://github.com/vmware/govmomi/blob/master/govc/README.md#usage
*/
package find

64
vendor/github.com/vmware/govmomi/find/error.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package find
import "fmt"
type NotFoundError struct {
kind string
path string
}
func (e *NotFoundError) Error() string {
return fmt.Sprintf("%s '%s' not found", e.kind, e.path)
}
type MultipleFoundError struct {
kind string
path string
}
func (e *MultipleFoundError) Error() string {
return fmt.Sprintf("path '%s' resolves to multiple %ss", e.path, e.kind)
}
type DefaultNotFoundError struct {
kind string
}
func (e *DefaultNotFoundError) Error() string {
return fmt.Sprintf("no default %s found", e.kind)
}
type DefaultMultipleFoundError struct {
kind string
}
func (e DefaultMultipleFoundError) Error() string {
return fmt.Sprintf("default %s resolves to multiple instances, please specify", e.kind)
}
func toDefaultError(err error) error {
switch e := err.(type) {
case *NotFoundError:
return &DefaultNotFoundError{e.kind}
case *MultipleFoundError:
return &DefaultMultipleFoundError{e.kind}
default:
return err
}
}

1042
vendor/github.com/vmware/govmomi/find/finder.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

253
vendor/github.com/vmware/govmomi/find/recurser.go generated vendored Normal file
View File

@ -0,0 +1,253 @@
/*
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package find
import (
"context"
"os"
"path"
"strings"
"github.com/vmware/govmomi/list"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
)
// spec is used to specify per-search configuration, independent of the Finder instance.
type spec struct {
// Relative returns the root object to resolve Relative paths (starts with ".")
Relative func(ctx context.Context) (object.Reference, error)
// ListMode can be used to optionally force "ls" behavior, rather than "find" behavior
ListMode *bool
// Contents configures the Recurser to list the Contents of traversable leaf nodes.
// This is typically set to true when used from the ls command, where listing
// a folder means listing its Contents. This is typically set to false for
// commands that take managed entities that are not folders as input.
Contents bool
// Parents specifies the types which can contain the child types being searched for.
// for example, when searching for a HostSystem, parent types can be
// "ComputeResource" or "ClusterComputeResource".
Parents []string
// Include specifies which types to be included in the results, used only in "find" mode.
Include []string
// Nested should be set to types that can be Nested, used only in "find" mode.
Nested []string
// ChildType avoids traversing into folders that can't contain the Include types, used only in "find" mode.
ChildType []string
}
func (s *spec) traversable(o mo.Reference) bool {
ref := o.Reference()
switch ref.Type {
case "Datacenter":
if len(s.Include) == 1 && s.Include[0] == "Datacenter" {
// No point in traversing deeper as Datacenters cannot be nested
return false
}
return true
case "Folder":
if f, ok := o.(mo.Folder); ok {
// TODO: Not making use of this yet, but here we can optimize when searching the entire
// inventory across Datacenters for specific types, for example: 'govc ls -t VirtualMachine /**'
// should not traverse into a Datacenter's host, network or datatore folders.
if !s.traversableChildType(f.ChildType) {
return false
}
}
return true
}
for _, kind := range s.Parents {
if kind == ref.Type {
return true
}
}
return false
}
func (s *spec) traversableChildType(ctypes []string) bool {
if len(s.ChildType) == 0 {
return true
}
for _, t := range ctypes {
for _, c := range s.ChildType {
if t == c {
return true
}
}
}
return false
}
func (s *spec) wanted(e list.Element) bool {
if len(s.Include) == 0 {
return true
}
w := e.Object.Reference().Type
for _, kind := range s.Include {
if w == kind {
return true
}
}
return false
}
// listMode is a global option to revert to the original Finder behavior,
// disabling the newer "find" mode.
var listMode = os.Getenv("GOVMOMI_FINDER_LIST_MODE") == "true"
func (s *spec) listMode(isPath bool) bool {
if listMode {
return true
}
if s.ListMode != nil {
return *s.ListMode
}
return isPath
}
type recurser struct {
Collector *property.Collector
// All configures the recurses to fetch complete objects for leaf nodes.
All bool
}
func (r recurser) List(ctx context.Context, s *spec, root list.Element, parts []string) ([]list.Element, error) {
if len(parts) == 0 {
// Include non-traversable leaf elements in result. For example, consider
// the pattern "./vm/my-vm-*", where the pattern should match the VMs and
// not try to traverse them.
//
// Include traversable leaf elements in result, if the contents
// field is set to false.
//
if !s.Contents || !s.traversable(root.Object.Reference()) {
return []list.Element{root}, nil
}
}
k := list.Lister{
Collector: r.Collector,
Reference: root.Object.Reference(),
Prefix: root.Path,
}
if r.All && len(parts) < 2 {
k.All = true
}
in, err := k.List(ctx)
if err != nil {
return nil, err
}
// This folder is a leaf as far as the glob goes.
if len(parts) == 0 {
return in, nil
}
all := parts
pattern := parts[0]
parts = parts[1:]
var out []list.Element
for _, e := range in {
matched, err := path.Match(pattern, path.Base(e.Path))
if err != nil {
return nil, err
}
if !matched {
matched = strings.HasSuffix(e.Path, "/"+path.Join(all...))
if matched {
// name contains a '/'
out = append(out, e)
}
continue
}
nres, err := r.List(ctx, s, e, parts)
if err != nil {
return nil, err
}
out = append(out, nres...)
}
return out, nil
}
func (r recurser) Find(ctx context.Context, s *spec, root list.Element, parts []string) ([]list.Element, error) {
var out []list.Element
if len(parts) > 0 {
pattern := parts[0]
matched, err := path.Match(pattern, path.Base(root.Path))
if err != nil {
return nil, err
}
if matched && s.wanted(root) {
out = append(out, root)
}
}
if !s.traversable(root.Object) {
return out, nil
}
k := list.Lister{
Collector: r.Collector,
Reference: root.Object.Reference(),
Prefix: root.Path,
}
in, err := k.List(ctx)
if err != nil {
return nil, err
}
for _, e := range in {
nres, err := r.Find(ctx, s, e, parts)
if err != nil {
return nil, err
}
out = append(out, nres...)
}
return out, nil
}

563
vendor/github.com/vmware/govmomi/list/lister.go generated vendored Normal file
View File

@ -0,0 +1,563 @@
/*
Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package list
import (
"context"
"fmt"
"path"
"reflect"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Element struct {
Path string
Object mo.Reference
}
func (e Element) String() string {
return fmt.Sprintf("%s @ %s", e.Object.Reference(), e.Path)
}
func ToElement(r mo.Reference, prefix string) Element {
var name string
// Comments about types to be expected in folders copied from the
// documentation of the Folder managed object:
// http://pubs.vmware.com/vsphere-55/topic/com.vmware.wssdk.apiref.doc/vim.Folder.html
switch m := r.(type) {
case mo.Folder:
name = m.Name
case mo.StoragePod:
name = m.Name
// { "vim.Datacenter" } - Identifies the root folder and its descendant
// folders. Data center folders can contain child data center folders and
// Datacenter managed objects. Datacenter objects contain virtual machine,
// compute resource, network entity, and datastore folders.
case mo.Datacenter:
name = m.Name
// { "vim.Virtualmachine", "vim.VirtualApp" } - Identifies a virtual machine
// folder. A virtual machine folder may contain child virtual machine
// folders. It also can contain VirtualMachine managed objects, templates,
// and VirtualApp managed objects.
case mo.VirtualMachine:
name = m.Name
case mo.VirtualApp:
name = m.Name
// { "vim.ComputeResource" } - Identifies a compute resource
// folder, which contains child compute resource folders and ComputeResource
// hierarchies.
case mo.ComputeResource:
name = m.Name
case mo.ClusterComputeResource:
name = m.Name
case mo.HostSystem:
name = m.Name
case mo.ResourcePool:
name = m.Name
// { "vim.Network" } - Identifies a network entity folder.
// Network entity folders on a vCenter Server can contain Network,
// DistributedVirtualSwitch, and DistributedVirtualPortgroup managed objects.
// Network entity folders on an ESXi host can contain only Network objects.
case mo.Network:
name = m.Name
case mo.OpaqueNetwork:
name = m.Name
case mo.DistributedVirtualSwitch:
name = m.Name
case mo.DistributedVirtualPortgroup:
name = m.Name
case mo.VmwareDistributedVirtualSwitch:
name = m.Name
// { "vim.Datastore" } - Identifies a datastore folder. Datastore folders can
// contain child datastore folders and Datastore managed objects.
case mo.Datastore:
name = m.Name
default:
panic("not implemented for type " + reflect.TypeOf(r).String())
}
e := Element{
Path: path.Join(prefix, name),
Object: r,
}
return e
}
type Lister struct {
Collector *property.Collector
Reference types.ManagedObjectReference
Prefix string
All bool
}
func (l Lister) retrieveProperties(ctx context.Context, req types.RetrieveProperties, dst *[]interface{}) error {
res, err := l.Collector.RetrieveProperties(ctx, req)
if err != nil {
return err
}
// Instead of using mo.LoadRetrievePropertiesResponse, use a custom loop to
// iterate over the results and ignore entries that have properties that
// could not be retrieved (a non-empty `missingSet` property). Since the
// returned objects are enumerated by vSphere in the first place, any object
// that has a non-empty `missingSet` property is indicative of a race
// condition in vSphere where the object was enumerated initially, but was
// removed before its properties could be collected.
for _, p := range res.Returnval {
v, err := mo.ObjectContentToType(p)
if err != nil {
// Ignore fault if it is ManagedObjectNotFound
if soap.IsVimFault(err) {
switch soap.ToVimFault(err).(type) {
case *types.ManagedObjectNotFound:
continue
}
}
return err
}
*dst = append(*dst, v)
}
return nil
}
func (l Lister) List(ctx context.Context) ([]Element, error) {
switch l.Reference.Type {
case "Folder", "StoragePod":
return l.ListFolder(ctx)
case "Datacenter":
return l.ListDatacenter(ctx)
case "ComputeResource", "ClusterComputeResource":
// Treat ComputeResource and ClusterComputeResource as one and the same.
// It doesn't matter from the perspective of the lister.
return l.ListComputeResource(ctx)
case "ResourcePool":
return l.ListResourcePool(ctx)
case "HostSystem":
return l.ListHostSystem(ctx)
case "VirtualApp":
return l.ListVirtualApp(ctx)
default:
return nil, fmt.Errorf("cannot traverse type " + l.Reference.Type)
}
}
func (l Lister) ListFolder(ctx context.Context) ([]Element, error) {
spec := types.PropertyFilterSpec{
ObjectSet: []types.ObjectSpec{
{
Obj: l.Reference,
SelectSet: []types.BaseSelectionSpec{
&types.TraversalSpec{
Path: "childEntity",
Skip: types.NewBool(false),
Type: "Folder",
},
},
Skip: types.NewBool(true),
},
},
}
// Retrieve all objects that we can deal with
childTypes := []string{
"Folder",
"Datacenter",
"VirtualApp",
"VirtualMachine",
"Network",
"ComputeResource",
"ClusterComputeResource",
"Datastore",
"DistributedVirtualSwitch",
}
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
// Additional basic properties.
switch t {
case "Folder":
pspec.PathSet = append(pspec.PathSet, "childType")
case "ComputeResource", "ClusterComputeResource":
// The ComputeResource and ClusterComputeResource are dereferenced in
// the ResourcePoolFlag. Make sure they always have their resourcePool
// field populated.
pspec.PathSet = append(pspec.PathSet, "resourcePool")
}
}
spec.PropSet = append(spec.PropSet, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{spec},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListDatacenter(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
// Include every datastore folder in the select set
fields := []string{
"vmFolder",
"hostFolder",
"datastoreFolder",
"networkFolder",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "Datacenter",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
pspec := types.PropertySpec{
Type: "Folder",
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name", "childType"}
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: []types.PropertySpec{pspec},
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListComputeResource(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"host",
"resourcePool",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "ComputeResource",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"HostSystem",
"ResourcePool",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListResourcePool(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"resourcePool",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "ResourcePool",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"ResourcePool",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListHostSystem(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"datastore",
"network",
"vm",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "HostSystem",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"Datastore",
"Network",
"VirtualMachine",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}
func (l Lister) ListVirtualApp(ctx context.Context) ([]Element, error) {
ospec := types.ObjectSpec{
Obj: l.Reference,
Skip: types.NewBool(true),
}
fields := []string{
"resourcePool",
"vm",
}
for _, f := range fields {
tspec := types.TraversalSpec{
Path: f,
Skip: types.NewBool(false),
Type: "VirtualApp",
}
ospec.SelectSet = append(ospec.SelectSet, &tspec)
}
childTypes := []string{
"ResourcePool",
"VirtualMachine",
}
var pspecs []types.PropertySpec
for _, t := range childTypes {
pspec := types.PropertySpec{
Type: t,
}
if l.All {
pspec.All = types.NewBool(true)
} else {
pspec.PathSet = []string{"name"}
}
pspecs = append(pspecs, pspec)
}
req := types.RetrieveProperties{
SpecSet: []types.PropertyFilterSpec{
{
ObjectSet: []types.ObjectSpec{ospec},
PropSet: pspecs,
},
},
}
var dst []interface{}
err := l.retrieveProperties(ctx, req, &dst)
if err != nil {
return nil, err
}
es := []Element{}
for _, v := range dst {
es = append(es, ToElement(v.(mo.Reference), l.Prefix))
}
return es, nil
}

44
vendor/github.com/vmware/govmomi/list/path.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package list
import (
"path"
"strings"
)
func ToParts(p string) []string {
p = path.Clean(p)
if p == "/" {
return []string{}
}
if len(p) > 0 {
// Prefix ./ if relative
if p[0] != '/' && p[0] != '.' {
p = "./" + p
}
}
ps := strings.Split(p, "/")
if ps[0] == "" {
// Start at root
ps = ps[1:]
}
return ps
}

238
vendor/github.com/vmware/govmomi/nfc/lease.go generated vendored Normal file
View File

@ -0,0 +1,238 @@
/*
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package nfc
import (
"context"
"errors"
"fmt"
"io"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type Lease struct {
types.ManagedObjectReference
c *vim25.Client
}
func NewLease(c *vim25.Client, ref types.ManagedObjectReference) *Lease {
return &Lease{ref, c}
}
// Abort wraps methods.Abort
func (l *Lease) Abort(ctx context.Context, fault *types.LocalizedMethodFault) error {
req := types.HttpNfcLeaseAbort{
This: l.Reference(),
Fault: fault,
}
_, err := methods.HttpNfcLeaseAbort(ctx, l.c, &req)
if err != nil {
return err
}
return nil
}
// Complete wraps methods.Complete
func (l *Lease) Complete(ctx context.Context) error {
req := types.HttpNfcLeaseComplete{
This: l.Reference(),
}
_, err := methods.HttpNfcLeaseComplete(ctx, l.c, &req)
if err != nil {
return err
}
return nil
}
// GetManifest wraps methods.GetManifest
func (l *Lease) GetManifest(ctx context.Context) error {
req := types.HttpNfcLeaseGetManifest{
This: l.Reference(),
}
_, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req)
if err != nil {
return err
}
return nil
}
// Progress wraps methods.Progress
func (l *Lease) Progress(ctx context.Context, percent int32) error {
req := types.HttpNfcLeaseProgress{
This: l.Reference(),
Percent: percent,
}
_, err := methods.HttpNfcLeaseProgress(ctx, l.c, &req)
if err != nil {
return err
}
return nil
}
type LeaseInfo struct {
types.HttpNfcLeaseInfo
Items []FileItem
}
func (l *Lease) newLeaseInfo(li *types.HttpNfcLeaseInfo, items []types.OvfFileItem) (*LeaseInfo, error) {
info := &LeaseInfo{
HttpNfcLeaseInfo: *li,
}
for _, device := range li.DeviceUrl {
u, err := l.c.ParseURL(device.Url)
if err != nil {
return nil, err
}
if device.SslThumbprint != "" {
// TODO: prefer host management IP
l.c.SetThumbprint(u.Host, device.SslThumbprint)
}
if len(items) == 0 {
// this is an export
item := types.OvfFileItem{
DeviceId: device.Key,
Path: device.TargetId,
Size: device.FileSize,
}
if item.Size == 0 {
item.Size = li.TotalDiskCapacityInKB * 1024
}
if item.Path == "" {
item.Path = path.Base(device.Url)
}
info.Items = append(info.Items, NewFileItem(u, item))
continue
}
// this is an import
for _, item := range items {
if device.ImportKey == item.DeviceId {
info.Items = append(info.Items, NewFileItem(u, item))
break
}
}
}
return info, nil
}
func (l *Lease) Wait(ctx context.Context, items []types.OvfFileItem) (*LeaseInfo, error) {
var lease mo.HttpNfcLease
pc := property.DefaultCollector(l.c)
err := property.Wait(ctx, pc, l.Reference(), []string{"state", "info", "error"}, func(pc []types.PropertyChange) bool {
done := false
for _, c := range pc {
if c.Val == nil {
continue
}
switch c.Name {
case "error":
val := c.Val.(types.LocalizedMethodFault)
lease.Error = &val
done = true
case "info":
val := c.Val.(types.HttpNfcLeaseInfo)
lease.Info = &val
case "state":
lease.State = c.Val.(types.HttpNfcLeaseState)
if lease.State != types.HttpNfcLeaseStateInitializing {
done = true
}
}
}
return done
})
if err != nil {
return nil, err
}
if lease.State == types.HttpNfcLeaseStateReady {
return l.newLeaseInfo(lease.Info, items)
}
if lease.Error != nil {
return nil, errors.New(lease.Error.LocalizedMessage)
}
return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State)
}
func (l *Lease) StartUpdater(ctx context.Context, info *LeaseInfo) *LeaseUpdater {
return newLeaseUpdater(ctx, l, info)
}
func (l *Lease) Upload(ctx context.Context, item FileItem, f io.Reader, opts soap.Upload) error {
if opts.Progress == nil {
opts.Progress = item
} else {
opts.Progress = progress.Tee(item, opts.Progress)
}
// Non-disk files (such as .iso) use the PUT method.
// Overwrite: t header is also required in this case (ovftool does the same)
if item.Create {
opts.Method = "PUT"
opts.Headers = map[string]string{
"Overwrite": "t",
}
} else {
opts.Method = "POST"
opts.Type = "application/x-vnd.vmware-streamVmdk"
}
return l.c.Upload(ctx, f, item.URL, &opts)
}
func (l *Lease) DownloadFile(ctx context.Context, file string, item FileItem, opts soap.Download) error {
if opts.Progress == nil {
opts.Progress = item
} else {
opts.Progress = progress.Tee(item, opts.Progress)
}
return l.c.DownloadFile(ctx, file, item.URL, &opts)
}

146
vendor/github.com/vmware/govmomi/nfc/lease_updater.go generated vendored Normal file
View File

@ -0,0 +1,146 @@
/*
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package nfc
import (
"context"
"log"
"net/url"
"sync"
"sync/atomic"
"time"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/types"
)
type FileItem struct {
types.OvfFileItem
URL *url.URL
ch chan progress.Report
}
func NewFileItem(u *url.URL, item types.OvfFileItem) FileItem {
return FileItem{
OvfFileItem: item,
URL: u,
ch: make(chan progress.Report),
}
}
func (o FileItem) Sink() chan<- progress.Report {
return o.ch
}
// File converts the FileItem.OvfFileItem to an OvfFile
func (o FileItem) File() types.OvfFile {
return types.OvfFile{
DeviceId: o.DeviceId,
Path: o.Path,
Size: o.Size,
}
}
type LeaseUpdater struct {
lease *Lease
pos int64 // Number of bytes
total int64 // Total number of bytes
done chan struct{} // When lease updater should stop
wg sync.WaitGroup // Track when update loop is done
}
func newLeaseUpdater(ctx context.Context, lease *Lease, info *LeaseInfo) *LeaseUpdater {
l := LeaseUpdater{
lease: lease,
done: make(chan struct{}),
}
for _, item := range info.Items {
l.total += item.Size
go l.waitForProgress(item)
}
// Kickstart update loop
l.wg.Add(1)
go l.run()
return &l
}
func (l *LeaseUpdater) waitForProgress(item FileItem) {
var pos, total int64
total = item.Size
for {
select {
case <-l.done:
return
case p, ok := <-item.ch:
// Return in case of error
if ok && p.Error() != nil {
return
}
if !ok {
// Last element on the channel, add to total
atomic.AddInt64(&l.pos, total-pos)
return
}
// Approximate progress in number of bytes
x := int64(float32(total) * (p.Percentage() / 100.0))
atomic.AddInt64(&l.pos, x-pos)
pos = x
}
}
}
func (l *LeaseUpdater) run() {
defer l.wg.Done()
tick := time.NewTicker(2 * time.Second)
defer tick.Stop()
for {
select {
case <-l.done:
return
case <-tick.C:
// From the vim api HttpNfcLeaseProgress(percent) doc, percent ==
// "Completion status represented as an integer in the 0-100 range."
// Always report the current value of percent, as it will renew the
// lease even if the value hasn't changed or is 0.
percent := int32(float32(100*atomic.LoadInt64(&l.pos)) / float32(l.total))
err := l.lease.Progress(context.TODO(), percent)
if err != nil {
log.Printf("NFC lease progress: %s", err)
return
}
}
}
}
func (l *LeaseUpdater) Done() {
close(l.done)
l.wg.Wait()
}

View File

@ -0,0 +1,174 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type AuthorizationManager struct {
Common
}
func NewAuthorizationManager(c *vim25.Client) *AuthorizationManager {
m := AuthorizationManager{
Common: NewCommon(c, *c.ServiceContent.AuthorizationManager),
}
return &m
}
type AuthorizationRoleList []types.AuthorizationRole
func (l AuthorizationRoleList) ById(id int32) *types.AuthorizationRole {
for _, role := range l {
if role.RoleId == id {
return &role
}
}
return nil
}
func (l AuthorizationRoleList) ByName(name string) *types.AuthorizationRole {
for _, role := range l {
if role.Name == name {
return &role
}
}
return nil
}
func (m AuthorizationManager) RoleList(ctx context.Context) (AuthorizationRoleList, error) {
var am mo.AuthorizationManager
err := m.Properties(ctx, m.Reference(), []string{"roleList"}, &am)
if err != nil {
return nil, err
}
return AuthorizationRoleList(am.RoleList), nil
}
func (m AuthorizationManager) RetrieveEntityPermissions(ctx context.Context, entity types.ManagedObjectReference, inherited bool) ([]types.Permission, error) {
req := types.RetrieveEntityPermissions{
This: m.Reference(),
Entity: entity,
Inherited: inherited,
}
res, err := methods.RetrieveEntityPermissions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) RemoveEntityPermission(ctx context.Context, entity types.ManagedObjectReference, user string, isGroup bool) error {
req := types.RemoveEntityPermission{
This: m.Reference(),
Entity: entity,
User: user,
IsGroup: isGroup,
}
_, err := methods.RemoveEntityPermission(ctx, m.Client(), &req)
return err
}
func (m AuthorizationManager) SetEntityPermissions(ctx context.Context, entity types.ManagedObjectReference, permission []types.Permission) error {
req := types.SetEntityPermissions{
This: m.Reference(),
Entity: entity,
Permission: permission,
}
_, err := methods.SetEntityPermissions(ctx, m.Client(), &req)
return err
}
func (m AuthorizationManager) RetrieveRolePermissions(ctx context.Context, id int32) ([]types.Permission, error) {
req := types.RetrieveRolePermissions{
This: m.Reference(),
RoleId: id,
}
res, err := methods.RetrieveRolePermissions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) RetrieveAllPermissions(ctx context.Context) ([]types.Permission, error) {
req := types.RetrieveAllPermissions{
This: m.Reference(),
}
res, err := methods.RetrieveAllPermissions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) AddRole(ctx context.Context, name string, ids []string) (int32, error) {
req := types.AddAuthorizationRole{
This: m.Reference(),
Name: name,
PrivIds: ids,
}
res, err := methods.AddAuthorizationRole(ctx, m.Client(), &req)
if err != nil {
return -1, err
}
return res.Returnval, nil
}
func (m AuthorizationManager) RemoveRole(ctx context.Context, id int32, failIfUsed bool) error {
req := types.RemoveAuthorizationRole{
This: m.Reference(),
RoleId: id,
FailIfUsed: failIfUsed,
}
_, err := methods.RemoveAuthorizationRole(ctx, m.Client(), &req)
return err
}
func (m AuthorizationManager) UpdateRole(ctx context.Context, id int32, name string, ids []string) error {
req := types.UpdateAuthorizationRole{
This: m.Reference(),
RoleId: id,
NewName: name,
PrivIds: ids,
}
_, err := methods.UpdateAuthorizationRole(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,86 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
type DisabledMethodRequest struct {
Method string `xml:"method"`
Reason string `xml:"reasonId"`
}
type disableMethodsRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Entity []types.ManagedObjectReference `xml:"entity"`
Method []DisabledMethodRequest `xml:"method"`
Source string `xml:"sourceId"`
Scope bool `xml:"sessionScope,omitempty"`
}
type disableMethodsBody struct {
Req *disableMethodsRequest `xml:"urn:internalvim25 DisableMethods,omitempty"`
Res interface{} `xml:"urn:vim25 DisableMethodsResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *disableMethodsBody) Fault() *soap.Fault { return b.Err }
func (m AuthorizationManager) DisableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []DisabledMethodRequest, source string) error {
var reqBody, resBody disableMethodsBody
reqBody.Req = &disableMethodsRequest{
This: m.Reference(),
Entity: entity,
Method: method,
Source: source,
}
return m.Client().RoundTrip(ctx, &reqBody, &resBody)
}
type enableMethodsRequest struct {
This types.ManagedObjectReference `xml:"_this"`
Entity []types.ManagedObjectReference `xml:"entity"`
Method []string `xml:"method"`
Source string `xml:"sourceId"`
}
type enableMethodsBody struct {
Req *enableMethodsRequest `xml:"urn:internalvim25 EnableMethods,omitempty"`
Res interface{} `xml:"urn:vim25 EnableMethodsResponse,omitempty"`
Err *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *enableMethodsBody) Fault() *soap.Fault { return b.Err }
func (m AuthorizationManager) EnableMethods(ctx context.Context, entity []types.ManagedObjectReference, method []string, source string) error {
var reqBody, resBody enableMethodsBody
reqBody.Req = &enableMethodsRequest{
This: m.Reference(),
Entity: entity,
Method: method,
Source: source,
}
return m.Client().RoundTrip(ctx, &reqBody, &resBody)
}

View File

@ -0,0 +1,70 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type ClusterComputeResource struct {
ComputeResource
}
func NewClusterComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ClusterComputeResource {
return &ClusterComputeResource{
ComputeResource: *NewComputeResource(c, ref),
}
}
func (c ClusterComputeResource) Configuration(ctx context.Context) (*types.ClusterConfigInfoEx, error) {
var obj mo.ClusterComputeResource
err := c.Properties(ctx, c.Reference(), []string{"configurationEx"}, &obj)
if err != nil {
return nil, err
}
return obj.ConfigurationEx.(*types.ClusterConfigInfoEx), nil
}
func (c ClusterComputeResource) AddHost(ctx context.Context, spec types.HostConnectSpec, asConnected bool, license *string, resourcePool *types.ManagedObjectReference) (*Task, error) {
req := types.AddHost_Task{
This: c.Reference(),
Spec: spec,
AsConnected: asConnected,
}
if license != nil {
req.License = *license
}
if resourcePool != nil {
req.ResourcePool = resourcePool
}
res, err := methods.AddHost_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}

132
vendor/github.com/vmware/govmomi/object/common.go generated vendored Normal file
View File

@ -0,0 +1,132 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"fmt"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var (
ErrNotSupported = errors.New("product/version specific feature not supported by target")
)
// Common contains the fields and functions common to all objects.
type Common struct {
InventoryPath string
c *vim25.Client
r types.ManagedObjectReference
}
func (c Common) String() string {
ref := fmt.Sprintf("%v", c.Reference())
if c.InventoryPath == "" {
return ref
}
return fmt.Sprintf("%s @ %s", ref, c.InventoryPath)
}
func NewCommon(c *vim25.Client, r types.ManagedObjectReference) Common {
return Common{c: c, r: r}
}
func (c Common) Reference() types.ManagedObjectReference {
return c.r
}
func (c Common) Client() *vim25.Client {
return c.c
}
// Name returns the base name of the InventoryPath field
func (c Common) Name() string {
if c.InventoryPath == "" {
return ""
}
return path.Base(c.InventoryPath)
}
func (c *Common) SetInventoryPath(p string) {
c.InventoryPath = p
}
// ObjectName returns the base name of the InventoryPath field if set,
// otherwise fetches the mo.ManagedEntity.Name field via the property collector.
func (c Common) ObjectName(ctx context.Context) (string, error) {
var o mo.ManagedEntity
err := c.Properties(ctx, c.Reference(), []string{"name"}, &o)
if err != nil {
return "", err
}
if o.Name != "" {
return o.Name, nil
}
// Network has its own "name" field...
var n mo.Network
err = c.Properties(ctx, c.Reference(), []string{"name"}, &n)
if err != nil {
return "", err
}
return n.Name, nil
}
func (c Common) Properties(ctx context.Context, r types.ManagedObjectReference, ps []string, dst interface{}) error {
return property.DefaultCollector(c.c).RetrieveOne(ctx, r, ps, dst)
}
func (c Common) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: c.Reference(),
}
res, err := methods.Destroy_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}
func (c Common) Rename(ctx context.Context, name string) (*Task, error) {
req := types.Rename_Task{
This: c.Reference(),
NewName: name,
}
res, err := methods.Rename_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}

View File

@ -0,0 +1,111 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"path"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type ComputeResource struct {
Common
}
func NewComputeResource(c *vim25.Client, ref types.ManagedObjectReference) *ComputeResource {
return &ComputeResource{
Common: NewCommon(c, ref),
}
}
func (c ComputeResource) Hosts(ctx context.Context) ([]*HostSystem, error) {
var cr mo.ComputeResource
err := c.Properties(ctx, c.Reference(), []string{"host"}, &cr)
if err != nil {
return nil, err
}
if len(cr.Host) == 0 {
return nil, nil
}
var hs []mo.HostSystem
pc := property.DefaultCollector(c.Client())
err = pc.Retrieve(ctx, cr.Host, []string{"name"}, &hs)
if err != nil {
return nil, err
}
var hosts []*HostSystem
for _, h := range hs {
host := NewHostSystem(c.Client(), h.Reference())
host.InventoryPath = path.Join(c.InventoryPath, h.Name)
hosts = append(hosts, host)
}
return hosts, nil
}
func (c ComputeResource) Datastores(ctx context.Context) ([]*Datastore, error) {
var cr mo.ComputeResource
err := c.Properties(ctx, c.Reference(), []string{"datastore"}, &cr)
if err != nil {
return nil, err
}
var dss []*Datastore
for _, ref := range cr.Datastore {
ds := NewDatastore(c.c, ref)
dss = append(dss, ds)
}
return dss, nil
}
func (c ComputeResource) ResourcePool(ctx context.Context) (*ResourcePool, error) {
var cr mo.ComputeResource
err := c.Properties(ctx, c.Reference(), []string{"resourcePool"}, &cr)
if err != nil {
return nil, err
}
return NewResourcePool(c.c, *cr.ResourcePool), nil
}
func (c ComputeResource) Reconfigure(ctx context.Context, spec types.BaseComputeResourceConfigSpec, modify bool) (*Task, error) {
req := types.ReconfigureComputeResource_Task{
This: c.Reference(),
Spec: spec,
Modify: modify,
}
res, err := methods.ReconfigureComputeResource_Task(ctx, c.c, &req)
if err != nil {
return nil, err
}
return NewTask(c.c, res.Returnval), nil
}

View File

@ -0,0 +1,146 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"strconv"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
var (
ErrKeyNameNotFound = errors.New("key name not found")
)
type CustomFieldsManager struct {
Common
}
// GetCustomFieldsManager wraps NewCustomFieldsManager, returning ErrNotSupported
// when the client is not connected to a vCenter instance.
func GetCustomFieldsManager(c *vim25.Client) (*CustomFieldsManager, error) {
if c.ServiceContent.CustomFieldsManager == nil {
return nil, ErrNotSupported
}
return NewCustomFieldsManager(c), nil
}
func NewCustomFieldsManager(c *vim25.Client) *CustomFieldsManager {
m := CustomFieldsManager{
Common: NewCommon(c, *c.ServiceContent.CustomFieldsManager),
}
return &m
}
func (m CustomFieldsManager) Add(ctx context.Context, name string, moType string, fieldDefPolicy *types.PrivilegePolicyDef, fieldPolicy *types.PrivilegePolicyDef) (*types.CustomFieldDef, error) {
req := types.AddCustomFieldDef{
This: m.Reference(),
Name: name,
MoType: moType,
FieldDefPolicy: fieldDefPolicy,
FieldPolicy: fieldPolicy,
}
res, err := methods.AddCustomFieldDef(ctx, m.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (m CustomFieldsManager) Remove(ctx context.Context, key int32) error {
req := types.RemoveCustomFieldDef{
This: m.Reference(),
Key: key,
}
_, err := methods.RemoveCustomFieldDef(ctx, m.c, &req)
return err
}
func (m CustomFieldsManager) Rename(ctx context.Context, key int32, name string) error {
req := types.RenameCustomFieldDef{
This: m.Reference(),
Key: key,
Name: name,
}
_, err := methods.RenameCustomFieldDef(ctx, m.c, &req)
return err
}
func (m CustomFieldsManager) Set(ctx context.Context, entity types.ManagedObjectReference, key int32, value string) error {
req := types.SetField{
This: m.Reference(),
Entity: entity,
Key: key,
Value: value,
}
_, err := methods.SetField(ctx, m.c, &req)
return err
}
type CustomFieldDefList []types.CustomFieldDef
func (m CustomFieldsManager) Field(ctx context.Context) (CustomFieldDefList, error) {
var fm mo.CustomFieldsManager
err := m.Properties(ctx, m.Reference(), []string{"field"}, &fm)
if err != nil {
return nil, err
}
return fm.Field, nil
}
func (m CustomFieldsManager) FindKey(ctx context.Context, name string) (int32, error) {
field, err := m.Field(ctx)
if err != nil {
return -1, err
}
for _, def := range field {
if def.Name == name {
return def.Key, nil
}
}
k, err := strconv.Atoi(name)
if err == nil {
// assume literal int key
return int32(k), nil
}
return -1, ErrKeyNameNotFound
}
func (l CustomFieldDefList) ByKey(key int32) *types.CustomFieldDef {
for _, def := range l {
if def.Key == key {
return &def
}
}
return nil
}

View File

@ -0,0 +1,166 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type CustomizationSpecManager struct {
Common
}
func NewCustomizationSpecManager(c *vim25.Client) *CustomizationSpecManager {
cs := CustomizationSpecManager{
Common: NewCommon(c, *c.ServiceContent.CustomizationSpecManager),
}
return &cs
}
func (cs CustomizationSpecManager) DoesCustomizationSpecExist(ctx context.Context, name string) (bool, error) {
req := types.DoesCustomizationSpecExist{
This: cs.Reference(),
Name: name,
}
res, err := methods.DoesCustomizationSpecExist(ctx, cs.c, &req)
if err != nil {
return false, err
}
return res.Returnval, nil
}
func (cs CustomizationSpecManager) GetCustomizationSpec(ctx context.Context, name string) (*types.CustomizationSpecItem, error) {
req := types.GetCustomizationSpec{
This: cs.Reference(),
Name: name,
}
res, err := methods.GetCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (cs CustomizationSpecManager) CreateCustomizationSpec(ctx context.Context, item types.CustomizationSpecItem) error {
req := types.CreateCustomizationSpec{
This: cs.Reference(),
Item: item,
}
_, err := methods.CreateCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) OverwriteCustomizationSpec(ctx context.Context, item types.CustomizationSpecItem) error {
req := types.OverwriteCustomizationSpec{
This: cs.Reference(),
Item: item,
}
_, err := methods.OverwriteCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) DeleteCustomizationSpec(ctx context.Context, name string) error {
req := types.DeleteCustomizationSpec{
This: cs.Reference(),
Name: name,
}
_, err := methods.DeleteCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) DuplicateCustomizationSpec(ctx context.Context, name string, newName string) error {
req := types.DuplicateCustomizationSpec{
This: cs.Reference(),
Name: name,
NewName: newName,
}
_, err := methods.DuplicateCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) RenameCustomizationSpec(ctx context.Context, name string, newName string) error {
req := types.RenameCustomizationSpec{
This: cs.Reference(),
Name: name,
NewName: newName,
}
_, err := methods.RenameCustomizationSpec(ctx, cs.c, &req)
if err != nil {
return err
}
return nil
}
func (cs CustomizationSpecManager) CustomizationSpecItemToXml(ctx context.Context, item types.CustomizationSpecItem) (string, error) {
req := types.CustomizationSpecItemToXml{
This: cs.Reference(),
Item: item,
}
res, err := methods.CustomizationSpecItemToXml(ctx, cs.c, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
func (cs CustomizationSpecManager) XmlToCustomizationSpecItem(ctx context.Context, xml string) (*types.CustomizationSpecItem, error) {
req := types.XmlToCustomizationSpecItem{
This: cs.Reference(),
SpecItemXml: xml,
}
res, err := methods.XmlToCustomizationSpecItem(ctx, cs.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

129
vendor/github.com/vmware/govmomi/object/datacenter.go generated vendored Normal file
View File

@ -0,0 +1,129 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type DatacenterFolders struct {
VmFolder *Folder
HostFolder *Folder
DatastoreFolder *Folder
NetworkFolder *Folder
}
type Datacenter struct {
Common
}
func NewDatacenter(c *vim25.Client, ref types.ManagedObjectReference) *Datacenter {
return &Datacenter{
Common: NewCommon(c, ref),
}
}
func (d *Datacenter) Folders(ctx context.Context) (*DatacenterFolders, error) {
var md mo.Datacenter
ps := []string{"name", "vmFolder", "hostFolder", "datastoreFolder", "networkFolder"}
err := d.Properties(ctx, d.Reference(), ps, &md)
if err != nil {
return nil, err
}
df := &DatacenterFolders{
VmFolder: NewFolder(d.c, md.VmFolder),
HostFolder: NewFolder(d.c, md.HostFolder),
DatastoreFolder: NewFolder(d.c, md.DatastoreFolder),
NetworkFolder: NewFolder(d.c, md.NetworkFolder),
}
paths := []struct {
name string
path *string
}{
{"vm", &df.VmFolder.InventoryPath},
{"host", &df.HostFolder.InventoryPath},
{"datastore", &df.DatastoreFolder.InventoryPath},
{"network", &df.NetworkFolder.InventoryPath},
}
for _, p := range paths {
*p.path = fmt.Sprintf("/%s/%s", md.Name, p.name)
}
return df, nil
}
func (d Datacenter) Destroy(ctx context.Context) (*Task, error) {
req := types.Destroy_Task{
This: d.Reference(),
}
res, err := methods.Destroy_Task(ctx, d.c, &req)
if err != nil {
return nil, err
}
return NewTask(d.c, res.Returnval), nil
}
// PowerOnVM powers on multiple virtual machines with a single vCenter call.
// If called against ESX, serially powers on the list of VMs and the returned *Task will always be nil.
func (d Datacenter) PowerOnVM(ctx context.Context, vm []types.ManagedObjectReference, option ...types.BaseOptionValue) (*Task, error) {
if d.Client().IsVC() {
req := types.PowerOnMultiVM_Task{
This: d.Reference(),
Vm: vm,
Option: option,
}
res, err := methods.PowerOnMultiVM_Task(ctx, d.c, &req)
if err != nil {
return nil, err
}
return NewTask(d.c, res.Returnval), nil
}
for _, ref := range vm {
obj := NewVirtualMachine(d.Client(), ref)
task, err := obj.PowerOn(ctx)
if err != nil {
return nil, err
}
err = task.Wait(ctx)
if err != nil {
// Ignore any InvalidPowerState fault, as it indicates the VM is already powered on
if f, ok := err.(types.HasFault); ok {
if _, ok = f.Fault().(*types.InvalidPowerState); !ok {
return nil, err
}
}
}
}
return nil, nil
}

435
vendor/github.com/vmware/govmomi/object/datastore.go generated vendored Normal file
View File

@ -0,0 +1,435 @@
/*
Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"fmt"
"io"
"math/rand"
"os"
"path"
"strings"
"context"
"net/http"
"net/url"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// DatastoreNoSuchDirectoryError is returned when a directory could not be found.
type DatastoreNoSuchDirectoryError struct {
verb string
subject string
}
func (e DatastoreNoSuchDirectoryError) Error() string {
return fmt.Sprintf("cannot %s '%s': No such directory", e.verb, e.subject)
}
// DatastoreNoSuchFileError is returned when a file could not be found.
type DatastoreNoSuchFileError struct {
verb string
subject string
}
func (e DatastoreNoSuchFileError) Error() string {
return fmt.Sprintf("cannot %s '%s': No such file", e.verb, e.subject)
}
type Datastore struct {
Common
DatacenterPath string
}
func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore {
return &Datastore{
Common: NewCommon(c, ref),
}
}
func (d Datastore) Path(path string) string {
return (&DatastorePath{
Datastore: d.Name(),
Path: path,
}).String()
}
// NewURL constructs a url.URL with the given file path for datastore access over HTTP.
func (d Datastore) NewURL(path string) *url.URL {
u := d.c.URL()
return &url.URL{
Scheme: u.Scheme,
Host: u.Host,
Path: fmt.Sprintf("/folder/%s", path),
RawQuery: url.Values{
"dcPath": []string{d.DatacenterPath},
"dsName": []string{d.Name()},
}.Encode(),
}
}
// URL is deprecated, use NewURL instead.
func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) {
return d.NewURL(path), nil
}
func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) {
var do mo.Datastore
err := d.Properties(ctx, d.Reference(), []string{"browser"}, &do)
if err != nil {
return nil, err
}
return NewHostDatastoreBrowser(d.c, do.Browser), nil
}
func (d Datastore) useServiceTicket() bool {
// If connected to workstation, service ticketing not supported
// If connected to ESX, service ticketing not needed
if !d.c.IsVC() {
return false
}
key := "GOVMOMI_USE_SERVICE_TICKET"
val := d.c.URL().Query().Get(key)
if val == "" {
val = os.Getenv(key)
}
if val == "1" || val == "true" {
return true
}
return false
}
func (d Datastore) useServiceTicketHostName(name string) bool {
// No need if talking directly to ESX.
if !d.c.IsVC() {
return false
}
// If version happens to be < 5.1
if name == "" {
return false
}
// If the HostSystem is using DHCP on a network without dynamic DNS,
// HostSystem.Config.Network.DnsConfig.HostName is set to "localhost" by default.
// This resolves to "localhost.localdomain" by default via /etc/hosts on ESX.
// In that case, we will stick with the HostSystem.Name which is the IP address that
// was used to connect the host to VC.
if name == "localhost.localdomain" {
return false
}
// Still possible to have HostName that don't resolve via DNS,
// so we default to false.
key := "GOVMOMI_USE_SERVICE_TICKET_HOSTNAME"
val := d.c.URL().Query().Get(key)
if val == "" {
val = os.Getenv(key)
}
if val == "1" || val == "true" {
return true
}
return false
}
type datastoreServiceTicketHostKey struct{}
// HostContext returns a Context where the given host will be used for datastore HTTP access
// via the ServiceTicket method.
func (d Datastore) HostContext(ctx context.Context, host *HostSystem) context.Context {
return context.WithValue(ctx, datastoreServiceTicketHostKey{}, host)
}
// ServiceTicket obtains a ticket via AcquireGenericServiceTicket and returns it an http.Cookie with the url.URL
// that can be used along with the ticket cookie to access the given path. An host is chosen at random unless the
// the given Context was created with a specific host via the HostContext method.
func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) {
u := d.NewURL(path)
host, ok := ctx.Value(datastoreServiceTicketHostKey{}).(*HostSystem)
if !ok {
if !d.useServiceTicket() {
return u, nil, nil
}
hosts, err := d.AttachedHosts(ctx)
if err != nil {
return nil, nil, err
}
if len(hosts) == 0 {
// Fallback to letting vCenter choose a host
return u, nil, nil
}
// Pick a random attached host
host = hosts[rand.Intn(len(hosts))]
}
ips, err := host.ManagementIPs(ctx)
if err != nil {
return nil, nil, err
}
if len(ips) > 0 {
// prefer a ManagementIP
u.Host = ips[0].String()
} else {
// fallback to inventory name
u.Host, err = host.ObjectName(ctx)
if err != nil {
return nil, nil, err
}
}
// VC datacenter path will not be valid against ESX
q := u.Query()
delete(q, "dcPath")
u.RawQuery = q.Encode()
spec := types.SessionManagerHttpServiceRequestSpec{
Url: u.String(),
// See SessionManagerHttpServiceRequestSpecMethod enum
Method: fmt.Sprintf("http%s%s", method[0:1], strings.ToLower(method[1:])),
}
sm := session.NewManager(d.Client())
ticket, err := sm.AcquireGenericServiceTicket(ctx, &spec)
if err != nil {
return nil, nil, err
}
cookie := &http.Cookie{
Name: "vmware_cgi_ticket",
Value: ticket.Id,
}
if d.useServiceTicketHostName(ticket.HostName) {
u.Host = ticket.HostName
}
d.Client().SetThumbprint(u.Host, ticket.SslThumbprint)
return u, cookie, nil
}
func (d Datastore) uploadTicket(ctx context.Context, path string, param *soap.Upload) (*url.URL, *soap.Upload, error) {
p := soap.DefaultUpload
if param != nil {
p = *param // copy
}
u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
if err != nil {
return nil, nil, err
}
p.Ticket = ticket
return u, &p, nil
}
func (d Datastore) downloadTicket(ctx context.Context, path string, param *soap.Download) (*url.URL, *soap.Download, error) {
p := soap.DefaultDownload
if param != nil {
p = *param // copy
}
u, ticket, err := d.ServiceTicket(ctx, path, p.Method)
if err != nil {
return nil, nil, err
}
p.Ticket = ticket
return u, &p, nil
}
// Upload via soap.Upload with an http service ticket
func (d Datastore) Upload(ctx context.Context, f io.Reader, path string, param *soap.Upload) error {
u, p, err := d.uploadTicket(ctx, path, param)
if err != nil {
return err
}
return d.Client().Upload(ctx, f, u, p)
}
// UploadFile via soap.Upload with an http service ticket
func (d Datastore) UploadFile(ctx context.Context, file string, path string, param *soap.Upload) error {
u, p, err := d.uploadTicket(ctx, path, param)
if err != nil {
return err
}
return d.Client().UploadFile(ctx, file, u, p)
}
// Download via soap.Download with an http service ticket
func (d Datastore) Download(ctx context.Context, path string, param *soap.Download) (io.ReadCloser, int64, error) {
u, p, err := d.downloadTicket(ctx, path, param)
if err != nil {
return nil, 0, err
}
return d.Client().Download(ctx, u, p)
}
// DownloadFile via soap.Download with an http service ticket
func (d Datastore) DownloadFile(ctx context.Context, path string, file string, param *soap.Download) error {
u, p, err := d.downloadTicket(ctx, path, param)
if err != nil {
return err
}
return d.Client().DownloadFile(ctx, file, u, p)
}
// AttachedHosts returns hosts that have this Datastore attached, accessible and writable.
func (d Datastore) AttachedHosts(ctx context.Context) ([]*HostSystem, error) {
var ds mo.Datastore
var hosts []*HostSystem
pc := property.DefaultCollector(d.Client())
err := pc.RetrieveOne(ctx, d.Reference(), []string{"host"}, &ds)
if err != nil {
return nil, err
}
mounts := make(map[types.ManagedObjectReference]types.DatastoreHostMount)
var refs []types.ManagedObjectReference
for _, host := range ds.Host {
refs = append(refs, host.Key)
mounts[host.Key] = host
}
var hs []mo.HostSystem
err = pc.Retrieve(ctx, refs, []string{"runtime.connectionState", "runtime.powerState"}, &hs)
if err != nil {
return nil, err
}
for _, host := range hs {
if host.Runtime.ConnectionState == types.HostSystemConnectionStateConnected &&
host.Runtime.PowerState == types.HostSystemPowerStatePoweredOn {
mount := mounts[host.Reference()]
info := mount.MountInfo
if *info.Mounted && *info.Accessible && info.AccessMode == string(types.HostMountModeReadWrite) {
hosts = append(hosts, NewHostSystem(d.Client(), mount.Key))
}
}
}
return hosts, nil
}
// AttachedClusterHosts returns hosts that have this Datastore attached, accessible and writable and are members of the given cluster.
func (d Datastore) AttachedClusterHosts(ctx context.Context, cluster *ComputeResource) ([]*HostSystem, error) {
var hosts []*HostSystem
clusterHosts, err := cluster.Hosts(ctx)
if err != nil {
return nil, err
}
attachedHosts, err := d.AttachedHosts(ctx)
if err != nil {
return nil, err
}
refs := make(map[types.ManagedObjectReference]bool)
for _, host := range attachedHosts {
refs[host.Reference()] = true
}
for _, host := range clusterHosts {
if refs[host.Reference()] {
hosts = append(hosts, host)
}
}
return hosts, nil
}
func (d Datastore) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
b, err := d.Browser(ctx)
if err != nil {
return nil, err
}
spec := types.HostDatastoreBrowserSearchSpec{
Details: &types.FileQueryFlags{
FileType: true,
FileSize: true,
Modification: true,
FileOwner: types.NewBool(true),
},
MatchPattern: []string{path.Base(file)},
}
dsPath := d.Path(path.Dir(file))
task, err := b.SearchDatastore(ctx, dsPath, &spec)
if err != nil {
return nil, err
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
if types.IsFileNotFound(err) {
// FileNotFound means the base path doesn't exist.
return nil, DatastoreNoSuchDirectoryError{"stat", dsPath}
}
return nil, err
}
res := info.Result.(types.HostDatastoreBrowserSearchResults)
if len(res.File) == 0 {
// File doesn't exist
return nil, DatastoreNoSuchFileError{"stat", d.Path(file)}
}
return res.File[0], nil
}
// Type returns the type of file system volume.
func (d Datastore) Type(ctx context.Context) (types.HostFileSystemVolumeFileSystemType, error) {
var mds mo.Datastore
if err := d.Properties(ctx, d.Reference(), []string{"summary.type"}, &mds); err != nil {
return types.HostFileSystemVolumeFileSystemType(""), err
}
return types.HostFileSystemVolumeFileSystemType(mds.Summary.Type), nil
}

View File

@ -0,0 +1,414 @@
/*
Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"path"
"sync"
"time"
"github.com/vmware/govmomi/vim25/soap"
)
// DatastoreFile implements io.Reader, io.Seeker and io.Closer interfaces for datastore file access.
type DatastoreFile struct {
d Datastore
ctx context.Context
name string
buf io.Reader
body io.ReadCloser
length int64
offset struct {
read, seek int64
}
}
// Open opens the named file relative to the Datastore.
func (d Datastore) Open(ctx context.Context, name string) (*DatastoreFile, error) {
return &DatastoreFile{
d: d,
name: name,
length: -1,
ctx: ctx,
}, nil
}
// Read reads up to len(b) bytes from the DatastoreFile.
func (f *DatastoreFile) Read(b []byte) (int, error) {
if f.offset.read != f.offset.seek {
// A Seek() call changed the offset, we need to issue a new GET
_ = f.Close()
f.offset.read = f.offset.seek
} else if f.buf != nil {
// f.buf + f behaves like an io.MultiReader
n, err := f.buf.Read(b)
if err == io.EOF {
f.buf = nil // buffer has been drained
}
if n > 0 {
return n, nil
}
}
body, err := f.get()
if err != nil {
return 0, err
}
n, err := body.Read(b)
f.offset.read += int64(n)
f.offset.seek += int64(n)
return n, err
}
// Close closes the DatastoreFile.
func (f *DatastoreFile) Close() error {
var err error
if f.body != nil {
err = f.body.Close()
f.body = nil
}
f.buf = nil
return err
}
// Seek sets the offset for the next Read on the DatastoreFile.
func (f *DatastoreFile) Seek(offset int64, whence int) (int64, error) {
switch whence {
case io.SeekStart:
case io.SeekCurrent:
offset += f.offset.seek
case io.SeekEnd:
if f.length < 0 {
_, err := f.Stat()
if err != nil {
return 0, err
}
}
offset += f.length
default:
return 0, errors.New("Seek: invalid whence")
}
// allow negative SeekStart for initial Range request
if offset < 0 {
return 0, errors.New("Seek: invalid offset")
}
f.offset.seek = offset
return offset, nil
}
type fileStat struct {
file *DatastoreFile
header http.Header
}
func (s *fileStat) Name() string {
return path.Base(s.file.name)
}
func (s *fileStat) Size() int64 {
return s.file.length
}
func (s *fileStat) Mode() os.FileMode {
return 0
}
func (s *fileStat) ModTime() time.Time {
return time.Now() // no Last-Modified
}
func (s *fileStat) IsDir() bool {
return false
}
func (s *fileStat) Sys() interface{} {
return s.header
}
func statusError(res *http.Response) error {
if res.StatusCode == http.StatusNotFound {
return os.ErrNotExist
}
return errors.New(res.Status)
}
// Stat returns the os.FileInfo interface describing file.
func (f *DatastoreFile) Stat() (os.FileInfo, error) {
// TODO: consider using Datastore.Stat() instead
u, p, err := f.d.downloadTicket(f.ctx, f.name, &soap.Download{Method: "HEAD"})
if err != nil {
return nil, err
}
res, err := f.d.Client().DownloadRequest(f.ctx, u, p)
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
return nil, statusError(res)
}
f.length = res.ContentLength
return &fileStat{f, res.Header}, nil
}
func (f *DatastoreFile) get() (io.Reader, error) {
if f.body != nil {
return f.body, nil
}
u, p, err := f.d.downloadTicket(f.ctx, f.name, nil)
if err != nil {
return nil, err
}
if f.offset.read != 0 {
p.Headers = map[string]string{
"Range": fmt.Sprintf("bytes=%d-", f.offset.read),
}
}
res, err := f.d.Client().DownloadRequest(f.ctx, u, p)
if err != nil {
return nil, err
}
switch res.StatusCode {
case http.StatusOK:
f.length = res.ContentLength
case http.StatusPartialContent:
var start, end int
cr := res.Header.Get("Content-Range")
_, err = fmt.Sscanf(cr, "bytes %d-%d/%d", &start, &end, &f.length)
if err != nil {
f.length = -1
}
case http.StatusRequestedRangeNotSatisfiable:
// ok: Read() will return io.EOF
default:
return nil, statusError(res)
}
if f.length < 0 {
_ = res.Body.Close()
return nil, errors.New("unable to determine file size")
}
f.body = res.Body
return f.body, nil
}
func lastIndexLines(s []byte, line *int, include func(l int, m string) bool) (int64, bool) {
i := len(s) - 1
done := false
for i > 0 {
o := bytes.LastIndexByte(s[:i], '\n')
if o < 0 {
break
}
msg := string(s[o+1 : i+1])
if !include(*line, msg) {
done = true
break
} else {
i = o
*line++
}
}
return int64(i), done
}
// Tail seeks to the position of the last N lines of the file.
func (f *DatastoreFile) Tail(n int) error {
return f.TailFunc(n, func(line int, _ string) bool { return n > line })
}
// TailFunc will seek backwards in the datastore file until it hits a line that does
// not satisfy the supplied `include` function.
func (f *DatastoreFile) TailFunc(lines int, include func(line int, message string) bool) error {
// Read the file in reverse using bsize chunks
const bsize = int64(1024 * 16)
fsize, err := f.Seek(0, io.SeekEnd)
if err != nil {
return err
}
if lines == 0 {
return nil
}
chunk := int64(-1)
buf := bytes.NewBuffer(make([]byte, 0, bsize))
line := 0
for {
var eof bool
var pos int64
nread := bsize
offset := chunk * bsize
remain := fsize + offset
if remain < 0 {
if pos, err = f.Seek(0, io.SeekStart); err != nil {
return err
}
nread = bsize + remain
eof = true
} else {
if pos, err = f.Seek(offset, io.SeekEnd); err != nil {
return err
}
}
if _, err = io.CopyN(buf, f, nread); err != nil {
if err != io.EOF {
return err
}
}
b := buf.Bytes()
idx, done := lastIndexLines(b, &line, include)
if done {
if chunk == -1 {
// We found all N lines in the last chunk of the file.
// The seek offset is also now at the current end of file.
// Save this buffer to avoid another GET request when Read() is called.
buf.Next(int(idx + 1))
f.buf = buf
return nil
}
if _, err = f.Seek(pos+idx+1, io.SeekStart); err != nil {
return err
}
break
}
if eof {
if remain < 0 {
// We found < N lines in the entire file, so seek to the start.
_, _ = f.Seek(0, io.SeekStart)
}
break
}
chunk--
buf.Reset()
}
return nil
}
type followDatastoreFile struct {
r *DatastoreFile
c chan struct{}
i time.Duration
o sync.Once
}
// Read reads up to len(b) bytes from the DatastoreFile being followed.
// This method will block until data is read, an error other than io.EOF is returned or Close() is called.
func (f *followDatastoreFile) Read(p []byte) (int, error) {
offset := f.r.offset.seek
stop := false
for {
n, err := f.r.Read(p)
if err != nil && err == io.EOF {
_ = f.r.Close() // GET request body has been drained.
if stop {
return n, err
}
err = nil
}
if n > 0 {
return n, err
}
select {
case <-f.c:
// Wake up and stop polling once the body has been drained
stop = true
case <-time.After(f.i):
}
info, serr := f.r.Stat()
if serr != nil {
// Return EOF rather than 404 if the file goes away
if serr == os.ErrNotExist {
_ = f.r.Close()
return 0, io.EOF
}
return 0, serr
}
if info.Size() < offset {
// assume file has be truncated
offset, err = f.r.Seek(0, io.SeekStart)
if err != nil {
return 0, err
}
}
}
}
// Close will stop Follow polling and close the underlying DatastoreFile.
func (f *followDatastoreFile) Close() error {
f.o.Do(func() { close(f.c) })
return nil
}
// Follow returns an io.ReadCloser to stream the file contents as data is appended.
func (f *DatastoreFile) Follow(interval time.Duration) io.ReadCloser {
return &followDatastoreFile{
r: f,
c: make(chan struct{}),
i: interval,
}
}

View File

@ -0,0 +1,228 @@
/*
Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"log"
"path"
"strings"
"github.com/vmware/govmomi/vim25/progress"
"github.com/vmware/govmomi/vim25/soap"
)
// DatastoreFileManager combines FileManager and VirtualDiskManager to manage files on a Datastore
type DatastoreFileManager struct {
Datacenter *Datacenter
Datastore *Datastore
FileManager *FileManager
VirtualDiskManager *VirtualDiskManager
Force bool
DatacenterTarget *Datacenter
}
// NewFileManager creates a new instance of DatastoreFileManager
func (d Datastore) NewFileManager(dc *Datacenter, force bool) *DatastoreFileManager {
c := d.Client()
m := &DatastoreFileManager{
Datacenter: dc,
Datastore: &d,
FileManager: NewFileManager(c),
VirtualDiskManager: NewVirtualDiskManager(c),
Force: force,
DatacenterTarget: dc,
}
return m
}
func (m *DatastoreFileManager) WithProgress(ctx context.Context, s progress.Sinker) context.Context {
return context.WithValue(ctx, m, s)
}
func (m *DatastoreFileManager) wait(ctx context.Context, task *Task) error {
var logger progress.Sinker
if s, ok := ctx.Value(m).(progress.Sinker); ok {
logger = s
}
_, err := task.WaitForResult(ctx, logger)
return err
}
// Delete dispatches to the appropriate Delete method based on file name extension
func (m *DatastoreFileManager) Delete(ctx context.Context, name string) error {
switch path.Ext(name) {
case ".vmdk":
return m.DeleteVirtualDisk(ctx, name)
default:
return m.DeleteFile(ctx, name)
}
}
// DeleteFile calls FileManager.DeleteDatastoreFile
func (m *DatastoreFileManager) DeleteFile(ctx context.Context, name string) error {
p := m.Path(name)
task, err := m.FileManager.DeleteDatastoreFile(ctx, p.String(), m.Datacenter)
if err != nil {
return err
}
return m.wait(ctx, task)
}
// DeleteVirtualDisk calls VirtualDiskManager.DeleteVirtualDisk
// Regardless of the Datastore type, DeleteVirtualDisk will fail if 'ddb.deletable=false',
// so if Force=true this method attempts to set 'ddb.deletable=true' before starting the delete task.
func (m *DatastoreFileManager) DeleteVirtualDisk(ctx context.Context, name string) error {
p := m.Path(name)
var merr error
if m.Force {
merr = m.markDiskAsDeletable(ctx, p)
}
task, err := m.VirtualDiskManager.DeleteVirtualDisk(ctx, p.String(), m.Datacenter)
if err != nil {
log.Printf("markDiskAsDeletable(%s): %s", p, merr)
return err
}
return m.wait(ctx, task)
}
// CopyFile calls FileManager.CopyDatastoreFile
func (m *DatastoreFileManager) CopyFile(ctx context.Context, src string, dst string) error {
srcp := m.Path(src)
dstp := m.Path(dst)
task, err := m.FileManager.CopyDatastoreFile(ctx, srcp.String(), m.Datacenter, dstp.String(), m.DatacenterTarget, m.Force)
if err != nil {
return err
}
return m.wait(ctx, task)
}
// Copy dispatches to the appropriate FileManager or VirtualDiskManager Copy method based on file name extension
func (m *DatastoreFileManager) Copy(ctx context.Context, src string, dst string) error {
srcp := m.Path(src)
dstp := m.Path(dst)
f := m.FileManager.CopyDatastoreFile
if srcp.IsVMDK() {
// types.VirtualDiskSpec=nil as it is not implemented by vCenter
f = func(ctx context.Context, src string, srcDC *Datacenter, dst string, dstDC *Datacenter, force bool) (*Task, error) {
return m.VirtualDiskManager.CopyVirtualDisk(ctx, src, srcDC, dst, dstDC, nil, force)
}
}
task, err := f(ctx, srcp.String(), m.Datacenter, dstp.String(), m.DatacenterTarget, m.Force)
if err != nil {
return err
}
return m.wait(ctx, task)
}
// MoveFile calls FileManager.MoveDatastoreFile
func (m *DatastoreFileManager) MoveFile(ctx context.Context, src string, dst string) error {
srcp := m.Path(src)
dstp := m.Path(dst)
task, err := m.FileManager.MoveDatastoreFile(ctx, srcp.String(), m.Datacenter, dstp.String(), m.DatacenterTarget, m.Force)
if err != nil {
return err
}
return m.wait(ctx, task)
}
// Move dispatches to the appropriate FileManager or VirtualDiskManager Move method based on file name extension
func (m *DatastoreFileManager) Move(ctx context.Context, src string, dst string) error {
srcp := m.Path(src)
dstp := m.Path(dst)
f := m.FileManager.MoveDatastoreFile
if srcp.IsVMDK() {
f = m.VirtualDiskManager.MoveVirtualDisk
}
task, err := f(ctx, srcp.String(), m.Datacenter, dstp.String(), m.DatacenterTarget, m.Force)
if err != nil {
return err
}
return m.wait(ctx, task)
}
// Path converts path name to a DatastorePath
func (m *DatastoreFileManager) Path(name string) *DatastorePath {
var p DatastorePath
if !p.FromString(name) {
p.Path = name
p.Datastore = m.Datastore.Name()
}
return &p
}
func (m *DatastoreFileManager) markDiskAsDeletable(ctx context.Context, path *DatastorePath) error {
r, _, err := m.Datastore.Download(ctx, path.Path, &soap.DefaultDownload)
if err != nil {
return err
}
defer r.Close()
hasFlag := false
buf := new(bytes.Buffer)
s := bufio.NewScanner(&io.LimitedReader{R: r, N: 2048}) // should be only a few hundred bytes, limit to be sure
for s.Scan() {
line := s.Text()
if strings.HasPrefix(line, "ddb.deletable") {
hasFlag = true
continue
}
fmt.Fprintln(buf, line)
}
if err := s.Err(); err != nil {
return err // any error other than EOF
}
if !hasFlag {
return nil // already deletable, so leave as-is
}
// rewrite the .vmdk with ddb.deletable flag removed (the default is true)
return m.Datastore.Upload(ctx, buf, path.Path, &soap.DefaultUpload)
}

View File

@ -0,0 +1,71 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"fmt"
"path"
"strings"
)
// DatastorePath contains the components of a datastore path.
type DatastorePath struct {
Datastore string
Path string
}
// FromString parses a datastore path.
// Returns true if the path could be parsed, false otherwise.
func (p *DatastorePath) FromString(s string) bool {
if len(s) == 0 {
return false
}
s = strings.TrimSpace(s)
if !strings.HasPrefix(s, "[") {
return false
}
s = s[1:]
ix := strings.Index(s, "]")
if ix < 0 {
return false
}
p.Datastore = s[:ix]
p.Path = strings.TrimSpace(s[ix+1:])
return true
}
// String formats a datastore path.
func (p *DatastorePath) String() string {
s := fmt.Sprintf("[%s]", p.Datastore)
if p.Path == "" {
return s
}
return strings.Join([]string{s, p.Path}, " ")
}
// IsVMDK returns true if Path has a ".vmdk" extension
func (p *DatastorePath) IsVMDK() bool {
return path.Ext(p.Path) == ".vmdk"
}

View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"io"
"math"
)
// DiagnosticLog wraps DiagnosticManager.BrowseLog
type DiagnosticLog struct {
m DiagnosticManager
Key string
Host *HostSystem
Start int32
}
// Seek to log position starting at the last nlines of the log
func (l *DiagnosticLog) Seek(ctx context.Context, nlines int32) error {
h, err := l.m.BrowseLog(ctx, l.Host, l.Key, math.MaxInt32, 0)
if err != nil {
return err
}
l.Start = h.LineEnd - nlines
return nil
}
// Copy log starting from l.Start to the given io.Writer
// Returns on error or when end of log is reached.
func (l *DiagnosticLog) Copy(ctx context.Context, w io.Writer) (int, error) {
const max = 500 // VC max == 500, ESX max == 1000
written := 0
for {
h, err := l.m.BrowseLog(ctx, l.Host, l.Key, l.Start, max)
if err != nil {
return 0, err
}
for _, line := range h.LineText {
n, err := fmt.Fprintln(w, line)
written += n
if err != nil {
return written, err
}
}
l.Start += int32(len(h.LineText))
if l.Start >= h.LineEnd {
break
}
}
return written, nil
}

View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type DiagnosticManager struct {
Common
}
func NewDiagnosticManager(c *vim25.Client) *DiagnosticManager {
m := DiagnosticManager{
Common: NewCommon(c, *c.ServiceContent.DiagnosticManager),
}
return &m
}
func (m DiagnosticManager) Log(ctx context.Context, host *HostSystem, key string) *DiagnosticLog {
return &DiagnosticLog{
m: m,
Key: key,
Host: host,
}
}
func (m DiagnosticManager) BrowseLog(ctx context.Context, host *HostSystem, key string, start, lines int32) (*types.DiagnosticManagerLogHeader, error) {
req := types.BrowseDiagnosticLog{
This: m.Reference(),
Key: key,
Start: start,
Lines: lines,
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.BrowseDiagnosticLog(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (m DiagnosticManager) GenerateLogBundles(ctx context.Context, includeDefault bool, host []*HostSystem) (*Task, error) {
req := types.GenerateLogBundles_Task{
This: m.Reference(),
IncludeDefault: includeDefault,
}
if host != nil {
for _, h := range host {
req.Host = append(req.Host, h.Reference())
}
}
res, err := methods.GenerateLogBundles_Task(ctx, m.c, &req)
if err != nil {
return nil, err
}
return NewTask(m.c, res.Returnval), nil
}
func (m DiagnosticManager) QueryDescriptions(ctx context.Context, host *HostSystem) ([]types.DiagnosticManagerLogDescriptor, error) {
req := types.QueryDescriptions{
This: m.Reference(),
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.QueryDescriptions(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,80 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type DistributedVirtualPortgroup struct {
Common
}
func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualPortgroup {
return &DistributedVirtualPortgroup{
Common: NewCommon(c, ref),
}
}
// EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this DistributedVirtualPortgroup
func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
var dvp mo.DistributedVirtualPortgroup
var dvs mo.DistributedVirtualSwitch
prop := "config.distributedVirtualSwitch"
if err := p.Properties(ctx, p.Reference(), []string{"key", prop}, &dvp); err != nil {
return nil, err
}
// "This property should always be set unless the user's setting does not have System.Read privilege on the object referred to by this property."
if dvp.Config.DistributedVirtualSwitch == nil {
return nil, fmt.Errorf("no System.Read privilege on: %s.%s", p.Reference(), prop)
}
if err := p.Properties(ctx, *dvp.Config.DistributedVirtualSwitch, []string{"uuid"}, &dvs); err != nil {
return nil, err
}
backing := &types.VirtualEthernetCardDistributedVirtualPortBackingInfo{
Port: types.DistributedVirtualSwitchPortConnection{
PortgroupKey: dvp.Key,
SwitchUuid: dvs.Uuid,
},
}
return backing, nil
}
func (p DistributedVirtualPortgroup) Reconfigure(ctx context.Context, spec types.DVPortgroupConfigSpec) (*Task, error) {
req := types.ReconfigureDVPortgroup_Task{
This: p.Reference(),
Spec: spec,
}
res, err := methods.ReconfigureDVPortgroup_Task(ctx, p.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(p.Client(), res.Returnval), nil
}

View File

@ -0,0 +1,80 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type DistributedVirtualSwitch struct {
Common
}
func NewDistributedVirtualSwitch(c *vim25.Client, ref types.ManagedObjectReference) *DistributedVirtualSwitch {
return &DistributedVirtualSwitch{
Common: NewCommon(c, ref),
}
}
func (s DistributedVirtualSwitch) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) {
return nil, ErrNotSupported // TODO: just to satisfy NetworkReference interface for the finder
}
func (s DistributedVirtualSwitch) Reconfigure(ctx context.Context, spec types.BaseDVSConfigSpec) (*Task, error) {
req := types.ReconfigureDvs_Task{
This: s.Reference(),
Spec: spec,
}
res, err := methods.ReconfigureDvs_Task(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(s.Client(), res.Returnval), nil
}
func (s DistributedVirtualSwitch) AddPortgroup(ctx context.Context, spec []types.DVPortgroupConfigSpec) (*Task, error) {
req := types.AddDVPortgroup_Task{
This: s.Reference(),
Spec: spec,
}
res, err := methods.AddDVPortgroup_Task(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(s.Client(), res.Returnval), nil
}
func (s DistributedVirtualSwitch) FetchDVPorts(ctx context.Context, criteria *types.DistributedVirtualSwitchPortCriteria) ([]types.DistributedVirtualPort, error) {
req := &types.FetchDVPorts{
This: s.Reference(),
Criteria: criteria,
}
res, err := methods.FetchDVPorts(ctx, s.Client(), req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,113 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type ExtensionManager struct {
Common
}
// GetExtensionManager wraps NewExtensionManager, returning ErrNotSupported
// when the client is not connected to a vCenter instance.
func GetExtensionManager(c *vim25.Client) (*ExtensionManager, error) {
if c.ServiceContent.ExtensionManager == nil {
return nil, ErrNotSupported
}
return NewExtensionManager(c), nil
}
func NewExtensionManager(c *vim25.Client) *ExtensionManager {
o := ExtensionManager{
Common: NewCommon(c, *c.ServiceContent.ExtensionManager),
}
return &o
}
func (m ExtensionManager) List(ctx context.Context) ([]types.Extension, error) {
var em mo.ExtensionManager
err := m.Properties(ctx, m.Reference(), []string{"extensionList"}, &em)
if err != nil {
return nil, err
}
return em.ExtensionList, nil
}
func (m ExtensionManager) Find(ctx context.Context, key string) (*types.Extension, error) {
req := types.FindExtension{
This: m.Reference(),
ExtensionKey: key,
}
res, err := methods.FindExtension(ctx, m.c, &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m ExtensionManager) Register(ctx context.Context, extension types.Extension) error {
req := types.RegisterExtension{
This: m.Reference(),
Extension: extension,
}
_, err := methods.RegisterExtension(ctx, m.c, &req)
return err
}
func (m ExtensionManager) SetCertificate(ctx context.Context, key string, certificatePem string) error {
req := types.SetExtensionCertificate{
This: m.Reference(),
ExtensionKey: key,
CertificatePem: certificatePem,
}
_, err := methods.SetExtensionCertificate(ctx, m.c, &req)
return err
}
func (m ExtensionManager) Unregister(ctx context.Context, key string) error {
req := types.UnregisterExtension{
This: m.Reference(),
ExtensionKey: key,
}
_, err := methods.UnregisterExtension(ctx, m.c, &req)
return err
}
func (m ExtensionManager) Update(ctx context.Context, extension types.Extension) error {
req := types.UpdateExtension{
This: m.Reference(),
Extension: extension,
}
_, err := methods.UpdateExtension(ctx, m.c, &req)
return err
}

126
vendor/github.com/vmware/govmomi/object/file_manager.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type FileManager struct {
Common
}
func NewFileManager(c *vim25.Client) *FileManager {
f := FileManager{
Common: NewCommon(c, *c.ServiceContent.FileManager),
}
return &f
}
func (f FileManager) CopyDatastoreFile(ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) {
req := types.CopyDatastoreFile_Task{
This: f.Reference(),
SourceName: sourceName,
DestinationName: destinationName,
Force: types.NewBool(force),
}
if sourceDatacenter != nil {
ref := sourceDatacenter.Reference()
req.SourceDatacenter = &ref
}
if destinationDatacenter != nil {
ref := destinationDatacenter.Reference()
req.DestinationDatacenter = &ref
}
res, err := methods.CopyDatastoreFile_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
// DeleteDatastoreFile deletes the specified file or folder from the datastore.
func (f FileManager) DeleteDatastoreFile(ctx context.Context, name string, dc *Datacenter) (*Task, error) {
req := types.DeleteDatastoreFile_Task{
This: f.Reference(),
Name: name,
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
res, err := methods.DeleteDatastoreFile_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
// MakeDirectory creates a folder using the specified name.
func (f FileManager) MakeDirectory(ctx context.Context, name string, dc *Datacenter, createParentDirectories bool) error {
req := types.MakeDirectory{
This: f.Reference(),
Name: name,
CreateParentDirectories: types.NewBool(createParentDirectories),
}
if dc != nil {
ref := dc.Reference()
req.Datacenter = &ref
}
_, err := methods.MakeDirectory(ctx, f.c, &req)
return err
}
func (f FileManager) MoveDatastoreFile(ctx context.Context, sourceName string, sourceDatacenter *Datacenter, destinationName string, destinationDatacenter *Datacenter, force bool) (*Task, error) {
req := types.MoveDatastoreFile_Task{
This: f.Reference(),
SourceName: sourceName,
DestinationName: destinationName,
Force: types.NewBool(force),
}
if sourceDatacenter != nil {
ref := sourceDatacenter.Reference()
req.SourceDatacenter = &ref
}
if destinationDatacenter != nil {
ref := destinationDatacenter.Reference()
req.DestinationDatacenter = &ref
}
res, err := methods.MoveDatastoreFile_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}

227
vendor/github.com/vmware/govmomi/object/folder.go generated vendored Normal file
View File

@ -0,0 +1,227 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type Folder struct {
Common
}
func NewFolder(c *vim25.Client, ref types.ManagedObjectReference) *Folder {
return &Folder{
Common: NewCommon(c, ref),
}
}
func NewRootFolder(c *vim25.Client) *Folder {
f := NewFolder(c, c.ServiceContent.RootFolder)
f.InventoryPath = "/"
return f
}
func (f Folder) Children(ctx context.Context) ([]Reference, error) {
var mf mo.Folder
err := f.Properties(ctx, f.Reference(), []string{"childEntity"}, &mf)
if err != nil {
return nil, err
}
var rs []Reference
for _, e := range mf.ChildEntity {
if r := NewReference(f.c, e); r != nil {
rs = append(rs, r)
}
}
return rs, nil
}
func (f Folder) CreateDatacenter(ctx context.Context, datacenter string) (*Datacenter, error) {
req := types.CreateDatacenter{
This: f.Reference(),
Name: datacenter,
}
res, err := methods.CreateDatacenter(ctx, f.c, &req)
if err != nil {
return nil, err
}
// Response will be nil if this is an ESX host that does not belong to a vCenter
if res == nil {
return nil, nil
}
return NewDatacenter(f.c, res.Returnval), nil
}
func (f Folder) CreateCluster(ctx context.Context, cluster string, spec types.ClusterConfigSpecEx) (*ClusterComputeResource, error) {
req := types.CreateClusterEx{
This: f.Reference(),
Name: cluster,
Spec: spec,
}
res, err := methods.CreateClusterEx(ctx, f.c, &req)
if err != nil {
return nil, err
}
// Response will be nil if this is an ESX host that does not belong to a vCenter
if res == nil {
return nil, nil
}
return NewClusterComputeResource(f.c, res.Returnval), nil
}
func (f Folder) CreateFolder(ctx context.Context, name string) (*Folder, error) {
req := types.CreateFolder{
This: f.Reference(),
Name: name,
}
res, err := methods.CreateFolder(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewFolder(f.c, res.Returnval), err
}
func (f Folder) CreateStoragePod(ctx context.Context, name string) (*StoragePod, error) {
req := types.CreateStoragePod{
This: f.Reference(),
Name: name,
}
res, err := methods.CreateStoragePod(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewStoragePod(f.c, res.Returnval), err
}
func (f Folder) AddStandaloneHost(ctx context.Context, spec types.HostConnectSpec, addConnected bool, license *string, compResSpec *types.BaseComputeResourceConfigSpec) (*Task, error) {
req := types.AddStandaloneHost_Task{
This: f.Reference(),
Spec: spec,
AddConnected: addConnected,
}
if license != nil {
req.License = *license
}
if compResSpec != nil {
req.CompResSpec = *compResSpec
}
res, err := methods.AddStandaloneHost_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) CreateVM(ctx context.Context, config types.VirtualMachineConfigSpec, pool *ResourcePool, host *HostSystem) (*Task, error) {
req := types.CreateVM_Task{
This: f.Reference(),
Config: config,
Pool: pool.Reference(),
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
res, err := methods.CreateVM_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) RegisterVM(ctx context.Context, path string, name string, asTemplate bool, pool *ResourcePool, host *HostSystem) (*Task, error) {
req := types.RegisterVM_Task{
This: f.Reference(),
Path: path,
AsTemplate: asTemplate,
}
if name != "" {
req.Name = name
}
if host != nil {
ref := host.Reference()
req.Host = &ref
}
if pool != nil {
ref := pool.Reference()
req.Pool = &ref
}
res, err := methods.RegisterVM_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) CreateDVS(ctx context.Context, spec types.DVSCreateSpec) (*Task, error) {
req := types.CreateDVS_Task{
This: f.Reference(),
Spec: spec,
}
res, err := methods.CreateDVS_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}
func (f Folder) MoveInto(ctx context.Context, list []types.ManagedObjectReference) (*Task, error) {
req := types.MoveIntoFolder_Task{
This: f.Reference(),
List: list,
}
res, err := methods.MoveIntoFolder_Task(ctx, f.c, &req)
if err != nil {
return nil, err
}
return NewTask(f.c, res.Returnval), nil
}

View File

@ -0,0 +1,72 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HistoryCollector struct {
Common
}
func NewHistoryCollector(c *vim25.Client, ref types.ManagedObjectReference) *HistoryCollector {
return &HistoryCollector{
Common: NewCommon(c, ref),
}
}
func (h HistoryCollector) Destroy(ctx context.Context) error {
req := types.DestroyCollector{
This: h.Reference(),
}
_, err := methods.DestroyCollector(ctx, h.c, &req)
return err
}
func (h HistoryCollector) Reset(ctx context.Context) error {
req := types.ResetCollector{
This: h.Reference(),
}
_, err := methods.ResetCollector(ctx, h.c, &req)
return err
}
func (h HistoryCollector) Rewind(ctx context.Context) error {
req := types.RewindCollector{
This: h.Reference(),
}
_, err := methods.RewindCollector(ctx, h.c, &req)
return err
}
func (h HistoryCollector) SetPageSize(ctx context.Context, maxCount int32) error {
req := types.SetCollectorPageSize{
This: h.Reference(),
MaxCount: maxCount,
}
_, err := methods.SetCollectorPageSize(ctx, h.c, &req)
return err
}

View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostAccountManager struct {
Common
}
func NewHostAccountManager(c *vim25.Client, ref types.ManagedObjectReference) *HostAccountManager {
return &HostAccountManager{
Common: NewCommon(c, ref),
}
}
func (m HostAccountManager) Create(ctx context.Context, user *types.HostAccountSpec) error {
req := types.CreateUser{
This: m.Reference(),
User: user,
}
_, err := methods.CreateUser(ctx, m.Client(), &req)
return err
}
func (m HostAccountManager) Update(ctx context.Context, user *types.HostAccountSpec) error {
req := types.UpdateUser{
This: m.Reference(),
User: user,
}
_, err := methods.UpdateUser(ctx, m.Client(), &req)
return err
}
func (m HostAccountManager) Remove(ctx context.Context, userName string) error {
req := types.RemoveUser{
This: m.Reference(),
UserName: userName,
}
_, err := methods.RemoveUser(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,250 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"io"
"net/url"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// HostCertificateInfo provides helpers for types.HostCertificateManagerCertificateInfo
type HostCertificateInfo struct {
types.HostCertificateManagerCertificateInfo
ThumbprintSHA1 string
ThumbprintSHA256 string
Err error
Certificate *x509.Certificate `json:"-"`
subjectName *pkix.Name
issuerName *pkix.Name
}
// FromCertificate converts x509.Certificate to HostCertificateInfo
func (info *HostCertificateInfo) FromCertificate(cert *x509.Certificate) *HostCertificateInfo {
info.Certificate = cert
info.subjectName = &cert.Subject
info.issuerName = &cert.Issuer
info.Issuer = info.fromName(info.issuerName)
info.NotBefore = &cert.NotBefore
info.NotAfter = &cert.NotAfter
info.Subject = info.fromName(info.subjectName)
info.ThumbprintSHA1 = soap.ThumbprintSHA1(cert)
// SHA-256 for info purposes only, API fields all use SHA-1
sum := sha256.Sum256(cert.Raw)
hex := make([]string, len(sum))
for i, b := range sum {
hex[i] = fmt.Sprintf("%02X", b)
}
info.ThumbprintSHA256 = strings.Join(hex, ":")
if info.Status == "" {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusUnknown)
}
return info
}
// FromURL connects to the given URL.Host via tls.Dial with the given tls.Config and populates the HostCertificateInfo
// via tls.ConnectionState. If the certificate was verified with the given tls.Config, the Err field will be nil.
// Otherwise, Err will be set to the x509.UnknownAuthorityError or x509.HostnameError.
// If tls.Dial returns an error of any other type, that error is returned.
func (info *HostCertificateInfo) FromURL(u *url.URL, config *tls.Config) error {
addr := u.Host
if !(strings.LastIndex(addr, ":") > strings.LastIndex(addr, "]")) {
addr += ":443"
}
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
switch err.(type) {
case x509.UnknownAuthorityError:
case x509.HostnameError:
default:
return err
}
info.Err = err
conn, err = tls.Dial("tcp", addr, &tls.Config{InsecureSkipVerify: true})
if err != nil {
return err
}
} else {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusGood)
}
state := conn.ConnectionState()
_ = conn.Close()
info.FromCertificate(state.PeerCertificates[0])
return nil
}
var emailAddressOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}
func (info *HostCertificateInfo) fromName(name *pkix.Name) string {
var attrs []string
oids := map[string]string{
emailAddressOID.String(): "emailAddress",
}
for _, attr := range name.Names {
if key, ok := oids[attr.Type.String()]; ok {
attrs = append(attrs, fmt.Sprintf("%s=%s", key, attr.Value))
}
}
attrs = append(attrs, fmt.Sprintf("CN=%s", name.CommonName))
add := func(key string, vals []string) {
for _, val := range vals {
attrs = append(attrs, fmt.Sprintf("%s=%s", key, val))
}
}
elts := []struct {
key string
val []string
}{
{"OU", name.OrganizationalUnit},
{"O", name.Organization},
{"L", name.Locality},
{"ST", name.Province},
{"C", name.Country},
}
for _, elt := range elts {
add(elt.key, elt.val)
}
return strings.Join(attrs, ",")
}
func (info *HostCertificateInfo) toName(s string) *pkix.Name {
var name pkix.Name
for _, pair := range strings.Split(s, ",") {
attr := strings.SplitN(pair, "=", 2)
if len(attr) != 2 {
continue
}
v := attr[1]
switch strings.ToLower(attr[0]) {
case "cn":
name.CommonName = v
case "ou":
name.OrganizationalUnit = append(name.OrganizationalUnit, v)
case "o":
name.Organization = append(name.Organization, v)
case "l":
name.Locality = append(name.Locality, v)
case "st":
name.Province = append(name.Province, v)
case "c":
name.Country = append(name.Country, v)
case "emailaddress":
name.Names = append(name.Names, pkix.AttributeTypeAndValue{Type: emailAddressOID, Value: v})
}
}
return &name
}
// SubjectName parses Subject into a pkix.Name
func (info *HostCertificateInfo) SubjectName() *pkix.Name {
if info.subjectName != nil {
return info.subjectName
}
return info.toName(info.Subject)
}
// IssuerName parses Issuer into a pkix.Name
func (info *HostCertificateInfo) IssuerName() *pkix.Name {
if info.issuerName != nil {
return info.issuerName
}
return info.toName(info.Issuer)
}
// Write outputs info similar to the Chrome Certificate Viewer.
func (info *HostCertificateInfo) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
s := func(val string) string {
if val != "" {
return val
}
return "<Not Part Of Certificate>"
}
ss := func(val []string) string {
return s(strings.Join(val, ","))
}
name := func(n *pkix.Name) {
fmt.Fprintf(tw, " Common Name (CN):\t%s\n", s(n.CommonName))
fmt.Fprintf(tw, " Organization (O):\t%s\n", ss(n.Organization))
fmt.Fprintf(tw, " Organizational Unit (OU):\t%s\n", ss(n.OrganizationalUnit))
}
status := info.Status
if info.Err != nil {
status = fmt.Sprintf("ERROR %s", info.Err)
}
fmt.Fprintf(tw, "Certificate Status:\t%s\n", status)
fmt.Fprintln(tw, "Issued To:\t")
name(info.SubjectName())
fmt.Fprintln(tw, "Issued By:\t")
name(info.IssuerName())
fmt.Fprintln(tw, "Validity Period:\t")
fmt.Fprintf(tw, " Issued On:\t%s\n", info.NotBefore)
fmt.Fprintf(tw, " Expires On:\t%s\n", info.NotAfter)
if info.ThumbprintSHA1 != "" {
fmt.Fprintln(tw, "Thumbprints:\t")
if info.ThumbprintSHA256 != "" {
fmt.Fprintf(tw, " SHA-256 Thumbprint:\t%s\n", info.ThumbprintSHA256)
}
fmt.Fprintf(tw, " SHA-1 Thumbprint:\t%s\n", info.ThumbprintSHA1)
}
return tw.Flush()
}

View File

@ -0,0 +1,162 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
// HostCertificateManager provides helper methods around the HostSystem.ConfigManager.CertificateManager
type HostCertificateManager struct {
Common
Host *HostSystem
}
// NewHostCertificateManager creates a new HostCertificateManager helper
func NewHostCertificateManager(c *vim25.Client, ref types.ManagedObjectReference, host types.ManagedObjectReference) *HostCertificateManager {
return &HostCertificateManager{
Common: NewCommon(c, ref),
Host: NewHostSystem(c, host),
}
}
// CertificateInfo wraps the host CertificateManager certificateInfo property with the HostCertificateInfo helper.
// The ThumbprintSHA1 field is set to HostSystem.Summary.Config.SslThumbprint if the host system is managed by a vCenter.
func (m HostCertificateManager) CertificateInfo(ctx context.Context) (*HostCertificateInfo, error) {
var hs mo.HostSystem
var cm mo.HostCertificateManager
pc := property.DefaultCollector(m.Client())
err := pc.RetrieveOne(ctx, m.Reference(), []string{"certificateInfo"}, &cm)
if err != nil {
return nil, err
}
_ = pc.RetrieveOne(ctx, m.Host.Reference(), []string{"summary.config.sslThumbprint"}, &hs)
return &HostCertificateInfo{
HostCertificateManagerCertificateInfo: cm.CertificateInfo,
ThumbprintSHA1: hs.Summary.Config.SslThumbprint,
}, nil
}
// GenerateCertificateSigningRequest requests the host system to generate a certificate-signing request (CSR) for itself.
// The CSR is then typically provided to a Certificate Authority to sign and issue the SSL certificate for the host system.
// Use InstallServerCertificate to import this certificate.
func (m HostCertificateManager) GenerateCertificateSigningRequest(ctx context.Context, useIPAddressAsCommonName bool) (string, error) {
req := types.GenerateCertificateSigningRequest{
This: m.Reference(),
UseIpAddressAsCommonName: useIPAddressAsCommonName,
}
res, err := methods.GenerateCertificateSigningRequest(ctx, m.Client(), &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// GenerateCertificateSigningRequestByDn requests the host system to generate a certificate-signing request (CSR) for itself.
// Alternative version similar to GenerateCertificateSigningRequest but takes a Distinguished Name (DN) as a parameter.
func (m HostCertificateManager) GenerateCertificateSigningRequestByDn(ctx context.Context, distinguishedName string) (string, error) {
req := types.GenerateCertificateSigningRequestByDn{
This: m.Reference(),
DistinguishedName: distinguishedName,
}
res, err := methods.GenerateCertificateSigningRequestByDn(ctx, m.Client(), &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// InstallServerCertificate imports the given SSL certificate to the host system.
func (m HostCertificateManager) InstallServerCertificate(ctx context.Context, cert string) error {
req := types.InstallServerCertificate{
This: m.Reference(),
Cert: cert,
}
_, err := methods.InstallServerCertificate(ctx, m.Client(), &req)
if err != nil {
return err
}
// NotifyAffectedService is internal, not exposing as we don't have a use case other than with InstallServerCertificate
// Without this call, hostd needs to be restarted to use the updated certificate
// Note: using Refresh as it has the same struct/signature, we just need to use different xml name tags
body := struct {
Req *types.Refresh `xml:"urn:vim25 NotifyAffectedServices,omitempty"`
Res *types.RefreshResponse `xml:"urn:vim25 NotifyAffectedServicesResponse,omitempty"`
methods.RefreshBody
}{
Req: &types.Refresh{This: m.Reference()},
}
return m.Client().RoundTrip(ctx, &body, &body)
}
// ListCACertificateRevocationLists returns the SSL CRLs of Certificate Authorities that are trusted by the host system.
func (m HostCertificateManager) ListCACertificateRevocationLists(ctx context.Context) ([]string, error) {
req := types.ListCACertificateRevocationLists{
This: m.Reference(),
}
res, err := methods.ListCACertificateRevocationLists(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
// ListCACertificates returns the SSL certificates of Certificate Authorities that are trusted by the host system.
func (m HostCertificateManager) ListCACertificates(ctx context.Context) ([]string, error) {
req := types.ListCACertificates{
This: m.Reference(),
}
res, err := methods.ListCACertificates(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
// ReplaceCACertificatesAndCRLs replaces the trusted CA certificates and CRL used by the host system.
// These determine whether the server can verify the identity of an external entity.
func (m HostCertificateManager) ReplaceCACertificatesAndCRLs(ctx context.Context, caCert []string, caCrl []string) error {
req := types.ReplaceCACertificatesAndCRLs{
This: m.Reference(),
CaCert: caCert,
CaCrl: caCrl,
}
_, err := methods.ReplaceCACertificatesAndCRLs(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,196 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostConfigManager struct {
Common
}
func NewHostConfigManager(c *vim25.Client, ref types.ManagedObjectReference) *HostConfigManager {
return &HostConfigManager{
Common: NewCommon(c, ref),
}
}
func (m HostConfigManager) DatastoreSystem(ctx context.Context) (*HostDatastoreSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.datastoreSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostDatastoreSystem(m.c, *h.ConfigManager.DatastoreSystem), nil
}
func (m HostConfigManager) NetworkSystem(ctx context.Context) (*HostNetworkSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.networkSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostNetworkSystem(m.c, *h.ConfigManager.NetworkSystem), nil
}
func (m HostConfigManager) FirewallSystem(ctx context.Context) (*HostFirewallSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.firewallSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostFirewallSystem(m.c, *h.ConfigManager.FirewallSystem), nil
}
func (m HostConfigManager) StorageSystem(ctx context.Context) (*HostStorageSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.storageSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostStorageSystem(m.c, *h.ConfigManager.StorageSystem), nil
}
func (m HostConfigManager) VirtualNicManager(ctx context.Context) (*HostVirtualNicManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.virtualNicManager"}, &h)
if err != nil {
return nil, err
}
return NewHostVirtualNicManager(m.c, *h.ConfigManager.VirtualNicManager, m.Reference()), nil
}
func (m HostConfigManager) VsanSystem(ctx context.Context) (*HostVsanSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanSystem"}, &h)
if err != nil {
return nil, err
}
// Added in 5.5
if h.ConfigManager.VsanSystem == nil {
return nil, ErrNotSupported
}
return NewHostVsanSystem(m.c, *h.ConfigManager.VsanSystem), nil
}
func (m HostConfigManager) VsanInternalSystem(ctx context.Context) (*HostVsanInternalSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanInternalSystem"}, &h)
if err != nil {
return nil, err
}
// Added in 5.5
if h.ConfigManager.VsanInternalSystem == nil {
return nil, ErrNotSupported
}
return NewHostVsanInternalSystem(m.c, *h.ConfigManager.VsanInternalSystem), nil
}
func (m HostConfigManager) AccountManager(ctx context.Context) (*HostAccountManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.accountManager"}, &h)
if err != nil {
return nil, err
}
ref := h.ConfigManager.AccountManager // Added in 6.0
if ref == nil {
// Versions < 5.5 can use the ServiceContent ref,
// but we can only use it when connected directly to ESX.
c := m.Client()
if !c.IsVC() {
ref = c.ServiceContent.AccountManager
}
if ref == nil {
return nil, ErrNotSupported
}
}
return NewHostAccountManager(m.c, *ref), nil
}
func (m HostConfigManager) OptionManager(ctx context.Context) (*OptionManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.advancedOption"}, &h)
if err != nil {
return nil, err
}
return NewOptionManager(m.c, *h.ConfigManager.AdvancedOption), nil
}
func (m HostConfigManager) ServiceSystem(ctx context.Context) (*HostServiceSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.serviceSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostServiceSystem(m.c, *h.ConfigManager.ServiceSystem), nil
}
func (m HostConfigManager) CertificateManager(ctx context.Context) (*HostCertificateManager, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.certificateManager"}, &h)
if err != nil {
return nil, err
}
// Added in 6.0
if h.ConfigManager.CertificateManager == nil {
return nil, ErrNotSupported
}
return NewHostCertificateManager(m.c, *h.ConfigManager.CertificateManager, m.Reference()), nil
}
func (m HostConfigManager) DateTimeSystem(ctx context.Context) (*HostDateTimeSystem, error) {
var h mo.HostSystem
err := m.Properties(ctx, m.Reference(), []string{"configManager.dateTimeSystem"}, &h)
if err != nil {
return nil, err
}
return NewHostDateTimeSystem(m.c, *h.ConfigManager.DateTimeSystem), nil
}

View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDatastoreBrowser struct {
Common
}
func NewHostDatastoreBrowser(c *vim25.Client, ref types.ManagedObjectReference) *HostDatastoreBrowser {
return &HostDatastoreBrowser{
Common: NewCommon(c, ref),
}
}
func (b HostDatastoreBrowser) SearchDatastore(ctx context.Context, datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) {
req := types.SearchDatastore_Task{
This: b.Reference(),
DatastorePath: datastorePath,
SearchSpec: searchSpec,
}
res, err := methods.SearchDatastore_Task(ctx, b.c, &req)
if err != nil {
return nil, err
}
return NewTask(b.c, res.Returnval), nil
}
func (b HostDatastoreBrowser) SearchDatastoreSubFolders(ctx context.Context, datastorePath string, searchSpec *types.HostDatastoreBrowserSearchSpec) (*Task, error) {
req := types.SearchDatastoreSubFolders_Task{
This: b.Reference(),
DatastorePath: datastorePath,
SearchSpec: searchSpec,
}
res, err := methods.SearchDatastoreSubFolders_Task(ctx, b.c, &req)
if err != nil {
return nil, err
}
return NewTask(b.c, res.Returnval), nil
}

View File

@ -0,0 +1,119 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDatastoreSystem struct {
Common
}
func NewHostDatastoreSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostDatastoreSystem {
return &HostDatastoreSystem{
Common: NewCommon(c, ref),
}
}
func (s HostDatastoreSystem) CreateLocalDatastore(ctx context.Context, name string, path string) (*Datastore, error) {
req := types.CreateLocalDatastore{
This: s.Reference(),
Name: name,
Path: path,
}
res, err := methods.CreateLocalDatastore(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewDatastore(s.Client(), res.Returnval), nil
}
func (s HostDatastoreSystem) CreateNasDatastore(ctx context.Context, spec types.HostNasVolumeSpec) (*Datastore, error) {
req := types.CreateNasDatastore{
This: s.Reference(),
Spec: spec,
}
res, err := methods.CreateNasDatastore(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewDatastore(s.Client(), res.Returnval), nil
}
func (s HostDatastoreSystem) CreateVmfsDatastore(ctx context.Context, spec types.VmfsDatastoreCreateSpec) (*Datastore, error) {
req := types.CreateVmfsDatastore{
This: s.Reference(),
Spec: spec,
}
res, err := methods.CreateVmfsDatastore(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewDatastore(s.Client(), res.Returnval), nil
}
func (s HostDatastoreSystem) Remove(ctx context.Context, ds *Datastore) error {
req := types.RemoveDatastore{
This: s.Reference(),
Datastore: ds.Reference(),
}
_, err := methods.RemoveDatastore(ctx, s.Client(), &req)
if err != nil {
return err
}
return nil
}
func (s HostDatastoreSystem) QueryAvailableDisksForVmfs(ctx context.Context) ([]types.HostScsiDisk, error) {
req := types.QueryAvailableDisksForVmfs{
This: s.Reference(),
}
res, err := methods.QueryAvailableDisksForVmfs(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (s HostDatastoreSystem) QueryVmfsDatastoreCreateOptions(ctx context.Context, devicePath string) ([]types.VmfsDatastoreOption, error) {
req := types.QueryVmfsDatastoreCreateOptions{
This: s.Reference(),
DevicePath: devicePath,
}
res, err := methods.QueryVmfsDatastoreCreateOptions(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,69 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"time"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostDateTimeSystem struct {
Common
}
func NewHostDateTimeSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostDateTimeSystem {
return &HostDateTimeSystem{
Common: NewCommon(c, ref),
}
}
func (s HostDateTimeSystem) UpdateConfig(ctx context.Context, config types.HostDateTimeConfig) error {
req := types.UpdateDateTimeConfig{
This: s.Reference(),
Config: config,
}
_, err := methods.UpdateDateTimeConfig(ctx, s.c, &req)
return err
}
func (s HostDateTimeSystem) Update(ctx context.Context, date time.Time) error {
req := types.UpdateDateTime{
This: s.Reference(),
DateTime: date,
}
_, err := methods.UpdateDateTime(ctx, s.c, &req)
return err
}
func (s HostDateTimeSystem) Query(ctx context.Context) (*time.Time, error) {
req := types.QueryDateTime{
This: s.Reference(),
}
res, err := methods.QueryDateTime(ctx, s.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}

View File

@ -0,0 +1,181 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"fmt"
"strings"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostFirewallSystem struct {
Common
}
func NewHostFirewallSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostFirewallSystem {
return &HostFirewallSystem{
Common: NewCommon(c, ref),
}
}
func (s HostFirewallSystem) DisableRuleset(ctx context.Context, id string) error {
req := types.DisableRuleset{
This: s.Reference(),
Id: id,
}
_, err := methods.DisableRuleset(ctx, s.c, &req)
return err
}
func (s HostFirewallSystem) EnableRuleset(ctx context.Context, id string) error {
req := types.EnableRuleset{
This: s.Reference(),
Id: id,
}
_, err := methods.EnableRuleset(ctx, s.c, &req)
return err
}
func (s HostFirewallSystem) Refresh(ctx context.Context) error {
req := types.RefreshFirewall{
This: s.Reference(),
}
_, err := methods.RefreshFirewall(ctx, s.c, &req)
return err
}
func (s HostFirewallSystem) Info(ctx context.Context) (*types.HostFirewallInfo, error) {
var fs mo.HostFirewallSystem
err := s.Properties(ctx, s.Reference(), []string{"firewallInfo"}, &fs)
if err != nil {
return nil, err
}
return fs.FirewallInfo, nil
}
// HostFirewallRulesetList provides helpers for a slice of types.HostFirewallRuleset
type HostFirewallRulesetList []types.HostFirewallRuleset
// ByRule returns a HostFirewallRulesetList where Direction, PortType and Protocol are equal and Port is within range
func (l HostFirewallRulesetList) ByRule(rule types.HostFirewallRule) HostFirewallRulesetList {
var matches HostFirewallRulesetList
for _, rs := range l {
for _, r := range rs.Rule {
if r.PortType != rule.PortType ||
r.Protocol != rule.Protocol ||
r.Direction != rule.Direction {
continue
}
if r.EndPort == 0 && rule.Port == r.Port ||
rule.Port >= r.Port && rule.Port <= r.EndPort {
matches = append(matches, rs)
break
}
}
}
return matches
}
// EnabledByRule returns a HostFirewallRulesetList with Match(rule) applied and filtered via Enabled()
// if enabled param is true, otherwise filtered via Disabled().
// An error is returned if the resulting list is empty.
func (l HostFirewallRulesetList) EnabledByRule(rule types.HostFirewallRule, enabled bool) (HostFirewallRulesetList, error) {
var matched, skipped HostFirewallRulesetList
var matchedKind, skippedKind string
l = l.ByRule(rule)
if enabled {
matched = l.Enabled()
matchedKind = "enabled"
skipped = l.Disabled()
skippedKind = "disabled"
} else {
matched = l.Disabled()
matchedKind = "disabled"
skipped = l.Enabled()
skippedKind = "enabled"
}
if len(matched) == 0 {
msg := fmt.Sprintf("%d %s firewall rulesets match %s %s %s %d, %d %s rulesets match",
len(matched), matchedKind,
rule.Direction, rule.Protocol, rule.PortType, rule.Port,
len(skipped), skippedKind)
if len(skipped) != 0 {
msg += fmt.Sprintf(": %s", strings.Join(skipped.Keys(), ", "))
}
return nil, errors.New(msg)
}
return matched, nil
}
// Enabled returns a HostFirewallRulesetList with enabled rules
func (l HostFirewallRulesetList) Enabled() HostFirewallRulesetList {
var matches HostFirewallRulesetList
for _, rs := range l {
if rs.Enabled {
matches = append(matches, rs)
}
}
return matches
}
// Disabled returns a HostFirewallRulesetList with disabled rules
func (l HostFirewallRulesetList) Disabled() HostFirewallRulesetList {
var matches HostFirewallRulesetList
for _, rs := range l {
if !rs.Enabled {
matches = append(matches, rs)
}
}
return matches
}
// Keys returns the HostFirewallRuleset.Key for each ruleset in the list
func (l HostFirewallRulesetList) Keys() []string {
var keys []string
for _, rs := range l {
keys = append(keys, rs.Key)
}
return keys
}

View File

@ -0,0 +1,358 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostNetworkSystem struct {
Common
}
func NewHostNetworkSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostNetworkSystem {
return &HostNetworkSystem{
Common: NewCommon(c, ref),
}
}
// AddPortGroup wraps methods.AddPortGroup
func (o HostNetworkSystem) AddPortGroup(ctx context.Context, portgrp types.HostPortGroupSpec) error {
req := types.AddPortGroup{
This: o.Reference(),
Portgrp: portgrp,
}
_, err := methods.AddPortGroup(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// AddServiceConsoleVirtualNic wraps methods.AddServiceConsoleVirtualNic
func (o HostNetworkSystem) AddServiceConsoleVirtualNic(ctx context.Context, portgroup string, nic types.HostVirtualNicSpec) (string, error) {
req := types.AddServiceConsoleVirtualNic{
This: o.Reference(),
Portgroup: portgroup,
Nic: nic,
}
res, err := methods.AddServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// AddVirtualNic wraps methods.AddVirtualNic
func (o HostNetworkSystem) AddVirtualNic(ctx context.Context, portgroup string, nic types.HostVirtualNicSpec) (string, error) {
req := types.AddVirtualNic{
This: o.Reference(),
Portgroup: portgroup,
Nic: nic,
}
res, err := methods.AddVirtualNic(ctx, o.c, &req)
if err != nil {
return "", err
}
return res.Returnval, nil
}
// AddVirtualSwitch wraps methods.AddVirtualSwitch
func (o HostNetworkSystem) AddVirtualSwitch(ctx context.Context, vswitchName string, spec *types.HostVirtualSwitchSpec) error {
req := types.AddVirtualSwitch{
This: o.Reference(),
VswitchName: vswitchName,
Spec: spec,
}
_, err := methods.AddVirtualSwitch(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// QueryNetworkHint wraps methods.QueryNetworkHint
func (o HostNetworkSystem) QueryNetworkHint(ctx context.Context, device []string) error {
req := types.QueryNetworkHint{
This: o.Reference(),
Device: device,
}
_, err := methods.QueryNetworkHint(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RefreshNetworkSystem wraps methods.RefreshNetworkSystem
func (o HostNetworkSystem) RefreshNetworkSystem(ctx context.Context) error {
req := types.RefreshNetworkSystem{
This: o.Reference(),
}
_, err := methods.RefreshNetworkSystem(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemovePortGroup wraps methods.RemovePortGroup
func (o HostNetworkSystem) RemovePortGroup(ctx context.Context, pgName string) error {
req := types.RemovePortGroup{
This: o.Reference(),
PgName: pgName,
}
_, err := methods.RemovePortGroup(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemoveServiceConsoleVirtualNic wraps methods.RemoveServiceConsoleVirtualNic
func (o HostNetworkSystem) RemoveServiceConsoleVirtualNic(ctx context.Context, device string) error {
req := types.RemoveServiceConsoleVirtualNic{
This: o.Reference(),
Device: device,
}
_, err := methods.RemoveServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemoveVirtualNic wraps methods.RemoveVirtualNic
func (o HostNetworkSystem) RemoveVirtualNic(ctx context.Context, device string) error {
req := types.RemoveVirtualNic{
This: o.Reference(),
Device: device,
}
_, err := methods.RemoveVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RemoveVirtualSwitch wraps methods.RemoveVirtualSwitch
func (o HostNetworkSystem) RemoveVirtualSwitch(ctx context.Context, vswitchName string) error {
req := types.RemoveVirtualSwitch{
This: o.Reference(),
VswitchName: vswitchName,
}
_, err := methods.RemoveVirtualSwitch(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// RestartServiceConsoleVirtualNic wraps methods.RestartServiceConsoleVirtualNic
func (o HostNetworkSystem) RestartServiceConsoleVirtualNic(ctx context.Context, device string) error {
req := types.RestartServiceConsoleVirtualNic{
This: o.Reference(),
Device: device,
}
_, err := methods.RestartServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateConsoleIpRouteConfig wraps methods.UpdateConsoleIpRouteConfig
func (o HostNetworkSystem) UpdateConsoleIpRouteConfig(ctx context.Context, config types.BaseHostIpRouteConfig) error {
req := types.UpdateConsoleIpRouteConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateConsoleIpRouteConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateDnsConfig wraps methods.UpdateDnsConfig
func (o HostNetworkSystem) UpdateDnsConfig(ctx context.Context, config types.BaseHostDnsConfig) error {
req := types.UpdateDnsConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateDnsConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateIpRouteConfig wraps methods.UpdateIpRouteConfig
func (o HostNetworkSystem) UpdateIpRouteConfig(ctx context.Context, config types.BaseHostIpRouteConfig) error {
req := types.UpdateIpRouteConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateIpRouteConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateIpRouteTableConfig wraps methods.UpdateIpRouteTableConfig
func (o HostNetworkSystem) UpdateIpRouteTableConfig(ctx context.Context, config types.HostIpRouteTableConfig) error {
req := types.UpdateIpRouteTableConfig{
This: o.Reference(),
Config: config,
}
_, err := methods.UpdateIpRouteTableConfig(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateNetworkConfig wraps methods.UpdateNetworkConfig
func (o HostNetworkSystem) UpdateNetworkConfig(ctx context.Context, config types.HostNetworkConfig, changeMode string) (*types.HostNetworkConfigResult, error) {
req := types.UpdateNetworkConfig{
This: o.Reference(),
Config: config,
ChangeMode: changeMode,
}
res, err := methods.UpdateNetworkConfig(ctx, o.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
// UpdatePhysicalNicLinkSpeed wraps methods.UpdatePhysicalNicLinkSpeed
func (o HostNetworkSystem) UpdatePhysicalNicLinkSpeed(ctx context.Context, device string, linkSpeed *types.PhysicalNicLinkInfo) error {
req := types.UpdatePhysicalNicLinkSpeed{
This: o.Reference(),
Device: device,
LinkSpeed: linkSpeed,
}
_, err := methods.UpdatePhysicalNicLinkSpeed(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdatePortGroup wraps methods.UpdatePortGroup
func (o HostNetworkSystem) UpdatePortGroup(ctx context.Context, pgName string, portgrp types.HostPortGroupSpec) error {
req := types.UpdatePortGroup{
This: o.Reference(),
PgName: pgName,
Portgrp: portgrp,
}
_, err := methods.UpdatePortGroup(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateServiceConsoleVirtualNic wraps methods.UpdateServiceConsoleVirtualNic
func (o HostNetworkSystem) UpdateServiceConsoleVirtualNic(ctx context.Context, device string, nic types.HostVirtualNicSpec) error {
req := types.UpdateServiceConsoleVirtualNic{
This: o.Reference(),
Device: device,
Nic: nic,
}
_, err := methods.UpdateServiceConsoleVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateVirtualNic wraps methods.UpdateVirtualNic
func (o HostNetworkSystem) UpdateVirtualNic(ctx context.Context, device string, nic types.HostVirtualNicSpec) error {
req := types.UpdateVirtualNic{
This: o.Reference(),
Device: device,
Nic: nic,
}
_, err := methods.UpdateVirtualNic(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}
// UpdateVirtualSwitch wraps methods.UpdateVirtualSwitch
func (o HostNetworkSystem) UpdateVirtualSwitch(ctx context.Context, vswitchName string, spec types.HostVirtualSwitchSpec) error {
req := types.UpdateVirtualSwitch{
This: o.Reference(),
VswitchName: vswitchName,
Spec: spec,
}
_, err := methods.UpdateVirtualSwitch(ctx, o.c, &req)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,88 @@
/*
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostServiceSystem struct {
Common
}
func NewHostServiceSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostServiceSystem {
return &HostServiceSystem{
Common: NewCommon(c, ref),
}
}
func (s HostServiceSystem) Service(ctx context.Context) ([]types.HostService, error) {
var ss mo.HostServiceSystem
err := s.Properties(ctx, s.Reference(), []string{"serviceInfo.service"}, &ss)
if err != nil {
return nil, err
}
return ss.ServiceInfo.Service, nil
}
func (s HostServiceSystem) Start(ctx context.Context, id string) error {
req := types.StartService{
This: s.Reference(),
Id: id,
}
_, err := methods.StartService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) Stop(ctx context.Context, id string) error {
req := types.StopService{
This: s.Reference(),
Id: id,
}
_, err := methods.StopService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) Restart(ctx context.Context, id string) error {
req := types.RestartService{
This: s.Reference(),
Id: id,
}
_, err := methods.RestartService(ctx, s.Client(), &req)
return err
}
func (s HostServiceSystem) UpdatePolicy(ctx context.Context, id string, policy string) error {
req := types.UpdateServicePolicy{
This: s.Reference(),
Id: id,
Policy: policy,
}
_, err := methods.UpdateServicePolicy(ctx, s.Client(), &req)
return err
}

View File

@ -0,0 +1,174 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"errors"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostStorageSystem struct {
Common
}
func NewHostStorageSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostStorageSystem {
return &HostStorageSystem{
Common: NewCommon(c, ref),
}
}
func (s HostStorageSystem) RetrieveDiskPartitionInfo(ctx context.Context, devicePath string) (*types.HostDiskPartitionInfo, error) {
req := types.RetrieveDiskPartitionInfo{
This: s.Reference(),
DevicePath: []string{devicePath},
}
res, err := methods.RetrieveDiskPartitionInfo(ctx, s.c, &req)
if err != nil {
return nil, err
}
if res.Returnval == nil || len(res.Returnval) == 0 {
return nil, errors.New("no partition info")
}
return &res.Returnval[0], nil
}
func (s HostStorageSystem) ComputeDiskPartitionInfo(ctx context.Context, devicePath string, layout types.HostDiskPartitionLayout) (*types.HostDiskPartitionInfo, error) {
req := types.ComputeDiskPartitionInfo{
This: s.Reference(),
DevicePath: devicePath,
Layout: layout,
}
res, err := methods.ComputeDiskPartitionInfo(ctx, s.c, &req)
if err != nil {
return nil, err
}
return &res.Returnval, nil
}
func (s HostStorageSystem) UpdateDiskPartitionInfo(ctx context.Context, devicePath string, spec types.HostDiskPartitionSpec) error {
req := types.UpdateDiskPartitions{
This: s.Reference(),
DevicePath: devicePath,
Spec: spec,
}
_, err := methods.UpdateDiskPartitions(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) RescanAllHba(ctx context.Context) error {
req := types.RescanAllHba{
This: s.Reference(),
}
_, err := methods.RescanAllHba(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) Refresh(ctx context.Context) error {
req := types.RefreshStorageSystem{
This: s.Reference(),
}
_, err := methods.RefreshStorageSystem(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) RescanVmfs(ctx context.Context) error {
req := types.RescanVmfs{
This: s.Reference(),
}
_, err := methods.RescanVmfs(ctx, s.c, &req)
return err
}
func (s HostStorageSystem) MarkAsSsd(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsSsd_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsSsd_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) MarkAsNonSsd(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsNonSsd_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsNonSsd_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) MarkAsLocal(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsLocal_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsLocal_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) MarkAsNonLocal(ctx context.Context, uuid string) (*Task, error) {
req := types.MarkAsNonLocal_Task{
This: s.Reference(),
ScsiDiskUuid: uuid,
}
res, err := methods.MarkAsNonLocal_Task(ctx, s.c, &req)
if err != nil {
return nil, err
}
return NewTask(s.c, res.Returnval), nil
}
func (s HostStorageSystem) AttachScsiLun(ctx context.Context, uuid string) error {
req := types.AttachScsiLun{
This: s.Reference(),
LunUuid: uuid,
}
_, err := methods.AttachScsiLun(ctx, s.c, &req)
return err
}

153
vendor/github.com/vmware/govmomi/object/host_system.go generated vendored Normal file
View File

@ -0,0 +1,153 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"fmt"
"net"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostSystem struct {
Common
}
func NewHostSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostSystem {
return &HostSystem{
Common: NewCommon(c, ref),
}
}
func (h HostSystem) ConfigManager() *HostConfigManager {
return NewHostConfigManager(h.c, h.Reference())
}
func (h HostSystem) ResourcePool(ctx context.Context) (*ResourcePool, error) {
var mh mo.HostSystem
err := h.Properties(ctx, h.Reference(), []string{"parent"}, &mh)
if err != nil {
return nil, err
}
var mcr *mo.ComputeResource
var parent interface{}
switch mh.Parent.Type {
case "ComputeResource":
mcr = new(mo.ComputeResource)
parent = mcr
case "ClusterComputeResource":
mcc := new(mo.ClusterComputeResource)
mcr = &mcc.ComputeResource
parent = mcc
default:
return nil, fmt.Errorf("unknown host parent type: %s", mh.Parent.Type)
}
err = h.Properties(ctx, *mh.Parent, []string{"resourcePool"}, parent)
if err != nil {
return nil, err
}
pool := NewResourcePool(h.c, *mcr.ResourcePool)
return pool, nil
}
func (h HostSystem) ManagementIPs(ctx context.Context) ([]net.IP, error) {
var mh mo.HostSystem
err := h.Properties(ctx, h.Reference(), []string{"config.virtualNicManagerInfo.netConfig"}, &mh)
if err != nil {
return nil, err
}
var ips []net.IP
for _, nc := range mh.Config.VirtualNicManagerInfo.NetConfig {
if nc.NicType == "management" && len(nc.CandidateVnic) > 0 {
ip := net.ParseIP(nc.CandidateVnic[0].Spec.Ip.IpAddress)
if ip != nil {
ips = append(ips, ip)
}
}
}
return ips, nil
}
func (h HostSystem) Disconnect(ctx context.Context) (*Task, error) {
req := types.DisconnectHost_Task{
This: h.Reference(),
}
res, err := methods.DisconnectHost_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}
func (h HostSystem) Reconnect(ctx context.Context, cnxSpec *types.HostConnectSpec, reconnectSpec *types.HostSystemReconnectSpec) (*Task, error) {
req := types.ReconnectHost_Task{
This: h.Reference(),
CnxSpec: cnxSpec,
ReconnectSpec: reconnectSpec,
}
res, err := methods.ReconnectHost_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}
func (h HostSystem) EnterMaintenanceMode(ctx context.Context, timeout int32, evacuate bool, spec *types.HostMaintenanceSpec) (*Task, error) {
req := types.EnterMaintenanceMode_Task{
This: h.Reference(),
Timeout: timeout,
EvacuatePoweredOffVms: types.NewBool(evacuate),
MaintenanceSpec: spec,
}
res, err := methods.EnterMaintenanceMode_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}
func (h HostSystem) ExitMaintenanceMode(ctx context.Context, timeout int32) (*Task, error) {
req := types.ExitMaintenanceMode_Task{
This: h.Reference(),
Timeout: timeout,
}
res, err := methods.ExitMaintenanceMode_Task(ctx, h.c, &req)
if err != nil {
return nil, err
}
return NewTask(h.c, res.Returnval), nil
}

View File

@ -0,0 +1,93 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostVirtualNicManager struct {
Common
Host *HostSystem
}
func NewHostVirtualNicManager(c *vim25.Client, ref types.ManagedObjectReference, host types.ManagedObjectReference) *HostVirtualNicManager {
return &HostVirtualNicManager{
Common: NewCommon(c, ref),
Host: NewHostSystem(c, host),
}
}
func (m HostVirtualNicManager) Info(ctx context.Context) (*types.HostVirtualNicManagerInfo, error) {
var vnm mo.HostVirtualNicManager
err := m.Properties(ctx, m.Reference(), []string{"info"}, &vnm)
if err != nil {
return nil, err
}
return &vnm.Info, nil
}
func (m HostVirtualNicManager) DeselectVnic(ctx context.Context, nicType string, device string) error {
if nicType == string(types.HostVirtualNicManagerNicTypeVsan) {
// Avoid fault.NotSupported:
// "Error deselecting device '$device': VSAN interfaces must be deselected using vim.host.VsanSystem"
s, err := m.Host.ConfigManager().VsanSystem(ctx)
if err != nil {
return err
}
return s.updateVnic(ctx, device, false)
}
req := types.DeselectVnicForNicType{
This: m.Reference(),
NicType: nicType,
Device: device,
}
_, err := methods.DeselectVnicForNicType(ctx, m.Client(), &req)
return err
}
func (m HostVirtualNicManager) SelectVnic(ctx context.Context, nicType string, device string) error {
if nicType == string(types.HostVirtualNicManagerNicTypeVsan) {
// Avoid fault.NotSupported:
// "Error selecting device '$device': VSAN interfaces must be selected using vim.host.VsanSystem"
s, err := m.Host.ConfigManager().VsanSystem(ctx)
if err != nil {
return err
}
return s.updateVnic(ctx, device, true)
}
req := types.SelectVnicForNicType{
This: m.Reference(),
NicType: nicType,
Device: device,
}
_, err := methods.SelectVnicForNicType(ctx, m.Client(), &req)
return err
}

View File

@ -0,0 +1,117 @@
/*
Copyright (c) 2017 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"encoding/json"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
type HostVsanInternalSystem struct {
Common
}
func NewHostVsanInternalSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanInternalSystem {
m := HostVsanInternalSystem{
Common: NewCommon(c, ref),
}
return &m
}
// QueryVsanObjectUuidsByFilter returns vSAN DOM object uuids by filter.
func (m HostVsanInternalSystem) QueryVsanObjectUuidsByFilter(ctx context.Context, uuids []string, limit int32, version int32) ([]string, error) {
req := types.QueryVsanObjectUuidsByFilter{
This: m.Reference(),
Uuids: uuids,
Limit: &limit,
Version: version,
}
res, err := methods.QueryVsanObjectUuidsByFilter(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
type VsanObjExtAttrs struct {
Type string `json:"Object type"`
Class string `json:"Object class"`
Size string `json:"Object size"`
Path string `json:"Object path"`
Name string `json:"User friendly name"`
}
func (a *VsanObjExtAttrs) DatastorePath(dir string) string {
l := len(dir)
path := a.Path
if len(path) >= l {
path = a.Path[l:]
}
if path != "" {
return path
}
return a.Name // vmnamespace
}
// GetVsanObjExtAttrs is internal and intended for troubleshooting/debugging situations in the field.
// WARNING: This API can be slow because we do IOs (reads) to all the objects.
func (m HostVsanInternalSystem) GetVsanObjExtAttrs(ctx context.Context, uuids []string) (map[string]VsanObjExtAttrs, error) {
req := types.GetVsanObjExtAttrs{
This: m.Reference(),
Uuids: uuids,
}
res, err := methods.GetVsanObjExtAttrs(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
var attrs map[string]VsanObjExtAttrs
err = json.Unmarshal([]byte(res.Returnval), &attrs)
return attrs, err
}
// DeleteVsanObjects is internal and intended for troubleshooting/debugging only.
// WARNING: This API can be slow because we do IOs to all the objects.
// DOM won't allow access to objects which have lost quorum. Such objects can be deleted with the optional "force" flag.
// These objects may however re-appear with quorum if the absent components come back (network partition gets resolved, etc.)
func (m HostVsanInternalSystem) DeleteVsanObjects(ctx context.Context, uuids []string, force *bool) ([]types.HostVsanInternalSystemDeleteVsanObjectsResult, error) {
req := types.DeleteVsanObjects{
This: m.Reference(),
Uuids: uuids,
Force: force,
}
res, err := methods.DeleteVsanObjects(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@ -0,0 +1,88 @@
/*
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package object
import (
"context"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type HostVsanSystem struct {
Common
}
func NewHostVsanSystem(c *vim25.Client, ref types.ManagedObjectReference) *HostVsanSystem {
return &HostVsanSystem{
Common: NewCommon(c, ref),
}
}
func (s HostVsanSystem) Update(ctx context.Context, config types.VsanHostConfigInfo) (*Task, error) {
req := types.UpdateVsan_Task{
This: s.Reference(),
Config: config,
}
res, err := methods.UpdateVsan_Task(ctx, s.Client(), &req)
if err != nil {
return nil, err
}
return NewTask(s.Client(), res.Returnval), nil
}
// updateVnic in support of the HostVirtualNicManager.{SelectVnic,DeselectVnic} methods
func (s HostVsanSystem) updateVnic(ctx context.Context, device string, enable bool) error {
var vsan mo.HostVsanSystem
err := s.Properties(ctx, s.Reference(), []string{"config.networkInfo.port"}, &vsan)
if err != nil {
return err
}
info := vsan.Config
var port []types.VsanHostConfigInfoNetworkInfoPortConfig
for _, p := range info.NetworkInfo.Port {
if p.Device == device {
continue
}
port = append(port, p)
}
if enable {
port = append(port, types.VsanHostConfigInfoNetworkInfoPortConfig{
Device: device,
})
}
info.NetworkInfo.Port = port
task, err := s.Update(ctx, info)
if err != nil {
return err
}
_, err = task.WaitForResult(ctx, nil)
return err
}

Some files were not shown because too many files have changed in this diff Show More