Update vendor dir and Godeps.json with new Godep

This commit is contained in:
saadali
2016-05-11 16:59:55 -07:00
parent b83af3d481
commit c708e2cc82
2053 changed files with 955 additions and 140589 deletions

View File

@@ -1,116 +0,0 @@
/*
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 event
import (
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/types"
)
func multipleObjectEvents(ctx context.Context, m Manager, objects []types.ManagedObjectReference, pageSize int32, tail bool, force bool, prop []string, f func([]types.BaseEvent) error) error {
// create an EventHistoryCollector for each object
var collectors []types.ManagedObjectReference
for _, o := range objects {
filter := types.EventFilterSpec{
Entity: &types.EventFilterSpecByEntity{
Entity: o,
Recursion: types.EventFilterSpecRecursionOptionAll,
},
}
collector, err := m.CreateCollectorForEvents(ctx, filter)
if err != nil {
return fmt.Errorf("[%#v] %s", o, err)
}
defer collector.Destroy(ctx)
err = collector.SetPageSize(ctx, pageSize)
if err != nil {
return err
}
collectors = append(collectors, collector.Reference())
}
// create and populate a ListView
viewMgr := view.NewManager(m.Client())
listView, err := viewMgr.CreateListView(ctx, collectors)
if err != nil {
return err
}
count := 0
// Retrieve the property from the objects in the ListView
return property.WaitForView(ctx, property.DefaultCollector(m.Client()), listView.Reference(), collectors[0], prop, func(pc []types.PropertyChange) bool {
for _, u := range pc {
if u.Name != prop[0] {
continue
}
if u.Val == nil {
continue
}
f(u.Val.(types.ArrayOfEvent).Event)
}
count++
if count == len(collectors) && !tail {
return true
}
return false
})
}
func singleObjectEvents(ctx context.Context, m Manager, object types.ManagedObjectReference, pageSize int32, tail bool, force bool, prop []string, f func([]types.BaseEvent) error) error {
filter := types.EventFilterSpec{
Entity: &types.EventFilterSpecByEntity{
Entity: object,
Recursion: types.EventFilterSpecRecursionOptionAll,
},
}
collector, err := m.CreateCollectorForEvents(ctx, filter)
if err != nil {
return fmt.Errorf("[%#v] %s", object, err)
}
defer collector.Destroy(ctx)
err = collector.SetPageSize(ctx, pageSize)
if err != nil {
return err
}
return property.Wait(ctx, property.DefaultCollector(m.Client()), collector.Reference(), prop, func(pc []types.PropertyChange) bool {
for _, u := range pc {
if u.Name != prop[0] {
continue
}
if u.Val == nil {
continue
}
f(u.Val.(types.ArrayOfEvent).Event)
}
if !tail {
return true
}
return false
})
}

View File

@@ -1,75 +0,0 @@
/*
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 event
import (
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type HistoryCollector struct {
*object.HistoryCollector
}
func NewHistoryCollector(c *vim25.Client, ref types.ManagedObjectReference) *HistoryCollector {
return &HistoryCollector{
HistoryCollector: object.NewHistoryCollector(c, ref),
}
}
func (h HistoryCollector) LatestPage(ctx context.Context) ([]types.BaseEvent, error) {
var o mo.EventHistoryCollector
err := h.Properties(ctx, h.Reference(), []string{"latestPage"}, &o)
if err != nil {
return nil, err
}
return o.LatestPage, nil
}
func (h HistoryCollector) ReadNextEvents(ctx context.Context, maxCount int32) ([]types.BaseEvent, error) {
req := types.ReadNextEvents{
This: h.Reference(),
MaxCount: maxCount,
}
res, err := methods.ReadNextEvents(ctx, h.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (h HistoryCollector) ReadPreviousEvents(ctx context.Context, maxCount int32) ([]types.BaseEvent, error) {
req := types.ReadPreviousEvents{
This: h.Reference(),
MaxCount: maxCount,
}
res, err := methods.ReadPreviousEvents(ctx, h.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}

View File

@@ -1,180 +0,0 @@
/*
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 event
import (
"fmt"
"reflect"
"sync"
"github.com/vmware/govmomi/object"
"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"
"golang.org/x/net/context"
)
type Manager struct {
object.Common
eventCategory map[string]string
eventCategoryMu *sync.Mutex
maxObjects int
}
func NewManager(c *vim25.Client) *Manager {
m := Manager{
Common: object.NewCommon(c, *c.ServiceContent.EventManager),
eventCategory: make(map[string]string),
eventCategoryMu: new(sync.Mutex),
maxObjects: 10,
}
return &m
}
func (m Manager) CreateCollectorForEvents(ctx context.Context, filter types.EventFilterSpec) (*HistoryCollector, error) {
req := types.CreateCollectorForEvents{
This: m.Common.Reference(),
Filter: filter,
}
res, err := methods.CreateCollectorForEvents(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return NewHistoryCollector(m.Client(), res.Returnval), nil
}
func (m Manager) LogUserEvent(ctx context.Context, entity types.ManagedObjectReference, msg string) error {
req := types.LogUserEvent{
This: m.Common.Reference(),
Entity: entity,
Msg: msg,
}
_, err := methods.LogUserEvent(ctx, m.Client(), &req)
if err != nil {
return err
}
return nil
}
func (m Manager) PostEvent(ctx context.Context, eventToPost types.BaseEvent, taskInfo types.TaskInfo) error {
req := types.PostEvent{
This: m.Common.Reference(),
EventToPost: eventToPost,
TaskInfo: &taskInfo,
}
_, err := methods.PostEvent(ctx, m.Client(), &req)
if err != nil {
return err
}
return nil
}
func (m Manager) QueryEvents(ctx context.Context, filter types.EventFilterSpec) ([]types.BaseEvent, error) {
req := types.QueryEvents{
This: m.Common.Reference(),
Filter: filter,
}
res, err := methods.QueryEvents(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m Manager) RetrieveArgumentDescription(ctx context.Context, eventTypeID string) ([]types.EventArgDesc, error) {
req := types.RetrieveArgumentDescription{
This: m.Common.Reference(),
EventTypeId: eventTypeID,
}
res, err := methods.RetrieveArgumentDescription(ctx, m.Client(), &req)
if err != nil {
return nil, err
}
return res.Returnval, nil
}
func (m Manager) eventCategoryMap(ctx context.Context) (map[string]string, error) {
m.eventCategoryMu.Lock()
defer m.eventCategoryMu.Unlock()
if len(m.eventCategory) != 0 {
return m.eventCategory, nil
}
var o mo.EventManager
ps := []string{"description.eventInfo"}
err := property.DefaultCollector(m.Client()).RetrieveOne(ctx, m.Common.Reference(), ps, &o)
if err != nil {
return nil, err
}
for _, info := range o.Description.EventInfo {
m.eventCategory[info.Key] = info.Category
}
return m.eventCategory, nil
}
// EventCategory returns the category for an event, such as "info" or "error" for example.
func (m Manager) EventCategory(ctx context.Context, event types.BaseEvent) (string, error) {
// Most of the event details are included in the Event.FullFormattedMessage, but the category
// is only available via the EventManager description.eventInfo property. The value of this
// property is static, so we fetch and once and cache.
eventCategory, err := m.eventCategoryMap(ctx)
if err != nil {
return "", err
}
class := reflect.TypeOf(event).Elem().Name()
return eventCategory[class], nil
}
// Get the events from the specified object(s) and optionanlly tail the event stream
func (m Manager) Events(ctx context.Context, objects []types.ManagedObjectReference, pageSize int32, tail bool, force bool, f func([]types.BaseEvent) error) error {
if len(objects) >= m.maxObjects && !force {
return fmt.Errorf("Maximum number of objects to monitor (%d) exceeded, refine search \n", m.maxObjects)
}
// property that will be monitored
prop := []string{"latestPage"}
// call to helper functions to reduce the number of temporary objects
if len(objects) > 1 {
return multipleObjectEvents(ctx, m, objects, pageSize, tail, force, prop, f)
}
return singleObjectEvents(ctx, m, objects[0], pageSize, tail, force, prop, f)
}

View File

@@ -1,45 +0,0 @@
/*
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 event
import (
"sort"
"github.com/vmware/govmomi/vim25/types"
)
// Sort events in accending order base on Key
// From the EventHistoryCollector.latestPage sdk docs:
// The "oldest event" is the one with the smallest key (event ID).
// The events in the returned page are unordered.
func Sort(events []types.BaseEvent) {
sort.Sort(baseEvent(events))
}
type baseEvent []types.BaseEvent
func (d baseEvent) Len() int {
return len(d)
}
func (d baseEvent) Less(i, j int) bool {
return d[i].GetEvent().Key < d[j].GetEvent().Key
}
func (d baseEvent) Swap(i, j int) {
d[i], d[j] = d[j], d[i]
}

View File

@@ -1,180 +0,0 @@
/*
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.
*/
/*
This example program shows how the `finder` and `property` packages can
be used to navigate a vSphere inventory structure using govmomi.
*/
package main
import (
"flag"
"fmt"
"net/url"
"os"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
// GetEnvString returns string from environment variable.
func GetEnvString(v string, def string) string {
r := os.Getenv(v)
if r == "" {
return def
}
return r
}
// GetEnvBool returns boolean from environment variable.
func GetEnvBool(v string, def bool) bool {
r := os.Getenv(v)
if r == "" {
return def
}
switch strings.ToLower(r[0:1]) {
case "t", "y", "1":
return true
}
return false
}
const (
envURL = "GOVMOMI_URL"
envUserName = "GOVMOMI_USERNAME"
envPassword = "GOVMOMI_PASSWORD"
envInsecure = "GOVMOMI_INSECURE"
)
var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", GetEnvString(envURL, "https://username:password@host/sdk"), urlDescription)
var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", GetEnvBool(envInsecure, false), insecureDescription)
func processOverride(u *url.URL) {
envUsername := os.Getenv(envUserName)
envPassword := os.Getenv(envPassword)
// Override username if provided
if envUsername != "" {
var password string
var ok bool
if u.User != nil {
password, ok = u.User.Password()
}
if ok {
u.User = url.UserPassword(envUsername, password)
} else {
u.User = url.User(envUsername)
}
}
// Override password if provided
if envPassword != "" {
var username string
if u.User != nil {
username = u.User.Username()
}
u.User = url.UserPassword(username, envPassword)
}
}
func exit(err error) {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
flag.Parse()
// Parse URL from string
u, err := url.Parse(*urlFlag)
if err != nil {
exit(err)
}
// Override username and/or password as required
processOverride(u)
// Connect and log in to ESX or vCenter
c, err := govmomi.NewClient(ctx, u, *insecureFlag)
if err != nil {
exit(err)
}
f := find.NewFinder(c.Client, true)
// Find one and only datacenter
dc, err := f.DefaultDatacenter(ctx)
if err != nil {
exit(err)
}
// Make future calls local to this datacenter
f.SetDatacenter(dc)
// Find datastores in datacenter
dss, err := f.DatastoreList(ctx, "*")
if err != nil {
exit(err)
}
pc := property.DefaultCollector(c.Client)
// Convert datastores into list of references
var refs []types.ManagedObjectReference
for _, ds := range dss {
refs = append(refs, ds.Reference())
}
// Retrieve summary property for all datastores
var dst []mo.Datastore
err = pc.Retrieve(ctx, refs, []string{"summary"}, &dst)
if err != nil {
exit(err)
}
// Print summary per datastore
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Name:\tType:\tCapacity:\tFree:\n")
for _, ds := range dst {
fmt.Fprintf(tw, "%s\t", ds.Summary.Name)
fmt.Fprintf(tw, "%s\t", ds.Summary.Type)
fmt.Fprintf(tw, "%s\t", units.ByteSize(ds.Summary.Capacity))
fmt.Fprintf(tw, "%s\t", units.ByteSize(ds.Summary.FreeSpace))
fmt.Fprintf(tw, "\n")
}
tw.Flush()
}

View File

@@ -1,3 +0,0 @@
source "https://rubygems.org"
gem "nokogiri"

View File

@@ -1,12 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
mini_portile (0.6.0)
nokogiri (1.6.3.1)
mini_portile (= 0.6.0)
PLATFORMS
ruby
DEPENDENCIES
nokogiri

View File

@@ -1,38 +0,0 @@
#!/bin/bash
# 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.
set -e
if [ ! -f rbvmomi/vmodl.db ]; then
git clone https://github.com/vmware/rbvmomi
fi
dst=../vim25
pkgs=$(echo $dst/{types,methods,mo})
mkdir -p $pkgs
bundle exec ruby gen_from_wsdl.rb $dst
bundle exec ruby gen_from_vmodl.rb $dst
for p in $pkgs
do
echo $p
cd $p
goimports -w *.go
go install
cd -
done

View File

@@ -1,217 +0,0 @@
# 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.
$:.unshift(File.expand_path(File.dirname(__FILE__)))
require "vim_wsdl"
require "test/unit"
PATH = File.expand_path("../rbvmomi", __FILE__)
def read(file)
File.open(File.join(PATH, file))
end
class Prop
def initialize(vmodl, data)
@vmodl = vmodl
@data = data
end
def slice?
@data["is-array"]
end
def optional?
@data["is-optional"]
end
def name
@data["name"]
end
def var_field
n = name
n[0].capitalize + n[1..-1]
end
def var_type_prefix(base=false)
if slice?
"[]"
else
if optional? && !base
"*"
else
""
end
end
end
def var_type
type = @data["wsdl_type"]
if @vmodl.managed_hash.has_key?(type)
type = "ManagedObjectReference"
end
# Fix up type from vmodl
case type
when "TypeName", "MethodName"
type = "xsd:string"
when "ManagedObject"
type = "ManagedObjectReference"
when "xsd:anyType"
type = "AnyType"
end
if type =~ /^xsd:(.*)$/
type = $1
case type
when "string"
when "int"
type = "int32"
when "boolean"
type ="bool"
when "long"
type ="int64"
when "dateTime"
type ="time.Time"
prefix += "*" if !slice? && optional?
when "byte"
when "double"
type ="float64"
when "float"
type ="float32"
when "short"
type ="int16"
when "base64Binary"
type ="[]byte"
else
raise "unknown type: %s" % type
end
else
if Peek.base?(type)
type = "Base" + type
base = true
end
type = "types." + type
end
var_type_prefix(base) + type
end
def var_tag
"mo:\"%s\"" % name
end
def dump(io)
io.print "%s %s `%s`\n" % [var_field, var_type, var_tag]
end
end
class Managed
def initialize(vmodl, name, data)
@vmodl = vmodl
@name = name
@data = data
end
def name
@name
end
def props
@data["props"].map do |p|
Prop.new(@vmodl, p)
end
end
def dump(io)
include_ref_getter = false
io.print "type %s struct {\n" % name
case @data["wsdl_base"]
when nil, "ManagedObject", "View"
include_ref_getter = true
io.print "Self types.ManagedObjectReference\n\n"
else
io.print "%s\n\n" % @data["wsdl_base"]
end
props.each do |p|
p.dump(io)
end
io.print "}\n\n"
if include_ref_getter
io.print "func (m %s) Reference() types.ManagedObjectReference {\n" % [name]
io.print "return m.Self\n"
io.print "}\n\n"
end
end
def dump_init(io)
io.print "func init() {\n"
io.print "t[\"%s\"] = reflect.TypeOf((*%s)(nil)).Elem()\n" % [name, name]
io.print "}\n\n"
end
end
class Vmodl
def initialize(data)
@data = Marshal.load(data)
end
def managed_hash
@managed_hash ||= begin
h = {}
managed.each do |m|
h[m.name] = m
end
h
end
end
def managed
@data.map do |k,v|
next if !v.is_a?(Hash)
next if v["kind"] != "managed"
next if k =~ /^pbm/i
Managed.new(self, k, v)
end.compact
end
end
if !File.directory?(ARGV.first)
raise "first argument not a directory"
end
wsdl = WSDL.new(WSDL.read "vim.wsdl")
wsdl.validate_assumptions!
wsdl.peek()
File.open(File.join(ARGV.first, "mo/mo.go"), "w") do |io|
io.print WSDL.header("mo")
vmodl = Vmodl.new(read "vmodl.db")
vmodl.
managed.
sort_by { |m| m.name }.
each { |m| m.dump(io); m.dump_init(io); }
end
exit(0)

View File

@@ -1,70 +0,0 @@
# 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.
$:.unshift(File.expand_path(File.dirname(__FILE__)))
require "vim_wsdl"
if !File.directory?(ARGV.first)
raise "first argument not a directory"
end
wsdl = WSDL.new(WSDL.read "vim.wsdl")
wsdl.validate_assumptions!
wsdl.peek()
ifs = Peek.types.keys.select { |name| Peek.base?(name) }.size()
puts "%d classes, %d interfaces" % [Peek.types.size(), ifs]
File.open(File.join(ARGV.first, "types/enum.go"), "w") do |io|
io.print WSDL.header("types")
wsdl.
types.
sort_by { |x| x.name }.
uniq { |x| x.name }.
select { |x| x.name[0] == x.name[0].upcase }. # Only capitalized methods for now...
select { |t| t.is_enum? }.
each { |e| e.dump(io); e.dump_init(io) }
end
File.open(File.join(ARGV.first, "types/types.go"), "w") do |io|
io.print WSDL.header("types")
wsdl.
types.
sort_by { |x| x.name }.
uniq { |x| x.name }.
select { |x| x.name[0] == x.name[0].upcase }. # Only capitalized methods for now...
select { |t| !t.is_enum? }.
each { |e| e.dump(io); e.dump_init(io) }
end
File.open(File.join(ARGV.first, "types/if.go"), "w") do |io|
io.print WSDL.header("types")
Peek.dump_interfaces(io)
end
File.open(File.join(ARGV.first, "methods/methods.go"), "w") do |io|
io.print WSDL.header("methods")
wsdl.
operations.
sort_by { |x| x.name }.
select { |x| x.name[0] == x.name[0].upcase }. # Only capitalized methods for now...
each { |e| e.dump(io) }
end
exit(0)

View File

@@ -1,803 +0,0 @@
# 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.
require "nokogiri"
require "test/unit"
class Peek
class Type
attr_accessor :parent, :children, :klass
def initialize(name)
@name = name
@children = []
end
def base?
return !children.empty?
end
end
@@types = {}
@@refs = {}
@@enums = {}
def self.types
return @@types
end
def self.refs
return @@refs
end
def self.enums
return @@enums
end
def self.ref(type)
refs[type] = true
end
def self.enum(type)
enums[type] = true
end
def self.enum?(type)
enums[type]
end
def self.register(name)
raise unless name
types[name] ||= Type.new(name)
end
def self.base?(name)
return unless c = types[name]
c.base?
end
def self.dump_interfaces(io)
types.keys.sort.each do |name|
next unless base?(name)
types[name].klass.dump_interface(io, name)
end
end
end
class EnumValue
def initialize(type, value)
@type = type
@value = value
end
def type_name
@type.name
end
def var_name
n = @type.name
v = var_value
if v == ""
n += "Null"
else
n += (v[0].capitalize + v[1..-1])
end
return n
end
def var_value
@value
end
def dump(io)
io.print "%s = %s(\"%s\")\n" % [var_name, type_name, var_value]
end
end
class Simple
include Test::Unit::Assertions
attr_accessor :name, :type
def initialize(node)
@node = node
end
def name
@name || @node["name"]
end
def type
@type || @node["type"]
end
def is_enum?
false
end
def dump_init(io)
# noop
end
def var_name
n = self.name
n = n[1..-1] if n[0] == "_" # Strip leading _
n = n[0].capitalize + n[1..-1] # Capitalize
return n
end
def vim_type?
ns, _ = self.type.split(":", 2)
ns == "vim25" or ns == "internalvim25" or ns == "internalreflect"
end
def vim_type(t = self.type)
ns, t = t.split(":", 2)
if ns != "vim25" and ns != "internalvim25" and ns != "internalreflect"
raise
end
t
end
def base_type?
vim_type? && Peek.base?(vim_type)
end
def enum_type?
vim_type? && Peek.enum?(vim_type)
end
def any_type?
self.type == "xsd:anyType"
end
def pointer_type?
["UnitNumber"].include?(var_name)
end
def var_type
t = self.type
prefix = ""
prefix += "[]" if slice?
if t =~ /^xsd:(.*)$/
t = $1
case t
when "string"
when "int"
if pointer_type?
prefix += "*"
self.need_omitempty = false
end
t = "int32"
when "boolean"
t = "bool"
if !slice? && optional?
prefix += "*"
self.need_omitempty = false
end
when "long"
t = "int64"
when "dateTime"
t = "time.Time"
if !slice? && optional?
prefix += "*"
self.need_omitempty = false
end
when "anyType"
t = "AnyType"
when "byte"
when "double"
t = "float64"
when "float"
t = "float32"
when "short"
t = "int16"
when "base64Binary"
t = "[]byte"
when "anyURI"
t = "url.URL"
else
raise "unknown type: %s" % t
end
else
t = vim_type
if base_type?
prefix += "Base"
else
prefix += "*" if !slice? && !enum_type? && optional?
end
end
prefix + t
end
def slice?
test_attr("maxOccurs", "unbounded")
end
def optional?
test_attr("minOccurs", "0")
end
def need_omitempty=(v)
@need_omitempty = v
end
def need_omitempty?
var_type # HACK: trigger setting need_omitempty if necessary
if @need_omitempty.nil?
@need_omitempty = optional?
else
@need_omitempty
end
end
def need_typeattr?
base_type? || any_type?
end
protected
def test_attr(attr, expected)
actual = @node.attr(attr)
if actual != nil
case actual
when expected
true
else
raise "%s=%s" % [value, type.attr(value)]
end
else
false
end
end
end
class Element < Simple
def initialize(node)
super(node)
end
def has_type?
!@node["type"].nil?
end
def child
cs = @node.element_children
assert_equal 1, cs.length
assert_equal "complexType", cs.first.name
t = ComplexType.new(cs.first)
t.name = self.name
t
end
def dump(io)
if has_type?
io.print "type %s %s\n\n" % [name, var_type]
else
child.dump(io)
end
end
def dump_init(io)
if has_type?
io.print "func init() {\n"
io.print "t[\"%s\"] = reflect.TypeOf((*%s)(nil)).Elem()\n" % [name, name]
io.print "}\n\n"
end
end
def dump_field(io)
tag = name
tag += ",omitempty" if need_omitempty?
tag += ",typeattr" if need_typeattr?
io.print "%s %s `xml:\"%s\"`\n" % [var_name, var_type, tag]
end
def peek(type=nil)
if has_type?
return if self.type =~ /^xsd:/
Peek.ref(vim_type)
else
child.peek()
end
end
end
class Attribute < Simple
def dump_field(io)
tag = name
tag += ",omitempty" if need_omitempty?
tag += ",attr"
io.print "%s %s `xml:\"%s\"`\n" % [var_name, var_type, tag]
end
end
class SimpleType < Simple
def is_enum?
true
end
def dump(io)
enums = @node.xpath(".//xsd:enumeration").map do |n|
EnumValue.new(self, n["value"])
end
io.print "type %s string\n\n" % name
io.print "const (\n"
enums.each { |e| e.dump(io) }
io.print ")\n\n"
end
def dump_init(io)
io.print "func init() {\n"
io.print "t[\"%s\"] = reflect.TypeOf((*%s)(nil)).Elem()\n" % [name, name]
io.print "}\n\n"
end
def peek
Peek.enum(name)
end
end
class ComplexType < Simple
class SimpleContent < Simple
def dump(io)
attr = Attribute.new(@node.at_xpath(".//xsd:attribute"))
attr.dump_field(io)
# HACK DELUXE(PN)
extension = @node.at_xpath(".//xsd:extension")
type = extension["base"].split(":", 2)[1]
io.print "Value %s `xml:\",chardata\"`\n" % type
end
def peek
end
end
class ComplexContent < Simple
def base
extension = @node.at_xpath(".//xsd:extension")
assert_not_nil extension
base = extension["base"]
assert_not_nil base
vim_type(base)
end
def dump(io)
Sequence.new(@node).dump(io, base)
end
def dump_interface(io, name)
Sequence.new(@node).dump_interface(io, name)
end
def peek
Sequence.new(@node).peek(base)
end
end
class Sequence < Simple
def sequence
sequence = @node.at_xpath(".//xsd:sequence")
if sequence != nil
sequence.element_children.map do |n|
Element.new(n)
end
else
nil
end
end
def dump(io, base = nil)
return unless elements = sequence
io.print "%s\n\n" % base
elements.each do |e|
e.dump_field(io)
end
end
def dump_interface(io, name)
method = "Get%s() *%s" % [name, name]
io.print "func (b *%s) %s { return b }\n" % [name, method]
io.print "type Base%s interface {\n" % name
io.print "%s\n" % method
io.print "}\n\n"
io.print "func init() {\n"
io.print "t[\"Base%s\"] = reflect.TypeOf((*%s)(nil)).Elem()\n" % [name, name]
io.print "}\n\n"
end
def peek(base = nil)
return unless elements = sequence
name = @node.attr("name")
return unless name
elements.each do |e|
e.peek(name)
end
c = Peek.register(name)
if base
c.parent = base
Peek.register(c.parent).children << name
end
end
end
def klass
@klass ||= begin
cs = @node.element_children
if !cs.empty?
assert_equal 1, cs.length
case cs.first.name
when "simpleContent"
SimpleContent.new(@node)
when "complexContent"
ComplexContent.new(@node)
when "sequence"
Sequence.new(@node)
else
raise "don't know what to do for element: %s..." % cs.first.name
end
end
end
end
def dump_init(io)
io.print "func init() {\n"
io.print "t[\"%s\"] = reflect.TypeOf((*%s)(nil)).Elem()\n" % [name, name]
io.print "}\n\n"
end
def dump(io)
io.print "type %s struct {\n" % name
klass.dump(io) if klass
io.print "}\n\n"
end
def peek
Peek.register(name).klass = klass
klass.peek if klass
end
end
class Schema
include Test::Unit::Assertions
def initialize(xml, parent = nil)
@xml = Nokogiri::XML.parse(xml)
end
def targetNamespace
@xml.root["targetNamespace"]
end
# We have some assumptions about structure, make sure they hold.
def validate_assumptions!
# Every enumeration is part of a restriction
@xml.xpath(".//xsd:enumeration").each do |n|
assert_equal "restriction", n.parent.name
end
# See type == enum
@xml.xpath(".//xsd:restriction").each do |n|
# Every restriction has type xsd:string (it's an enum)
assert_equal "xsd:string", n["base"]
# Every restriction is part of a simpleType
assert_equal "simpleType", n.parent.name
# Every restriction is alone
assert_equal 1, n.parent.element_children.size
end
# See type == complex_content
@xml.xpath(".//xsd:complexContent").each do |n|
# complexContent is child of complexType
assert_equal "complexType", n.parent.name
end
# See type == complex_type
@xml.xpath(".//xsd:complexType").each do |n|
cc = n.element_children
# OK to have an empty complexType
next if cc.size == 0
# Require 1 element otherwise
assert_equal 1, cc.size
case cc.first.name
when "complexContent"
# complexContent has 1 "extension" element
cc = cc.first.element_children
assert_equal 1, cc.size
assert_equal "extension", cc.first.name
# extension has 1 "sequence" element
ec = cc.first.element_children
assert_equal 1, ec.size
assert_equal "sequence", ec.first.name
# sequence has N "element" elements
sc = ec.first.element_children
assert sc.all? { |e| e.name == "element" }
when "simpleContent"
# simpleContent has 1 "extension" element
cc = cc.first.element_children
assert_equal 1, cc.size
assert_equal "extension", cc.first.name
# extension has 1 or more "attribute" elements
ec = cc.first.element_children
assert_not_equal 0, ec.size
assert_equal "attribute", ec.first.name
when "sequence"
# sequence has N "element" elements
sc = cc.first.element_children
assert sc.all? { |e| e.name == "element" }
else
raise "unknown element: %s" % cc.first.name
end
end
imports.each do |i|
i.validate_assumptions!
end
includes.each do |i|
i.validate_assumptions!
end
end
def types
return to_enum(:types) unless block_given?
imports.each do |i|
i.types do |t|
yield t
end
end
includes.each do |i|
i.types do |t|
yield t
end
end
@xml.root.children.each do |n|
case n.class.to_s
when "Nokogiri::XML::Text"
next
when "Nokogiri::XML::Element"
case n.name
when "include", "import"
next
when "element"
yield Element.new(n)
when "simpleType"
yield SimpleType.new(n)
when "complexType"
yield ComplexType.new(n)
else
raise "unknown child: %s" % n.name
end
else
raise "unknown type: %s" % n.class
end
end
end
def imports
@imports ||= @xml.root.xpath(".//xmlns:import").map do |n|
Schema.new(WSDL.read n["schemaLocation"])
end
end
def includes
@includes ||= @xml.root.xpath(".//xmlns:include").map do |n|
Schema.new(WSDL.read n["schemaLocation"])
end
end
end
class Operation
include Test::Unit::Assertions
def initialize(wsdl, operation_node)
@wsdl = wsdl
@operation_node = operation_node
end
def name
@operation_node["name"]
end
def namespace
type = @operation_node.at_xpath("./xmlns:input").attr("message")
keep_ns(type)
end
def remove_ns(x)
ns, x = x.split(":", 2)
if ns != "vim25" and ns != "internalvim25" and ns != "internalreflect"
raise
end
x
end
def keep_ns(x)
ns, x = x.split(":", 2)
if ns != "vim25" and ns != "internalvim25" and ns != "internalreflect"
raise
end
ns
end
def find_type_for(type)
type = remove_ns(type)
message = @wsdl.message(type)
assert_not_nil message
part = message.at_xpath("./xmlns:part")
assert_not_nil message
remove_ns(part["element"])
end
def input
type = @operation_node.at_xpath("./xmlns:input").attr("message")
find_type_for(type)
end
def go_input
"types." + input
end
def output
type = @operation_node.at_xpath("./xmlns:output").attr("message")
find_type_for(type)
end
def go_output
"types." + output
end
def dump(io)
io.print <<EOS
type #{name}Body struct{
Req *#{go_input} `xml:"urn:#{namespace} #{input},omitempty"`
Res *#{go_output} `xml:"urn:#{namespace} #{output},omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *#{name}Body) Fault() *soap.Fault { return b.Fault_ }
EOS
io.print "func %s(ctx context.Context, r soap.RoundTripper, req *%s) (*%s, error) {\n" % [name, go_input, go_output]
io.print <<EOS
var reqBody, resBody #{name}Body
reqBody.Req = req
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
return nil, err
}
return resBody.Res, nil
EOS
io.print "}\n\n"
end
end
class WSDL
attr_reader :xml
PATH = File.expand_path("../sdk", __FILE__)
def self.read(file)
File.open(File.join(PATH, file))
end
def initialize(xml)
@xml = Nokogiri::XML.parse(xml)
end
def validate_assumptions!
schemas.each do |s|
s.validate_assumptions!
end
end
def types(&blk)
return to_enum(:types) unless block_given?
schemas.each do |s|
s.types(&blk)
end
end
def schemas
@schemas ||= @xml.xpath('.//xmlns:types/xsd:schema').map do |n|
Schema.new(n.to_xml)
end
end
def operations
@operations ||= @xml.xpath('.//xmlns:portType/xmlns:operation').map do |o|
Operation.new(self, o)
end
end
def message(type)
@messages ||= begin
h = {}
@xml.xpath('.//xmlns:message').each do |n|
h[n.attr("name")] = n
end
h
end
@messages[type]
end
def peek
types.
sort_by { |x| x.name }.
uniq { |x| x.name }.
select { |x| x.name[0] == x.name[0].upcase }. # Only capitalized methods for now...
each { |e| e.peek() }
end
def self.header(name)
return <<EOF
/*
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 #{name}
EOF
end
end

View File

@@ -1 +0,0 @@
/govc*

View File

@@ -1,91 +0,0 @@
# changelog
### 0.5.0 (2016-03-30)
* Add dvs.portgroup.info command
* Add `-folder` flag to vm.create command
* Add `-dump` flag to OutputFlag
* Add `-f` flag to events command
* Add `-mode` flag to vm.disk.create command
* Add `-net` flag to device.info command
* Add `-eager` and `-thick` options to vm.create command
### 0.4.0 (2016-02-26)
* Add support for placement in datastore cluster to vm.create command
* Add support for creating new disks in vm.create command
* Add `-p` and `-a` options to govc datastore.ls command
### 0.3.0 (2016-01-16)
* Add permissions.{ls,set,remove} commands
* Add datastore.{create,remove} commands.
The new create command supports both creating NAS and VMFS datastores.
* Add dvs.{create,add} and dvs.portgroup.add commands
* Add host.vnic.{service,info} commands
* Add cluster.{create,change,add} commands
* Add host.{disconnect,reconnect,remove,maintenance.enter,maintenance.exit} commands
* Add license.decode, license.assigned.list and license.assign commands
* Add firewall.ruleset.find command
* Add logs, logs.ls and logs.download commands
* Add support for LoginExtensionByCertificate with new `-cert` and `-key` flags
* Add govc extension.{info,register,unregister,setcert} commands
* Add govc vapp.{info,destroy,power} commands
### 0.2.0 (2015-09-15)
* The `vm.power` guest `-s` and `-r` options will fallback to hard `-off` / `-reset` if tools is unavailable and `-force` flag is given
* Add `PowerOn, InjectOvfEnv, WaitForIP` options to `import.ovf` and `import.ova` option spec file
* Add `import.spec` to produce an example json document
* Add `-options` to `import.ovf` and `import.ova`
* Add `-folder` to `import.ovf` and `import.ova`
* Add `fields` command to manage custom fields
* Add `datastore.info` command
* Add `events` command
* Add `-net.address` (Hardware Address) option to `vm.change` and `vm.create`
* Add `host.add` command to add host to datacenter.
* Add `GOVC_USERNAME` and `GOVC_PASSWORD` to allow overriding username and/or
password (used when they contain special characters that prevent them from
being embedded in the URL).
* Add `-e' (ExtraConfig) option to `vm.change` and `vm.info`
* Retry twice on temporary network errors.
* Add `host.autostart` commands to manage VM autostart.
* Add `-persist-session` flag to control whether or not the session is
persisted to disk (defaults to true).
### 0.1.0 (2015-03-17)
Prior to this version the changes to govc's command set were not documented.

View File

@@ -1,122 +0,0 @@
# govc
govc is a vSphere CLI built on top of govmomi.
## Installation
You can find prebuilt govc binaries on the [releases page](https://github.com/vmware/govmomi/releases).
Download and install a binary locally like this:
```sh
curl $URL_TO_BINARY | gzip -d > /usr/local/bin/govc
chmod +x /usr/local/bin/govc
```
### Source
You can install the latest govc version from source if you have the Go toolchain installed.
```sh
go get github.com/vmware/govmomi/govc
```
(make sure `$GOPATH/bin` is in your `PATH`)
## Usage
govc exposes its functionality through subcommands. Option flags
to these subcommands are often shared.
Common flags include:
* `-u`: ESXi or vCenter URL (ex: `user:pass@host`)
* `-debug`: Trace requests and responses (to `~/.govmomi/debug`)
Managed entities can be referred to by their absolute path or by their relative
path. For example, when specifying a datastore to use for a subcommand, you can
either specify it as `/mydatacenter/datastore/mydatastore`, or as
`mydatastore`. If you're not sure about the name of the datastore, or even the
full path to the datastore, you can specify a pattern to match. Both
`/*center/*/my*` (absolute) and `my*store` (relative) will resolve to the same
datastore, given there are no other datastores that match those globs.
The relative path in this example can only be used if the command can
umambigously resolve a datacenter to use as origin for the query. If no
datacenter is specified, govc defaults to the only datacenter, if there is only
one. The datacenter itself can be specified as a pattern as well, enabling the
following arguments: `-dc='my*' -ds='*store'`. The datastore pattern is looked
up and matched relative to the datacenter which itself is specified as a
pattern.
Besides specifying managed entities as arguments, they can also be specified
using environment variables. The following environment variables are used by govc
to set defaults:
* `GOVC_USERNAME`: USERNAME to use.
* `GOVC_PASSWORD`: PASSWORD to use.
* `GOVC_URL`: URL of ESXi or vCenter instance to connect to.
> The URL scheme defaults to `https` and the URL path defaults to `/sdk`.
> This means that specifying `user:pass@host` is equivalent to
> `https://user:pass@host/sdk`.
> If password include special characters like `#` or `:` you can use
> `GOVC_USERNAME` and `GOVC_PASSWORD` to have a simple `GOVC_URL`
* `GOVC_INSECURE`: Allow establishing insecure connections.
> Use this option when the host you're connecting is using self-signed
> certificates, or is otherwise trusted. Set this option to `1` to enable.
* `GOVC_DATACENTER`
* `GOVC_DATASTORE`
* `GOVC_NETWORK`
* `GOVC_RESOURCE_POOL`
* `GOVC_HOST`
* `GOVC_GUEST_LOGIN`: Guest credentials for guest operations
* `GOVC_VIM_NAMESPACE`: Vim namespace defaults to `urn:vim25`
* `GOVC_VIM_VERSION`: Vim version defaults to `6.0`
## Examples
* About
```
$ export GOVC_URL="192.168.1.20"
$ export GOVC_USERNAME="domain\administrator"
$ export GOVC_PASSWORD="Password123#"
$ govc about
Name: VMware vCenter Server
Vendor: VMware, Inc.
Version: 6.0.0
Build: 2656761
OS type: linux-x64
API type: VirtualCenter
API version: 6.0
Product ID: vpx
UUID: c9f0242f-10e3-4e10-85d7-5eea7c855188
```
* [Upload ssh public key to a VM](examples/lib/ssh.sh)
* [Create and configure a vCenter VM](examples/vcsa.sh)
## Projects using govc
* [Kubernetes vSphere Provider](https://github.com/GoogleCloudPlatform/kubernetes/tree/master/cluster/vsphere)
* [Emacs govc package](./emacs)
## License
govc is available under the [Apache 2 license](../LICENSE).

View File

@@ -1,69 +0,0 @@
/*
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 about
import (
"flag"
"fmt"
"os"
"text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type about struct {
*flags.ClientFlag
}
func init() {
cli.Register("about", &about{})
}
func (cmd *about) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *about) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *about) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
a := c.ServiceContent.About
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "Name:\t%s\n", a.Name)
fmt.Fprintf(tw, "Vendor:\t%s\n", a.Vendor)
fmt.Fprintf(tw, "Version:\t%s\n", a.Version)
fmt.Fprintf(tw, "Build:\t%s\n", a.Build)
fmt.Fprintf(tw, "OS type:\t%s\n", a.OsType)
fmt.Fprintf(tw, "API type:\t%s\n", a.ApiType)
fmt.Fprintf(tw, "API version:\t%s\n", a.ApiVersion)
fmt.Fprintf(tw, "Product ID:\t%s\n", a.ProductLineId)
fmt.Fprintf(tw, "UUID:\t%s\n", a.InstanceUuid)
return tw.Flush()
}

View File

@@ -1,32 +0,0 @@
#!/bin/bash -e
git_version=$(git describe)
if git_status=$(git status --porcelain 2>/dev/null) && [ -n "${git_status}" ]; then
git_version="${git_version}-dirty"
fi
ldflags="-X github.com/vmware/govmomi/govc/version.gitVersion=${git_version}"
BUILD_OS=${BUILD_OS:-darwin linux windows freebsd}
BUILD_ARCH=${BUILD_ARCH:-386 amd64}
for os in ${BUILD_OS}; do
export GOOS="${os}"
for arch in ${BUILD_ARCH}; do
export GOARCH="${arch}"
out="govc_${os}_${arch}"
if [ "${os}" == "windows" ]; then
out="${out}.exe"
fi
set -x
go build \
-o="${out}" \
-pkgdir="./_pkg" \
-compiler='gc' \
-ldflags="${ldflags}" \
github.com/vmware/govmomi/govc
set +x
done
done

View File

@@ -1,142 +0,0 @@
/*
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 cli
import (
"flag"
"fmt"
"io/ioutil"
"os"
"sort"
"text/tabwriter"
"golang.org/x/net/context"
)
type HasFlags interface {
// Register may be called more than once and should be idempotent.
Register(ctx context.Context, f *flag.FlagSet)
// Process may be called more than once and should be idempotent.
Process(ctx context.Context) error
}
type Command interface {
HasFlags
Run(ctx context.Context, f *flag.FlagSet) error
}
func generalHelp() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
cmds := []string{}
for name := range commands {
cmds = append(cmds, name)
}
sort.Strings(cmds)
for _, name := range cmds {
fmt.Fprintf(os.Stderr, " %s\n", name)
}
}
func commandHelp(name string, cmd Command, f *flag.FlagSet) {
type HasUsage interface {
Usage() string
}
fmt.Fprintf(os.Stderr, "Usage: %s %s [OPTIONS]", os.Args[0], name)
if u, ok := cmd.(HasUsage); ok {
fmt.Fprintf(os.Stderr, " %s", u.Usage())
}
fmt.Fprintf(os.Stderr, "\n")
type HasDescription interface {
Description() string
}
if u, ok := cmd.(HasDescription); ok {
fmt.Fprintf(os.Stderr, "%s\n", u.Description())
}
n := 0
f.VisitAll(func(_ *flag.Flag) {
n += 1
})
if n > 0 {
fmt.Fprintf(os.Stderr, "\nOptions:\n")
tw := tabwriter.NewWriter(os.Stderr, 2, 0, 2, ' ', 0)
f.VisitAll(func(f *flag.Flag) {
fmt.Fprintf(tw, "\t-%s=%s\t%s\n", f.Name, f.DefValue, f.Usage)
})
tw.Flush()
}
}
func Run(args []string) int {
var err error
if len(args) == 0 {
generalHelp()
return 1
}
// Look up real command name in aliases table.
name, ok := aliases[args[0]]
if !ok {
name = args[0]
}
cmd, ok := commands[name]
if !ok {
generalHelp()
return 1
}
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.SetOutput(ioutil.Discard)
ctx := context.Background()
cmd.Register(ctx, fs)
if err = fs.Parse(args[1:]); err != nil {
goto error
}
if err = cmd.Process(ctx); err != nil {
goto error
}
if err = cmd.Run(ctx, fs); err != nil {
goto error
}
return 0
error:
if err == flag.ErrHelp {
commandHelp(args[0], cmd, fs)
} else {
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
}
return 1
}

View File

@@ -1,33 +0,0 @@
/*
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 cli
var commands = map[string]Command{}
var aliases = map[string]string{}
func Register(name string, c Command) {
commands[name] = c
}
func Alias(name string, alias string) {
aliases[alias] = name
}
func Commands() map[string]Command {
return commands
}

View File

@@ -1,129 +0,0 @@
/*
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 cluster
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type add struct {
*flags.DatacenterFlag
*flags.HostConnectFlag
cluster string
connect bool
license string
}
func init() {
cli.Register("cluster.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.HostConnectFlag, ctx = flags.NewHostConnectFlag(ctx)
cmd.HostConnectFlag.Register(ctx, f)
f.StringVar(&cmd.cluster, "cluster", "*", "Path to cluster")
f.StringVar(&cmd.license, "license", "", "Assign license key")
f.BoolVar(&cmd.connect, "connect", true, "Immediately connect to host")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostConnectFlag.Process(ctx); err != nil {
return err
}
if cmd.HostName == "" {
return flag.ErrHelp
}
if cmd.UserName == "" {
return flag.ErrHelp
}
if cmd.Password == "" {
return flag.ErrHelp
}
return nil
}
func (cmd *add) Description() string {
return `Add host to cluster.
The host is added to the cluster specified by the 'cluster' flag.`
}
func (cmd *add) Add(ctx context.Context, cluster *object.ClusterComputeResource) error {
spec := cmd.HostConnectSpec
var license *string
if cmd.license != "" {
license = &cmd.license
}
task, err := cluster.AddHost(ctx, spec, cmd.connect, license, nil)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to cluster %s... ", spec.HostName, cluster.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 0 {
return flag.ErrHelp
}
finder, err := cmd.Finder()
if err != nil {
return err
}
cluster, err := finder.ClusterComputeResource(ctx, cmd.cluster)
if err != nil {
return nil
}
err = cmd.Add(ctx, cluster)
if err == nil {
return nil
}
// Check if we failed due to SSLVerifyFault and -noverify is set
if err := cmd.AcceptThumbprint(err); err != nil {
return err
}
// Accepted unverified thumbprint, try again
return cmd.Add(ctx, cluster)
}

View File

@@ -1,109 +0,0 @@
/*
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 cluster
import (
"flag"
"strings"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type change struct {
*flags.DatacenterFlag
types.ClusterConfigSpecEx
}
func init() {
cli.Register("cluster.change", &change{})
}
func (cmd *change) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.DrsConfig = new(types.ClusterDrsConfigInfo)
cmd.DasConfig = new(types.ClusterDasConfigInfo)
cmd.VsanConfig = new(types.VsanClusterConfigInfo)
cmd.VsanConfig.DefaultConfig = new(types.VsanClusterConfigInfoHostDefaultInfo)
// DRS
f.Var(flags.NewOptionalBool(&cmd.DrsConfig.Enabled), "drs-enabled", "Enable DRS")
drsModes := []string{
string(types.DrsBehaviorManual),
string(types.DrsBehaviorPartiallyAutomated),
string(types.DrsBehaviorFullyAutomated),
}
f.StringVar((*string)(&cmd.DrsConfig.DefaultVmBehavior), "drs-mode", "",
"DRS behavior for virtual machines: "+strings.Join(drsModes, ", "))
// HA
f.Var(flags.NewOptionalBool(&cmd.DasConfig.Enabled), "ha-enabled", "Enable HA")
// vSAN
f.Var(flags.NewOptionalBool(&cmd.VsanConfig.Enabled), "vsan-enabled", "Enable vSAN")
f.Var(flags.NewOptionalBool(&cmd.VsanConfig.DefaultConfig.AutoClaimStorage), "vsan-autoclaim", "")
}
func (cmd *change) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *change) Usage() string {
return "CLUSTER..."
}
func (cmd *change) Description() string {
return `Change configuration of the given clusters.`
}
func (cmd *change) Run(ctx context.Context, f *flag.FlagSet) error {
finder, err := cmd.Finder()
if err != nil {
return err
}
for _, path := range f.Args() {
clusters, err := finder.ClusterComputeResourceList(ctx, path)
if err != nil {
return err
}
for _, cluster := range clusters {
task, err := cluster.Reconfigure(ctx, &cmd.ClusterConfigSpecEx, true)
if err != nil {
return err
}
_, err = task.WaitForResult(ctx, nil)
if err != nil {
return err
}
}
}
return nil
}

View File

@@ -1,104 +0,0 @@
/*
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 cluster
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*flags.DatacenterFlag
parent string
types.ClusterConfigSpecEx
}
func init() {
cli.Register("cluster.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.parent, "parent", "", "Path to parent folder for the new cluster")
}
func (cmd *create) Usage() string {
return "CLUSTER"
}
func (cmd *create) Description() string {
return `Create CLUSTER in datacenter.
The cluster is added to the folder specified by the 'parent' flag. If not given,
this defaults to the hosts folder in the specified or default datacenter.`
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
var parent *object.Folder
if f.NArg() != 1 {
return flag.ErrHelp
}
if cmd.parent == "" {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
parent = folders.HostFolder
} else {
finder, err := cmd.Finder()
if err != nil {
return err
}
parent, err = finder.Folder(ctx, cmd.parent)
if err != nil {
return err
}
}
_, err := parent.CreateCluster(ctx, f.Arg(0), cmd.ClusterConfigSpecEx)
if err != nil {
return err
}
return nil
}

View File

@@ -1,85 +0,0 @@
/*
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 datacenter
import (
"flag"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type create struct {
*flags.ClientFlag
}
func init() {
cli.Register("datacenter.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *create) Usage() string {
return "[DATACENTER NAME]..."
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
datacenters := f.Args()
if len(datacenters) < 1 {
return flag.ErrHelp
}
client, err := cmd.ClientFlag.Client()
if err != nil {
return err
}
finder := find.NewFinder(client, false)
rootFolder := object.NewRootFolder(client)
for _, datacenterToCreate := range datacenters {
_, err := finder.Datacenter(context.TODO(), datacenterToCreate)
if err == nil {
// The datacenter was found, no need to create it
continue
}
switch err.(type) {
case *find.NotFoundError:
_, err = rootFolder.CreateDatacenter(context.TODO(), datacenterToCreate)
if err != nil {
return err
}
default:
return err
}
}
return nil
}

View File

@@ -1,81 +0,0 @@
/*
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 datacenter
import (
"flag"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type destroy struct {
*flags.ClientFlag
}
func init() {
cli.Register("datacenter.destroy", &destroy{})
}
func (cmd *destroy) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *destroy) Usage() string {
return "[DATACENTER NAME]..."
}
func (cmd *destroy) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *destroy) Run(ctx context.Context, f *flag.FlagSet) error {
if len(f.Args()) < 1 {
return flag.ErrHelp
}
datacentersToDestroy := f.Args()
client, err := cmd.ClientFlag.Client()
if err != nil {
return err
}
finder := find.NewFinder(client, false)
for _, datacenterToDestroy := range datacentersToDestroy {
foundDatacenters, err := finder.DatacenterList(context.TODO(), datacenterToDestroy)
if err != nil {
return err
}
for _, foundDatacenter := range foundDatacenters {
task, err := foundDatacenter.Destroy(context.TODO())
if err != nil {
return err
}
if err := task.Wait(context.TODO()); err != nil {
return err
}
}
}
return nil
}

View File

@@ -1,99 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type cp struct {
*flags.OutputFlag
*flags.DatastoreFlag
force bool
}
func init() {
cli.Register("datastore.cp", &cp{})
}
func (cmd *cp) Register(ctx context.Context, f *flag.FlagSet) {
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
}
func (cmd *cp) Process(ctx context.Context) error {
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *cp) Usage() string {
return "SRC DST"
}
func (cmd *cp) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return errors.New("SRC and DST arguments are required")
}
c, err := cmd.Client()
if err != nil {
return err
}
dc, err := cmd.Datacenter()
if err != nil {
return err
}
// TODO: support cross-datacenter copy
src, err := cmd.DatastorePath(args[0])
if err != nil {
return err
}
dst, err := cmd.DatastorePath(args[1])
if err != nil {
return err
}
m := object.NewFileManager(c)
task, err := m.CopyDatastoreFile(context.TODO(), src, dc, dst, dc, cmd.force)
if err != nil {
return err
}
return task.Wait(context.TODO())
}

View File

@@ -1,273 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"fmt"
"os"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type create struct {
*flags.HostSystemFlag
// Generic options
Type typeFlag
Name string
Force bool
// Options for NAS
RemoteHost string
RemotePath string
AccessMode string
UserName string
Password string
// Options for VMFS
DiskCanonicalName string
}
func init() {
cli.Register("datastore.create", &create{})
}
var nasTypes = []string{
string(types.HostFileSystemVolumeFileSystemTypeNFS),
string(types.HostFileSystemVolumeFileSystemTypeNFS41),
string(types.HostFileSystemVolumeFileSystemTypeCIFS),
}
var vmfsTypes = []string{
string(types.HostFileSystemVolumeFileSystemTypeVMFS),
}
var allTypes = []string{}
func init() {
allTypes = append(allTypes, nasTypes...)
allTypes = append(allTypes, vmfsTypes...)
}
type typeFlag string
func (t *typeFlag) Set(s string) error {
s = strings.ToLower(s)
for _, e := range allTypes {
if s == strings.ToLower(e) {
*t = typeFlag(e)
return nil
}
}
return fmt.Errorf("unknown type")
}
func (t *typeFlag) String() string {
return string(*t)
}
func (t *typeFlag) partOf(m []string) bool {
for _, e := range m {
if t.String() == e {
return true
}
}
return false
}
func (t *typeFlag) IsNasType() bool {
return t.partOf(nasTypes)
}
func (t *typeFlag) IsVmfsType() bool {
return t.partOf(vmfsTypes)
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
modes := []string{
string(types.HostMountModeReadOnly),
string(types.HostMountModeReadWrite),
}
f.StringVar(&cmd.Name, "name", "", "Datastore name")
f.Var(&cmd.Type, "type", fmt.Sprintf("Datastore type (%s)", strings.Join(allTypes, "|")))
f.BoolVar(&cmd.Force, "force", false, "Ignore DuplicateName error if datastore is already mounted on a host")
// Options for NAS
f.StringVar(&cmd.RemoteHost, "remote-host", "", "Remote hostname of the NAS datastore")
f.StringVar(&cmd.RemotePath, "remote-path", "", "Remote path of the NFS mount point")
f.StringVar(&cmd.AccessMode, "mode", modes[0],
fmt.Sprintf("Access mode for the mount point (%s)", strings.Join(modes, "|")))
f.StringVar(&cmd.UserName, "username", "", "Username to use when connecting (CIFS only)")
f.StringVar(&cmd.Password, "password", "", "Password to use when connecting (CIFS only)")
// Options for VMFS
f.StringVar(&cmd.DiskCanonicalName, "disk", "", "Canonical name of disk (VMFS only)")
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Usage() string {
return "HOST..."
}
func (cmd *create) Description() string {
return `Create datastore on HOST.
Examples:
govc datastore.create -type nfs -name nfsDatastore -remote-host 10.143.2.232 -remote-path /share cluster1
govc datastore.create -type vmfs -name localDatastore -disk=mpx.vmhba0:C0:T0:L0 cluster1`
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
switch {
case cmd.Type.IsNasType():
return cmd.CreateNasDatastore(ctx, hosts)
case cmd.Type.IsVmfsType():
return cmd.CreateVmfsDatastore(ctx, hosts)
default:
return fmt.Errorf("unhandled type %#v", cmd.Type)
}
}
func (cmd *create) GetHostNasVolumeSpec() types.HostNasVolumeSpec {
s := types.HostNasVolumeSpec{
LocalPath: cmd.Name,
Type: cmd.Type.String(),
RemoteHost: cmd.RemoteHost,
RemotePath: cmd.RemotePath,
AccessMode: cmd.AccessMode,
UserName: cmd.UserName,
Password: cmd.Password,
}
return s
}
func (cmd *create) CreateNasDatastore(ctx context.Context, hosts []*object.HostSystem) error {
object := types.ManagedObjectReference{
Type: "Datastore",
Value: fmt.Sprintf("%s:%s", cmd.RemoteHost, cmd.RemotePath),
}
spec := cmd.GetHostNasVolumeSpec()
for _, host := range hosts {
ds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
_, err = ds.CreateNasDatastore(ctx, spec)
if err != nil {
if soap.IsSoapFault(err) {
switch fault := soap.ToSoapFault(err).VimFault().(type) {
case types.PlatformConfigFault:
if len(fault.FaultMessage) != 0 {
return errors.New(fault.FaultMessage[0].Message)
}
case types.DuplicateName:
if cmd.Force && fault.Object == object {
fmt.Fprintf(os.Stderr, "%s: '%s' already mounted\n",
host.InventoryPath, cmd.Name)
continue
}
}
}
return fmt.Errorf("%s: %s", host.InventoryPath, err)
}
}
return nil
}
func (cmd *create) CreateVmfsDatastore(ctx context.Context, hosts []*object.HostSystem) error {
for _, host := range hosts {
ds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
// Find the specified disk
disks, err := ds.QueryAvailableDisksForVmfs(ctx)
if err != nil {
return err
}
var disk *types.HostScsiDisk
for _, e := range disks {
if e.CanonicalName == cmd.DiskCanonicalName {
disk = &e
break
}
}
if disk == nil {
return fmt.Errorf("no eligible disk found for name %#v", cmd.DiskCanonicalName)
}
// Query for creation options and pick the right one
options, err := ds.QueryVmfsDatastoreCreateOptions(ctx, disk.DevicePath)
if err != nil {
return err
}
var option *types.VmfsDatastoreOption
for _, e := range options {
if _, ok := e.Info.(*types.VmfsDatastoreAllExtentOption); ok {
option = &e
break
}
}
if option == nil {
return fmt.Errorf("cannot use entire disk for datastore for name %#v", cmd.DiskCanonicalName)
}
spec := *option.Spec.(*types.VmfsDatastoreCreateSpec)
spec.Vmfs.VolumeName = cmd.Name
_, err = ds.CreateVmfsDatastore(ctx, spec)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,73 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/soap"
)
type download struct {
*flags.DatastoreFlag
}
func init() {
cli.Register("datastore.download", &download{})
}
func (cmd *download) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *download) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *download) Usage() string {
return "REMOTE LOCAL"
}
func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return errors.New("invalid arguments")
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
p := soap.DefaultDownload
if cmd.OutputFlag.TTY {
logger := cmd.ProgressLogger("Downloading... ")
p.Progress = logger
defer logger.Wait()
}
return ds.DownloadFile(context.TODO(), args[0], args[1], &p)
}

View File

@@ -1,153 +0,0 @@
/*
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 datastore
import (
"flag"
"fmt"
"io"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type info struct {
*flags.ClientFlag
*flags.OutputFlag
*flags.DatacenterFlag
}
func init() {
cli.Register("datastore.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[PATH]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
finder, err := cmd.Finder()
if err != nil {
return err
}
args := f.Args()
if len(args) == 0 {
args = []string{"*"}
}
var res infoResult
var props []string
if cmd.OutputFlag.JSON {
props = nil // Load everything
} else {
props = []string{"info", "summary"} // Load summary
}
for _, arg := range args {
objects, err := finder.DatastoreList(ctx, arg)
if err != nil {
return err
}
res.objects = append(res.objects, objects...)
}
if len(res.objects) != 0 {
refs := make([]types.ManagedObjectReference, 0, len(res.objects))
for _, o := range res.objects {
refs = append(refs, o.Reference())
}
pc := property.DefaultCollector(c)
err = pc.Retrieve(ctx, refs, props, &res.Datastores)
if err != nil {
return err
}
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Datastores []mo.Datastore
objects []*object.Datastore
}
func (r *infoResult) Write(w io.Writer) error {
// Maintain order via r.objects as Property collector does not always return results in order.
objects := make(map[types.ManagedObjectReference]mo.Datastore, len(r.Datastores))
for _, o := range r.Datastores {
objects[o.Reference()] = o
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, o := range r.objects {
ds := objects[o.Reference()]
s := ds.Summary
fmt.Fprintf(tw, "Name:\t%s\n", s.Name)
fmt.Fprintf(tw, " Path:\t%s\n", o.InventoryPath)
fmt.Fprintf(tw, " Type:\t%s\n", s.Type)
fmt.Fprintf(tw, " URL:\t%s\n", s.Url)
fmt.Fprintf(tw, " Capacity:\t%.1f GB\n", float64(s.Capacity)/(1<<30))
fmt.Fprintf(tw, " Free:\t%.1f GB\n", float64(s.FreeSpace)/(1<<30))
switch info := ds.Info.(type) {
case *types.NasDatastoreInfo:
fmt.Fprintf(tw, " Remote:\t%s:%s\n", info.Nas.RemoteHost, info.Nas.RemotePath)
}
}
return tw.Flush()
}

View File

@@ -1,232 +0,0 @@
/*
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 datastore
import (
"encoding/json"
"flag"
"fmt"
"io"
"path"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/units"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type ls struct {
*flags.DatastoreFlag
*flags.OutputFlag
long bool
slash bool
all bool
}
func init() {
cli.Register("datastore.ls", &ls{})
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
f.BoolVar(&cmd.long, "l", false, "Long listing format")
f.BoolVar(&cmd.slash, "p", false, "Write a slash (`/') after each filename if that file is a directory")
f.BoolVar(&cmd.all, "a", false, "Include entries whose names begin with a dot (.)")
}
func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Usage() string {
return "[FILE]..."
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore()
if err != nil {
return err
}
b, err := ds.Browser(context.TODO())
if err != nil {
return err
}
args := f.Args()
if len(args) == 0 {
args = []string{""}
}
result := &listOutput{
rs: make([]types.HostDatastoreBrowserSearchResults, 0),
cmd: cmd,
}
for _, arg := range args {
spec := types.HostDatastoreBrowserSearchSpec{
MatchPattern: []string{"*"},
}
if cmd.long {
spec.Details = &types.FileQueryFlags{
FileType: true,
FileSize: true,
FileOwner: types.NewBool(true), // TODO: omitempty is generated, but seems to be required
Modification: true,
}
}
for i := 0; ; i++ {
r, err := cmd.ListPath(b, arg, spec)
if err != nil {
// Treat the argument as a match pattern if not found as directory
if i == 0 && types.IsFileNotFound(err) {
spec.MatchPattern[0] = path.Base(arg)
arg = path.Dir(arg)
continue
}
return err
}
// Treat an empty result against match pattern as file not found
if i == 1 && len(r.File) == 0 {
return fmt.Errorf("File %s/%s was not found", r.FolderPath, spec.MatchPattern[0])
}
result.add(r)
break
}
}
return cmd.WriteResult(result)
}
func (cmd *ls) ListPath(b *object.HostDatastoreBrowser, path string, spec types.HostDatastoreBrowserSearchSpec) (types.HostDatastoreBrowserSearchResults, error) {
var res types.HostDatastoreBrowserSearchResults
path, err := cmd.DatastorePath(path)
if err != nil {
return res, err
}
task, err := b.SearchDatastore(context.TODO(), path, &spec)
if err != nil {
return res, err
}
info, err := task.WaitForResult(context.TODO(), nil)
if err != nil {
return res, err
}
res = info.Result.(types.HostDatastoreBrowserSearchResults)
return res, nil
}
type listOutput struct {
rs []types.HostDatastoreBrowserSearchResults
cmd *ls
}
func (o *listOutput) add(r types.HostDatastoreBrowserSearchResults) {
res := r
res.File = nil
for _, f := range r.File {
if f.GetFileInfo().Path[0] == '.' && !o.cmd.all {
continue
}
if o.cmd.slash {
if d, ok := f.(*types.FolderFileInfo); ok {
d.Path += "/"
}
}
res.File = append(res.File, f)
}
o.rs = append(o.rs, res)
}
// hasMultiplePaths returns whether or not the slice of search results contains
// results from more than one folder path.
func (o *listOutput) hasMultiplePaths() bool {
if len(o.rs) == 0 {
return false
}
p := o.rs[0].FolderPath
// Multiple paths if any entry is not equal to the first one.
for _, e := range o.rs {
if e.FolderPath != p {
return true
}
}
return false
}
func (o *listOutput) MarshalJSON() ([]byte, error) {
return json.Marshal(o.rs)
}
func (o *listOutput) Write(w io.Writer) error {
// Only include path header if we're dealing with more than one path.
includeHeader := false
if o.hasMultiplePaths() {
includeHeader = true
}
tw := tabwriter.NewWriter(w, 3, 0, 2, ' ', 0)
for i, r := range o.rs {
if includeHeader {
if i > 0 {
fmt.Fprintf(tw, "\n")
}
fmt.Fprintf(tw, "%s:\n", r.FolderPath)
}
for _, file := range r.File {
info := file.GetFileInfo()
if o.cmd.long {
fmt.Fprintf(tw, "%s\t%s\t%s\n", units.ByteSize(info.FileSize), info.Modification.Format("Mon Jan 2 15:04:05 2006"), info.Path)
} else {
fmt.Fprintf(tw, "%s\n", info.Path)
}
}
}
tw.Flush()
return nil
}

View File

@@ -1,95 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type mkdir struct {
*flags.DatastoreFlag
createParents bool
}
func init() {
cli.Register("datastore.mkdir", &mkdir{})
}
func (cmd *mkdir) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.createParents, "p", false, "Create intermediate directories as needed")
}
func (cmd *mkdir) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *mkdir) Usage() string {
return "DIRECTORY"
}
func (cmd *mkdir) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) == 0 {
return errors.New("missing operand")
}
c, err := cmd.Client()
if err != nil {
return err
}
dc, err := cmd.Datacenter()
if err != nil {
return err
}
// TODO(PN): Accept multiple args
path, err := cmd.DatastorePath(args[0])
if err != nil {
return err
}
m := object.NewFileManager(c)
err = m.MakeDirectory(context.TODO(), path, dc, cmd.createParents)
// ignore EEXIST if -p flag is given
if err != nil && cmd.createParents {
if soap.IsSoapFault(err) {
soapFault := soap.ToSoapFault(err)
if _, ok := soapFault.VimFault().(types.FileAlreadyExists); ok {
return nil
}
}
}
return err
}

View File

@@ -1,92 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type mv struct {
*flags.DatastoreFlag
force bool
}
func init() {
cli.Register("datastore.mv", &mv{})
}
func (cmd *mv) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
}
func (cmd *mv) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *mv) Usage() string {
return "SRC DST"
}
func (cmd *mv) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return errors.New("SRC and DST arguments are required")
}
c, err := cmd.Client()
if err != nil {
return err
}
dc, err := cmd.Datacenter()
if err != nil {
return err
}
// TODO: support cross-datacenter move
src, err := cmd.DatastorePath(args[0])
if err != nil {
return err
}
dst, err := cmd.DatastorePath(args[1])
if err != nil {
return err
}
m := object.NewFileManager(c)
task, err := m.MoveDatastoreFile(context.TODO(), src, dc, dst, dc, cmd.force)
if err != nil {
return err
}
return task.Wait(context.TODO())
}

View File

@@ -1,90 +0,0 @@
/*
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 datastore
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type remove struct {
*flags.HostSystemFlag
*flags.DatastoreFlag
}
func init() {
cli.Register("datastore.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string {
return "HOST..."
}
func (cmd *remove) Description() string {
return `Remove datastore from HOST.
Example:
govc datastore.remove -ds nfsDatastore cluster1
`
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
ds, err := cmd.Datastore()
if err != nil {
return err
}
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
hds, err := host.ConfigManager().DatastoreSystem(ctx)
if err != nil {
return err
}
err = hds.Remove(ctx, ds)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,96 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type rm struct {
*flags.DatastoreFlag
force bool
}
func init() {
cli.Register("datastore.rm", &rm{})
cli.Alias("datastore.rm", "datastore.delete")
}
func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
f.BoolVar(&cmd.force, "f", false, "Force; ignore nonexistent files and arguments")
}
func (cmd *rm) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rm) Usage() string {
return "FILE"
}
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) == 0 {
return errors.New("missing operand")
}
c, err := cmd.Client()
if err != nil {
return err
}
dc, err := cmd.Datacenter()
if err != nil {
return err
}
// TODO(PN): Accept multiple args
path, err := cmd.DatastorePath(args[0])
if err != nil {
return err
}
m := object.NewFileManager(c)
task, err := m.DeleteDatastoreFile(context.TODO(), path, dc)
if err != nil {
return err
}
err = task.Wait(context.TODO())
if err != nil {
if types.IsFileNotFound(err) && cmd.force {
// Ignore error
return nil
}
}
return err
}

View File

@@ -1,80 +0,0 @@
/*
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 datastore
import (
"errors"
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/soap"
)
type upload struct {
*flags.OutputFlag
*flags.DatastoreFlag
}
func init() {
cli.Register("datastore.upload", &upload{})
}
func (cmd *upload) Register(ctx context.Context, f *flag.FlagSet) {
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
}
func (cmd *upload) Process(ctx context.Context) error {
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *upload) Usage() string {
return "LOCAL REMOTE"
}
func (cmd *upload) Run(ctx context.Context, f *flag.FlagSet) error {
args := f.Args()
if len(args) != 2 {
return errors.New("invalid arguments")
}
ds, err := cmd.Datastore()
if err != nil {
return err
}
p := soap.DefaultUpload
if cmd.OutputFlag.TTY {
logger := cmd.ProgressLogger("Uploading... ")
p.Progress = logger
defer logger.Wait()
}
return ds.UploadFile(context.TODO(), args[0], args[1], &p)
}

View File

@@ -1,83 +0,0 @@
/*
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 device
import (
"flag"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type boot struct {
*flags.VirtualMachineFlag
order string
types.VirtualMachineBootOptions
}
func init() {
cli.Register("device.boot", &boot{})
}
func (cmd *boot) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.Int64Var(&cmd.BootDelay, "delay", 0, "Delay in ms before starting the boot sequence")
f.StringVar(&cmd.order, "order", "", "Boot device order")
f.Int64Var(&cmd.BootRetryDelay, "retry-delay", 0, "Delay in ms before a boot retry")
cmd.BootRetryEnabled = types.NewBool(false)
f.BoolVar(cmd.BootRetryEnabled, "retry", false, "If true, retry boot after retry-delay")
cmd.EnterBIOSSetup = types.NewBool(false)
f.BoolVar(cmd.EnterBIOSSetup, "setup", false, "If true, enter BIOS setup on next boot")
}
func (cmd *boot) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *boot) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
if cmd.order != "" {
o := strings.Split(cmd.order, ",")
cmd.BootOrder = devices.BootOrder(o)
}
return vm.SetBootOptions(context.TODO(), &cmd.VirtualMachineBootOptions)
}

View File

@@ -1,95 +0,0 @@
/*
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 cdrom
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type add struct {
*flags.VirtualMachineFlag
controller string
}
func init() {
cli.Register("device.cdrom.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.controller, "controller", "", "IDE controller name")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
c, err := devices.FindIDEController(cmd.controller)
if err != nil {
return err
}
d, err := devices.CreateCdrom(c)
if err != nil {
return err
}
err = vm.AddDevice(context.TODO(), d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(context.TODO())
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,78 +0,0 @@
/*
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 cdrom
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type eject struct {
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.cdrom.eject", &eject{})
}
func (cmd *eject) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "CD-ROM device name")
}
func (cmd *eject) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *eject) Description() string {
return `Eject media from CD-ROM device.
If device is not specified, the first CD-ROM device is used.`
}
func (cmd *eject) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
c, err := devices.FindCdrom(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(context.TODO(), devices.EjectIso(c))
}

View File

@@ -1,93 +0,0 @@
/*
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 cdrom
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type insert struct {
*flags.DatastoreFlag
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.cdrom.insert", &insert{})
}
func (cmd *insert) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "CD-ROM device name")
}
func (cmd *insert) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *insert) Usage() string {
return "ISO"
}
func (cmd *insert) Description() string {
return `Insert media on datastore into CD-ROM device.
If device is not specified, the first CD-ROM device is used.`
}
func (cmd *insert) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil || f.NArg() != 1 {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
c, err := devices.FindCdrom(cmd.device)
if err != nil {
return err
}
iso, err := cmd.DatastorePath(f.Arg(0))
if err != nil {
return nil
}
return vm.EditDevice(context.TODO(), devices.InsertIso(c, iso))
}

View File

@@ -1,83 +0,0 @@
/*
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 device
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type connect struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.connect", &connect{})
}
func (cmd *connect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *connect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *connect) Usage() string {
return "DEVICE..."
}
func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
if err = devices.Connect(device); err != nil {
return err
}
if err = vm.EditDevice(context.TODO(), device); err != nil {
return err
}
}
return nil
}

View File

@@ -1,83 +0,0 @@
/*
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 device
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type disconnect struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.disconnect", &disconnect{})
}
func (cmd *disconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Usage() string {
return "DEVICE..."
}
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
if err = devices.Disconnect(device); err != nil {
return err
}
if err = vm.EditDevice(context.TODO(), device); err != nil {
return err
}
}
return nil
}

View File

@@ -1,86 +0,0 @@
/*
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 floppy
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type add struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.floppy.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
d, err := devices.CreateFloppy()
if err != nil {
return err
}
err = vm.AddDevice(context.TODO(), d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(context.TODO())
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,78 +0,0 @@
/*
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 floppy
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type eject struct {
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.floppy.eject", &eject{})
}
func (cmd *eject) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "Floppy device name")
}
func (cmd *eject) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *eject) Description() string {
return `Eject image from floppy device.
If device is not specified, the first floppy device is used.`
}
func (cmd *eject) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
c, err := devices.FindFloppy(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(context.TODO(), devices.EjectImg(c))
}

View File

@@ -1,93 +0,0 @@
/*
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 floppy
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type insert struct {
*flags.DatastoreFlag
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.floppy.insert", &insert{})
}
func (cmd *insert) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
cmd.DatastoreFlag.Register(ctx, f)
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "Floppy device name")
}
func (cmd *insert) Process(ctx context.Context) error {
if err := cmd.DatastoreFlag.Process(ctx); err != nil {
return err
}
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *insert) Usage() string {
return "IMG"
}
func (cmd *insert) Description() string {
return `Insert image on datastore into floppy device.
If device is not specified, the first floppy device is used.`
}
func (cmd *insert) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil || f.NArg() != 1 {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
c, err := devices.FindFloppy(cmd.device)
if err != nil {
return err
}
img, err := cmd.DatastorePath(f.Arg(0))
if err != nil {
return nil
}
return vm.EditDevice(context.TODO(), devices.InsertImg(c, img))
}

View File

@@ -1,185 +0,0 @@
/*
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 device
import (
"flag"
"fmt"
"io"
"os"
"strings"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type info struct {
*flags.VirtualMachineFlag
*flags.OutputFlag
*flags.NetworkFlag
}
func init() {
cli.Register("device.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
cmd.NetworkFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
if err := cmd.NetworkFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[DEVICE]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
res := infoResult{
list: devices,
}
if cmd.NetworkFlag.IsSet() {
net, err := cmd.Network()
if err != nil {
return err
}
backing, err := net.EthernetCardBackingInfo(context.TODO())
if err != nil {
return err
}
devices = devices.SelectByBackingInfo(backing)
}
if f.NArg() == 0 {
res.Devices = devices
} else {
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
res.Devices = append(res.Devices, device)
}
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Devices object.VirtualDeviceList
// need the full list of devices to lookup attached devices and controllers
list object.VirtualDeviceList
}
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, device := range r.Devices {
d := device.GetVirtualDevice()
info := d.DeviceInfo.GetDescription()
fmt.Fprintf(tw, "Name:\t%s\n", r.Devices.Name(device))
fmt.Fprintf(tw, " Type:\t%s\n", r.Devices.TypeName(device))
fmt.Fprintf(tw, " Label:\t%s\n", info.Label)
fmt.Fprintf(tw, " Summary:\t%s\n", info.Summary)
fmt.Fprintf(tw, " Key:\t%d\n", d.Key)
if c, ok := device.(types.BaseVirtualController); ok {
var attached []string
for _, key := range c.GetVirtualController().Device {
attached = append(attached, r.Devices.Name(r.list.FindByKey(key)))
}
fmt.Fprintf(tw, " Devices:\t%s\n", strings.Join(attached, ", "))
} else {
if c := r.list.FindByKey(d.ControllerKey); c != nil {
fmt.Fprintf(tw, " Controller:\t%s\n", r.Devices.Name(c))
if d.UnitNumber != nil {
fmt.Fprintf(tw, " Unit number:\t%d\n", *d.UnitNumber)
} else {
fmt.Fprintf(tw, " Unit number:\t<nil>\n")
}
}
}
if ca := d.Connectable; ca != nil {
fmt.Fprintf(tw, " Connected:\t%t\n", ca.Connected)
fmt.Fprintf(tw, " Start connected:\t%t\n", ca.StartConnected)
fmt.Fprintf(tw, " Guest control:\t%t\n", ca.AllowGuestControl)
fmt.Fprintf(tw, " Status:\t%s\n", ca.Status)
}
switch md := device.(type) {
case types.BaseVirtualEthernetCard:
fmt.Fprintf(tw, " MAC Address:\t%s\n", md.GetVirtualEthernetCard().MacAddress)
fmt.Fprintf(tw, " Address type:\t%s\n", md.GetVirtualEthernetCard().AddressType)
case *types.VirtualDisk:
if b, ok := md.Backing.(types.BaseVirtualDeviceFileBackingInfo); ok {
fmt.Fprintf(tw, " File:\t%s\n", b.GetVirtualDeviceFileBackingInfo().FileName)
}
if b, ok := md.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok && b.Parent != nil {
fmt.Fprintf(tw, " Parent:\t%s\n", b.Parent.GetVirtualDeviceFileBackingInfo().FileName)
}
case *types.VirtualSerialPort:
if b, ok := md.Backing.(*types.VirtualSerialPortURIBackingInfo); ok {
fmt.Fprintf(tw, " Direction:\t%s\n", b.Direction)
fmt.Fprintf(tw, " Service URI:\t%s\n", b.ServiceURI)
fmt.Fprintf(tw, " Proxy URI:\t%s\n", b.ProxyURI)
}
}
}
return tw.Flush()
}

View File

@@ -1,86 +0,0 @@
/*
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 device
import (
"flag"
"fmt"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type ls struct {
*flags.VirtualMachineFlag
boot bool
}
func init() {
cli.Register("device.ls", &ls{})
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.BoolVar(&cmd.boot, "boot", false, "List devices configured in the VM's boot options")
}
func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
if cmd.boot {
options, err := vm.BootOptions(context.TODO())
if err != nil {
return err
}
devices = devices.SelectBootOrder(options.BootOrder)
}
tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)
for _, device := range devices {
fmt.Fprintf(tw, "%s\t%s\t%s\n", devices.Name(device), devices.TypeName(device),
device.GetVirtualDevice().DeviceInfo.GetDescription().Summary)
}
return tw.Flush()
}

View File

@@ -1,79 +0,0 @@
/*
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 device
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type remove struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string {
return "DEVICE..."
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
for _, name := range f.Args() {
device := devices.Find(name)
if device == nil {
return fmt.Errorf("device '%s' not found", name)
}
if err = vm.RemoveDevice(context.TODO(), device); err != nil {
return err
}
}
return nil
}

View File

@@ -1,107 +0,0 @@
/*
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 scsi
import (
"flag"
"fmt"
"strings"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type add struct {
*flags.VirtualMachineFlag
controller string
sharedBus string
hotAddRemove bool
}
func init() {
cli.Register("device.scsi.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
var ctypes []string
ct := object.SCSIControllerTypes()
for _, t := range ct {
ctypes = append(ctypes, ct.Type(t))
}
f.StringVar(&cmd.controller, "type", ct.Type(ct[0]),
fmt.Sprintf("SCSI controller type (%s)", strings.Join(ctypes, "|")))
f.StringVar(&cmd.sharedBus, "sharing", string(types.VirtualSCSISharingNoSharing), "SCSI sharing")
f.BoolVar(&cmd.hotAddRemove, "hot", false, "Enable hot-add/remove")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
d, err := devices.CreateSCSIController(cmd.controller)
if err != nil {
return err
}
c := d.(types.BaseVirtualSCSIController).GetVirtualSCSIController()
c.HotAddRemove = &cmd.hotAddRemove
c.SharedBus = types.VirtualSCSISharing(cmd.sharedBus)
err = vm.AddDevice(context.TODO(), d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(context.TODO())
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,86 +0,0 @@
/*
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 serial
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type add struct {
*flags.VirtualMachineFlag
}
func init() {
cli.Register("device.serial.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
d, err := devices.CreateSerialPort()
if err != nil {
return err
}
err = vm.AddDevice(context.TODO(), d)
if err != nil {
return err
}
// output name of device we just created
devices, err = vm.Device(context.TODO())
if err != nil {
return err
}
devices = devices.SelectByType(d)
name := devices.Name(devices[len(devices)-1])
fmt.Println(name)
return nil
}

View File

@@ -1,74 +0,0 @@
/*
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 serial
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type connect struct {
*flags.VirtualMachineFlag
device string
client bool
}
func init() {
cli.Register("device.serial.connect", &connect{})
}
func (cmd *connect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "serial port device name")
f.BoolVar(&cmd.client, "client", false, "Use client direction")
}
func (cmd *connect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *connect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
d, err := devices.FindSerialPort(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(context.TODO(), devices.ConnectSerialPort(d, f.Arg(0), cmd.client))
}

View File

@@ -1,72 +0,0 @@
/*
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 serial
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"golang.org/x/net/context"
)
type disconnect struct {
*flags.VirtualMachineFlag
device string
}
func init() {
cli.Register("device.serial.disconnect", &disconnect{})
}
func (cmd *disconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
cmd.VirtualMachineFlag.Register(ctx, f)
f.StringVar(&cmd.device, "device", "", "serial port device name")
}
func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
vm, err := cmd.VirtualMachine()
if err != nil {
return err
}
if vm == nil {
return flag.ErrHelp
}
devices, err := vm.Device(context.TODO())
if err != nil {
return err
}
d, err := devices.FindSerialPort(cmd.device)
if err != nil {
return err
}
return vm.EditDevice(context.TODO(), devices.DisconnectSerialPort(d))
}

View File

@@ -1,145 +0,0 @@
/*
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 dvs
import (
"flag"
"fmt"
"os"
"strings"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*flags.HostSystemFlag
path string
pnic string
}
func init() {
cli.Register("dvs.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.StringVar(&cmd.path, "dvs", "", "DVS path")
f.StringVar(&cmd.pnic, "pnic", "vmnic0", "Name of the host physical NIC")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string {
return "HOST..."
}
func (cmd *add) Description() string {
return `Add hosts to DVS.`
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() == 0 {
return flag.ErrHelp
}
finder, err := cmd.Finder()
if err != nil {
return err
}
net, err := finder.Network(ctx, cmd.path)
if err != nil {
return err
}
dvs, ok := net.(*object.DistributedVirtualSwitch)
if !ok {
return fmt.Errorf("%s (%T) is not of type %T", cmd.path, net, dvs)
}
var s mo.VmwareDistributedVirtualSwitch
err = dvs.Properties(ctx, dvs.Reference(), []string{"config"}, &s)
if err != nil {
return err
}
backing := new(types.DistributedVirtualSwitchHostMemberPnicBacking)
for _, vmnic := range strings.Split(cmd.pnic, ",") {
backing.PnicSpec = append(backing.PnicSpec, types.DistributedVirtualSwitchHostMemberPnicSpec{
PnicDevice: strings.TrimSpace(vmnic),
})
}
config := &types.DVSConfigSpec{
ConfigVersion: s.Config.GetDVSConfigInfo().ConfigVersion,
}
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
existing := make(map[string]bool)
// TODO: host.pnic.info command
for _, member := range s.Config.GetDVSConfigInfo().Host {
existing[member.Config.Host.Value] = true
}
for _, host := range hosts {
ref := host.Reference()
if existing[ref.Value] {
fmt.Fprintf(os.Stderr, "%s is already a member of %s\n", host.InventoryPath, dvs.InventoryPath)
continue
}
config.Host = append(config.Host, types.DistributedVirtualSwitchHostMemberConfigSpec{
Operation: "add",
Host: ref,
Backing: backing,
})
}
if len(config.Host) == 0 {
return nil
}
task, err := dvs.Reconfigure(ctx, config)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %d hosts to dvs %s... ", len(config.Host), dvs.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,119 +0,0 @@
/*
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 dvs
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type create struct {
*flags.DatacenterFlag
types.DVSCreateSpec
configSpec *types.VMwareDVSConfigSpec
parent string
}
func init() {
cli.Register("dvs.create", &create{})
}
func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.configSpec = new(types.VMwareDVSConfigSpec)
cmd.DVSCreateSpec.ConfigSpec = cmd.configSpec
f.StringVar(&cmd.parent, "parent", "", "Path to parent folder for the new dvs")
}
func (cmd *create) Usage() string {
return "DVS"
}
func (cmd *create) Description() string {
return `Create DVS (DistributedVirtualSwitch) in datacenter.
The dvs is added to the folder specified by the 'parent' flag. If not given,
this defaults to the network folder in the specified or default datacenter.`
}
func (cmd *create) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
var parent *object.Folder
if f.NArg() != 1 {
return flag.ErrHelp
}
name := f.Arg(0)
if cmd.parent == "" {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
parent = folders.NetworkFolder
} else {
finder, err := cmd.Finder()
if err != nil {
return err
}
parent, err = finder.Folder(ctx, cmd.parent)
if err != nil {
return err
}
}
cmd.configSpec.Name = name
task, err := parent.CreateDVS(ctx, cmd.DVSCreateSpec)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to folder %s... ", name, parent.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,108 +0,0 @@
/*
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 portgroup
import (
"flag"
"fmt"
"strings"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*flags.DatacenterFlag
types.DVPortgroupConfigSpec
path string
}
func init() {
cli.Register("dvs.portgroup.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.path, "dvs", "", "DVS path")
ptypes := []string{
string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
string(types.DistributedVirtualPortgroupPortgroupTypeLateBinding),
string(types.DistributedVirtualPortgroupPortgroupTypeEphemeral),
}
f.StringVar(&cmd.DVPortgroupConfigSpec.Type, "type", ptypes[0],
fmt.Sprintf("Portgroup type (%s)", strings.Join(ptypes, "|")))
cmd.DVPortgroupConfigSpec.NumPorts = 128 // default
f.Var(flags.NewInt32(&cmd.DVPortgroupConfigSpec.NumPorts), "nports", "Number of ports")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string {
return "NAME"
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() == 0 {
return flag.ErrHelp
}
name := f.Arg(0)
finder, err := cmd.Finder()
if err != nil {
return err
}
net, err := finder.Network(ctx, cmd.path)
if err != nil {
return err
}
dvs, ok := net.(*object.DistributedVirtualSwitch)
if !ok {
return fmt.Errorf("%s (%T) is not of type %T", cmd.path, net, dvs)
}
cmd.DVPortgroupConfigSpec.Name = name
task, err := dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{cmd.DVPortgroupConfigSpec})
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s portgroup to dvs %s... ", name, dvs.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}

View File

@@ -1,165 +0,0 @@
/*
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 portgroup
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type info struct {
*flags.DatacenterFlag
pg string
active bool
connected bool
inside bool
uplinkPort bool
vlanID int
count uint
}
func init() {
cli.Register("dvs.portgroup.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
f.StringVar(&cmd.pg, "pg", "", "Distributed Virtual Portgroup")
f.BoolVar(&cmd.active, "active", false, "Filter by port active or inactive status")
f.BoolVar(&cmd.connected, "connected", false, "Filter by port connected or disconnected status")
f.BoolVar(&cmd.inside, "inside", true, "Filter by port inside or outside status")
f.BoolVar(&cmd.uplinkPort, "uplinkPort", false, "Filter for uplink ports")
f.IntVar(&cmd.vlanID, "vlan", 0, "Filter by VLAN ID (0 = unfiltered)")
f.UintVar(&cmd.count, "count", 0, "Number of matches to return (0 = unlimited)")
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
client, err := cmd.Client()
if err != nil {
return err
}
finder, err := cmd.Finder()
if err != nil {
return err
}
// Retrieve DVS reference
net, err := finder.Network(ctx, f.Arg(0))
if err != nil {
return err
}
// Convert to DVS object type
dvs, ok := net.(*object.DistributedVirtualSwitch)
if !ok {
return fmt.Errorf("%s (%s) is not a DVS", f.Arg(0), net.Reference().Type)
}
// Set base search criteria
criteria := types.DistributedVirtualSwitchPortCriteria{
Connected: types.NewBool(cmd.connected),
Active: types.NewBool(cmd.active),
UplinkPort: types.NewBool(cmd.uplinkPort),
Inside: types.NewBool(cmd.inside),
}
// If a distributed virtual portgroup path is set, then add its portgroup key to the base criteria
if len(cmd.pg) > 0 {
// Retrieve distributed virtual portgroup reference
net, err = finder.Network(ctx, cmd.pg)
if err != nil {
return err
}
// Convert distributed virtual portgroup object type
dvpg, ok := net.(*object.DistributedVirtualPortgroup)
if !ok {
return fmt.Errorf("%s (%s) is not a DVPG", cmd.pg, net.Reference().Type)
}
// Obtain portgroup key property
var dvp mo.DistributedVirtualPortgroup
if err := dvpg.Properties(ctx, dvpg.Reference(), []string{"key"}, &dvp); err != nil {
return err
}
// Add portgroup key to port search criteria
criteria.PortgroupKey = []string{dvp.Key}
}
// Prepare request
req := types.FetchDVPorts{
This: dvs.Reference(),
Criteria: &criteria,
}
// Fetch ports
res, err := methods.FetchDVPorts(ctx, client, &req)
if err != nil {
return err
}
var returnedPorts uint
// Iterate over returned ports
for _, port := range res.Returnval {
portConfigSetting := port.Config.Setting.(*types.VMwareDVSPortSetting)
portVlan := portConfigSetting.Vlan.(*types.VmwareDistributedVirtualSwitchVlanIdSpec)
portVlanID := portVlan.VlanId
// Show port info if: VLAN ID is not defined, or VLAN ID matches requested VLAN
if cmd.vlanID == 0 || portVlanID == int32(cmd.vlanID) {
returnedPorts++
fmt.Printf("PortgroupKey: %s\n", port.PortgroupKey)
fmt.Printf("DvsUuid: %s\n", port.DvsUuid)
fmt.Printf("VlanId: %d\n", portVlanID)
fmt.Printf("PortKey: %s\n\n", port.Key)
// If we are limiting the count and have reached the count, then stop returning output
if cmd.count > 0 && returnedPorts == cmd.count {
break
}
}
}
return nil
}

View File

@@ -1,3 +0,0 @@
.cask
elpa
*.elc

View File

@@ -1,10 +0,0 @@
(source gnu)
(source melpa)
(package-file "govc.el")
(development
(depends-on "dash")
(depends-on "json-mode")
(depends-on "magit")
(depends-on "s"))

View File

@@ -1,27 +0,0 @@
CASK = cask
EMACS_BIN ?= emacs
EMACS_FLAGS =
EMACS_EXEC = $(CASK) exec $(EMACS_BIN) --no-site-file --no-site-lisp --batch $(EMACS_FLAGS)
OBJECTS = govc.elc
elpa:
$(CASK) install
$(CASK) update
touch $@
.PHONY: build test docs clean
build: elpa $(OBJECTS)
test: build docs
$(EMACS_EXEC) -l test/make.el -f make-test
docs: build
$(EMACS_EXEC) -l test/make.el -f make-docs
clean:
rm -f $(OBJECTS) elpa
rm -rf .cask
%.elc: %.el
$(EMACS_EXEC) -f batch-byte-compile $<

View File

@@ -1,226 +0,0 @@
# govc.el
Interface to govc for managing VMware ESXi and vCenter.
The goal of this package is to provide a simple interface for commonly used
govc commands within Emacs. This includes table based inventory/state modes
for vms, hosts, datastores and pools. The keymap for each mode provides
shortcuts for easily feeding the data in view to other govc commands.
Within the various govc modes, press `?` to see a popup menu of options.
A menu bar is enabled for certain modes, such as `govc-vm-mode` and `govc-host-mode`.
There is also a `govc` menu at all times under the `Tools` menu.
The recommended way to install govc.el is via MELPA (http://melpa.org/).
## govc-mode
Running `govc-global-mode` creates key bindings to the various govc modes.
The default prefix is `C-c ;` and can be changed by setting `govc-keymap-prefix`.
### govc-command-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>h</kbd> | Host info via govc
<kbd>p</kbd> | Pool info via govc
<kbd>v</kbd> | VM info via govc
<kbd>s</kbd> | Datastore info via govc
### govc-urls
List of URLs for use with `govc-session`.
The `govc-session-name` displayed by `govc-mode-line` uses `url-target` (anchor)
if set, otherwise `url-host` is used.
Example:
```
(setq govc-urls `("root:vagrant@localhost:18443#Vagrant-ESXi"
"root:password@192.168.1.192#Intel-NUC"
"Administrator@vsphere.local:password!@vcva-clovervm"))
```
To enter a URL that is not in the list, prefix `universal-argument`, for example:
`C-u M-x govc-vm`
When in `govc-vm` or `govc-host` mode, a default URL is composed with the
current session credentials and the IP address of the current vm/host and
the vm/host name as the session name. This makes it easier to connect to
nested ESX/vCenter VMs or directly to an ESX host.
### govc-session-url
ESX or vCenter URL set by `govc-session` via `govc-urls` selection.
### govc-session-insecure
Skip verification of server certificate when true.
This variable is set to the value of the `GOVC_INSECURE` env var by default.
It can also be set per-url via the query string (insecure=true). For example:
```
(setq govc-urls `("root:password@hostname?insecure=true"))
```
### govc-session-datacenter
Datacenter to use for the current `govc-session`.
If the endpoint has a single Datacenter it will be used by default, otherwise
`govc-session` will prompt for selection. It can also be set per-url via the
query string. For example:
```
(setq govc-urls `("root:password@hostname?datacenter=dc1"))
```
### govc-session-datastore
Datastore to use for the current `govc-session`.
If the endpoint has a single Datastore it will be used by default, otherwise
`govc-session` will prompt for selection. It can also be set per-url via the
query string. For example:
```
(setq govc-urls `("root:password@hostname?datastore=vsanDatastore"))
```
## govc-tabulated-list-mode
Generic table bindings to mark/unmark rows.
In addition to any hooks its parent mode `tabulated-list-mode` might have run,
this mode runs the hook `govc-tabulated-list-mode-hook`, as the final step
during initialization.
### govc-tabulated-list-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>m</kbd> | Mark and move to the next line
<kbd>u</kbd> | Unmark and move to the next line
<kbd>t</kbd> | Toggle mark
<kbd>U</kbd> | Unmark all
<kbd>M-&</kbd> | Shell CMD with current `govc-session` exported as GOVC_ env vars
<kbd>M-w</kbd> | Copy current selection or region to the kill ring
<kbd>M-E</kbd> | Export session to `process-environment` and `kill-ring`
## govc-host-mode
Major mode for handling a list of govc hosts.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-host-mode-hook`, as the final step
during initialization.
### govc-host-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>E</kbd> | Events via govc events -n `govc-max-events`
<kbd>J</kbd> | JSON via govc host
<kbd>N</kbd> | Netstat via `govc-esxcli-netstat-info` with current host id
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>p</kbd> | Pool-mode with current session
<kbd>s</kbd> | Datastore-mode with current session
<kbd>v</kbd> | VM-mode with current session
## govc-pool-mode
Major mode for handling a list of govc pools.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-pool-mode-hook`, as the final step
during initialization.
### govc-pool-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>E</kbd> | Events via govc events -n `govc-max-events`
<kbd>J</kbd> | JSON via govc pool
<kbd>D</kbd> | Destroy via `govc-pool-destroy` on the pool selection
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>h</kbd> | Host-mode with current session
<kbd>s</kbd> | Datastore-mode with current session
<kbd>v</kbd> | VM-mode with current session
## govc-datastore-mode
Major mode for govc datastore.info.
In addition to any hooks its parent mode `tabulated-list-mode` might have run,
this mode runs the hook `govc-datastore-mode-hook`, as the final step
during initialization.
### govc-datastore-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>J</kbd> | JSON via govc datastore
<kbd>RET</kbd> | Browse datastore
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>h</kbd> | Host-mode with current session
<kbd>p</kbd> | Pool-mode with current session
<kbd>v</kbd> | VM-mode with current session
## govc-datastore-ls-mode
Major mode govc datastore.ls.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-datastore-ls-mode-hook`, as the final step
during initialization.
### govc-datastore-ls-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>J</kbd> | JSON via govc datastore
<kbd>D</kbd> | Delete selected datastore paths
<kbd>+</kbd> | Mkdir via govc datastore
<kbd>DEL</kbd> | Up to parent folder
<kbd>RET</kbd> | Open datastore folder or file
## govc-vm-mode
Major mode for handling a list of govc vms.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-vm-mode-hook`, as the final step
during initialization.
### govc-vm-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>E</kbd> | Events via govc events -n `govc-max-events`
<kbd>J</kbd> | JSON via govc vm
<kbd>X</kbd> | ExtraConfig via `govc-vm-extra-config` on the current selection
<kbd>RET</kbd> | Devices via `govc-device` on the current selection
<kbd>C</kbd> | Console screenshot via `govc-vm-screen` on the current selection
<kbd>V</kbd> | VNC via `govc-vm-vnc` on the current selection
<kbd>D</kbd> | Destroy via `govc-vm-destroy` on the current selection
<kbd>^</kbd> | Start via `govc-vm-start` on the current selection
<kbd>!</kbd> | Shutdown via `govc-vm-shutdown` on the current selection
<kbd>@</kbd> | Reboot via `govc-vm-reboot` on the current selection
<kbd>&</kbd> | Suspend via `govc-vm-suspend` on the current selection
<kbd>H</kbd> | Host info via `govc-host` with host(s) of current selection
<kbd>S</kbd> | Datastore via `govc-datastore-ls` with datastore of current selection
<kbd>P</kbd> | Ping VM
<kbd>c</kbd> | Connect new session for the current govc mode
<kbd>h</kbd> | Host-mode with current session
<kbd>p</kbd> | Pool-mode with current session
<kbd>s</kbd> | Datastore-mode with current session
## govc-device-mode
Major mode for handling a govc device.
In addition to any hooks its parent mode `govc-tabulated-list-mode` might have run,
this mode runs the hook `govc-device-mode-hook`, as the final step
during initialization.
### govc-device-mode-map
Keybinding | Description
---------------|------------------------------------------------------------
<kbd>J</kbd> | JSON via govc device
<kbd>RET</kbd> | Tabulated govc device

File diff suppressed because it is too large Load Diff

View File

@@ -1,137 +0,0 @@
(defconst testsuite-dir
(if load-file-name
(file-name-directory load-file-name)
;; Fall back to default directory (in case of M-x eval-buffer)
default-directory)
"Directory of the test suite.")
(defconst govc-test-helper-path
(concat (expand-file-name (concat testsuite-dir "/../../test/test_helper.bash"))))
(load (expand-file-name "../govc" testsuite-dir) nil :no-message)
(ert-deftest test-govc-url-parse ()
(dolist (u '("root:vagrant@localhost:18443"
"Administrator@vsphere.local:vagrant@localhost"
"https://root:vagrant@localhost:18443/sdk"
"https://Administrator@vsphere.local:vagrant@localhost/sdk"))
(should (equal u (url-recreate-url (govc-url-parse u))))))
(ert-deftest test-govc-session-set-url ()
(should (equal govc-session-insecure nil))
(should (equal govc-session-datacenter nil))
(with-temp-buffer
(govc-session-set-url "vc.example.com?insecure=true&datacenter=foo&ignored=true")
(should (equal govc-session-insecure "true"))
(should (equal govc-session-datacenter "foo"))
(should (equal govc-session-datastore nil))))
(ert-deftest test-govc-copy-environment ()
(let ((process-environment)
(govc-session-url "vc.example.com")
(govc-session-insecure "false")
(govc-session-datacenter "dc1")
(govc-session-datastore "ds1"))
(govc-export-environment '-)
(dolist (e govc-environment-map)
(should (equal nil (getenv (car e)))))
(govc-export-environment (universal-argument))
(dolist (e govc-environment-map)
(should (not (equal nil (getenv (car e))))))))
(defun govc-test-env ()
(let ((url (getenv "GOVC_TEST_URL")))
(unless url
(ert-skip "env GOVC_TEST_URL not set"))
(setq govc-session-url url
govc-session-insecure "true")))
(defun govc-test-helper (arg)
(shell-command-to-string (format "bash -c \"source %s; %s\"" govc-test-helper-path arg)))
(defun govc-test-new-vm ()
(s-trim-right (govc-test-helper "new_empty_vm")))
(defun govc-test-new-id ()
(s-trim-right (govc-test-helper "new_id")))
(defun govc-test-teardown ()
(ignore-errors
(govc-test-helper "teardown")))
(ert-deftest test-govc-vm-info ()
(govc-test-env)
(unwind-protect
(let ((id (govc-test-new-vm)))
(govc-json-info "vm.info" (list id))
(with-current-buffer "*govc-json*"
(goto-char (point-min))
(let ((data (json-read)))
(should (= (length data) 1))
(should (cdr (assq 'VirtualMachines data)))))
(govc-json-info "vm.info" (list "ENOENT"))
(with-current-buffer "*govc-json*"
(goto-char (point-min))
(let ((data (json-read)))
(should (= (length data) 1))
(should (not (cdr (assq 'VirtualMachines data))))))
(let ((govc-args (list id))
(len1)
(len2))
(setq len1 (length (govc-vm-extra-config)))
(should (>= len1 1))
(govc "vm.change" "-vm" id
"-e" "govc-test-one=1"
"-e" "govc-test-two:2.2=2"
;; test that we don't choke on \n
"-e" "foo=bar
baz")
(setq len2 (length (govc-vm-extra-config)))
(should (= (- len2 len1) 3)))
(let ((govc-filter "*"))
(should (>= (length (govc-vm-info)) 1)))
(let ((govc-filter "ENOENT"))
(should (= (length (govc-vm-info)) 0)))
(govc-vm-screen id))
(govc-test-teardown)))
(ert-deftest test-govc-datastore-ls-entries ()
(govc-test-env)
(unwind-protect
(let ((id (govc-test-new-id)))
(should (>= (length (govc-datastore-ls-entries)) 1))
(let ((govc-filter (concat id "/")))
(should-error (govc-datastore-ls-entries))
(govc "datastore.mkdir" id)
(should (= (length (govc-datastore-ls-entries)) 0))
(dotimes (i 3)
(govc "datastore.mkdir" (format "%s/dir %d" id i)))
(let ((entries (govc-datastore-ls-entries)))
(should (= (length entries) 3))
(should (s-starts-with? (concat id "/dir ") (caar entries))))))
(govc-test-teardown)))
(ert-deftest test-govc-pool-ls ()
(govc-test-env)
(unwind-protect
(let* ((pools (govc-ls-pool))
(num (length pools))
(path (concat (car pools) "/" (govc-test-new-id))))
(should (>= num 1))
(message "%d existing pools [%S]" num pools)
(govc "pool.create" path)
(setq pools (govc-ls-pool))
(govc-pool-destroy path)
(should (= (- (length pools) num) 1)))
(govc-test-teardown)))
(ert-deftest test-govc-about ()
(govc-test-env)
(govc "about"))

View File

@@ -1,58 +0,0 @@
#!/usr/bin/env emacs --script
(let ((current-directory (file-name-directory load-file-name)))
(setq project-test-path (expand-file-name "." current-directory))
(setq project-root-path (expand-file-name ".." current-directory)))
(add-to-list 'load-path project-root-path)
(add-to-list 'load-path project-test-path)
(require 'lisp-mnt)
(require 'govc)
(require 's)
(defun make-test ()
(dolist (test-file (or argv (directory-files project-test-path t "-test.el$")))
(load test-file nil t))
(ert-run-tests-batch-and-exit t))
(defun govc-help ()
"Summary of govc modes in markdown format."
(interactive)
(with-help-window (help-buffer) ; TODO: this turned into a mess, but does the job of generating README.md from govc.el
(dolist (kind '(govc-mode govc-urls govc-session-url govc-session-insecure govc-session-datacenter govc-session-datastore
tabulated-list host pool datastore datastore-ls vm device))
(let* ((name (if (boundp kind) (symbol-name kind) (format "govc-%s-mode" kind)))
(map (if (equal 'govc-mode kind) 'govc-command-map (intern (concat name "-map"))))
(doc (lambda (f &optional all)
(let* ((txt (if (functionp f) (documentation f t) (documentation-property f 'variable-documentation)))
(ix (if all (length txt) (s-index-of "." txt))))
(s-replace (format "\n\n\\\{%s\}" (concat name "-map")) ""
(s-replace "'" "`" (substring txt 0 ix)))))))
(princ (concat (s-repeat (if (and (boundp kind) (not (fboundp kind))) 3 2) "#") " " name "\n"))
(princ (concat "\n" (funcall doc (intern name) t) "\n\n"))
(when (boundp map)
(princ (concat "### " (symbol-name map) "\n\n"))
(princ "Keybinding | Description\n")
(princ "---------------|------------------------------------------------------------\n")
(dolist (kl (govc-keymap-list (symbol-value map)))
(let ((key (govc-key-description (car kl))))
(princ (format "<kbd>%s</kbd>%s| %s\n" key (s-repeat (- 4 (length key)) " ") (funcall doc (nth 2 kl))))))
(princ "\n"))))))
(defun make-docs ()
(let ((commentary)
(summary))
(with-current-buffer (find-file-noselect (concat project-root-path "/govc.el"))
(setq commentary (s-replace ";;; Commentary:" "" (lm-commentary))
summary (lm-summary)))
(let ((readme (find-file-noselect (concat project-root-path "/README.md"))))
(with-current-buffer readme
(erase-buffer)
(govc-help)
(with-current-buffer (help-buffer)
(copy-to-buffer readme (point-min) (point-max)))
(goto-char (point-min))
(insert (concat "# govc.el\n\n" summary ".\n"))
(insert (s-replace "'" "`" (replace-regexp-in-string ";; ?" "" commentary t t)))
(save-buffer 0)))))

View File

@@ -1,120 +0,0 @@
/*
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 events
import (
"flag"
"fmt"
"os"
"strings"
"time"
"github.com/vmware/govmomi/event"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type events struct {
*flags.DatacenterFlag
Max int32
Tail bool
Force bool
}
func init() {
// initialize with the maximum allowed objects set
cli.Register("events", &events{})
}
func (cmd *events) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.Max = 25 // default
f.Var(flags.NewInt32(&cmd.Max), "n", "Output the last N events")
f.BoolVar(&cmd.Tail, "f", false, "Tail event stream")
f.BoolVar(&cmd.Force, "force", false, "Force event collection: use with CAUTION ")
}
func (cmd *events) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *events) printEvents(ctx context.Context, page []types.BaseEvent, m *event.Manager) error {
event.Sort(page)
for _, e := range page {
cat, err := m.EventCategory(ctx, e)
if err != nil {
return err
}
event := e.GetEvent()
msg := strings.TrimSpace(event.FullFormattedMessage)
if t, ok := e.(*types.TaskEvent); ok {
msg = fmt.Sprintf("%s (target=%s %s)", msg, t.Info.Entity.Type, t.Info.EntityName)
}
fmt.Fprintf(os.Stdout, "[%s] [%s] %s\n",
event.CreatedTime.Local().Format(time.ANSIC),
cat, msg)
}
return nil
}
func (cmd *events) Usage() string {
return "[PATH]..."
}
func (cmd *events) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
objs, err := cmd.ManagedObjects(ctx, f.Args())
if err != nil {
return err
}
if len(objs) > 0 {
// need an event manager
m := event.NewManager(c)
// get the event stream
err := m.Events(ctx, objs, cmd.Max, cmd.Tail, cmd.Force, func(ee []types.BaseEvent) error {
err = cmd.printEvents(ctx, ee, m)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,44 +0,0 @@
function public-key {
local dir=${HOME}/.ssh
for f in $HOME/.ssh/{id_{rsa,dsa},*}.pub; do
if [ -r $f ]; then
echo $f
return
fi
done
echo "Can't find public key file..."
exit 1
}
PUBLIC_KEY_FILE=${PUBLIC_KEY_FILE-$(public-key)}
SSH_OPTS="-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet"
function upload-public-key {
local vm_name=$1
local dir=$2
if [ -z "$dir" ]
then
uid=$(echo $GOVC_GUEST_LOGIN | awk -F: '{print $1}')
dir=$(govc guest.getenv -vm ${vm_name} HOME | awk -F= '{print $2}')
if [ -z "$dir" ]
then
echo "Can't find ${uid}'s HOME dir..."
exit 1
fi
fi
govc guest.mkdir \
-vm ${vm_name} \
-p \
${dir}/.ssh
govc guest.upload \
-vm ${vm_name} \
-f \
${PUBLIC_KEY_FILE} \
${dir}/.ssh/authorized_keys
}

View File

@@ -1,57 +0,0 @@
#!/bin/bash -e
lib=$(readlink -nf $(dirname $0))/lib
. $lib/ssh.sh
ova=$1
if [ -z "$ova" ]
then
ova=./VMware-vCenter-Server-Appliance-5.5.0.10300-2000350_OVF10.ova
fi
# default to local Vagrant esxbox for testing
export GOVC_URL=${GOVC_URL-"https://root:vagrant@localhost:8443/sdk"}
# default VCSA credentials
export GOVC_GUEST_LOGIN=root:vmware
# VM name as defined in the VCSA .ovf
vm_name=VMware_vCenter_Server_Appliance
echo "Importing $ova..."
govc import.ova $ova
echo "Powering on $vm_name..."
govc vm.power -on $vm_name
echo "Waiting for $vm_name's IP address..."
vc=$(govc vm.ip $vm_name)
govc vm.info $vm_name
echo "Uploading ssh public key to $vm_name..."
upload-public-key $vm_name
echo "Configuring vCenter Server Appliance..."
# http://www.virtuallyghetto.com/2012/02/automating-vcenter-server-appliance.html
ssh ${SSH_OPTS} root@$vc <<EOF
echo "Accepting EULA ..."
/usr/sbin/vpxd_servicecfg eula accept
echo "Configuring Embedded DB ..."
/usr/sbin/vpxd_servicecfg db write embedded
echo "Configuring SSO..."
/usr/sbin/vpxd_servicecfg sso write embedded
echo "Starting VCSA ..."
/usr/sbin/vpxd_servicecfg service start
EOF
vc_url=https://${GOVC_GUEST_LOGIN}@${vc}/sdk
echo "VCSA configured and ready..."
govc about -u $vc_url

View File

@@ -1,121 +0,0 @@
/*
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 extension
import (
"flag"
"fmt"
"io"
"os"
"text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
type info struct {
*flags.ClientFlag
*flags.OutputFlag
}
func init() {
cli.Register("extension.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return "[KEY]..."
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
list, err := m.List(ctx)
if err != nil {
return err
}
var res infoResult
if f.NArg() == 0 {
res.Extensions = list
} else {
exts := make(map[string]types.Extension)
for _, e := range list {
exts[e.Key] = e
}
for _, key := range f.Args() {
if e, ok := exts[key]; ok {
res.Extensions = append(res.Extensions, e)
} else {
return fmt.Errorf("extension %s not found", key)
}
}
}
return cmd.WriteResult(&res)
}
type infoResult struct {
Extensions []types.Extension
}
func (r *infoResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, e := range r.Extensions {
fmt.Fprintf(tw, "Name:\t%s\n", e.Key)
fmt.Fprintf(tw, " Version:\t%s\n", e.Version)
fmt.Fprintf(tw, " Description:\t%s\n", e.Description.GetDescription().Summary)
fmt.Fprintf(tw, " Company:\t%s\n", e.Company)
fmt.Fprintf(tw, " Last heartbeat time:\t%s\n", e.LastHeartbeatTime)
fmt.Fprintf(tw, " Subject name:\t%s\n", e.SubjectName)
fmt.Fprintf(tw, " Type:\t%s\n", e.Type)
}
return tw.Flush()
}

View File

@@ -1,81 +0,0 @@
/*
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 extension
import (
"encoding/json"
"flag"
"os"
"time"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type register struct {
*flags.ClientFlag
update bool
}
func init() {
cli.Register("extension.register", &register{})
}
func (cmd *register) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
f.BoolVar(&cmd.update, "update", false, "Update extension")
}
func (cmd *register) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *register) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
var e types.Extension
e.Description = new(types.Description)
if err = json.NewDecoder(os.Stdin).Decode(&e); err != nil {
return err
}
e.LastHeartbeatTime = time.Now().UTC()
if cmd.update {
return m.Update(ctx, e)
}
return m.Register(ctx, e)
}

View File

@@ -1,171 +0,0 @@
/*
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 extension
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"io/ioutil"
"math/big"
"os"
"time"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type setcert struct {
*flags.ClientFlag
cert string
org string
encodedCert bytes.Buffer
}
func init() {
cli.Register("extension.setcert", &setcert{})
}
func (cmd *setcert) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
f.StringVar(&cmd.cert, "cert-pem", "-", "PEM encoded certificate")
f.StringVar(&cmd.org, "org", "VMware", "Organization for generated certificate")
}
func (cmd *setcert) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *setcert) Usage() string {
return "ID"
}
func (cmd *setcert) Description() string {
return `The '-cert-pem' option can be one of the following:
'-' : Read the certificate from stdin
'+' : Generate a new key pair and save locally to ID.crt and ID.key
... : Any other value is passed as-is to ExtensionManager.SetCertificate
`
}
func (cmd *setcert) create(id string) error {
certFile, err := os.Create(id + ".crt")
if err != nil {
return err
}
defer certFile.Close()
keyFile, err := os.Create(id + ".key")
if err != nil {
return err
}
defer keyFile.Close()
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
notBefore := time.Now()
notAfter := notBefore.Add(5 * 365 * 24 * time.Hour) // 5 years
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return err
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{cmd.org},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
return err
}
err = pem.Encode(&cmd.encodedCert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
return err
}
_, err = certFile.Write(cmd.encodedCert.Bytes())
if err != nil {
return err
}
err = pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
if err != nil {
return err
}
return nil
}
func (cmd *setcert) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
if f.NArg() != 1 {
return flag.ErrHelp
}
key := f.Arg(0)
if cmd.cert == "-" {
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}
cmd.cert = string(b)
} else if cmd.cert == "+" {
if err := cmd.create(key); err != nil {
return fmt.Errorf("creating certificate: %s", err)
}
cmd.cert = cmd.encodedCert.String()
}
return m.SetCertificate(ctx, key, cmd.cert)
}

View File

@@ -1,66 +0,0 @@
/*
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 extension
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type unregister struct {
*flags.ClientFlag
}
func init() {
cli.Register("extension.unregister", &unregister{})
}
func (cmd *unregister) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *unregister) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *unregister) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetExtensionManager(c)
if err != nil {
return err
}
for _, key := range f.Args() {
if err = m.Unregister(ctx, key); err != nil {
return err
}
}
return nil
}

View File

@@ -1,78 +0,0 @@
/*
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 fields
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type add struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string {
return "NAME"
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 1 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
name := f.Arg(0)
def, err := m.Add(ctx, name, "", nil, nil)
if err != nil {
return err
}
fmt.Printf("%d\n", def.Key)
return nil
}

View File

@@ -1,74 +0,0 @@
/*
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 fields
import (
"flag"
"fmt"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type ls struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.ls", &ls{})
}
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
field, err := m.Field(ctx)
if err != nil {
return err
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for _, def := range field {
fmt.Fprintf(tw, "%d\t%s\n", def.Key, def.Name)
}
return tw.Flush()
}

View File

@@ -1,75 +0,0 @@
/*
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 fields
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type rename struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.rename", &rename{})
}
func (cmd *rename) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *rename) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rename) Usage() string {
return "KEY NAME"
}
func (cmd *rename) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() != 2 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
key, err := m.FindKey(ctx, f.Arg(0))
if err != nil {
return err
}
name := f.Arg(1)
return m.Rename(ctx, key, name)
}

View File

@@ -1,75 +0,0 @@
/*
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 fields
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type rm struct {
*flags.ClientFlag
}
func init() {
cli.Register("fields.rm", &rm{})
}
func (cmd *rm) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
}
func (cmd *rm) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *rm) Usage() string {
return "KEY..."
}
func (cmd *rm) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
for _, name := range f.Args() {
key, err := m.FindKey(ctx, name)
if err != nil {
return err
}
if err := m.Remove(ctx, key); err != nil {
return err
}
}
return nil
}

View File

@@ -1,89 +0,0 @@
/*
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 fields
import (
"flag"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type set struct {
*flags.DatacenterFlag
}
func init() {
cli.Register("fields.set", &set{})
}
func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
}
func (cmd *set) Process(ctx context.Context) error {
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *set) Usage() string {
return "KEY VALUE PATH..."
}
func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
if f.NArg() < 3 {
return flag.ErrHelp
}
c, err := cmd.Client()
if err != nil {
return err
}
m, err := object.GetCustomFieldsManager(c)
if err != nil {
return err
}
args := f.Args()
key, err := m.FindKey(ctx, args[0])
if err != nil {
return err
}
val := args[1]
objs, err := cmd.ManagedObjects(ctx, args[2:])
if err != nil {
return err
}
for _, ref := range objs {
err := m.Set(ctx, ref, key, val)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,435 +0,0 @@
/*
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 flags
import (
"crypto/sha1"
"crypto/tls"
"encoding/json"
"errors"
"flag"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"golang.org/x/net/context"
)
const (
envURL = "GOVC_URL"
envUsername = "GOVC_USERNAME"
envPassword = "GOVC_PASSWORD"
envCertificate = "GOVC_CERTIFICATE"
envPrivateKey = "GOVC_PRIVATE_KEY"
envInsecure = "GOVC_INSECURE"
envPersist = "GOVC_PERSIST_SESSION"
envMinAPIVersion = "GOVC_MIN_API_VERSION"
envVimNamespace = "GOVC_VIM_NAMESPACE"
envVimVersion = "GOVC_VIM_VERSION"
)
const cDescr = "ESX or vCenter URL"
type ClientFlag struct {
common
*DebugFlag
url *url.URL
username string
password string
cert string
key string
insecure bool
persist bool
minAPIVersion string
vimNamespace string
vimVersion string
client *vim25.Client
}
var clientFlagKey = flagKey("client")
func NewClientFlag(ctx context.Context) (*ClientFlag, context.Context) {
if v := ctx.Value(clientFlagKey); v != nil {
return v.(*ClientFlag), ctx
}
v := &ClientFlag{}
v.DebugFlag, ctx = NewDebugFlag(ctx)
ctx = context.WithValue(ctx, clientFlagKey, v)
return v, ctx
}
func (flag *ClientFlag) URLWithoutPassword() *url.URL {
if flag.url == nil {
return nil
}
withoutCredentials := *flag.url
withoutCredentials.User = url.User(flag.url.User.Username())
return &withoutCredentials
}
func (flag *ClientFlag) String() string {
url := flag.URLWithoutPassword()
if url == nil {
return ""
}
return url.String()
}
func (flag *ClientFlag) Set(s string) error {
var err error
flag.url, err = soap.ParseURL(s)
return err
}
func (flag *ClientFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DebugFlag.Register(ctx, f)
{
flag.Set(os.Getenv(envURL))
usage := fmt.Sprintf("%s [%s]", cDescr, envURL)
f.Var(flag, "u", usage)
}
{
flag.username = os.Getenv(envUsername)
flag.password = os.Getenv(envPassword)
}
{
value := os.Getenv(envCertificate)
usage := fmt.Sprintf("Certificate [%s]", envCertificate)
f.StringVar(&flag.cert, "cert", value, usage)
}
{
value := os.Getenv(envPrivateKey)
usage := fmt.Sprintf("Private key [%s]", envPrivateKey)
f.StringVar(&flag.key, "key", value, usage)
}
{
insecure := false
switch env := strings.ToLower(os.Getenv(envInsecure)); env {
case "1", "true":
insecure = true
}
usage := fmt.Sprintf("Skip verification of server certificate [%s]", envInsecure)
f.BoolVar(&flag.insecure, "k", insecure, usage)
}
{
persist := true
switch env := strings.ToLower(os.Getenv(envPersist)); env {
case "0", "false":
persist = false
}
usage := fmt.Sprintf("Persist session to disk [%s]", envPersist)
f.BoolVar(&flag.persist, "persist-session", persist, usage)
}
{
env := os.Getenv(envMinAPIVersion)
if env == "" {
env = "5.5"
}
flag.minAPIVersion = env
}
{
value := os.Getenv(envVimNamespace)
if value == "" {
value = soap.DefaultVimNamespace
}
usage := fmt.Sprintf("Vim namespace [%s]", envVimNamespace)
f.StringVar(&flag.vimNamespace, "vim-namespace", value, usage)
}
{
value := os.Getenv(envVimVersion)
if value == "" {
value = soap.DefaultVimVersion
}
usage := fmt.Sprintf("Vim version [%s]", envVimVersion)
f.StringVar(&flag.vimVersion, "vim-version", value, usage)
}
})
}
func (flag *ClientFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DebugFlag.Process(ctx); err != nil {
return err
}
if flag.url == nil {
return errors.New("specify an " + cDescr)
}
// Override username if set
if flag.username != "" {
var password string
var ok bool
if flag.url.User != nil {
password, ok = flag.url.User.Password()
}
if ok {
flag.url.User = url.UserPassword(flag.username, password)
} else {
flag.url.User = url.User(flag.username)
}
}
// Override password if set
if flag.password != "" {
var username string
if flag.url.User != nil {
username = flag.url.User.Username()
}
flag.url.User = url.UserPassword(username, flag.password)
}
return nil
})
}
// Retry twice when a temporary I/O error occurs.
// This means a maximum of 3 attempts.
func attachRetries(rt soap.RoundTripper) soap.RoundTripper {
return vim25.Retry(rt, vim25.TemporaryNetworkError(3))
}
func (flag *ClientFlag) sessionFile() string {
url := flag.URLWithoutPassword()
// Key session file off of full URI and insecure setting.
// Hash key to get a predictable, canonical format.
key := fmt.Sprintf("%s#insecure=%t", url.String(), flag.insecure)
name := fmt.Sprintf("%040x", sha1.Sum([]byte(key)))
return filepath.Join(os.Getenv("HOME"), ".govmomi", "sessions", name)
}
func (flag *ClientFlag) saveClient(c *vim25.Client) error {
if !flag.persist {
return nil
}
p := flag.sessionFile()
err := os.MkdirAll(filepath.Dir(p), 0700)
if err != nil {
return err
}
f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer f.Close()
err = json.NewEncoder(f).Encode(c)
if err != nil {
return err
}
return nil
}
func (flag *ClientFlag) restoreClient(c *vim25.Client) (bool, error) {
if !flag.persist {
return false, nil
}
f, err := os.Open(flag.sessionFile())
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
defer f.Close()
dec := json.NewDecoder(f)
err = dec.Decode(c)
if err != nil {
return false, err
}
return true, nil
}
func (flag *ClientFlag) loadClient() (*vim25.Client, error) {
c := new(vim25.Client)
ok, err := flag.restoreClient(c)
if err != nil {
return nil, err
}
if !ok || !c.Valid() {
return nil, nil
}
// Add retry functionality before making any calls
c.RoundTripper = attachRetries(c.RoundTripper)
m := session.NewManager(c)
u, err := m.UserSession(context.TODO())
if err != nil {
return nil, err
}
// If the session is nil, the client is not authenticated
if u == nil {
return nil, nil
}
return c, nil
}
func (flag *ClientFlag) newClient() (*vim25.Client, error) {
sc := soap.NewClient(flag.url, flag.insecure)
isTunnel := false
if flag.cert != "" {
isTunnel = true
cert, err := tls.LoadX509KeyPair(flag.cert, flag.key)
if err != nil {
return nil, err
}
sc.SetCertificate(cert)
}
// Set namespace and version
sc.Namespace = flag.vimNamespace
sc.Version = flag.vimVersion
// Add retry functionality before making any calls
rt := attachRetries(sc)
c, err := vim25.NewClient(context.TODO(), rt)
if err != nil {
return nil, err
}
// Set client, since we didn't pass it in the constructor
c.Client = sc
m := session.NewManager(c)
u := flag.url.User
if isTunnel {
err = m.LoginExtensionByCertificate(context.TODO(), u.Username(), "")
if err != nil {
return nil, err
}
} else {
err = m.Login(context.TODO(), u)
if err != nil {
return nil, err
}
}
err = flag.saveClient(c)
if err != nil {
return nil, err
}
return c, nil
}
// apiVersionValid returns whether or not the API version supported by the
// server the client is connected to is not recent enough.
func apiVersionValid(c *vim25.Client, minVersionString string) error {
if minVersionString == "-" {
// Disable version check
return nil
}
apiVersion := c.ServiceContent.About.ApiVersion
if strings.HasSuffix(apiVersion, ".x") {
// Skip version check for development builds
return nil
}
realVersion, err := ParseVersion(apiVersion)
if err != nil {
return err
}
minVersion, err := ParseVersion(minVersionString)
if err != nil {
return err
}
if !minVersion.Lte(realVersion) {
err = fmt.Errorf("Require API version %s, connected to API version %s (set %s to override)",
minVersionString,
c.ServiceContent.About.ApiVersion,
envMinAPIVersion)
return err
}
return nil
}
func (flag *ClientFlag) Client() (*vim25.Client, error) {
if flag.client != nil {
return flag.client, nil
}
c, err := flag.loadClient()
if err != nil {
return nil, err
}
// loadClient returns nil if it was unable to load a session from disk
if c == nil {
c, err = flag.newClient()
if err != nil {
return nil, err
}
}
// Check that the endpoint has the right API version
err = apiVersionValid(c, flag.minAPIVersion)
if err != nil {
return nil, err
}
flag.client = c
return flag.client, nil
}

View File

@@ -1,38 +0,0 @@
/*
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 flags
import "sync"
// Key type for storing flag instances in a context.Context.
type flagKey string
// Type to help flags out with only registering/processing once.
type common struct {
register sync.Once
process sync.Once
}
func (c *common) RegisterOnce(fn func()) {
c.register.Do(fn)
}
func (c *common) ProcessOnce(fn func() error) (err error) {
c.process.Do(func() {
err = fn()
})
return err
}

View File

@@ -1,154 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type DatacenterFlag struct {
common
*ClientFlag
*OutputFlag
path string
dc *object.Datacenter
finder *find.Finder
err error
}
var datacenterFlagKey = flagKey("datacenter")
func NewDatacenterFlag(ctx context.Context) (*DatacenterFlag, context.Context) {
if v := ctx.Value(datacenterFlagKey); v != nil {
return v.(*DatacenterFlag), ctx
}
v := &DatacenterFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.OutputFlag, ctx = NewOutputFlag(ctx)
ctx = context.WithValue(ctx, datacenterFlagKey, v)
return v, ctx
}
func (flag *DatacenterFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.OutputFlag.Register(ctx, f)
env := "GOVC_DATACENTER"
value := os.Getenv(env)
usage := fmt.Sprintf("Datacenter [%s]", env)
f.StringVar(&flag.path, "dc", value, usage)
})
}
func (flag *DatacenterFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *DatacenterFlag) Finder() (*find.Finder, error) {
if flag.finder != nil {
return flag.finder, nil
}
c, err := flag.Client()
if err != nil {
return nil, err
}
finder := find.NewFinder(c, flag.JSON || flag.Dump)
// Datacenter is not required (ls command for example).
// Set for relative func if dc flag is given or
// if there is a single (default) Datacenter
if flag.dc, err = finder.DatacenterOrDefault(context.TODO(), flag.path); err != nil {
return nil, err
}
finder.SetDatacenter(flag.dc)
flag.finder = finder
return flag.finder, nil
}
func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) {
if flag.dc != nil {
return flag.dc, nil
}
_, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.err != nil {
// Should only happen if no dc is specified and len(dcs) > 1
return nil, flag.err
}
return flag.dc, err
}
func (flag *DatacenterFlag) ManagedObjects(ctx context.Context, args []string) ([]types.ManagedObjectReference, error) {
var refs []types.ManagedObjectReference
c, err := flag.Client()
if err != nil {
return nil, err
}
if len(args) == 0 {
refs = append(refs, c.ServiceContent.RootFolder)
return refs, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
for _, arg := range args {
elements, err := finder.ManagedObjectList(ctx, arg)
if err != nil {
return nil, err
}
for _, e := range elements {
refs = append(refs, e.Object.Reference())
}
}
return refs, nil
}

View File

@@ -1,133 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"net/url"
"os"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type DatastoreFlag struct {
common
*DatacenterFlag
Name string
ds *object.Datastore
}
var datastoreFlagKey = flagKey("datastore")
// NewCustomDatastoreFlag creates and returns a new DatastoreFlag without
// trying to retrieve an existing one from the specified context.
func NewCustomDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
v := &DatastoreFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
return v, ctx
}
func NewDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) {
if v := ctx.Value(datastoreFlagKey); v != nil {
return v.(*DatastoreFlag), ctx
}
v, ctx := NewCustomDatastoreFlag(ctx)
ctx = context.WithValue(ctx, datastoreFlagKey, v)
return v, ctx
}
func (f *DatastoreFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.RegisterOnce(func() {
f.DatacenterFlag.Register(ctx, fs)
env := "GOVC_DATASTORE"
value := os.Getenv(env)
usage := fmt.Sprintf("Datastore [%s]", env)
fs.StringVar(&f.Name, "ds", value, usage)
})
}
func (f *DatastoreFlag) Process(ctx context.Context) error {
return f.ProcessOnce(func() error {
if err := f.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (f *DatastoreFlag) Datastore() (*object.Datastore, error) {
if f.ds != nil {
return f.ds, nil
}
finder, err := f.Finder()
if err != nil {
return nil, err
}
if f.ds, err = finder.DatastoreOrDefault(context.TODO(), f.Name); err != nil {
return nil, err
}
return f.ds, nil
}
func (f *DatastoreFlag) DatastorePath(name string) (string, error) {
ds, err := f.Datastore()
if err != nil {
return "", err
}
return ds.Path(name), nil
}
func (f *DatastoreFlag) DatastoreURL(path string) (*url.URL, error) {
dc, err := f.Datacenter()
if err != nil {
return nil, err
}
ds, err := f.Datastore()
if err != nil {
return nil, err
}
u, err := ds.URL(context.TODO(), dc, path)
if err != nil {
return nil, err
}
return u, nil
}
func (f *DatastoreFlag) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) {
ds, err := f.Datastore()
if err != nil {
return nil, err
}
return ds.Stat(ctx, file)
}

View File

@@ -1,93 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"golang.org/x/net/context"
"github.com/vmware/govmomi/vim25/debug"
)
type DebugFlag struct {
common
enable bool
}
var debugFlagKey = flagKey("debug")
func NewDebugFlag(ctx context.Context) (*DebugFlag, context.Context) {
if v := ctx.Value(debugFlagKey); v != nil {
return v.(*DebugFlag), ctx
}
v := &DebugFlag{}
ctx = context.WithValue(ctx, debugFlagKey, v)
return v, ctx
}
func (flag *DebugFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
env := "GOVC_DEBUG"
enable := false
switch env := strings.ToLower(os.Getenv(env)); env {
case "1", "true":
enable = true
}
usage := fmt.Sprintf("Store debug logs [%s]", env)
f.BoolVar(&flag.enable, "debug", enable, usage)
})
}
func (flag *DebugFlag) Process(ctx context.Context) error {
if !flag.enable {
return nil
}
return flag.ProcessOnce(func() error {
// Base path for storing debug logs.
r := os.Getenv("GOVC_DEBUG_PATH")
if r == "" {
r = filepath.Join(os.Getenv("HOME"), ".govmomi")
}
r = filepath.Join(r, "debug")
// Path for this particular run.
now := time.Now().Format("2006-01-02T15-04-05.999999999")
r = filepath.Join(r, now)
err := os.MkdirAll(r, 0700)
if err != nil {
return err
}
p := debug.FileProvider{
Path: r,
}
debug.SetProvider(&p)
return nil
})
}

View File

@@ -1,32 +0,0 @@
/*
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 flags
import (
"flag"
"golang.org/x/net/context"
)
type EmptyFlag struct{}
func (flag *EmptyFlag) Register(ctx context.Context, f *flag.FlagSet) {
}
func (flag *EmptyFlag) Process(ctx context.Context) error {
return nil
}

View File

@@ -1,85 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type FolderFlag struct {
common
*DatacenterFlag
name string
folder *object.Folder
}
var folderFlagKey = flagKey("folder")
func NewFolderFlag(ctx context.Context) (*FolderFlag, context.Context) {
if v := ctx.Value(folderFlagKey); v != nil {
return v.(*FolderFlag), ctx
}
v := &FolderFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, folderFlagKey, v)
return v, ctx
}
func (flag *FolderFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_FOLDER"
value := os.Getenv(env)
usage := fmt.Sprintf("Folder [%s]", env)
f.StringVar(&flag.name, "folder", value, usage)
})
}
func (flag *FolderFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *FolderFlag) Folder() (*object.Folder, error) {
if flag.folder != nil {
return flag.folder, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.folder, err = finder.FolderOrDefault(context.TODO(), flag.name); err != nil {
return nil, err
}
return flag.folder, nil
}

View File

@@ -1,79 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/vim25/types"
)
type HostConnectFlag struct {
common
types.HostConnectSpec
noverify bool
}
var hostConnectFlagKey = flagKey("hostConnect")
func NewHostConnectFlag(ctx context.Context) (*HostConnectFlag, context.Context) {
if v := ctx.Value(hostConnectFlagKey); v != nil {
return v.(*HostConnectFlag), ctx
}
v := &HostConnectFlag{}
ctx = context.WithValue(ctx, hostConnectFlagKey, v)
return v, ctx
}
func (flag *HostConnectFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
f.StringVar(&flag.HostName, "hostname", "", "Hostname or IP address of the host")
f.StringVar(&flag.UserName, "username", "", "Username of administration account on the host")
f.StringVar(&flag.Password, "password", "", "Password of administration account on the host")
f.StringVar(&flag.SslThumbprint, "fingerprint", "", "Fingerprint of the host's SSL certificate")
f.BoolVar(&flag.Force, "force", false, "Force when host is managed by another VC")
f.BoolVar(&flag.noverify, "noverify", false, "When true, ignore host SSL certificate verification error")
})
}
func (flag *HostConnectFlag) Process(ctx context.Context) error {
return nil
}
// AcceptThumbprint returns nil if the given error is an SSLVerifyFault and -noverify is true.
// In which case, flag.SslThumbprint is set to fault.Thumbprint and the caller should retry the task.
func (flag *HostConnectFlag) AcceptThumbprint(err error) error {
if f, ok := err.(types.HasFault); ok {
switch fault := f.Fault().(type) {
case *types.SSLVerifyFault:
if flag.noverify {
flag.SslThumbprint = fault.Thumbprint
return nil
}
return fmt.Errorf("%s Fingerprint is %s", err, fault.Thumbprint)
}
}
return err
}

View File

@@ -1,141 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type HostSystemFlag struct {
common
*ClientFlag
*DatacenterFlag
*SearchFlag
name string
host *object.HostSystem
pool *object.ResourcePool
}
var hostSystemFlagKey = flagKey("hostSystem")
func NewHostSystemFlag(ctx context.Context) (*HostSystemFlag, context.Context) {
if v := ctx.Value(hostSystemFlagKey); v != nil {
return v.(*HostSystemFlag), ctx
}
v := &HostSystemFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchHosts)
ctx = context.WithValue(ctx, hostSystemFlagKey, v)
return v, ctx
}
func (flag *HostSystemFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
env := "GOVC_HOST"
value := os.Getenv(env)
usage := fmt.Sprintf("Host system [%s]", env)
f.StringVar(&flag.name, "host", value, usage)
})
}
func (flag *HostSystemFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *HostSystemFlag) HostSystemIfSpecified() (*object.HostSystem, error) {
if flag.host != nil {
return flag.host, nil
}
// Use search flags if specified.
if flag.SearchFlag.IsSet() {
host, err := flag.SearchFlag.HostSystem()
if err != nil {
return nil, err
}
flag.host = host
return flag.host, nil
}
// Never look for a default host system.
// A host system parameter is optional for vm creation. It uses a mandatory
// resource pool parameter to determine where the vm should be placed.
if flag.name == "" {
return nil, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.host, err = finder.HostSystem(context.TODO(), flag.name)
return flag.host, err
}
func (flag *HostSystemFlag) HostSystem() (*object.HostSystem, error) {
host, err := flag.HostSystemIfSpecified()
if err != nil {
return nil, err
}
if host != nil {
return host, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.host, err = finder.DefaultHostSystem(context.TODO())
return flag.host, err
}
func (flag *HostSystemFlag) HostNetworkSystem() (*object.HostNetworkSystem, error) {
host, err := flag.HostSystem()
if err != nil {
return nil, err
}
return host.ConfigManager().NetworkSystem(context.TODO())
}

View File

@@ -1,46 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"strconv"
)
// This flag type is internal to stdlib:
// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go
type int32Value int32
func (i *int32Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
*i = int32Value(v)
return err
}
func (i *int32Value) Get() interface{} {
return int32(*i)
}
func (i *int32Value) String() string {
return fmt.Sprintf("%v", *i)
}
// NewInt32 behaves as flag.IntVar, but using an int32 type.
func NewInt32(v *int32) flag.Value {
return (*int32Value)(v)
}

View File

@@ -1,131 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type NetworkFlag struct {
common
*DatacenterFlag
name string
net object.NetworkReference
adapter string
address string
isset bool
}
var networkFlagKey = flagKey("network")
func NewNetworkFlag(ctx context.Context) (*NetworkFlag, context.Context) {
if v := ctx.Value(networkFlagKey); v != nil {
return v.(*NetworkFlag), ctx
}
v := &NetworkFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, networkFlagKey, v)
return v, ctx
}
func (flag *NetworkFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_NETWORK"
value := os.Getenv(env)
flag.name = value
usage := fmt.Sprintf("Network [%s]", env)
f.Var(flag, "net", usage)
f.StringVar(&flag.adapter, "net.adapter", "e1000", "Network adapter type")
f.StringVar(&flag.address, "net.address", "", "Network hardware address")
})
}
func (flag *NetworkFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *NetworkFlag) String() string {
return flag.name
}
func (flag *NetworkFlag) Set(name string) error {
flag.name = name
flag.isset = true
return nil
}
func (flag *NetworkFlag) IsSet() bool {
return flag.isset
}
func (flag *NetworkFlag) Network() (object.NetworkReference, error) {
if flag.net != nil {
return flag.net, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.net, err = finder.NetworkOrDefault(context.TODO(), flag.name); err != nil {
return nil, err
}
return flag.net, nil
}
func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) {
net, err := flag.Network()
if err != nil {
return nil, err
}
backing, err := net.EthernetCardBackingInfo(context.TODO())
if err != nil {
return nil, err
}
device, err := object.EthernetCardTypes().CreateEthernetCard(flag.adapter, backing)
if err != nil {
return nil, err
}
if flag.address != "" {
card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
card.AddressType = string(types.VirtualEthernetCardMacTypeManual)
card.MacAddress = flag.address
}
return device, nil
}

View File

@@ -1,55 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"strconv"
)
type optionalBool struct {
val **bool
}
func (b *optionalBool) Set(s string) error {
v, err := strconv.ParseBool(s)
*b.val = &v
return err
}
func (b *optionalBool) Get() interface{} {
if *b.val == nil {
return nil
}
return **b.val
}
func (b *optionalBool) String() string {
if *b.val == nil {
return "<nil>"
}
return fmt.Sprintf("%v", **b.val)
}
func (b *optionalBool) IsBoolFlag() bool { return true }
// NewOptionalBool returns a flag.Value implementation where there is no default value.
// This avoids sending a default value over the wire as using flag.BoolVar() would.
func NewOptionalBool(v **bool) flag.Value {
return &optionalBool{v}
}

View File

@@ -1,217 +0,0 @@
/*
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 flags
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"sync"
"time"
"golang.org/x/net/context"
"github.com/vmware/govmomi/vim25/progress"
"github.com/davecgh/go-spew/spew"
)
type OutputWriter interface {
Write(io.Writer) error
}
type OutputFlag struct {
common
JSON bool
TTY bool
Dump bool
}
var outputFlagKey = flagKey("output")
func NewOutputFlag(ctx context.Context) (*OutputFlag, context.Context) {
if v := ctx.Value(outputFlagKey); v != nil {
return v.(*OutputFlag), ctx
}
v := &OutputFlag{}
ctx = context.WithValue(ctx, outputFlagKey, v)
return v, ctx
}
func (flag *OutputFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
f.BoolVar(&flag.JSON, "json", false, "Enable JSON output")
f.BoolVar(&flag.Dump, "dump", false, "Enable output dump")
})
}
func (flag *OutputFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if !flag.JSON {
// Assume we have a tty if not outputting JSON
flag.TTY = true
}
return nil
})
}
// Log outputs the specified string, prefixed with the current time.
// A newline is not automatically added. If the specified string
// starts with a '\r', the current line is cleared first.
func (flag *OutputFlag) Log(s string) (int, error) {
if len(s) > 0 && s[0] == '\r' {
flag.Write([]byte{'\r', 033, '[', 'K'})
s = s[1:]
}
return flag.WriteString(time.Now().Format("[02-01-06 15:04:05] ") + s)
}
func (flag *OutputFlag) Write(b []byte) (int, error) {
if !flag.TTY {
return 0, nil
}
n, err := os.Stdout.Write(b)
os.Stdout.Sync()
return n, err
}
func (flag *OutputFlag) WriteString(s string) (int, error) {
return flag.Write([]byte(s))
}
func (flag *OutputFlag) WriteResult(result OutputWriter) error {
var err error
var out = os.Stdout
if flag.JSON {
err = json.NewEncoder(out).Encode(result)
} else if flag.Dump {
scs := spew.ConfigState{Indent: " "}
scs.Fdump(out, result)
} else {
err = result.Write(out)
}
return err
}
type progressLogger struct {
flag *OutputFlag
prefix string
wg sync.WaitGroup
sink chan chan progress.Report
done chan struct{}
}
func newProgressLogger(flag *OutputFlag, prefix string) *progressLogger {
p := &progressLogger{
flag: flag,
prefix: prefix,
sink: make(chan chan progress.Report),
done: make(chan struct{}),
}
p.wg.Add(1)
go p.loopA()
return p
}
// loopA runs before Sink() has been called.
func (p *progressLogger) loopA() {
var err error
defer p.wg.Done()
tick := time.NewTicker(100 * time.Millisecond)
defer tick.Stop()
for stop := false; !stop; {
select {
case ch := <-p.sink:
err = p.loopB(tick, ch)
stop = true
case <-p.done:
stop = true
case <-tick.C:
line := fmt.Sprintf("\r%s", p.prefix)
p.flag.Log(line)
}
}
if err != nil && err != io.EOF {
p.flag.Log(fmt.Sprintf("\r%sError: %s\n", p.prefix, err))
} else {
p.flag.Log(fmt.Sprintf("\r%sOK\n", p.prefix))
}
}
// loopA runs after Sink() has been called.
func (p *progressLogger) loopB(tick *time.Ticker, ch <-chan progress.Report) error {
var r progress.Report
var ok bool
var err error
for ok = true; ok; {
select {
case r, ok = <-ch:
if !ok {
break
}
err = r.Error()
case <-tick.C:
line := fmt.Sprintf("\r%s", p.prefix)
if r != nil {
line += fmt.Sprintf("(%.0f%%", r.Percentage())
detail := r.Detail()
if detail != "" {
line += fmt.Sprintf(", %s", detail)
}
line += ")"
}
p.flag.Log(line)
}
}
return err
}
func (p *progressLogger) Sink() chan<- progress.Report {
ch := make(chan progress.Report)
p.sink <- ch
return ch
}
func (p *progressLogger) Wait() {
close(p.done)
p.wg.Wait()
}
func (flag *OutputFlag) ProgressLogger(prefix string) *progressLogger {
return newProgressLogger(flag, prefix)
}

View File

@@ -1,85 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type ResourcePoolFlag struct {
common
*DatacenterFlag
name string
pool *object.ResourcePool
}
var resourcePoolFlagKey = flagKey("resourcePool")
func NewResourcePoolFlag(ctx context.Context) (*ResourcePoolFlag, context.Context) {
if v := ctx.Value(resourcePoolFlagKey); v != nil {
return v.(*ResourcePoolFlag), ctx
}
v := &ResourcePoolFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, resourcePoolFlagKey, v)
return v, ctx
}
func (flag *ResourcePoolFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
env := "GOVC_RESOURCE_POOL"
value := os.Getenv(env)
usage := fmt.Sprintf("Resource pool [%s]", env)
f.StringVar(&flag.name, "pool", value, usage)
})
}
func (flag *ResourcePoolFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) {
if flag.pool != nil {
return flag.pool, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
if flag.pool, err = finder.ResourcePoolOrDefault(context.TODO(), flag.name); err != nil {
return nil, err
}
return flag.pool, nil
}

View File

@@ -1,392 +0,0 @@
/*
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 flags
import (
"errors"
"flag"
"fmt"
"strings"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25"
"golang.org/x/net/context"
)
const (
SearchVirtualMachines = iota + 1
SearchHosts
SearchVirtualApps
)
type SearchFlag struct {
common
*ClientFlag
*DatacenterFlag
t int
entity string
byDatastorePath string
byDNSName string
byInventoryPath string
byIP string
byUUID string
isset bool
}
var searchFlagKey = flagKey("search")
func NewSearchFlag(ctx context.Context, t int) (*SearchFlag, context.Context) {
if v := ctx.Value(searchFlagKey); v != nil {
return v.(*SearchFlag), ctx
}
v := &SearchFlag{
t: t,
}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
switch t {
case SearchVirtualMachines:
v.entity = "VM"
case SearchHosts:
v.entity = "host"
case SearchVirtualApps:
v.entity = "vapp"
default:
panic("invalid search type")
}
ctx = context.WithValue(ctx, searchFlagKey, v)
return v, ctx
}
func (flag *SearchFlag) Register(ctx context.Context, fs *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, fs)
flag.DatacenterFlag.Register(ctx, fs)
register := func(v *string, f string, d string) {
f = fmt.Sprintf("%s.%s", strings.ToLower(flag.entity), f)
d = fmt.Sprintf(d, flag.entity)
fs.StringVar(v, f, "", d)
}
switch flag.t {
case SearchVirtualMachines:
register(&flag.byDatastorePath, "path", "Find %s by path to .vmx file")
}
switch flag.t {
case SearchVirtualMachines, SearchHosts:
register(&flag.byDNSName, "dns", "Find %s by FQDN")
register(&flag.byIP, "ip", "Find %s by IP address")
register(&flag.byUUID, "uuid", "Find %s by instance UUID")
}
register(&flag.byInventoryPath, "ipath", "Find %s by inventory path")
})
}
func (flag *SearchFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
flags := []string{
flag.byDatastorePath,
flag.byDNSName,
flag.byInventoryPath,
flag.byIP,
flag.byUUID,
}
flag.isset = false
for _, f := range flags {
if f != "" {
if flag.isset {
return errors.New("cannot use more than one search flag")
}
flag.isset = true
}
}
return nil
})
}
func (flag *SearchFlag) IsSet() bool {
return flag.isset
}
func (flag *SearchFlag) searchIndex(c *vim25.Client) *object.SearchIndex {
return object.NewSearchIndex(c)
}
func (flag *SearchFlag) searchByDatastorePath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByDatastorePath(context.TODO(), dc, flag.byDatastorePath)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) searchByDNSName(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByDnsName(context.TODO(), dc, flag.byDNSName, true)
case SearchHosts:
return flag.searchIndex(c).FindByDnsName(context.TODO(), dc, flag.byDNSName, false)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) searchByInventoryPath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
// TODO(PN): The datacenter flag should not be set because it is ignored.
return flag.searchIndex(c).FindByInventoryPath(context.TODO(), flag.byInventoryPath)
}
func (flag *SearchFlag) searchByIP(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByIp(context.TODO(), dc, flag.byIP, true)
case SearchHosts:
return flag.searchIndex(c).FindByIp(context.TODO(), dc, flag.byIP, false)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) {
switch flag.t {
case SearchVirtualMachines:
return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, true, nil)
case SearchHosts:
return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, false, nil)
default:
panic("unsupported type")
}
}
func (flag *SearchFlag) search() (object.Reference, error) {
var ref object.Reference
var err error
c, err := flag.Client()
if err != nil {
return nil, err
}
dc, err := flag.Datacenter()
if err != nil {
return nil, err
}
switch {
case flag.byDatastorePath != "":
ref, err = flag.searchByDatastorePath(c, dc)
case flag.byDNSName != "":
ref, err = flag.searchByDNSName(c, dc)
case flag.byInventoryPath != "":
ref, err = flag.searchByInventoryPath(c, dc)
case flag.byIP != "":
ref, err = flag.searchByIP(c, dc)
case flag.byUUID != "":
ref, err = flag.searchByUUID(c, dc)
default:
err = errors.New("no search flag specified")
}
if err != nil {
return nil, err
}
if ref == nil {
return nil, fmt.Errorf("no such %s", flag.entity)
}
return ref, nil
}
func (flag *SearchFlag) VirtualMachine() (*object.VirtualMachine, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
vm, ok := ref.(*object.VirtualMachine)
if !ok {
return nil, fmt.Errorf("expected VirtualMachine entity, got %s", ref.Reference().Type)
}
return vm, nil
}
func (flag *SearchFlag) VirtualMachines(args []string) ([]*object.VirtualMachine, error) {
var out []*object.VirtualMachine
if flag.IsSet() {
vm, err := flag.VirtualMachine()
if err != nil {
return nil, err
}
out = append(out, vm)
return out, nil
}
// List virtual machines
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
var nfe error
// List virtual machines for every argument
for _, arg := range args {
vms, err := finder.VirtualMachineList(context.TODO(), arg)
if err != nil {
if _, ok := err.(*find.NotFoundError); ok {
// Let caller decide how to handle NotFoundError
nfe = err
continue
}
return nil, err
}
out = append(out, vms...)
}
return out, nfe
}
func (flag *SearchFlag) VirtualApp() (*object.VirtualApp, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
app, ok := ref.(*object.VirtualApp)
if !ok {
return nil, fmt.Errorf("expected VirtualApp entity, got %s", ref.Reference().Type)
}
return app, nil
}
func (flag *SearchFlag) VirtualApps(args []string) ([]*object.VirtualApp, error) {
var out []*object.VirtualApp
if flag.IsSet() {
app, err := flag.VirtualApp()
if err != nil {
return nil, err
}
out = append(out, app)
return out, nil
}
// List virtual apps
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
// List virtual apps for every argument
for _, arg := range args {
apps, err := finder.VirtualAppList(context.TODO(), arg)
if err != nil {
return nil, err
}
out = append(out, apps...)
}
return out, nil
}
func (flag *SearchFlag) HostSystem() (*object.HostSystem, error) {
ref, err := flag.search()
if err != nil {
return nil, err
}
host, ok := ref.(*object.HostSystem)
if !ok {
return nil, fmt.Errorf("expected HostSystem entity, got %s", ref.Reference().Type)
}
return host, nil
}
func (flag *SearchFlag) HostSystems(args []string) ([]*object.HostSystem, error) {
var out []*object.HostSystem
if flag.IsSet() {
host, err := flag.HostSystem()
if err != nil {
return nil, err
}
out = append(out, host)
return out, nil
}
// List host system
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
// List host systems for every argument
for _, arg := range args {
vms, err := finder.HostSystemList(context.TODO(), arg)
if err != nil {
return nil, err
}
out = append(out, vms...)
}
return out, nil
}

View File

@@ -1,78 +0,0 @@
package flags
import (
"flag"
"fmt"
"os"
"golang.org/x/net/context"
"github.com/vmware/govmomi/object"
)
type StoragePodFlag struct {
common
*DatacenterFlag
Name string
sp *object.StoragePod
}
var storagePodFlagKey = flagKey("storagePod")
func NewStoragePodFlag(ctx context.Context) (*StoragePodFlag, context.Context) {
if v := ctx.Value(storagePodFlagKey); v != nil {
return v.(*StoragePodFlag), ctx
}
v := &StoragePodFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
ctx = context.WithValue(ctx, storagePodFlagKey, v)
return v, ctx
}
func (f *StoragePodFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.RegisterOnce(func() {
f.DatacenterFlag.Register(ctx, fs)
env := "GOVC_DATASTORE_CLUSTER"
value := os.Getenv(env)
usage := fmt.Sprintf("Datastore cluster [%s]", env)
fs.StringVar(&f.Name, "datastore-cluster", value, usage)
})
}
func (f *StoragePodFlag) Process(ctx context.Context) error {
return f.DatacenterFlag.Process(ctx)
}
func (f *StoragePodFlag) Isset() bool {
return f.Name != ""
}
func (f *StoragePodFlag) StoragePod() (*object.StoragePod, error) {
if f.sp != nil {
return f.sp, nil
}
finder, err := f.Finder()
if err != nil {
return nil, err
}
if f.Isset() {
f.sp, err = finder.DatastoreCluster(context.TODO(), f.Name)
if err != nil {
return nil, err
}
} else {
f.sp, err = finder.DefaultDatastoreCluster(context.TODO())
if err != nil {
return nil, err
}
}
return f.sp, nil
}

View File

@@ -1,61 +0,0 @@
/*
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 flags
import (
"strconv"
"strings"
)
type version []int
func ParseVersion(s string) (version, error) {
v := make(version, 0)
ps := strings.Split(s, ".")
for _, p := range ps {
i, err := strconv.Atoi(p)
if err != nil {
return nil, err
}
v = append(v, i)
}
return v, nil
}
func (v version) Lte(u version) bool {
lv := len(v)
lu := len(u)
for i := 0; i < lv; i++ {
// Everything up to here has been equal and v has more elements than u.
if i >= lu {
return false
}
// Move to next digit if equal.
if v[i] == u[i] {
continue
}
return v[i] < u[i]
}
// Equal.
return true
}

View File

@@ -1,104 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type VirtualAppFlag struct {
common
*DatacenterFlag
*SearchFlag
name string
app *object.VirtualApp
}
var virtualAppFlagKey = flagKey("virtualApp")
func NewVirtualAppFlag(ctx context.Context) (*VirtualAppFlag, context.Context) {
if v := ctx.Value(virtualAppFlagKey); v != nil {
return v.(*VirtualAppFlag), ctx
}
v := &VirtualAppFlag{}
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualApps)
ctx = context.WithValue(ctx, virtualAppFlagKey, v)
return v, ctx
}
func (flag *VirtualAppFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
env := "GOVC_VAPP"
value := os.Getenv(env)
usage := fmt.Sprintf("Virtual App [%s]", env)
f.StringVar(&flag.name, "vapp", value, usage)
})
}
func (flag *VirtualAppFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *VirtualAppFlag) VirtualApp() (*object.VirtualApp, error) {
if flag.app != nil {
return flag.app, nil
}
// Use search flags if specified.
if flag.SearchFlag.IsSet() {
app, err := flag.SearchFlag.VirtualApp()
if err != nil {
return nil, err
}
flag.app = app
return flag.app, nil
}
// Never look for a default virtual app.
if flag.name == "" {
return nil, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.app, err = finder.VirtualApp(context.TODO(), flag.name)
return flag.app, err
}

View File

@@ -1,110 +0,0 @@
/*
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 flags
import (
"flag"
"fmt"
"os"
"github.com/vmware/govmomi/object"
"golang.org/x/net/context"
)
type VirtualMachineFlag struct {
common
*ClientFlag
*DatacenterFlag
*SearchFlag
name string
vm *object.VirtualMachine
}
var virtualMachineFlagKey = flagKey("virtualMachine")
func NewVirtualMachineFlag(ctx context.Context) (*VirtualMachineFlag, context.Context) {
if v := ctx.Value(virtualMachineFlagKey); v != nil {
return v.(*VirtualMachineFlag), ctx
}
v := &VirtualMachineFlag{}
v.ClientFlag, ctx = NewClientFlag(ctx)
v.DatacenterFlag, ctx = NewDatacenterFlag(ctx)
v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualMachines)
ctx = context.WithValue(ctx, virtualMachineFlagKey, v)
return v, ctx
}
func (flag *VirtualMachineFlag) Register(ctx context.Context, f *flag.FlagSet) {
flag.RegisterOnce(func() {
flag.ClientFlag.Register(ctx, f)
flag.DatacenterFlag.Register(ctx, f)
flag.SearchFlag.Register(ctx, f)
env := "GOVC_VM"
value := os.Getenv(env)
usage := fmt.Sprintf("Virtual machine [%s]", env)
f.StringVar(&flag.name, "vm", value, usage)
})
}
func (flag *VirtualMachineFlag) Process(ctx context.Context) error {
return flag.ProcessOnce(func() error {
if err := flag.ClientFlag.Process(ctx); err != nil {
return err
}
if err := flag.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := flag.SearchFlag.Process(ctx); err != nil {
return err
}
return nil
})
}
func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) {
if flag.vm != nil {
return flag.vm, nil
}
// Use search flags if specified.
if flag.SearchFlag.IsSet() {
vm, err := flag.SearchFlag.VirtualMachine()
if err != nil {
return nil, err
}
flag.vm = vm
return flag.vm, nil
}
// Never look for a default virtual machine.
if flag.name == "" {
return nil, nil
}
finder, err := flag.Finder()
if err != nil {
return nil, err
}
flag.vm, err = finder.VirtualMachine(context.TODO(), flag.name)
return flag.vm, err
}

View File

@@ -1,152 +0,0 @@
/*
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 host
import (
"flag"
"fmt"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type add struct {
*flags.ClientFlag
*flags.DatacenterFlag
*flags.HostConnectFlag
parent string
connect bool
}
func init() {
cli.Register("host.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)
cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
cmd.DatacenterFlag.Register(ctx, f)
cmd.HostConnectFlag, ctx = flags.NewHostConnectFlag(ctx)
cmd.HostConnectFlag.Register(ctx, f)
f.StringVar(&cmd.parent, "parent", "", "Path to folder to add the host to")
f.BoolVar(&cmd.connect, "connect", true, "Immediately connect to host")
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
if err := cmd.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := cmd.HostConnectFlag.Process(ctx); err != nil {
return err
}
if cmd.HostName == "" {
return flag.ErrHelp
}
if cmd.UserName == "" {
return flag.ErrHelp
}
if cmd.Password == "" {
return flag.ErrHelp
}
return nil
}
func (cmd *add) Description() string {
return `Add host to datacenter.
The host is added to the folder specified by the 'parent' flag. If not given,
this defaults to the hosts folder in the specified or default datacenter.`
}
func (cmd *add) Add(ctx context.Context, parent *object.Folder) error {
spec := cmd.HostConnectSpec
req := types.AddStandaloneHost_Task{
This: parent.Reference(),
Spec: spec,
AddConnected: cmd.connect,
}
res, err := methods.AddStandaloneHost_Task(ctx, parent.Client(), &req)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("adding %s to folder %s... ", spec.HostName, parent.InventoryPath))
defer logger.Wait()
task := object.NewTask(parent.Client(), res.Returnval)
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
var parent *object.Folder
if f.NArg() != 0 {
return flag.ErrHelp
}
if cmd.parent == "" {
dc, err := cmd.Datacenter()
if err != nil {
return err
}
folders, err := dc.Folders(ctx)
if err != nil {
return err
}
parent = folders.HostFolder
} else {
finder, err := cmd.Finder()
if err != nil {
return err
}
parent, err = finder.Folder(ctx, cmd.parent)
if err != nil {
return err
}
}
err := cmd.Add(ctx, parent)
if err == nil {
return nil
}
// Check if we failed due to SSLVerifyFault and -noverify is set
if err := cmd.AcceptThumbprint(err); err != nil {
return err
}
// Accepted unverified thumbprint, try again
return cmd.Add(ctx, parent)
}

View File

@@ -1,63 +0,0 @@
/*
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 autostart
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type add struct {
*AutostartFlag
}
func init() {
cli.Register("host.autostart.add", &add{})
}
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
}
func (cmd *add) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *add) Usage() string {
return "VM..."
}
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
var powerInfo = types.AutoStartPowerInfo{
StartAction: "powerOn",
StartDelay: -1,
StartOrder: -1,
StopAction: "systemDefault",
StopDelay: -1,
WaitForHeartbeat: types.AutoStartWaitHeartbeatSettingSystemDefault,
}
return cmd.ReconfigureVMs(f.Args(), powerInfo)
}

View File

@@ -1,173 +0,0 @@
/*
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 autostart
import (
"errors"
"flag"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/net/context"
)
type AutostartFlag struct {
*flags.ClientFlag
*flags.DatacenterFlag
*flags.HostSystemFlag
}
func newAutostartFlag(ctx context.Context) (*AutostartFlag, context.Context) {
f := &AutostartFlag{}
f.ClientFlag, ctx = flags.NewClientFlag(ctx)
f.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
f.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
return f, ctx
}
func (f *AutostartFlag) Register(ctx context.Context, fs *flag.FlagSet) {
f.ClientFlag.Register(ctx, fs)
f.DatacenterFlag.Register(ctx, fs)
f.HostSystemFlag.Register(ctx, fs)
}
func (f *AutostartFlag) Process(ctx context.Context) error {
if err := f.ClientFlag.Process(ctx); err != nil {
return err
}
if err := f.DatacenterFlag.Process(ctx); err != nil {
return err
}
if err := f.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
// VirtualMachines returns list of virtual machine objects based on the
// arguments specified on the command line. This helper is defined in
// flags.SearchFlag as well, but that pulls in other virtual machine flags that
// are not relevant here.
func (f *AutostartFlag) VirtualMachines(args []string) ([]*object.VirtualMachine, error) {
if len(args) == 0 {
return nil, errors.New("no argument")
}
finder, err := f.Finder()
if err != nil {
return nil, err
}
var out []*object.VirtualMachine
for _, arg := range args {
vms, err := finder.VirtualMachineList(context.TODO(), arg)
if err != nil {
return nil, err
}
out = append(out, vms...)
}
return out, nil
}
func (f *AutostartFlag) HostAutoStartManager() (*mo.HostAutoStartManager, error) {
h, err := f.HostSystem()
if err != nil {
return nil, err
}
var mhs mo.HostSystem
err = h.Properties(context.TODO(), h.Reference(), []string{"configManager.autoStartManager"}, &mhs)
if err != nil {
return nil, err
}
var mhas mo.HostAutoStartManager
err = h.Properties(context.TODO(), *mhs.ConfigManager.AutoStartManager, nil, &mhas)
if err != nil {
return nil, err
}
return &mhas, nil
}
func (f *AutostartFlag) ReconfigureDefaults(template types.AutoStartDefaults) error {
c, err := f.Client()
if err != nil {
return err
}
mhas, err := f.HostAutoStartManager()
if err != nil {
return err
}
req := types.ReconfigureAutostart{
This: mhas.Reference(),
Spec: types.HostAutoStartManagerConfig{
Defaults: &template,
},
}
_, err = methods.ReconfigureAutostart(context.TODO(), c, &req)
if err != nil {
return err
}
return nil
}
func (f *AutostartFlag) ReconfigureVMs(args []string, template types.AutoStartPowerInfo) error {
c, err := f.Client()
if err != nil {
return err
}
mhas, err := f.HostAutoStartManager()
if err != nil {
return err
}
req := types.ReconfigureAutostart{
This: mhas.Reference(),
Spec: types.HostAutoStartManagerConfig{
PowerInfo: make([]types.AutoStartPowerInfo, 0),
},
}
vms, err := f.VirtualMachines(args)
if err != nil {
return err
}
for _, vm := range vms {
pi := template
pi.Key = vm.Reference()
req.Spec.PowerInfo = append(req.Spec.PowerInfo, pi)
}
_, err = methods.ReconfigureAutostart(context.TODO(), c, &req)
if err != nil {
return err
}
return nil
}

View File

@@ -1,63 +0,0 @@
/*
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 autostart
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)
type configure struct {
*AutostartFlag
types.AutoStartDefaults
}
func init() {
cli.Register("host.autostart.configure", &configure{})
}
func (cmd *configure) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
f.Var(flags.NewOptionalBool(&cmd.Enabled), "enabled", "")
f.Var(flags.NewInt32(&cmd.StartDelay), "start-delay", "")
f.StringVar(&cmd.StopAction, "stop-action", "", "")
f.Var(flags.NewInt32(&cmd.StopDelay), "stop-delay", "")
f.Var(flags.NewOptionalBool(&cmd.WaitForHeartbeat), "wait-for-heartbeat", "")
}
func (cmd *configure) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *configure) Usage() string {
return ""
}
func (cmd *configure) Run(ctx context.Context, f *flag.FlagSet) error {
return cmd.ReconfigureDefaults(cmd.AutoStartDefaults)
}

View File

@@ -1,143 +0,0 @@
/*
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 autostart
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"text/tabwriter"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/mo"
"golang.org/x/net/context"
)
type info struct {
cli.Command
*AutostartFlag
*flags.OutputFlag
}
func init() {
cli.Register("host.autostart.info", &info{})
}
func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
}
func (cmd *info) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
if err := cmd.OutputFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *info) Usage() string {
return ""
}
func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error {
client, err := cmd.Client()
if err != nil {
return err
}
mhas, err := cmd.HostAutoStartManager()
if err != nil {
return err
}
return cmd.WriteResult(&infoResult{client, mhas})
}
type infoResult struct {
client *vim25.Client
mhas *mo.HostAutoStartManager
}
func (r *infoResult) MarshalJSON() ([]byte, error) {
return json.Marshal(r.mhas)
}
// vmPaths resolves the paths for the VMs in the result.
func (r *infoResult) vmPaths() (map[string]string, error) {
paths := make(map[string]string)
for _, info := range r.mhas.Config.PowerInfo {
mes, err := mo.Ancestors(context.TODO(), r.client, r.client.ServiceContent.PropertyCollector, info.Key)
if err != nil {
return nil, err
}
path := ""
for _, me := range mes {
// Skip root entity in building inventory path.
if me.Parent == nil {
continue
}
path += "/" + me.Name
}
paths[info.Key.Value] = path
}
return paths, nil
}
func (r *infoResult) Write(w io.Writer) error {
paths, err := r.vmPaths()
if err != nil {
return err
}
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
fmt.Fprintf(tw, "VM")
fmt.Fprintf(tw, "\tStartAction")
fmt.Fprintf(tw, "\tStartDelay")
fmt.Fprintf(tw, "\tStartOrder")
fmt.Fprintf(tw, "\tStopAction")
fmt.Fprintf(tw, "\tStopDelay")
fmt.Fprintf(tw, "\tWaitForHeartbeat")
fmt.Fprintf(tw, "\n")
for _, info := range r.mhas.Config.PowerInfo {
fmt.Fprintf(tw, "%s", paths[info.Key.Value])
fmt.Fprintf(tw, "\t%s", info.StartAction)
fmt.Fprintf(tw, "\t%d", info.StartDelay)
fmt.Fprintf(tw, "\t%d", info.StartOrder)
fmt.Fprintf(tw, "\t%s", info.StopAction)
fmt.Fprintf(tw, "\t%d", info.StopDelay)
fmt.Fprintf(tw, "\t%s", info.WaitForHeartbeat)
fmt.Fprintf(tw, "\n")
}
_ = tw.Flush()
return nil
}

View File

@@ -1,63 +0,0 @@
/*
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 autostart
import (
"flag"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/vim25/types"
)
type remove struct {
*AutostartFlag
}
func init() {
cli.Register("host.autostart.remove", &remove{})
}
func (cmd *remove) Register(ctx context.Context, f *flag.FlagSet) {
cmd.AutostartFlag, ctx = newAutostartFlag(ctx)
cmd.AutostartFlag.Register(ctx, f)
}
func (cmd *remove) Process(ctx context.Context) error {
if err := cmd.AutostartFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *remove) Usage() string {
return "VM..."
}
func (cmd *remove) Run(ctx context.Context, f *flag.FlagSet) error {
var powerInfo = types.AutoStartPowerInfo{
StartAction: "none",
StartDelay: -1,
StartOrder: -1,
StopAction: "none",
StopDelay: -1,
WaitForHeartbeat: types.AutoStartWaitHeartbeatSettingSystemDefault,
}
return cmd.ReconfigureVMs(f.Args(), powerInfo)
}

View File

@@ -1,81 +0,0 @@
/*
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 host
import (
"flag"
"fmt"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
)
type disconnect struct {
*flags.HostSystemFlag
}
func init() {
cli.Register("host.disconnect", &disconnect{})
}
func (cmd *disconnect) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
}
func (cmd *disconnect) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *disconnect) Description() string {
return `Disconnect host from vCenter and instruct the host to stop sending heartbeats.`
}
func (cmd *disconnect) Disconnect(ctx context.Context, host *object.HostSystem) error {
task, err := host.Disconnect(ctx)
if err != nil {
return err
}
logger := cmd.ProgressLogger(fmt.Sprintf("%s disconnecting... ", host.InventoryPath))
defer logger.Wait()
_, err = task.WaitForResult(ctx, logger)
return err
}
func (cmd *disconnect) Run(ctx context.Context, f *flag.FlagSet) error {
hosts, err := cmd.HostSystems(f.Args())
if err != nil {
return err
}
for _, host := range hosts {
err = cmd.Disconnect(ctx, host)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,149 +0,0 @@
/*
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 esxcli
import (
"flag"
"fmt"
"strings"
"github.com/vmware/govmomi/vim25/types"
)
type Command struct {
name []string
args []string
}
type CommandInfoItem struct {
Name string `xml:"name"`
DisplayName string `xml:"displayName"`
Help string `xml:"help"`
}
type CommandInfoParam struct {
CommandInfoItem
Aliases []string `xml:"aliases"`
Flag bool `xml:"flag"`
}
type CommandInfoHint struct {
Key string `xml:"key"`
Value string `xml:"value"`
}
type CommandInfoHints []CommandInfoHint
type CommandInfoMethod struct {
CommandInfoItem
Param []CommandInfoParam `xml:"param"`
Hints CommandInfoHints `xml:"hints"`
}
type CommandInfo struct {
CommandInfoItem
Method []*CommandInfoMethod `xml:"method"`
}
func NewCommand(args []string) *Command {
c := &Command{}
for i, arg := range args {
if strings.HasPrefix(arg, "-") {
c.args = args[i:]
break
} else {
c.name = append(c.name, arg)
}
}
return c
}
func (c *Command) Namespace() string {
return strings.Join(c.name[:len(c.name)-1], ".")
}
func (c *Command) Name() string {
return c.name[len(c.name)-1]
}
func (c *Command) Method() string {
return "vim.EsxCLI." + strings.Join(c.name, ".")
}
func (c *Command) Moid() string {
return "ha-cli-handler-" + strings.Join(c.name[:len(c.name)-1], "-")
}
// Parse generates a flag.FlagSet based on the given []CommandInfoParam and
// returns arguments for use with methods.ExecuteSoap
func (c *Command) Parse(params []CommandInfoParam) ([]types.ReflectManagedMethodExecuterSoapArgument, error) {
flags := flag.NewFlagSet(strings.Join(c.name, " "), flag.ExitOnError)
vals := make([]string, len(params))
for i, p := range params {
v := &vals[i]
for _, a := range p.Aliases {
a = strings.TrimPrefix(a[1:], "-")
flags.StringVar(v, a, "", p.Help)
}
}
err := flags.Parse(c.args)
if err != nil {
return nil, err
}
args := []types.ReflectManagedMethodExecuterSoapArgument{}
for i, p := range params {
if vals[i] == "" {
continue
}
args = append(args, c.Argument(p.Name, vals[i]))
}
return args, nil
}
func (c *Command) Argument(name string, val string) types.ReflectManagedMethodExecuterSoapArgument {
return types.ReflectManagedMethodExecuterSoapArgument{
Name: name,
Val: fmt.Sprintf("<%s>%s</%s>", name, val, name),
}
}
func (h CommandInfoHints) Formatter() string {
for _, hint := range h {
if hint.Key == "formatter" {
return hint.Value
}
}
return "simple"
}
func (h CommandInfoHints) Fields() []string {
for _, hint := range h {
if strings.HasPrefix(hint.Key, "fields:") {
return strings.Split(hint.Value, ",")
}
}
return nil
}

View File

@@ -1,153 +0,0 @@
/*
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 esxcli
import (
"flag"
"fmt"
"os"
"sort"
"strings"
"text/tabwriter"
"golang.org/x/net/context"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
)
type esxcli struct {
*flags.HostSystemFlag
hints bool
}
func init() {
cli.Register("host.esxcli", &esxcli{})
}
func (cmd *esxcli) Usage() string {
return "COMMAND [ARG]..."
}
func (cmd *esxcli) Register(ctx context.Context, f *flag.FlagSet) {
cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx)
cmd.HostSystemFlag.Register(ctx, f)
f.BoolVar(&cmd.hints, "hints", true, "Use command info hints when formatting output")
}
func (cmd *esxcli) Process(ctx context.Context) error {
if err := cmd.HostSystemFlag.Process(ctx); err != nil {
return err
}
return nil
}
func (cmd *esxcli) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return nil
}
host, err := cmd.HostSystem()
if err != nil {
return err
}
e, err := NewExecutor(c, host)
if err != nil {
return err
}
res, err := e.Run(f.Args())
if err != nil {
return err
}
if len(res.Values) == 0 {
return nil
}
var formatType string
if cmd.hints {
formatType = res.Info.Hints.Formatter()
}
// TODO: OutputFlag / format options
switch formatType {
case "table":
cmd.formatTable(res)
default:
cmd.formatSimple(res)
}
return nil
}
func (cmd *esxcli) formatSimple(res *Response) {
var keys []string
for key := range res.Values[0] {
keys = append(keys, key)
}
sort.Strings(keys)
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
for i, rv := range res.Values {
if i > 0 {
fmt.Fprintln(tw)
_ = tw.Flush()
}
for _, key := range keys {
fmt.Fprintf(tw, "%s:\t%s\n", key, strings.Join(rv[key], ", "))
}
}
_ = tw.Flush()
}
func (cmd *esxcli) formatTable(res *Response) {
fields := res.Info.Hints.Fields()
tw := tabwriter.NewWriter(os.Stdout, len(fields), 0, 2, ' ', 0)
var hr []string
for _, name := range fields {
hr = append(hr, strings.Repeat("-", len(name)))
}
fmt.Fprintln(tw, strings.Join(fields, "\t"))
fmt.Fprintln(tw, strings.Join(hr, "\t"))
for _, vals := range res.Values {
var row []string
for _, name := range fields {
key := strings.Replace(name, " ", "", -1)
if val, ok := vals[key]; ok {
row = append(row, strings.Join(val, ", "))
} else {
row = append(row, "")
}
}
fmt.Fprintln(tw, strings.Join(row, "\t"))
}
_ = tw.Flush()
}

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