mirror of https://github.com/docker/docs.git
Dependencies update
Signed-off-by: Fabio Rapposelli <fabio@vmware.com>
This commit is contained in:
parent
2e90b7cb55
commit
e7c0ebab5e
|
|
@ -181,6 +181,11 @@
|
|||
{
|
||||
"ImportPath": "google.golang.org/cloud/internal",
|
||||
"Rev": "975617b05ea8a58727e6c1a06b6161ff4185a9f2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vmware/govmomi",
|
||||
"Comment": "prerelease-v0.1.0-73-gfc131d4-65-g482cd82",
|
||||
"Rev": "482cd823716e0fa9bc4e186d262a6ea23d940fbf"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
sudo: false
|
||||
language: go
|
||||
go: 1.4
|
||||
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go get golang.org/x/tools/cmd/goimports
|
||||
|
||||
script:
|
||||
- make check test
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# changelog
|
||||
|
||||
### (unreleased)
|
||||
|
||||
...
|
||||
|
||||
* Stop returning children from `ManagedObjectList`
|
||||
|
||||
Change the `ManagedObjectList` function in the `find` package to only
|
||||
return the managed objects specified by the path argument and not their
|
||||
children. The original behavior was used by govc's `ls` command and is
|
||||
now available in the newly added function `ManagedObjectListChildren`.
|
||||
|
||||
* Add retry functionality to vim25 package
|
||||
|
||||
* Change finder functions to no longer take varargs
|
||||
|
||||
The `find` package had functions to return a list of objects, given a
|
||||
variable number of patterns. This makes it impossible to distinguish which
|
||||
patterns produced results and which ones didn't.
|
||||
|
||||
In particular for govc, where multiple arguments can be passed from the
|
||||
command line, it is useful to let the user know which ones produce results
|
||||
and which ones don't.
|
||||
|
||||
To evaluate multiple patterns, the user should call the find functions
|
||||
multiple times (either serially or in parallel).
|
||||
|
||||
* Make optional boolean fields pointers (`vim25/types`).
|
||||
|
||||
False is the zero value of a boolean field, which means they are not serialized
|
||||
if the field is marked "omitempty". If the field is a pointer instead, the zero
|
||||
value will be the nil pointer, and both true and false values are serialized.
|
||||
|
||||
### 0.1.0 (2015-03-17)
|
||||
|
||||
Prior to this version the API of this library was in flux.
|
||||
|
||||
Notable changes w.r.t. the state of this library before March 2015 are:
|
||||
|
||||
* All functions that may execute a request take a `context.Context` parameter.
|
||||
* The `vim25` package contains a minimal client implementation.
|
||||
* The property collector and its convenience functions live in the `property` package.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# People who can (and typically have) contributed to this repository.
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
#
|
||||
|
||||
Alvaro Miranda <kikitux@gmail.com>
|
||||
Bob Killen <killen.bob@gmail.com>
|
||||
Bruce Downs <bdowns@vmware.com>
|
||||
Clint Greenwood <cgreenwood@vmware.com> <clint.greenwood@gmail.com>
|
||||
Danny Lockard <danny.lockard@banno.com>
|
||||
Doug MacEachern <dougm@vmware.com>
|
||||
Eric Yutao <eric.yutao@gmail.com>
|
||||
Faiyaz Ahmed <ahmedf@vmware.com>
|
||||
Gavin Gray <gavin@infinio.com>
|
||||
Gavrie Philipson <gavrie@philipson.co.il> <gavrie.philipson@elastifile.com>
|
||||
Mevan Samaratunga <mevansam@gmail.com>
|
||||
Pieter Noordhuis <pnoordhuis@vmware.com> <pcnoordhuis@gmail.com>
|
||||
S.Çağlar Onur <conur@vmware.com>
|
||||
Takaaki Furukawa <takaaki.frkw@gmail.com>
|
||||
Yang Yang <yangy@vmware.com>
|
||||
Yuya Kusakabe <yuya.kusakabe@gmail.com>
|
||||
Zee Yang <zeey@vmware.com> <zee.yang@gmail.com>
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
.PHONY: test
|
||||
|
||||
all: check test
|
||||
|
||||
check: goimports govet
|
||||
|
||||
goimports:
|
||||
@echo checking go imports...
|
||||
@! goimports -d . 2>&1 | egrep -v '^$$'
|
||||
|
||||
govet:
|
||||
@echo checking go vet...
|
||||
@go tool vet -structtags=false -methods=false .
|
||||
|
||||
test:
|
||||
go get
|
||||
go test -v $(TEST_OPTS) ./...
|
||||
|
||||
install:
|
||||
go install github.com/vmware/govmomi/govc
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
[](https://travis-ci.org/vmware/govmomi)
|
||||
|
||||
# govmomi
|
||||
|
||||
A Go library for interacting with VMware vSphere APIs (ESXi and/or vCenter).
|
||||
|
||||
For `govc`, a CLI built on top of govmomi, check out the [govc](./govc) directory.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This library is built for and tested against ESXi and vCenter 5.5.
|
||||
|
||||
If you're able to use it against older versions of ESXi and/or vCenter, please
|
||||
leave a note and we'll include it in this compatibility list.
|
||||
|
||||
## Documentation
|
||||
|
||||
The APIs exposed by this library very closely follow the API described in the [VMware vSphere API Reference Documentation][apiref].
|
||||
Refer to this document to become familiar with the upstream API.
|
||||
|
||||
The code in the `govmomi` package is a wrapper for the code that is generated from the vSphere API description.
|
||||
It primarily provides convenience functions for working with the vSphere API.
|
||||
See [godoc.org][godoc] for documentation.
|
||||
|
||||
[apiref]:http://pubs.vmware.com/vsphere-55/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html
|
||||
[godoc]:http://godoc.org/github.com/vmware/govmomi
|
||||
|
||||
## Status
|
||||
|
||||
Changes to the API are subject to [semantic versioning](http://semver.org).
|
||||
|
||||
Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
|
||||
|
||||
## License
|
||||
|
||||
govmomi is available under the [Apache 2 license](LICENSE).
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
This package is the root package of the govmomi library.
|
||||
|
||||
The library is structured as follows:
|
||||
|
||||
Package vim25
|
||||
|
||||
The minimal usable functionality is available through the vim25 package.
|
||||
It contains subpackages that contain generated types, managed objects, and all
|
||||
available methods. The vim25 package is entirely independent of the other
|
||||
packages in the govmomi tree -- it has no dependencies on its peers.
|
||||
|
||||
The vim25 package itself contains a client structure that is
|
||||
passed around throughout the entire library. It abstracts a session and its
|
||||
immutable state. See the vim25 package for more information.
|
||||
|
||||
Package session
|
||||
|
||||
The session package contains an abstraction for the session manager that allows
|
||||
a user to login and logout. It also provides access to the current session
|
||||
(i.e. to determine if the user is in fact logged in)
|
||||
|
||||
Package object
|
||||
|
||||
The object package contains wrappers for a selection of managed objects. The
|
||||
constructors of these objects all take a *vim25.Client, which they pass along
|
||||
to derived objects, if applicable.
|
||||
|
||||
Package govc
|
||||
|
||||
The govc package contains the govc CLI. The code in this tree is not intended
|
||||
to be used as a library. Any functionality that govc contains that _could_ be
|
||||
used as a library function but isn't, _should_ live in a root level package.
|
||||
|
||||
Other packages
|
||||
|
||||
Other packages, such as "event", "guest", or "license", provide wrappers for
|
||||
the respective subsystems. They are typically not needed in normal workflows so
|
||||
are kept outside the object package.
|
||||
*/
|
||||
package govmomi
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/session"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
*vim25.Client
|
||||
|
||||
SessionManager *session.Manager
|
||||
}
|
||||
|
||||
// NewClient creates a new client from a URL. The client authenticates with the
|
||||
// server before returning if the URL contains user information.
|
||||
func NewClient(ctx context.Context, u *url.URL, insecure bool) (*Client, error) {
|
||||
soapClient := soap.NewClient(u, insecure)
|
||||
vimClient, err := vim25.NewClient(ctx, soapClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
Client: vimClient,
|
||||
SessionManager: session.NewManager(vimClient),
|
||||
}
|
||||
|
||||
// Only login if the URL contains user information.
|
||||
if u.User != nil {
|
||||
err = c.Login(ctx, u.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Login dispatches to the SessionManager.
|
||||
func (c *Client) Login(ctx context.Context, u *url.Userinfo) error {
|
||||
return c.SessionManager.Login(ctx, u)
|
||||
}
|
||||
|
||||
// Logout dispatches to the SessionManager.
|
||||
func (c *Client) Logout(ctx context.Context) error {
|
||||
// Close any idle connections after logging out.
|
||||
defer c.Client.CloseIdleConnections()
|
||||
return c.SessionManager.Logout(ctx)
|
||||
}
|
||||
|
||||
// PropertyCollector returns the session's default property collector.
|
||||
func (c *Client) PropertyCollector() *property.Collector {
|
||||
return property.DefaultCollector(c.Client)
|
||||
}
|
||||
|
||||
// RetrieveOne dispatches to the Retrieve function on the default property collector.
|
||||
func (c *Client) RetrieveOne(ctx context.Context, obj types.ManagedObjectReference, p []string, dst interface{}) error {
|
||||
return c.PropertyCollector().RetrieveOne(ctx, obj, p, dst)
|
||||
}
|
||||
|
||||
// Retrieve dispatches to the Retrieve function on the default property collector.
|
||||
func (c *Client) Retrieve(ctx context.Context, objs []types.ManagedObjectReference, p []string, dst interface{}) error {
|
||||
return c.PropertyCollector().Retrieve(ctx, objs, p, dst)
|
||||
}
|
||||
|
||||
// Wait dispatches to property.Wait.
|
||||
func (c *Client) Wait(ctx context.Context, obj types.ManagedObjectReference, ps []string, f func([]types.PropertyChange) bool) error {
|
||||
return property.Wait(ctx, c.PropertyCollector(), obj, ps, f)
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#!/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
|
||||
|
||||
# This script shows for every request in a debug trace how long it took
|
||||
# and the name of the request body.
|
||||
|
||||
function body-name {
|
||||
(
|
||||
xmllint --shell $1 <<EOS
|
||||
setns soapenv=http://schemas.xmlsoap.org/soap/envelope/
|
||||
xpath name(//soapenv:Body/*)
|
||||
EOS
|
||||
) | head -1 | sed 's/.*Object is a string : \(.*\)$/\1/'
|
||||
}
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
cd $1
|
||||
fi
|
||||
|
||||
for req in $(find . -name '*.req.xml'); do
|
||||
base=$(basename $req .req.xml)
|
||||
session=$(echo $base | awk -F'-' "{printf \"%d\", \$1}")
|
||||
number=$(echo $base | awk -F'-' "{printf \"%d\", \$2}")
|
||||
client_log=$(dirname $req)/${session}-client.log
|
||||
took=$(awk "/ ${number} took / { print \$4 }" ${client_log})
|
||||
|
||||
printf "%s %8s: %s\n" ${base} ${took} $(body-name $req)
|
||||
done
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
*.box
|
||||
*.ova
|
||||
.vagrant
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# Using the VCSA base box, no provisioning, inventory will be empty.
|
||||
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.hostname = "vcsa"
|
||||
|
||||
config.vm.box = "vcsa"
|
||||
config.vm.synced_folder ".", "/vagrant", disabled: true
|
||||
|
||||
config.vm.network "forwarded_port", guest: 443, host: 16443
|
||||
end
|
||||
73
vendor/github.com/vmware/govmomi/contrib/vagrant/vcsa/create-box.sh
generated
vendored
Normal file
73
vendor/github.com/vmware/govmomi/contrib/vagrant/vcsa/create-box.sh
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
if [ "$(uname -s)" == "Darwin" ]
|
||||
then
|
||||
PATH="/Applications/VMware Fusion.app/Contents/Library:$PATH"
|
||||
PATH="/Applications/VMware Fusion.app/Contents/Library/VMware OVF Tool:$PATH"
|
||||
fi
|
||||
|
||||
ovf="$1"
|
||||
|
||||
if [ -z "$ovf" ]
|
||||
then
|
||||
ovf="./VMware-vCenter-Server-Appliance-5.5.0.10300-2000350_OVA10.ova"
|
||||
fi
|
||||
|
||||
dir=$(readlink -nf $(dirname $0))
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap "rm -rf $tmp" EXIT
|
||||
|
||||
cd $tmp
|
||||
|
||||
echo "Converting ovf..."
|
||||
ovftool $ovf ./vcsa.vmx
|
||||
|
||||
echo "Starting vm..."
|
||||
vmrun start vcsa.vmx nogui
|
||||
|
||||
echo "Waiting for vm ip..."
|
||||
ip=$(vmrun getGuestIPAddress vcsa.vmx -wait)
|
||||
|
||||
echo "Configuring vm for use with vagrant..."
|
||||
vmrun -gu root -gp vmware CopyFileFromHostToGuest vcsa.vmx \
|
||||
$dir/vagrant.sh /tmp/vagrant.sh
|
||||
|
||||
vmrun -gu root -gp vmware runProgramInGuest vcsa.vmx \
|
||||
/bin/sh -e /tmp/vagrant.sh
|
||||
|
||||
vmrun -gu root -gp vmware deleteFileInGuest vcsa.vmx \
|
||||
/tmp/vagrant.sh
|
||||
|
||||
echo "Configuring vCenter Server Appliance..."
|
||||
|
||||
ssh_opts="-oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oLogLevel=quiet"
|
||||
|
||||
ssh ${ssh_opts} -i ~/.vagrant.d/insecure_private_key vagrant@$ip <<EOF
|
||||
echo "Accepting EULA ..."
|
||||
sudo /usr/sbin/vpxd_servicecfg eula accept
|
||||
|
||||
echo "Configuring Embedded DB ..."
|
||||
sudo /usr/sbin/vpxd_servicecfg db write embedded
|
||||
|
||||
echo "Configuring SSO..."
|
||||
sudo /usr/sbin/vpxd_servicecfg sso write embedded
|
||||
|
||||
echo "Starting VCSA ..."
|
||||
sudo /usr/sbin/vpxd_servicecfg service start
|
||||
EOF
|
||||
|
||||
echo "Stopping vm..."
|
||||
vmrun stop vcsa.vmx
|
||||
|
||||
rm -f vmware.log
|
||||
|
||||
perl -pi -e 's/"bridged"/"nat"/' vcsa.vmx
|
||||
|
||||
echo '{"provider":"vmware_desktop"}' > ./metadata.json
|
||||
|
||||
cd $dir
|
||||
|
||||
tar -C $tmp -cvzf vcsa.box .
|
||||
|
||||
vagrant box add --name vcsa vcsa.box
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
|
||||
useradd vagrant -m -s /bin/bash
|
||||
groupmod -A vagrant wheel
|
||||
|
||||
echo -e "vagrant ALL=(ALL) NOPASSWD: ALL\n" >> /etc/sudoers
|
||||
|
||||
mkdir ~vagrant/.ssh
|
||||
wget --no-check-certificate \
|
||||
https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub \
|
||||
-O ~vagrant/.ssh/authorized_keys
|
||||
chown -R vagrant ~vagrant/.ssh
|
||||
chmod -R go-rwsx ~vagrant/.ssh
|
||||
|
||||
perl -pi -e 's/^#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
|
||||
perl -pi -e 's/^AllowTcpForwarding no//' /etc/ssh/sshd_config
|
||||
perl -pi -e 's/^PermitTunnel no//' /etc/ssh/sshd_config
|
||||
perl -pi -e 's/^MaxSessions \d+//' /etc/ssh/sshd_config
|
||||
|
||||
# disable password expiration
|
||||
for uid in root vagrant
|
||||
do
|
||||
chage -I -1 -E -1 -m 0 -M -1 $uid
|
||||
done
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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 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 int) ([]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 int) ([]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
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
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 event
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"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 {
|
||||
reference types.ManagedObjectReference
|
||||
|
||||
c *vim25.Client
|
||||
|
||||
eventCategory map[string]string
|
||||
eventCategoryMu *sync.Mutex
|
||||
}
|
||||
|
||||
func NewManager(c *vim25.Client) *Manager {
|
||||
m := Manager{
|
||||
reference: *c.ServiceContent.EventManager,
|
||||
|
||||
c: c,
|
||||
|
||||
eventCategoryMu: new(sync.Mutex),
|
||||
}
|
||||
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m Manager) CreateCollectorForEvents(ctx context.Context, filter types.EventFilterSpec) (*HistoryCollector, error) {
|
||||
req := types.CreateCollectorForEvents{
|
||||
This: m.reference,
|
||||
Filter: filter,
|
||||
}
|
||||
|
||||
res, err := methods.CreateCollectorForEvents(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewHistoryCollector(m.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (m Manager) LogUserEvent(ctx context.Context, entity types.ManagedObjectReference, msg string) error {
|
||||
req := types.LogUserEvent{
|
||||
This: m.reference,
|
||||
Entity: entity,
|
||||
Msg: msg,
|
||||
}
|
||||
|
||||
_, err := methods.LogUserEvent(ctx, m.c, &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.reference,
|
||||
EventToPost: eventToPost,
|
||||
TaskInfo: &taskInfo,
|
||||
}
|
||||
|
||||
_, err := methods.PostEvent(ctx, m.c, &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.reference,
|
||||
Filter: filter,
|
||||
}
|
||||
|
||||
res, err := methods.QueryEvents(ctx, m.c, &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.reference,
|
||||
EventTypeId: eventTypeID,
|
||||
}
|
||||
|
||||
res, err := methods.RetrieveArgumentDescription(ctx, m.c, &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 m.eventCategory != nil {
|
||||
return m.eventCategory, nil
|
||||
}
|
||||
|
||||
var o mo.EventManager
|
||||
|
||||
ps := []string{"description.eventInfo"}
|
||||
err := property.DefaultCollector(m.c).RetrieveOne(ctx, m.reference, ps, &o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.eventCategory = make(map[string]string, len(o.Description.EventInfo))
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
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 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]
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
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()
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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 find
|
||||
|
||||
import "fmt"
|
||||
|
||||
type NotFoundError struct {
|
||||
kind string
|
||||
path string
|
||||
}
|
||||
|
||||
func (e *NotFoundError) Error() string {
|
||||
return fmt.Sprintf("%s '%s' not found", e.kind, e.path)
|
||||
}
|
||||
|
||||
type MultipleFoundError struct {
|
||||
kind string
|
||||
path string
|
||||
}
|
||||
|
||||
func (e *MultipleFoundError) Error() string {
|
||||
return fmt.Sprintf("path '%s' resolves to multiple %ss", e.path, e.kind)
|
||||
}
|
||||
|
||||
type DefaultNotFoundError struct {
|
||||
kind string
|
||||
}
|
||||
|
||||
func (e *DefaultNotFoundError) Error() string {
|
||||
return fmt.Sprintf("no default %s found", e.kind)
|
||||
}
|
||||
|
||||
type DefaultMultipleFoundError struct {
|
||||
kind string
|
||||
}
|
||||
|
||||
func (e DefaultMultipleFoundError) Error() string {
|
||||
return fmt.Sprintf("default %s resolves to multiple instances, please specify", e.kind)
|
||||
}
|
||||
|
||||
func toDefaultError(err error) error {
|
||||
switch e := err.(type) {
|
||||
case *NotFoundError:
|
||||
return &DefaultNotFoundError{e.kind}
|
||||
case *MultipleFoundError:
|
||||
return &DefaultMultipleFoundError{e.kind}
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
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 find
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/list"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type Finder struct {
|
||||
client *vim25.Client
|
||||
recurser list.Recurser
|
||||
|
||||
dc *object.Datacenter
|
||||
folders *object.DatacenterFolders
|
||||
}
|
||||
|
||||
func NewFinder(client *vim25.Client, all bool) *Finder {
|
||||
f := &Finder{
|
||||
client: client,
|
||||
recurser: list.Recurser{
|
||||
Collector: property.DefaultCollector(client),
|
||||
All: all,
|
||||
},
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder {
|
||||
f.dc = dc
|
||||
f.folders = nil
|
||||
return f
|
||||
}
|
||||
|
||||
type findRelativeFunc func(ctx context.Context) (object.Reference, error)
|
||||
|
||||
func (f *Finder) find(ctx context.Context, fn findRelativeFunc, tl bool, arg string) ([]list.Element, error) {
|
||||
root := list.Element{
|
||||
Path: "/",
|
||||
Object: object.NewRootFolder(f.client),
|
||||
}
|
||||
|
||||
parts := list.ToParts(arg)
|
||||
|
||||
if len(parts) > 0 {
|
||||
switch parts[0] {
|
||||
case "..": // Not supported; many edge case, little value
|
||||
return nil, errors.New("cannot traverse up a tree")
|
||||
case ".": // Relative to whatever
|
||||
pivot, err := fn(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, pivot.Reference())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, me := range mes {
|
||||
// Skip root entity in building inventory path.
|
||||
if me.Parent == nil {
|
||||
continue
|
||||
}
|
||||
root.Path = path.Join(root.Path, me.Name)
|
||||
}
|
||||
|
||||
root.Object = pivot
|
||||
parts = parts[1:]
|
||||
}
|
||||
}
|
||||
|
||||
f.recurser.TraverseLeafs = tl
|
||||
es, err := f.recurser.Recurse(ctx, root, parts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return es, nil
|
||||
}
|
||||
|
||||
func (f *Finder) datacenter() (*object.Datacenter, error) {
|
||||
if f.dc == nil {
|
||||
return nil, errors.New("please specify a datacenter")
|
||||
}
|
||||
|
||||
return f.dc, nil
|
||||
}
|
||||
|
||||
func (f *Finder) dcFolders(ctx context.Context) (*object.DatacenterFolders, error) {
|
||||
if f.folders != nil {
|
||||
return f.folders, nil
|
||||
}
|
||||
|
||||
dc, err := f.datacenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
folders, err := dc.Folders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.folders = folders
|
||||
|
||||
return f.folders, nil
|
||||
}
|
||||
|
||||
func (f *Finder) dcReference(_ context.Context) (object.Reference, error) {
|
||||
dc, err := f.datacenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
func (f *Finder) vmFolder(ctx context.Context) (object.Reference, error) {
|
||||
folders, err := f.dcFolders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return folders.VmFolder, nil
|
||||
}
|
||||
|
||||
func (f *Finder) hostFolder(ctx context.Context) (object.Reference, error) {
|
||||
folders, err := f.dcFolders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return folders.HostFolder, nil
|
||||
}
|
||||
|
||||
func (f *Finder) datastoreFolder(ctx context.Context) (object.Reference, error) {
|
||||
folders, err := f.dcFolders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return folders.DatastoreFolder, nil
|
||||
}
|
||||
|
||||
func (f *Finder) networkFolder(ctx context.Context) (object.Reference, error) {
|
||||
folders, err := f.dcFolders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return folders.NetworkFolder, nil
|
||||
}
|
||||
|
||||
func (f *Finder) rootFolder(_ context.Context) (object.Reference, error) {
|
||||
return object.NewRootFolder(f.client), nil
|
||||
}
|
||||
|
||||
func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool) ([]list.Element, error) {
|
||||
fn := f.rootFolder
|
||||
|
||||
if f.dc != nil {
|
||||
fn = f.dcReference
|
||||
}
|
||||
|
||||
if len(path) == 0 {
|
||||
path = "."
|
||||
}
|
||||
|
||||
return f.find(ctx, fn, tl, path)
|
||||
}
|
||||
|
||||
func (f *Finder) ManagedObjectList(ctx context.Context, path string) ([]list.Element, error) {
|
||||
return f.managedObjectList(ctx, path, false)
|
||||
}
|
||||
|
||||
func (f *Finder) ManagedObjectListChildren(ctx context.Context, path string) ([]list.Element, error) {
|
||||
return f.managedObjectList(ctx, path, true)
|
||||
}
|
||||
|
||||
func (f *Finder) DatacenterList(ctx context.Context, path string) ([]*object.Datacenter, error) {
|
||||
es, err := f.find(ctx, f.rootFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dcs []*object.Datacenter
|
||||
for _, e := range es {
|
||||
ref := e.Object.Reference()
|
||||
if ref.Type == "Datacenter" {
|
||||
dcs = append(dcs, object.NewDatacenter(f.client, ref))
|
||||
}
|
||||
}
|
||||
|
||||
if len(dcs) == 0 {
|
||||
return nil, &NotFoundError{"datacenter", path}
|
||||
}
|
||||
|
||||
return dcs, nil
|
||||
}
|
||||
|
||||
func (f *Finder) Datacenter(ctx context.Context, path string) (*object.Datacenter, error) {
|
||||
dcs, err := f.DatacenterList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(dcs) > 1 {
|
||||
return nil, &MultipleFoundError{"datacenter", path}
|
||||
}
|
||||
|
||||
return dcs[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) DefaultDatacenter(ctx context.Context) (*object.Datacenter, error) {
|
||||
dc, err := f.Datacenter(ctx, "*")
|
||||
if err != nil {
|
||||
return nil, toDefaultError(err)
|
||||
}
|
||||
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
func (f *Finder) DatastoreList(ctx context.Context, path string) ([]*object.Datastore, error) {
|
||||
es, err := f.find(ctx, f.datastoreFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dss []*object.Datastore
|
||||
for _, e := range es {
|
||||
ref := e.Object.Reference()
|
||||
if ref.Type == "Datastore" {
|
||||
ds := object.NewDatastore(f.client, ref)
|
||||
ds.InventoryPath = e.Path
|
||||
|
||||
dss = append(dss, ds)
|
||||
}
|
||||
}
|
||||
|
||||
if len(dss) == 0 {
|
||||
return nil, &NotFoundError{"datastore", path}
|
||||
}
|
||||
|
||||
return dss, nil
|
||||
}
|
||||
|
||||
func (f *Finder) Datastore(ctx context.Context, path string) (*object.Datastore, error) {
|
||||
dss, err := f.DatastoreList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(dss) > 1 {
|
||||
return nil, &MultipleFoundError{"datastore", path}
|
||||
}
|
||||
|
||||
return dss[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) DefaultDatastore(ctx context.Context) (*object.Datastore, error) {
|
||||
ds, err := f.Datastore(ctx, "*")
|
||||
if err != nil {
|
||||
return nil, toDefaultError(err)
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ComputeResourceList(ctx context.Context, path string) ([]*object.ComputeResource, error) {
|
||||
es, err := f.find(ctx, f.hostFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var crs []*object.ComputeResource
|
||||
for _, e := range es {
|
||||
var cr *object.ComputeResource
|
||||
|
||||
switch o := e.Object.(type) {
|
||||
case mo.ComputeResource, mo.ClusterComputeResource:
|
||||
cr = object.NewComputeResource(f.client, o.Reference())
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
cr.InventoryPath = e.Path
|
||||
crs = append(crs, cr)
|
||||
}
|
||||
|
||||
if len(crs) == 0 {
|
||||
return nil, &NotFoundError{"compute resource", path}
|
||||
}
|
||||
|
||||
return crs, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ComputeResource(ctx context.Context, path string) (*object.ComputeResource, error) {
|
||||
crs, err := f.ComputeResourceList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(crs) > 1 {
|
||||
return nil, &MultipleFoundError{"compute resource", path}
|
||||
}
|
||||
|
||||
return crs[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) DefaultComputeResource(ctx context.Context) (*object.ComputeResource, error) {
|
||||
cr, err := f.ComputeResource(ctx, "*")
|
||||
if err != nil {
|
||||
return nil, toDefaultError(err)
|
||||
}
|
||||
|
||||
return cr, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ClusterComputeResourceList(ctx context.Context, path string) ([]*object.ClusterComputeResource, error) {
|
||||
es, err := f.find(ctx, f.hostFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ccrs []*object.ClusterComputeResource
|
||||
for _, e := range es {
|
||||
var ccr *object.ClusterComputeResource
|
||||
|
||||
switch o := e.Object.(type) {
|
||||
case mo.ClusterComputeResource:
|
||||
ccr = object.NewClusterComputeResource(f.client, o.Reference())
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
ccr.InventoryPath = e.Path
|
||||
ccrs = append(ccrs, ccr)
|
||||
}
|
||||
|
||||
if len(ccrs) == 0 {
|
||||
return nil, &NotFoundError{"cluster", path}
|
||||
}
|
||||
|
||||
return ccrs, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ClusterComputeResource(ctx context.Context, path string) (*object.ClusterComputeResource, error) {
|
||||
ccrs, err := f.ClusterComputeResourceList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ccrs) > 1 {
|
||||
return nil, &MultipleFoundError{"cluster", path}
|
||||
}
|
||||
|
||||
return ccrs[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) HostSystemList(ctx context.Context, path string) ([]*object.HostSystem, error) {
|
||||
es, err := f.find(ctx, f.hostFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var hss []*object.HostSystem
|
||||
for _, e := range es {
|
||||
var hs *object.HostSystem
|
||||
|
||||
switch o := e.Object.(type) {
|
||||
case mo.HostSystem:
|
||||
hs = object.NewHostSystem(f.client, o.Reference())
|
||||
case mo.ComputeResource:
|
||||
cr := object.NewComputeResource(f.client, o.Reference())
|
||||
hosts, err := cr.Hosts(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hs = object.NewHostSystem(f.client, hosts[0])
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
hs.InventoryPath = e.Path
|
||||
hss = append(hss, hs)
|
||||
}
|
||||
|
||||
if len(hss) == 0 {
|
||||
return nil, &NotFoundError{"host", path}
|
||||
}
|
||||
|
||||
return hss, nil
|
||||
}
|
||||
|
||||
func (f *Finder) HostSystem(ctx context.Context, path string) (*object.HostSystem, error) {
|
||||
hss, err := f.HostSystemList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(hss) > 1 {
|
||||
return nil, &MultipleFoundError{"host", path}
|
||||
}
|
||||
|
||||
return hss[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) DefaultHostSystem(ctx context.Context) (*object.HostSystem, error) {
|
||||
hs, err := f.HostSystem(ctx, "*/*")
|
||||
if err != nil {
|
||||
return nil, toDefaultError(err)
|
||||
}
|
||||
|
||||
return hs, nil
|
||||
}
|
||||
|
||||
func (f *Finder) NetworkList(ctx context.Context, path string) ([]object.NetworkReference, error) {
|
||||
es, err := f.find(ctx, f.networkFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ns []object.NetworkReference
|
||||
for _, e := range es {
|
||||
ref := e.Object.Reference()
|
||||
switch ref.Type {
|
||||
case "Network":
|
||||
r := object.NewNetwork(f.client, ref)
|
||||
r.InventoryPath = e.Path
|
||||
ns = append(ns, r)
|
||||
case "DistributedVirtualPortgroup":
|
||||
r := object.NewDistributedVirtualPortgroup(f.client, ref)
|
||||
r.InventoryPath = e.Path
|
||||
ns = append(ns, r)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ns) == 0 {
|
||||
return nil, &NotFoundError{"network", path}
|
||||
}
|
||||
|
||||
return ns, nil
|
||||
}
|
||||
|
||||
func (f *Finder) Network(ctx context.Context, path string) (object.NetworkReference, error) {
|
||||
networks, err := f.NetworkList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(networks) > 1 {
|
||||
return nil, &MultipleFoundError{"network", path}
|
||||
}
|
||||
|
||||
return networks[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) DefaultNetwork(ctx context.Context) (object.NetworkReference, error) {
|
||||
network, err := f.Network(ctx, "*")
|
||||
if err != nil {
|
||||
return nil, toDefaultError(err)
|
||||
}
|
||||
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ResourcePoolList(ctx context.Context, path string) ([]*object.ResourcePool, error) {
|
||||
es, err := f.find(ctx, f.hostFolder, true, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rps []*object.ResourcePool
|
||||
for _, e := range es {
|
||||
var rp *object.ResourcePool
|
||||
|
||||
switch o := e.Object.(type) {
|
||||
case mo.ResourcePool:
|
||||
rp = object.NewResourcePool(f.client, o.Reference())
|
||||
rp.InventoryPath = e.Path
|
||||
rps = append(rps, rp)
|
||||
}
|
||||
}
|
||||
|
||||
if len(rps) == 0 {
|
||||
return nil, &NotFoundError{"resource pool", path}
|
||||
}
|
||||
|
||||
return rps, nil
|
||||
}
|
||||
|
||||
func (f *Finder) ResourcePool(ctx context.Context, path string) (*object.ResourcePool, error) {
|
||||
rps, err := f.ResourcePoolList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(rps) > 1 {
|
||||
return nil, &MultipleFoundError{"resource pool", path}
|
||||
}
|
||||
|
||||
return rps[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) DefaultResourcePool(ctx context.Context) (*object.ResourcePool, error) {
|
||||
rp, err := f.ResourcePool(ctx, "*/Resources")
|
||||
if err != nil {
|
||||
return nil, toDefaultError(err)
|
||||
}
|
||||
|
||||
return rp, nil
|
||||
}
|
||||
|
||||
func (f *Finder) VirtualMachineList(ctx context.Context, path string) ([]*object.VirtualMachine, error) {
|
||||
es, err := f.find(ctx, f.vmFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var vms []*object.VirtualMachine
|
||||
for _, e := range es {
|
||||
switch o := e.Object.(type) {
|
||||
case mo.VirtualMachine:
|
||||
vm := object.NewVirtualMachine(f.client, o.Reference())
|
||||
vm.InventoryPath = e.Path
|
||||
vms = append(vms, vm)
|
||||
}
|
||||
}
|
||||
|
||||
if len(vms) == 0 {
|
||||
return nil, &NotFoundError{"vm", path}
|
||||
}
|
||||
|
||||
return vms, nil
|
||||
}
|
||||
|
||||
func (f *Finder) VirtualMachine(ctx context.Context, path string) (*object.VirtualMachine, error) {
|
||||
vms, err := f.VirtualMachineList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(vms) > 1 {
|
||||
return nil, &MultipleFoundError{"vm", path}
|
||||
}
|
||||
|
||||
return vms[0], nil
|
||||
}
|
||||
|
||||
func (f *Finder) VirtualAppList(ctx context.Context, path string) ([]*object.VirtualApp, error) {
|
||||
es, err := f.find(ctx, f.vmFolder, false, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apps []*object.VirtualApp
|
||||
for _, e := range es {
|
||||
switch o := e.Object.(type) {
|
||||
case mo.VirtualApp:
|
||||
app := object.NewVirtualApp(f.client, o.Reference())
|
||||
app.InventoryPath = e.Path
|
||||
apps = append(apps, app)
|
||||
}
|
||||
}
|
||||
|
||||
if len(apps) == 0 {
|
||||
return nil, &NotFoundError{"app", path}
|
||||
}
|
||||
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (f *Finder) VirtualApp(ctx context.Context, path string) (*object.VirtualApp, error) {
|
||||
apps, err := f.VirtualAppList(ctx, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(apps) > 1 {
|
||||
return nil, &MultipleFoundError{"app", path}
|
||||
}
|
||||
|
||||
return apps[0], nil
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
gem "nokogiri"
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/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
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
# 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"
|
||||
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)
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# 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)
|
||||
|
|
@ -0,0 +1,761 @@
|
|||
# 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.
|
||||
|
||||
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"
|
||||
end
|
||||
|
||||
def vim_type(t = self.type)
|
||||
ns, t = t.split(":", 2)
|
||||
raise if ns != "vim25"
|
||||
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 var_type
|
||||
t = self.type
|
||||
prefix = ""
|
||||
|
||||
prefix += "[]" if slice?
|
||||
|
||||
if t =~ /^xsd:(.*)$/
|
||||
t = $1
|
||||
case t
|
||||
when "string"
|
||||
when "int"
|
||||
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
|
||||
|
||||
includes.each do |i|
|
||||
i.validate_assumptions!
|
||||
end
|
||||
end
|
||||
|
||||
def types
|
||||
return to_enum(:types) unless block_given?
|
||||
|
||||
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 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 remove_ns(x)
|
||||
ns, x = x.split(":", 2)
|
||||
assert_equal "vim25", ns
|
||||
x
|
||||
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:vim25 #{input},omitempty"`
|
||||
Res *#{go_output} `xml:"urn:vim25 #{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 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
|
||||
|
|
@ -0,0 +1 @@
|
|||
/govc*
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
# changelog
|
||||
|
||||
### (unreleased)
|
||||
|
||||
* 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 `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).
|
||||
|
||||
* 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.
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
# 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
|
||||
|
||||
## 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)
|
||||
|
||||
## License
|
||||
|
||||
govc is available under the [Apache 2 license](../LICENSE).
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
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 about
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *about) Process() error { return nil }
|
||||
|
||||
func (cmd *about) Run(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()
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
if ! which gox > /dev/null; then
|
||||
echo "gox is not installed..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
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}
|
||||
|
||||
gox \
|
||||
-parallel=1 \
|
||||
-ldflags="${ldflags}" \
|
||||
-os="${BUILD_OS}" \
|
||||
-arch="${BUILD_ARCH}" \
|
||||
github.com/vmware/govmomi/govc
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
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 cli
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
type HasFlags interface {
|
||||
// Register may be called more than once and should be idempotent.
|
||||
Register(f *flag.FlagSet)
|
||||
|
||||
// Process may be called more than once and should be idempotent.
|
||||
Process() error
|
||||
}
|
||||
|
||||
type Command interface {
|
||||
HasFlags
|
||||
|
||||
Run(f *flag.FlagSet) error
|
||||
}
|
||||
|
||||
var hasFlagsType = reflect.TypeOf((*HasFlags)(nil)).Elem()
|
||||
|
||||
func RegisterCommand(h HasFlags, f *flag.FlagSet) {
|
||||
visited := make(map[interface{}]struct{})
|
||||
Walk(h, hasFlagsType, func(v interface{}) error {
|
||||
if _, ok := visited[v]; ok {
|
||||
return nil
|
||||
}
|
||||
visited[v] = struct{}{}
|
||||
v.(HasFlags).Register(f)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func ProcessCommand(h HasFlags) error {
|
||||
visited := make(map[interface{}]struct{})
|
||||
err := Walk(h, hasFlagsType, func(v interface{}) error {
|
||||
if _, ok := visited[v]; ok {
|
||||
return nil
|
||||
}
|
||||
visited[v] = struct{}{}
|
||||
err := v.(HasFlags).Process()
|
||||
return err
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
f := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
f.SetOutput(ioutil.Discard)
|
||||
|
||||
RegisterCommand(cmd, f)
|
||||
|
||||
if err := f.Parse(args[1:]); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
commandHelp(args[0], cmd, f)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := ProcessCommand(cmd); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
commandHelp(args[0], cmd, f)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := cmd.Run(f); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
commandHelp(args[0], cmd, f)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
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 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
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
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 cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type WalkFn func(c interface{}) error
|
||||
|
||||
// Walk recursively walks struct types that implement the specified interface.
|
||||
// Fields that implement the specified interface are expected to be pointer
|
||||
// values. This allows the function to cache pointer values on a per-type
|
||||
// basis. If, during a recursive walk, the same type is encountered twice, the
|
||||
// function creates a new value of that type the first time, and reuses that
|
||||
// same value the second time.
|
||||
//
|
||||
// This function is used to make sure that a hierarchy of flags where multiple
|
||||
// structs refer to the `Client` flag will not end up with more than one
|
||||
// instance of the actual client. Rather, every struct referring to the
|
||||
// `Client` flag will have a pointer to the same underlying `Client` struct.
|
||||
//
|
||||
func Walk(c interface{}, ifaceType reflect.Type, fn WalkFn) error {
|
||||
var walker WalkFn
|
||||
|
||||
visited := make(map[reflect.Type]reflect.Value)
|
||||
walker = func(c interface{}) error {
|
||||
v := reflect.ValueOf(c)
|
||||
if v.Kind() == reflect.Interface {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
|
||||
// Call user specified function.
|
||||
err := fn(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
ff := t.Field(i)
|
||||
ft := ff.Type
|
||||
fv := v.Field(i)
|
||||
|
||||
// Check that a pointer to this field's type doesn't implement the
|
||||
// specified interface. If it does, this field references the type as
|
||||
// value. This is not allowed because it prohibits a value from being
|
||||
// shared among multiple structs that reference it.
|
||||
//
|
||||
// For example: if a struct has two fields of the same type, they must
|
||||
// both point to the same value after this routine has executed. If these
|
||||
// fields are not a pointer type, the value cannot be shared.
|
||||
//
|
||||
if reflect.PtrTo(ft).Implements(ifaceType) {
|
||||
panic(fmt.Sprintf(`field "%s" in struct "%s" must be a pointer`, ff.Name, v.Type()))
|
||||
}
|
||||
|
||||
// Type must implement specified interface.
|
||||
if !ft.Implements(ifaceType) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Type must be a pointer.
|
||||
if ft.Kind() != reflect.Ptr {
|
||||
panic(fmt.Sprintf(`field "%s" in struct "%s" must be a pointer`, ff.Name, v.Type()))
|
||||
}
|
||||
|
||||
// Have not seen this type before, create a value.
|
||||
if _, ok := visited[ft]; !ok {
|
||||
visited[ft] = reflect.New(ft.Elem())
|
||||
}
|
||||
|
||||
// Make sure current field is set.
|
||||
if fv.IsNil() {
|
||||
fv.Set(visited[ft])
|
||||
}
|
||||
|
||||
// Recurse.
|
||||
err := walker(fv.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return walker(c)
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *create) Usage() string {
|
||||
return "[DATACENTER NAME]..."
|
||||
}
|
||||
|
||||
func (cmd *create) Process() error { return nil }
|
||||
|
||||
func (cmd *create) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *destroy) Usage() string {
|
||||
return "[DATACENTER NAME]..."
|
||||
}
|
||||
|
||||
func (cmd *destroy) Process() error { return nil }
|
||||
|
||||
func (cmd *destroy) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
|
||||
}
|
||||
|
||||
func (cmd *cp) Process() error { return nil }
|
||||
|
||||
func (cmd *cp) Usage() string {
|
||||
return "SRC DST"
|
||||
}
|
||||
|
||||
func (cmd *cp) Run(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())
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
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 datastore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *download) Process() error { return nil }
|
||||
|
||||
func (cmd *download) Usage() string {
|
||||
return "REMOTE LOCAL"
|
||||
}
|
||||
|
||||
func (cmd *download) Run(f *flag.FlagSet) error {
|
||||
args := f.Args()
|
||||
if len(args) != 2 {
|
||||
return errors.New("invalid arguments")
|
||||
}
|
||||
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u, err := cmd.DatastoreURL(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := soap.DefaultDownload
|
||||
if cmd.OutputFlag.TTY {
|
||||
logger := cmd.ProgressLogger("Downloading... ")
|
||||
p.Progress = logger
|
||||
defer logger.Wait()
|
||||
}
|
||||
|
||||
return c.Client.DownloadFile(args[1], u, &p)
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
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 datastore
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *info) Process() error { return nil }
|
||||
|
||||
func (cmd *info) Usage() string {
|
||||
return "[PATH]..."
|
||||
}
|
||||
|
||||
func (cmd *info) Run(f *flag.FlagSet) error {
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
finder, err := cmd.Finder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := f.Args()
|
||||
if len(args) == 0 {
|
||||
args = []string{"*"}
|
||||
}
|
||||
|
||||
datastores, err := finder.DatastoreList(ctx, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
refs := make([]types.ManagedObjectReference, 0, len(datastores))
|
||||
for _, ds := range datastores {
|
||||
refs = append(refs, ds.Reference())
|
||||
}
|
||||
|
||||
var res infoResult
|
||||
var props []string
|
||||
|
||||
if cmd.OutputFlag.JSON {
|
||||
props = nil // Load everything
|
||||
} else {
|
||||
props = []string{"info", "summary"} // Load summary
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (r *infoResult) Write(w io.Writer) error {
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
|
||||
|
||||
for _, ds := range r.Datastores {
|
||||
s := ds.Summary
|
||||
fmt.Fprintf(tw, "Name:\t%s\n", s.Name)
|
||||
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()
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
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 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
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("datastore.ls", &ls{})
|
||||
}
|
||||
|
||||
func (cmd *ls) Register(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.long, "l", false, "Long listing format")
|
||||
}
|
||||
|
||||
func (cmd *ls) Process() error { return nil }
|
||||
|
||||
func (cmd *ls) Usage() string {
|
||||
return "[FILE]..."
|
||||
}
|
||||
|
||||
func (cmd *ls) Run(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),
|
||||
long: cmd.long,
|
||||
}
|
||||
|
||||
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
|
||||
long bool
|
||||
}
|
||||
|
||||
func (o *listOutput) add(r types.HostDatastoreBrowserSearchResults) {
|
||||
o.rs = append(o.rs, r)
|
||||
}
|
||||
|
||||
// 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.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
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.createParents, "p", false, "Create intermediate directories as needed")
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Process() error { return nil }
|
||||
|
||||
func (cmd *mkdir) Usage() string {
|
||||
return "DIRECTORY"
|
||||
}
|
||||
|
||||
func (cmd *mkdir) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.force, "f", false, "If true, overwrite any identically named file at the destination")
|
||||
}
|
||||
|
||||
func (cmd *mv) Process() error { return nil }
|
||||
|
||||
func (cmd *mv) Usage() string {
|
||||
return "SRC DST"
|
||||
}
|
||||
|
||||
func (cmd *mv) Run(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())
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.force, "f", false, "Force; ignore nonexistent files and arguments")
|
||||
}
|
||||
|
||||
func (cmd *rm) Process() error { return nil }
|
||||
|
||||
func (cmd *rm) Usage() string {
|
||||
return "FILE"
|
||||
}
|
||||
|
||||
func (cmd *rm) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
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 datastore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *upload) Process() error { return nil }
|
||||
|
||||
func (cmd *upload) Usage() string {
|
||||
return "LOCAL REMOTE"
|
||||
}
|
||||
|
||||
func (cmd *upload) Run(f *flag.FlagSet) error {
|
||||
args := f.Args()
|
||||
if len(args) != 2 {
|
||||
return errors.New("invalid arguments")
|
||||
}
|
||||
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u, err := cmd.DatastoreURL(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := soap.DefaultUpload
|
||||
if cmd.OutputFlag.TTY {
|
||||
logger := cmd.ProgressLogger("Uploading... ")
|
||||
p.Progress = logger
|
||||
defer logger.Wait()
|
||||
}
|
||||
|
||||
return c.Client.UploadFile(args[0], u, &p)
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
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() error { return nil }
|
||||
|
||||
func (cmd *boot) Run(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)
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.controller, "controller", "", "IDE controller name")
|
||||
}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.device, "device", "", "CD-ROM device name")
|
||||
}
|
||||
|
||||
func (cmd *eject) Process() error { 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(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))
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.device, "device", "", "CD-ROM device name")
|
||||
}
|
||||
|
||||
func (cmd *insert) Process() error { 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(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))
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *connect) Process() error { return nil }
|
||||
|
||||
func (cmd *connect) Usage() string {
|
||||
return "DEVICE..."
|
||||
}
|
||||
|
||||
func (cmd *connect) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *disconnect) Process() error { return nil }
|
||||
|
||||
func (cmd *disconnect) Usage() string {
|
||||
return "DEVICE..."
|
||||
}
|
||||
|
||||
func (cmd *disconnect) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.device, "device", "", "Floppy device name")
|
||||
}
|
||||
|
||||
func (cmd *eject) Process() error { 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(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))
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.device, "device", "", "Floppy device name")
|
||||
}
|
||||
|
||||
func (cmd *insert) Process() error { 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(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))
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
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 device
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type info struct {
|
||||
*flags.VirtualMachineFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("device.info", &info{})
|
||||
}
|
||||
|
||||
func (cmd *info) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *info) Process() error { return nil }
|
||||
|
||||
func (cmd *info) Usage() string {
|
||||
return "DEVICE..."
|
||||
}
|
||||
|
||||
func (cmd *info) Run(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
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
|
||||
|
||||
for _, name := range f.Args() {
|
||||
device := devices.Find(name)
|
||||
if device == nil {
|
||||
return fmt.Errorf("device '%s' not found", name)
|
||||
}
|
||||
|
||||
d := device.GetVirtualDevice()
|
||||
info := d.DeviceInfo.GetDescription()
|
||||
|
||||
fmt.Fprintf(tw, "Name:\t%s\n", name)
|
||||
fmt.Fprintf(tw, " Type:\t%s\n", 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, devices.Name(devices.FindByKey(key)))
|
||||
}
|
||||
fmt.Fprintf(tw, " Devices:\t%s\n", strings.Join(attached, ", "))
|
||||
} else {
|
||||
if c := devices.FindByKey(d.ControllerKey); c != nil {
|
||||
fmt.Fprintf(tw, " Controller:\t%s\n", devices.Name(c))
|
||||
fmt.Fprintf(tw, " Unit number:\t%d\n", d.UnitNumber)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.boot, "boot", false, "List devices configured in the VM's boot options")
|
||||
}
|
||||
|
||||
func (cmd *ls) Process() error { return nil }
|
||||
|
||||
func (cmd *ls) Run(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()
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *remove) Process() error { return nil }
|
||||
|
||||
func (cmd *remove) Usage() string {
|
||||
return "DEVICE..."
|
||||
}
|
||||
|
||||
func (cmd *remove) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
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() error { return nil }
|
||||
|
||||
func (cmd *add) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.device, "device", "", "serial port device name")
|
||||
f.BoolVar(&cmd.client, "client", false, "Use client direction")
|
||||
}
|
||||
|
||||
func (cmd *connect) Process() error { return nil }
|
||||
|
||||
func (cmd *connect) Run(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))
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.device, "device", "", "serial port device name")
|
||||
}
|
||||
|
||||
func (cmd *disconnect) Process() error { return nil }
|
||||
|
||||
func (cmd *disconnect) Run(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))
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
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 events
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/event"
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/list"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type events struct {
|
||||
*flags.DatacenterFlag
|
||||
|
||||
Max int
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("events", &events{})
|
||||
}
|
||||
|
||||
func (cmd *events) Register(f *flag.FlagSet) {
|
||||
f.IntVar(&cmd.Max, "n", 25, "Output the last N events")
|
||||
}
|
||||
|
||||
func (cmd *events) Process() error { return nil }
|
||||
|
||||
func (cmd *events) Usage() string {
|
||||
return "[PATH]..."
|
||||
}
|
||||
|
||||
func (cmd *events) Run(f *flag.FlagSet) error {
|
||||
ctx := context.TODO()
|
||||
|
||||
finder, err := cmd.Finder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m := event.NewManager(c)
|
||||
|
||||
var objs []list.Element
|
||||
|
||||
args := f.Args()
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
|
||||
for _, arg := range args {
|
||||
es, err := finder.ManagedObjectList(ctx, arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objs = append(objs, es...)
|
||||
}
|
||||
|
||||
var events []types.BaseEvent
|
||||
|
||||
for _, o := range objs {
|
||||
filter := types.EventFilterSpec{
|
||||
Entity: &types.EventFilterSpecByEntity{
|
||||
Entity: o.Object.Reference(),
|
||||
Recursion: types.EventFilterSpecRecursionOptionAll,
|
||||
},
|
||||
}
|
||||
|
||||
collector, err := m.CreateCollectorForEvents(ctx, filter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[%s] %s", o.Path, err)
|
||||
}
|
||||
defer collector.Destroy(ctx)
|
||||
|
||||
err = collector.SetPageSize(ctx, cmd.Max)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
page, err := collector.LatestPage(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
events = append(events, page...)
|
||||
}
|
||||
|
||||
event.Sort(events)
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)
|
||||
|
||||
for _, e := range events {
|
||||
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(tw, "[%s]\t[%s]\t%s\n",
|
||||
event.CreatedTime.Local().Format(time.ANSIC),
|
||||
cat, msg)
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/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
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *add) Run(f *flag.FlagSet) error {
|
||||
if f.NArg() != 1 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *ls) Process() error { return nil }
|
||||
|
||||
func (cmd *ls) Run(f *flag.FlagSet) error {
|
||||
ctx := context.TODO()
|
||||
|
||||
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()
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *rename) Process() error { return nil }
|
||||
|
||||
func (cmd *rename) Usage() string {
|
||||
return "KEY NAME"
|
||||
}
|
||||
|
||||
func (cmd *rename) Run(f *flag.FlagSet) error {
|
||||
if f.NArg() != 2 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
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 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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *rm) Process() error { return nil }
|
||||
|
||||
func (cmd *rm) Usage() string {
|
||||
return "KEY..."
|
||||
}
|
||||
|
||||
func (cmd *rm) Run(f *flag.FlagSet) error {
|
||||
ctx := context.TODO()
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
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 fields
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/list"
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *set) Process() error { return nil }
|
||||
|
||||
func (cmd *set) Usage() string {
|
||||
return "KEY VALUE PATH..."
|
||||
}
|
||||
|
||||
func (cmd *set) Run(f *flag.FlagSet) error {
|
||||
if f.NArg() < 3 {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
finder, err := cmd.Finder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := object.GetCustomFieldsManager(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var objs []list.Element
|
||||
|
||||
args := f.Args()
|
||||
|
||||
key, err := m.FindKey(ctx, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
val := args[1]
|
||||
|
||||
for _, arg := range args[2:] {
|
||||
es, err := finder.ManagedObjectList(ctx, arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objs = append(objs, es...)
|
||||
}
|
||||
|
||||
for _, ref := range objs {
|
||||
err := m.Set(ctx, ref.Object.Reference(), key, val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
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 (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"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"
|
||||
envInsecure = "GOVC_INSECURE"
|
||||
envPersist = "GOVC_PERSIST_SESSION"
|
||||
envMinAPIVersion = "GOVC_MIN_API_VERSION"
|
||||
)
|
||||
|
||||
const cDescr = "ESX or vCenter URL"
|
||||
|
||||
type ClientFlag struct {
|
||||
*DebugFlag
|
||||
|
||||
register sync.Once
|
||||
|
||||
url *url.URL
|
||||
username string
|
||||
password string
|
||||
insecure bool
|
||||
persist bool
|
||||
minAPIVersion string
|
||||
|
||||
client *vim25.Client
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
var schemeMatch = regexp.MustCompile(`^\w+://`)
|
||||
|
||||
func (flag *ClientFlag) Set(s string) error {
|
||||
var err error
|
||||
|
||||
if s != "" {
|
||||
// Default the scheme to https
|
||||
if !schemeMatch.MatchString(s) {
|
||||
s = "https://" + s
|
||||
}
|
||||
|
||||
flag.url, err = url.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Default the path to /sdk
|
||||
if flag.url.Path == "" {
|
||||
flag.url.Path = "/sdk"
|
||||
}
|
||||
|
||||
if flag.url.User == nil {
|
||||
flag.url.User = url.UserPassword("", "")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Register(f *flag.FlagSet) {
|
||||
flag.register.Do(func() {
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
{
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *ClientFlag) Process() error {
|
||||
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()
|
||||
|
||||
enc := json.NewEncoder(f)
|
||||
err = enc.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)
|
||||
|
||||
// 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)
|
||||
err = m.Login(context.TODO(), flag.url.User)
|
||||
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 {
|
||||
realVersion, err := ParseVersion(c.ServiceContent.About.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
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type DatacenterFlag struct {
|
||||
*ClientFlag
|
||||
*OutputFlag
|
||||
|
||||
register sync.Once
|
||||
path string
|
||||
dc *object.Datacenter
|
||||
finder *find.Finder
|
||||
err error
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) Register(f *flag.FlagSet) {
|
||||
flag.register.Do(func() {
|
||||
env := "GOVC_DATACENTER"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Datacenter [%s]", env)
|
||||
f.StringVar(&flag.path, "dc", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *DatacenterFlag) Process() error { 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)
|
||||
|
||||
// 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.path == "" {
|
||||
flag.dc, flag.err = finder.DefaultDatacenter(context.TODO())
|
||||
} else {
|
||||
if flag.dc, err = finder.Datacenter(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
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
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 (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDatastoreDirNotExist = errors.New("datastore directory does not exist")
|
||||
ErrDatastoreFileNotExist = errors.New("datastore file does not exist")
|
||||
)
|
||||
|
||||
type DatastoreFlag struct {
|
||||
*DatacenterFlag
|
||||
|
||||
register sync.Once
|
||||
name string
|
||||
ds *object.Datastore
|
||||
}
|
||||
|
||||
func (flag *DatastoreFlag) Register(f *flag.FlagSet) {
|
||||
flag.register.Do(func() {
|
||||
env := "GOVC_DATASTORE"
|
||||
value := os.Getenv(env)
|
||||
usage := fmt.Sprintf("Datastore [%s]", env)
|
||||
f.StringVar(&flag.name, "ds", value, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func (flag *DatastoreFlag) Process() error { return nil }
|
||||
|
||||
func (flag *DatastoreFlag) Datastore() (*object.Datastore, error) {
|
||||
if flag.ds != nil {
|
||||
return flag.ds, nil
|
||||
}
|
||||
|
||||
finder, err := flag.Finder()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if flag.name == "" {
|
||||
flag.ds, err = finder.DefaultDatastore(context.TODO())
|
||||
} else {
|
||||
flag.ds, err = finder.Datastore(context.TODO(), flag.name)
|
||||
}
|
||||
|
||||
return flag.ds, err
|
||||
}
|
||||
|
||||
func (flag *DatastoreFlag) DatastorePath(name string) (string, error) {
|
||||
ds, err := flag.Datastore()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ds.Path(name), nil
|
||||
}
|
||||
|
||||
func (flag *DatastoreFlag) DatastoreURL(path string) (*url.URL, error) {
|
||||
dc, err := flag.Datacenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ds, err := flag.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 (flag *DatastoreFlag) Stat(file string) (types.BaseFileInfo, error) {
|
||||
ds, err := flag.Datastore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := ds.Browser(context.TODO())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spec := types.HostDatastoreBrowserSearchSpec{
|
||||
Details: &types.FileQueryFlags{
|
||||
FileType: true,
|
||||
FileOwner: types.NewBool(true), // TODO: omitempty is generated, but seems to be required
|
||||
},
|
||||
MatchPattern: []string{path.Base(file)},
|
||||
}
|
||||
|
||||
dsPath := ds.Path(path.Dir(file))
|
||||
task, err := b.SearchDatastore(context.TODO(), dsPath, &spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info, err := task.WaitForResult(context.TODO(), nil)
|
||||
if err != nil {
|
||||
if info != nil && info.Error != nil {
|
||||
_, ok := info.Error.Fault.(*types.FileNotFound)
|
||||
if ok {
|
||||
// FileNotFound means the base path doesn't exist.
|
||||
return nil, ErrDatastoreDirNotExist
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := info.Result.(types.HostDatastoreBrowserSearchResults)
|
||||
if len(res.File) == 0 {
|
||||
// File doesn't exist
|
||||
return nil, ErrDatastoreFileNotExist
|
||||
}
|
||||
|
||||
return res.File[0], nil
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/debug"
|
||||
)
|
||||
|
||||
type DebugFlag struct {
|
||||
enable bool
|
||||
}
|
||||
|
||||
func (flag *DebugFlag) Register(f *flag.FlagSet) {
|
||||
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() error {
|
||||
if flag.enable {
|
||||
// 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
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
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 "flag"
|
||||
|
||||
type EmptyFlag struct{}
|
||||
|
||||
func (flag *EmptyFlag) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (flag *EmptyFlag) Process() error { return nil }
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type HostSystemFlag struct {
|
||||
*ClientFlag
|
||||
*DatacenterFlag
|
||||
*SearchFlag
|
||||
|
||||
register sync.Once
|
||||
name string
|
||||
host *object.HostSystem
|
||||
pool *object.ResourcePool
|
||||
}
|
||||
|
||||
func (flag *HostSystemFlag) Register(f *flag.FlagSet) {
|
||||
flag.SearchFlag = NewSearchFlag(SearchHosts)
|
||||
|
||||
flag.register.Do(func() {
|
||||
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() error { 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())
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type NetworkFlag struct {
|
||||
*DatacenterFlag
|
||||
|
||||
register sync.Once
|
||||
name string
|
||||
net object.NetworkReference
|
||||
adapter string
|
||||
address string
|
||||
}
|
||||
|
||||
func NewNetworkFlag() *NetworkFlag {
|
||||
return &NetworkFlag{}
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Register(f *flag.FlagSet) {
|
||||
flag.register.Do(func() {
|
||||
env := "GOVC_NETWORK"
|
||||
value := os.Getenv(env)
|
||||
flag.Set(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() error { return nil }
|
||||
|
||||
func (flag *NetworkFlag) String() string {
|
||||
return flag.name
|
||||
}
|
||||
|
||||
func (flag *NetworkFlag) Set(name string) error {
|
||||
flag.name = name
|
||||
return nil
|
||||
}
|
||||
|
||||
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.name == "" {
|
||||
flag.net, err = finder.DefaultNetwork(context.TODO())
|
||||
} else {
|
||||
flag.net, err = finder.Network(context.TODO(), flag.name)
|
||||
}
|
||||
|
||||
return flag.net, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
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 (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/progress"
|
||||
)
|
||||
|
||||
type OutputWriter interface {
|
||||
Write(io.Writer) error
|
||||
}
|
||||
|
||||
type OutputFlag struct {
|
||||
JSON bool
|
||||
TTY bool
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) Register(f *flag.FlagSet) {
|
||||
f.BoolVar(&flag.JSON, "json", false, "Enable JSON output")
|
||||
}
|
||||
|
||||
func (flag *OutputFlag) Process() 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 {
|
||||
enc := json.NewEncoder(out)
|
||||
err = enc.Encode(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)
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type ResourcePoolFlag struct {
|
||||
*DatacenterFlag
|
||||
|
||||
register sync.Once
|
||||
name string
|
||||
pool *object.ResourcePool
|
||||
}
|
||||
|
||||
func (flag *ResourcePoolFlag) Register(f *flag.FlagSet) {
|
||||
flag.register.Do(func() {
|
||||
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() error { 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.name == "" {
|
||||
flag.pool, err = finder.DefaultResourcePool(context.TODO())
|
||||
} else {
|
||||
flag.pool, err = finder.ResourcePool(context.TODO(), flag.name)
|
||||
}
|
||||
|
||||
return flag.pool, err
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
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 (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const (
|
||||
SearchVirtualMachines = iota + 1
|
||||
SearchHosts
|
||||
)
|
||||
|
||||
type SearchFlag struct {
|
||||
*ClientFlag
|
||||
*DatacenterFlag
|
||||
|
||||
t int
|
||||
entity string
|
||||
|
||||
byDatastorePath string
|
||||
byDNSName string
|
||||
byInventoryPath string
|
||||
byIP string
|
||||
byUUID string
|
||||
|
||||
isset bool
|
||||
}
|
||||
|
||||
func NewSearchFlag(t int) *SearchFlag {
|
||||
s := SearchFlag{
|
||||
t: t,
|
||||
}
|
||||
|
||||
switch t {
|
||||
case SearchVirtualMachines:
|
||||
s.entity = "VM"
|
||||
case SearchHosts:
|
||||
s.entity = "host"
|
||||
default:
|
||||
panic("invalid search type")
|
||||
}
|
||||
|
||||
return &s
|
||||
}
|
||||
|
||||
func (flag *SearchFlag) Register(fs *flag.FlagSet) {
|
||||
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() error {
|
||||
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)
|
||||
case SearchHosts:
|
||||
return flag.searchIndex(c).FindByUuid(context.TODO(), dc, flag.byUUID, false)
|
||||
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
|
||||
}
|
||||
|
||||
// List virtual machines for every argument
|
||||
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 (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
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type VirtualMachineFlag struct {
|
||||
*ClientFlag
|
||||
*DatacenterFlag
|
||||
*SearchFlag
|
||||
|
||||
register sync.Once
|
||||
name string
|
||||
vm *object.VirtualMachine
|
||||
}
|
||||
|
||||
func (flag *VirtualMachineFlag) Register(f *flag.FlagSet) {
|
||||
flag.SearchFlag = NewSearchFlag(SearchVirtualMachines)
|
||||
|
||||
flag.register.Do(func() {
|
||||
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() error { 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
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
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 (
|
||||
"errors"
|
||||
"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
|
||||
|
||||
parent string
|
||||
|
||||
host string
|
||||
username string
|
||||
password string
|
||||
connect bool
|
||||
fingerprint string
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.add", &add{})
|
||||
}
|
||||
|
||||
func (cmd *add) Register(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.parent, "parent", "", "Path to folder to add the host to")
|
||||
|
||||
f.StringVar(&cmd.host, "host", "", "Hostname or IP address of the host")
|
||||
f.StringVar(&cmd.username, "username", "", "Username of administration account on the host")
|
||||
f.StringVar(&cmd.password, "password", "", "Password of administration account on the host")
|
||||
f.BoolVar(&cmd.connect, "connect", true, "Immediately connect to host")
|
||||
f.StringVar(&cmd.fingerprint, "fingerprint", "", "Fingerprint of the host's SSL certificate")
|
||||
}
|
||||
|
||||
func (cmd *add) Process() error {
|
||||
if cmd.host == "" {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
if cmd.username == "" {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
if cmd.password == "" {
|
||||
return flag.ErrHelp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *add) Usage() string {
|
||||
return "HOST"
|
||||
}
|
||||
|
||||
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) Run(f *flag.FlagSet) error {
|
||||
var ctx = context.Background()
|
||||
var parent *object.Folder
|
||||
|
||||
client, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
mo, err := finder.ManagedObjectList(ctx, cmd.parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(mo) == 0 {
|
||||
return errors.New("parent does not resolve to object")
|
||||
}
|
||||
|
||||
if len(mo) > 1 {
|
||||
return errors.New("parent resolves to more than one object")
|
||||
}
|
||||
|
||||
ref := mo[0].Object.Reference()
|
||||
if ref.Type != "Folder" {
|
||||
return errors.New("parent does not resolve to folder")
|
||||
}
|
||||
|
||||
parent = object.NewFolder(client, ref)
|
||||
}
|
||||
|
||||
req := types.AddStandaloneHost_Task{
|
||||
This: parent.Reference(),
|
||||
Spec: types.HostConnectSpec{
|
||||
HostName: cmd.host,
|
||||
UserName: cmd.username,
|
||||
Password: cmd.password,
|
||||
SslThumbprint: cmd.fingerprint,
|
||||
},
|
||||
AddConnected: cmd.connect,
|
||||
}
|
||||
|
||||
res, err := methods.AddStandaloneHost_Task(ctx, client, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task := object.NewTask(client, res.Returnval)
|
||||
_, err = task.WaitForResult(ctx, nil)
|
||||
if err != nil {
|
||||
f, ok := err.(types.HasFault)
|
||||
if !ok {
|
||||
return err
|
||||
}
|
||||
|
||||
switch fault := f.Fault().(type) {
|
||||
case *types.SSLVerifyFault:
|
||||
// Add fingerprint to error message
|
||||
return fmt.Errorf("%s Fingerprint is %s.", err.Error(), fault.Thumbprint)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *add) Run(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)
|
||||
}
|
||||
150
vendor/github.com/vmware/govmomi/govc/host/autostart/autostart.go
generated
vendored
Normal file
150
vendor/github.com/vmware/govmomi/govc/host/autostart/autostart.go
generated
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
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 (f *AutostartFlag) Register(fs *flag.FlagSet) {}
|
||||
|
||||
func (f *AutostartFlag) Process() error { 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
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type configure struct {
|
||||
*AutostartFlag
|
||||
|
||||
defaults types.AutoStartDefaults
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.autostart.configure", &configure{})
|
||||
}
|
||||
|
||||
func (cmd *configure) Register(f *flag.FlagSet) {
|
||||
cmd.defaults.Enabled = types.NewBool(false)
|
||||
f.BoolVar(cmd.defaults.Enabled, "enabled", false, "")
|
||||
|
||||
f.IntVar(&cmd.defaults.StartDelay, "start-delay", 0, "")
|
||||
f.StringVar(&cmd.defaults.StopAction, "stop-action", "", "")
|
||||
f.IntVar(&cmd.defaults.StopDelay, "stop-delay", 0, "")
|
||||
|
||||
cmd.defaults.WaitForHeartbeat = types.NewBool(false)
|
||||
f.BoolVar(cmd.defaults.WaitForHeartbeat, "wait-for-heartbeat", false, "")
|
||||
}
|
||||
|
||||
func (cmd *configure) Process() error { return nil }
|
||||
|
||||
func (cmd *configure) Usage() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (cmd *configure) Run(f *flag.FlagSet) error {
|
||||
// Note: this command cannot DISABLE autostart because the "Enabled" field is
|
||||
// marked "omitempty", which means that it is not included when it is false.
|
||||
// Also see: https://github.com/vmware/govmomi/issues/240
|
||||
return cmd.ReconfigureDefaults(cmd.defaults)
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package 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 {
|
||||
*AutostartFlag
|
||||
|
||||
*flags.OutputFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.autostart.info", &info{})
|
||||
}
|
||||
|
||||
func (cmd *info) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *info) Process() error { return nil }
|
||||
|
||||
func (cmd *info) Usage() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (cmd *info) Run(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
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"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(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *remove) Process() error { return nil }
|
||||
|
||||
func (cmd *remove) Usage() string {
|
||||
return "VM..."
|
||||
}
|
||||
|
||||
func (cmd *remove) Run(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)
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
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"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"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(f *flag.FlagSet) {
|
||||
f.BoolVar(&cmd.hints, "hints", true, "Use command info hints when formatting output")
|
||||
}
|
||||
|
||||
func (cmd *esxcli) Process() error { return nil }
|
||||
|
||||
func (cmd *esxcli) Run(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()
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type Executor struct {
|
||||
c *vim25.Client
|
||||
host *object.HostSystem
|
||||
mme *types.ReflectManagedMethodExecuter
|
||||
dtm *types.InternalDynamicTypeManager
|
||||
info map[string]*CommandInfo
|
||||
}
|
||||
|
||||
func NewExecutor(c *vim25.Client, host *object.HostSystem) (*Executor, error) {
|
||||
e := &Executor{
|
||||
c: c,
|
||||
host: host,
|
||||
info: make(map[string]*CommandInfo),
|
||||
}
|
||||
|
||||
{
|
||||
req := types.RetrieveManagedMethodExecuter{
|
||||
This: host.Reference(),
|
||||
}
|
||||
|
||||
res, err := methods.RetrieveManagedMethodExecuter(context.TODO(), c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.mme = res.Returnval
|
||||
}
|
||||
|
||||
{
|
||||
req := types.RetrieveDynamicTypeManager{
|
||||
This: host.Reference(),
|
||||
}
|
||||
|
||||
res, err := methods.RetrieveDynamicTypeManager(context.TODO(), c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.dtm = res.Returnval
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (e *Executor) CommandInfo(c *Command) (*CommandInfoMethod, error) {
|
||||
ns := c.Namespace()
|
||||
var info *CommandInfo
|
||||
var ok bool
|
||||
|
||||
if info, ok = e.info[ns]; !ok {
|
||||
req := types.ExecuteSoap{
|
||||
Moid: "ha-dynamic-type-manager-local-cli-cliinfo",
|
||||
Method: "vim.CLIInfo.FetchCLIInfo",
|
||||
Argument: []types.ReflectManagedMethodExecuterSoapArgument{
|
||||
c.Argument("typeName", "vim.EsxCLI."+ns),
|
||||
},
|
||||
}
|
||||
|
||||
info = new(CommandInfo)
|
||||
if err := e.Execute(&req, info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.info[ns] = info
|
||||
}
|
||||
|
||||
name := c.Name()
|
||||
for _, method := range info.Method {
|
||||
if method.Name == name {
|
||||
return method, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("method '%s' not found in name space '%s'", name, c.Namespace())
|
||||
}
|
||||
|
||||
func (e *Executor) NewRequest(args []string) (*types.ExecuteSoap, *CommandInfoMethod, error) {
|
||||
c := NewCommand(args)
|
||||
|
||||
info, err := e.CommandInfo(c)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sargs, err := c.Parse(info.Param)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sreq := types.ExecuteSoap{
|
||||
Moid: c.Moid(),
|
||||
Method: c.Method(),
|
||||
Argument: sargs,
|
||||
}
|
||||
|
||||
return &sreq, info, nil
|
||||
}
|
||||
|
||||
func (e *Executor) Execute(req *types.ExecuteSoap, res interface{}) error {
|
||||
req.This = e.mme.ManagedObjectReference
|
||||
req.Version = "urn:vim25/5.0"
|
||||
|
||||
x, err := methods.ExecuteSoap(context.TODO(), e.c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if x.Returnval != nil {
|
||||
if x.Returnval.Fault != nil {
|
||||
return errors.New(x.Returnval.Fault.FaultMsg)
|
||||
}
|
||||
|
||||
if err := xml.Unmarshal([]byte(x.Returnval.Response), res); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Executor) Run(args []string) (*Response, error) {
|
||||
req, info, err := e.NewRequest(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &Response{
|
||||
Info: info,
|
||||
}
|
||||
|
||||
if err := e.Execute(req, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
15
vendor/github.com/vmware/govmomi/govc/host/esxcli/fixtures/network_vm_list.xml
generated
vendored
Normal file
15
vendor/github.com/vmware/govmomi/govc/host/esxcli/fixtures/network_vm_list.xml
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="5.0" xsi:type="ArrayOfDataObject">
|
||||
<DataObject xsi:type="VimEsxCLInetworkvmlistVM">
|
||||
<Name>foo</Name>
|
||||
<Networks>VM Network</Networks>
|
||||
<Networks>dougm</Networks>
|
||||
<NumPorts>2</NumPorts>
|
||||
<WorldID>98842</WorldID>
|
||||
</DataObject>
|
||||
<DataObject xsi:type="VimEsxCLInetworkvmlistVM">
|
||||
<Name>bar</Name>
|
||||
<Networks>VM Network</Networks>
|
||||
<NumPorts>1</NumPorts>
|
||||
<WorldID>236235</WorldID>
|
||||
</DataObject>
|
||||
</obj>
|
||||
12
vendor/github.com/vmware/govmomi/govc/host/esxcli/fixtures/network_vm_port_list.xml
generated
vendored
Normal file
12
vendor/github.com/vmware/govmomi/govc/host/esxcli/fixtures/network_vm_port_list.xml
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="5.0" xsi:type="ArrayOfDataObject">
|
||||
<DataObject xsi:type="VimEsxCLInetworkvmportlistPort">
|
||||
<DVPortID></DVPortID>
|
||||
<IPAddress>192.168.247.149</IPAddress>
|
||||
<MACAddress>00:0c:29:12:b2:cf</MACAddress>
|
||||
<PortID>33554438</PortID>
|
||||
<Portgroup>VM Network</Portgroup>
|
||||
<TeamUplink>vmnic0</TeamUplink>
|
||||
<UplinkPortID>33554434</UplinkPortID>
|
||||
<vSwitch>vSwitch0</vSwitch>
|
||||
</DataObject>
|
||||
</obj>
|
||||
5
vendor/github.com/vmware/govmomi/govc/host/esxcli/fixtures/system_hostname_get.xml
generated
vendored
Normal file
5
vendor/github.com/vmware/govmomi/govc/host/esxcli/fixtures/system_hostname_get.xml
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="5.0" xsi:type="VimEsxCLIsystemhostnamegetFullyQualifiedHostName">
|
||||
<DomainName>localdomain</DomainName>
|
||||
<FullyQualifiedDomainName>esxbox.localdomain</FullyQualifiedDomainName>
|
||||
<HostName>esxbox</HostName>
|
||||
</obj>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
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 (
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type hostInfo struct {
|
||||
*Executor
|
||||
wids map[string]string
|
||||
}
|
||||
|
||||
type GuestInfo struct {
|
||||
c *vim25.Client
|
||||
hosts map[string]*hostInfo
|
||||
}
|
||||
|
||||
func NewGuestInfo(c *vim25.Client) *GuestInfo {
|
||||
return &GuestInfo{
|
||||
c: c,
|
||||
hosts: make(map[string]*hostInfo),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GuestInfo) hostInfo(ref *types.ManagedObjectReference) (*hostInfo, error) {
|
||||
// cache exectuor and uuid -> worldid map
|
||||
if h, ok := g.hosts[ref.Value]; ok {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
host := object.NewHostSystem(g.c, *ref)
|
||||
|
||||
e, err := NewExecutor(g.c, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := e.Run([]string{"vm", "process", "list"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ids := make(map[string]string, len(res.Values))
|
||||
|
||||
for _, process := range res.Values {
|
||||
// Normalize uuid, esxcli and mo.VirtualMachine have different formats
|
||||
uuid := strings.Replace(process["UUID"][0], " ", "", -1)
|
||||
uuid = strings.Replace(uuid, "-", "", -1)
|
||||
|
||||
ids[uuid] = process["WorldID"][0]
|
||||
}
|
||||
|
||||
h := &hostInfo{e, ids}
|
||||
g.hosts[ref.Value] = h
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// IpAddress attempts to find the guest IP address using esxcli.
|
||||
// ESX hosts must be configured with the /Net/GuestIPHack enabled.
|
||||
// For example:
|
||||
// $ govc host.esxcli -- system settings advanced set -o /Net/GuestIPHack -i 1
|
||||
func (g *GuestInfo) IpAddress(vm *object.VirtualMachine) (string, error) {
|
||||
var mvm mo.VirtualMachine
|
||||
|
||||
pc := property.DefaultCollector(g.c)
|
||||
err := pc.RetrieveOne(context.TODO(), vm.Reference(), []string{"runtime.host", "config.uuid"}, &mvm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
h, err := g.hostInfo(mvm.Runtime.Host)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Normalize uuid, esxcli and mo.VirtualMachine have different formats
|
||||
uuid := strings.Replace(mvm.Config.Uuid, "-", "", -1)
|
||||
|
||||
if wid, ok := h.wids[uuid]; ok {
|
||||
res, err := h.Run([]string{"network", "vm", "port", "list", "--world-id", wid})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(res.Values) == 1 {
|
||||
if ip, ok := res.Values[0]["IPAddress"]; ok {
|
||||
return ip[0], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package esxcli
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
type Values map[string][]string
|
||||
|
||||
type Response struct {
|
||||
Info *CommandInfoMethod
|
||||
Values []Values
|
||||
}
|
||||
|
||||
func (v Values) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if s, ok := t.(xml.StartElement); ok {
|
||||
t, err = d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key := s.Name.Local
|
||||
var val string
|
||||
if c, ok := t.(xml.CharData); ok {
|
||||
val = string(c)
|
||||
}
|
||||
v[key] = append(v[key], val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Response) Type(start xml.StartElement) string {
|
||||
for _, a := range start.Attr {
|
||||
if a.Name.Local == "type" {
|
||||
return a.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *Response) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
stype := r.Type(start)
|
||||
|
||||
if stype != "ArrayOfDataObject" {
|
||||
v := Values{}
|
||||
if err := d.DecodeElement(&v, &start); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Values = append(r.Values, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if s, ok := t.(xml.StartElement); ok {
|
||||
if s.Name.Local == "DataObject" {
|
||||
v := Values{}
|
||||
if err := d.DecodeElement(&v, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Values = append(r.Values, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
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 host
|
||||
|
||||
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"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type info struct {
|
||||
*flags.ClientFlag
|
||||
*flags.OutputFlag
|
||||
*flags.HostSystemFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.info", &info{})
|
||||
}
|
||||
|
||||
func (c *info) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (c *info) Process() error { return nil }
|
||||
|
||||
func (c *info) Run(f *flag.FlagSet) error {
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var hosts []*object.HostSystem
|
||||
|
||||
// We could do without the -host flag, leaving it for compat
|
||||
host, err := c.HostSystemIfSpecified()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Default only if there is a single host
|
||||
if host == nil && f.NArg() == 0 {
|
||||
host, err = c.HostSystem()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if host != nil {
|
||||
hosts = append(hosts, host)
|
||||
} else {
|
||||
hosts, err = c.HostSystems(f.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var res infoResult
|
||||
var props []string
|
||||
|
||||
if c.OutputFlag.JSON {
|
||||
props = nil // Load everything
|
||||
} else {
|
||||
props = []string{"summary"} // Load summary
|
||||
}
|
||||
|
||||
for _, host := range hosts {
|
||||
var h mo.HostSystem
|
||||
|
||||
pc := property.DefaultCollector(client)
|
||||
err = pc.RetrieveOne(context.TODO(), host.Reference(), props, &h)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.HostSystems = append(res.HostSystems, h)
|
||||
}
|
||||
|
||||
return c.WriteResult(&res)
|
||||
}
|
||||
|
||||
type infoResult struct {
|
||||
HostSystems []mo.HostSystem
|
||||
}
|
||||
|
||||
func (r *infoResult) Write(w io.Writer) error {
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
|
||||
|
||||
for _, host := range r.HostSystems {
|
||||
s := host.Summary
|
||||
h := s.Hardware
|
||||
z := s.QuickStats
|
||||
ncpu := int(h.NumCpuPkgs * h.NumCpuCores)
|
||||
cpuUsage := 100 * float64(z.OverallCpuUsage) / float64(ncpu*h.CpuMhz)
|
||||
memUsage := 100 * float64(z.OverallMemoryUsage<<20) / float64(h.MemorySize)
|
||||
|
||||
fmt.Fprintf(tw, "Name:\t%s\n", s.Config.Name)
|
||||
fmt.Fprintf(tw, " Manufacturer:\t%s\n", h.Vendor)
|
||||
fmt.Fprintf(tw, " Logical CPUs:\t%d CPUs @ %dMHz\n", ncpu, h.CpuMhz)
|
||||
fmt.Fprintf(tw, " Processor type:\t%s\n", h.CpuModel)
|
||||
fmt.Fprintf(tw, " CPU usage:\t%d MHz (%.1f%%)\n", z.OverallCpuUsage, cpuUsage)
|
||||
fmt.Fprintf(tw, " Memory:\t%dMB\n", h.MemorySize/(1024*1024))
|
||||
fmt.Fprintf(tw, " Memory usage:\t%d MB (%.1f%%)\n", z.OverallMemoryUsage, memUsage)
|
||||
fmt.Fprintf(tw, " Boot time:\t%s\n", s.Runtime.BootTime)
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
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 portgroup
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type add struct {
|
||||
*flags.HostSystemFlag
|
||||
|
||||
spec types.HostPortGroupSpec
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.portgroup.add", &add{})
|
||||
}
|
||||
|
||||
func (cmd *add) Register(f *flag.FlagSet) {
|
||||
f.StringVar(&cmd.spec.VswitchName, "vswitch", "", "vSwitch Name")
|
||||
f.IntVar(&cmd.spec.VlanId, "vlan", 0, "VLAN ID")
|
||||
}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *add) Run(f *flag.FlagSet) error {
|
||||
ns, err := cmd.HostNetworkSystem()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.spec.Name = f.Arg(0)
|
||||
|
||||
return ns.AddPortGroup(context.TODO(), cmd.spec)
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
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 portgroup
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type remove struct {
|
||||
*flags.HostSystemFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.portgroup.remove", &remove{})
|
||||
}
|
||||
|
||||
func (cmd *remove) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *remove) Process() error { return nil }
|
||||
|
||||
func (cmd *remove) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *remove) Run(f *flag.FlagSet) error {
|
||||
ns, err := cmd.HostNetworkSystem()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ns.RemovePortGroup(context.TODO(), f.Arg(0))
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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 vswitch
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type add struct {
|
||||
*flags.HostSystemFlag
|
||||
|
||||
nic string
|
||||
spec types.HostVirtualSwitchSpec
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.vswitch.add", &add{})
|
||||
}
|
||||
|
||||
func (cmd *add) Register(f *flag.FlagSet) {
|
||||
f.IntVar(&cmd.spec.NumPorts, "ports", 128, "Number of ports")
|
||||
f.IntVar(&cmd.spec.Mtu, "mtu", 0, "MTU")
|
||||
f.StringVar(&cmd.nic, "nic", "", "Bridge nic device")
|
||||
}
|
||||
|
||||
func (cmd *add) Process() error { return nil }
|
||||
|
||||
func (cmd *add) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *add) Run(f *flag.FlagSet) error {
|
||||
ns, err := cmd.HostNetworkSystem()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.nic != "" {
|
||||
cmd.spec.Bridge = &types.HostVirtualSwitchBondBridge{
|
||||
NicDevice: []string{cmd.nic},
|
||||
}
|
||||
}
|
||||
|
||||
return ns.AddVirtualSwitch(context.TODO(), f.Arg(0), &cmd.spec)
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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 vswitch
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type info struct {
|
||||
*flags.ClientFlag
|
||||
*flags.OutputFlag
|
||||
*flags.HostSystemFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.vswitch.info", &info{})
|
||||
}
|
||||
|
||||
func (cmd *info) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *info) Process() error { return nil }
|
||||
|
||||
func (cmd *info) Run(f *flag.FlagSet) error {
|
||||
client, err := cmd.Client()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ns, err := cmd.HostNetworkSystem()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var mns mo.HostNetworkSystem
|
||||
|
||||
pc := property.DefaultCollector(client)
|
||||
err = pc.RetrieveOne(context.TODO(), ns.Reference(), []string{"networkInfo.vswitch"}, &mns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
|
||||
|
||||
for i, s := range mns.NetworkInfo.Vswitch {
|
||||
if i > 0 {
|
||||
fmt.Fprintln(tw)
|
||||
}
|
||||
fmt.Fprintf(tw, "Name:\t%s\n", s.Name)
|
||||
fmt.Fprintf(tw, "Portgroup:\t%s\n", cmd.keys("key-vim.host.PortGroup-", s.Portgroup))
|
||||
fmt.Fprintf(tw, "Pnic:\t%s\n", cmd.keys("key-vim.host.PhysicalNic-", s.Pnic))
|
||||
fmt.Fprintf(tw, "MTU:\t%d\n", s.Mtu)
|
||||
fmt.Fprintf(tw, "Ports:\t%d\n", s.NumPorts)
|
||||
fmt.Fprintf(tw, "Ports Available:\t%d\n", s.NumPortsAvailable)
|
||||
}
|
||||
|
||||
return tw.Flush()
|
||||
}
|
||||
|
||||
func (cmd *info) keys(key string, vals []string) string {
|
||||
for i, val := range vals {
|
||||
vals[i] = strings.TrimPrefix(val, key)
|
||||
}
|
||||
return strings.Join(vals, ", ")
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
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 vswitch
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"github.com/vmware/govmomi/govc/cli"
|
||||
"github.com/vmware/govmomi/govc/flags"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type remove struct {
|
||||
*flags.HostSystemFlag
|
||||
}
|
||||
|
||||
func init() {
|
||||
cli.Register("host.vswitch.remove", &remove{})
|
||||
}
|
||||
|
||||
func (cmd *remove) Register(f *flag.FlagSet) {}
|
||||
|
||||
func (cmd *remove) Process() error { return nil }
|
||||
|
||||
func (cmd *remove) Usage() string {
|
||||
return "NAME"
|
||||
}
|
||||
|
||||
func (cmd *remove) Run(f *flag.FlagSet) error {
|
||||
ns, err := cmd.HostNetworkSystem()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ns.RemoveVirtualSwitch(context.TODO(), f.Arg(0))
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
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 importx
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Archive interface {
|
||||
Open(string) (io.ReadCloser, int64, error)
|
||||
}
|
||||
|
||||
type TapeArchive struct {
|
||||
path string
|
||||
}
|
||||
|
||||
type TapeArchiveEntry struct {
|
||||
io.Reader
|
||||
f *os.File
|
||||
}
|
||||
|
||||
func (t *TapeArchiveEntry) Close() error {
|
||||
return t.f.Close()
|
||||
}
|
||||
|
||||
func (t *TapeArchive) Open(name string) (io.ReadCloser, int64, error) {
|
||||
f, err := os.Open(t.path)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
r := tar.NewReader(f)
|
||||
|
||||
for {
|
||||
h, err := r.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
matched, err := filepath.Match(name, path.Base(h.Name))
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if matched {
|
||||
return &TapeArchiveEntry{r, f}, h.Size, nil
|
||||
}
|
||||
}
|
||||
|
||||
_ = f.Close()
|
||||
|
||||
return nil, 0, os.ErrNotExist
|
||||
}
|
||||
|
||||
type FileArchive struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (t *FileArchive) Open(name string) (io.ReadCloser, int64, error) {
|
||||
fpath := name
|
||||
if name != t.path {
|
||||
fpath = filepath.Join(filepath.Dir(t.path), name)
|
||||
}
|
||||
|
||||
s, err := os.Stat(fpath)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
f, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return f, s.Size(), nil
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
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 importx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
)
|
||||
|
||||
type importable struct {
|
||||
localPath string
|
||||
remotePath string
|
||||
}
|
||||
|
||||
func (i importable) Ext() string {
|
||||
return path.Ext(i.localPath)
|
||||
}
|
||||
|
||||
func (i importable) Base() string {
|
||||
return path.Base(i.localPath)
|
||||
}
|
||||
|
||||
func (i importable) BaseClean() string {
|
||||
b := i.Base()
|
||||
e := i.Ext()
|
||||
return b[:len(b)-len(e)]
|
||||
}
|
||||
|
||||
func (i importable) RemoteSrcVMDK() string {
|
||||
file := fmt.Sprintf("%s-src.vmdk", i.BaseClean())
|
||||
return i.toRemotePath(file)
|
||||
}
|
||||
|
||||
func (i importable) RemoteDstVMDK() string {
|
||||
file := fmt.Sprintf("%s.vmdk", i.BaseClean())
|
||||
return i.toRemotePath(file)
|
||||
}
|
||||
|
||||
func (i importable) toRemotePath(p string) string {
|
||||
if i.remotePath == "" {
|
||||
return p
|
||||
}
|
||||
|
||||
return path.Join(i.remotePath, p)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue