*: Bump version of vmware/govmomi

Bumping version to include changes that
better handle TLS errors. Bump nescessary
to prepare for when the version of Go is
bumped to 1.20

Signed-off-by: Madhav Jivrajani <madhav.jiv@gmail.com>
This commit is contained in:
Madhav Jivrajani
2023-01-02 20:56:02 +05:30
parent 45df8f0bb3
commit 8b064fa4be
263 changed files with 32336 additions and 4373 deletions

View File

@@ -0,0 +1,102 @@
/*
Copyright (c) 2014-2022 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 internal
import (
"fmt"
"sync"
)
// SharedLockingContext is used to identify when locks can be shared. In
// practice, simulator code uses the simulator.Context for a request, but in
// principle this could be anything.
type SharedLockingContext interface{}
// ObjectLock implements a basic "reference-counted" mutex, where a single
// SharedLockingContext can "share" the lock across code paths or child tasks.
type ObjectLock struct {
lock sync.Locker
stateLock sync.Mutex
heldBy SharedLockingContext
count int64
}
// NewObjectLock creates a new ObjectLock. Pass new(sync.Mutex) if you don't
// have a custom sync.Locker.
func NewObjectLock(lock sync.Locker) *ObjectLock {
return &ObjectLock{
lock: lock,
}
}
// try returns true if the lock has been acquired; false otherwise
func (l *ObjectLock) try(onBehalfOf SharedLockingContext) bool {
l.stateLock.Lock()
defer l.stateLock.Unlock()
if l.heldBy == onBehalfOf {
l.count = l.count + 1
return true
}
if l.heldBy == nil {
// we expect no contention for this lock (unless the object has a custom Locker)
l.lock.Lock()
l.count = 1
l.heldBy = onBehalfOf
return true
}
return false
}
// wait returns when there's a chance that try() might succeed.
// It is intended to be better than busy-waiting or sleeping.
func (l *ObjectLock) wait() {
l.lock.Lock()
l.lock.Unlock()
}
// Release decrements the reference count. The caller should pass their
// context, which is used to sanity check that the Unlock() call is valid. If
// this is the last reference to the lock for this SharedLockingContext, the lock
// is Unlocked and can be acquired by another SharedLockingContext.
func (l *ObjectLock) Release(onBehalfOf SharedLockingContext) {
l.stateLock.Lock()
defer l.stateLock.Unlock()
if l.heldBy != onBehalfOf {
panic(fmt.Sprintf("Attempt to unlock on behalf of %#v, but is held by %#v", onBehalfOf, l.heldBy))
}
l.count = l.count - 1
if l.count == 0 {
l.heldBy = nil
l.lock.Unlock()
}
}
// Acquire blocks until it can acquire the lock for onBehalfOf
func (l *ObjectLock) Acquire(onBehalfOf SharedLockingContext) {
acquired := false
for !acquired {
if l.try(onBehalfOf) {
return
} else {
l.wait()
}
}
}

View File

@@ -0,0 +1,353 @@
/*
Copyright (c) 2014-2022 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 internal
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"net"
"net/http"
"strings"
"sync"
"time"
)
// A Server is an HTTP server listening on a system-chosen port on the
// local loopback interface, for use in end-to-end HTTP tests.
type Server struct {
URL string // base URL of form http://ipaddr:port with no trailing slash
Listener net.Listener
// TLS is the optional TLS configuration, populated with a new config
// after TLS is started. If set on an unstarted server before StartTLS
// is called, existing fields are copied into the new config.
TLS *tls.Config
// Config may be changed after calling NewUnstartedServer and
// before Start or StartTLS.
Config *http.Server
// certificate is a parsed version of the TLS config certificate, if present.
certificate *x509.Certificate
// wg counts the number of outstanding HTTP requests on this server.
// Close blocks until all requests are finished.
wg sync.WaitGroup
mu sync.Mutex // guards closed and conns
closed bool
conns map[net.Conn]http.ConnState // except terminal states
// client is configured for use with the server.
// Its transport is automatically closed when Close is called.
client *http.Client
}
func newLocalListener(serve string) net.Listener {
if serve != "" {
l, err := net.Listen("tcp", serve)
if err != nil {
panic(fmt.Sprintf("httptest: failed to listen on %v: %v", serve, err))
}
return l
}
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
}
}
return l
}
// NewServer starts and returns a new Server.
// The caller should call Close when finished, to shut it down.
func NewServer(handler http.Handler) *Server {
ts := NewUnstartedServer(handler, "")
ts.Start()
return ts
}
// NewUnstartedServer returns a new Server but doesn't start it.
//
// After changing its configuration, the caller should call Start or
// StartTLS.
//
// The caller should call Close when finished, to shut it down.
// serve allows the server's listen address to be specified.
func NewUnstartedServer(handler http.Handler, serve string) *Server {
return &Server{
Listener: newLocalListener(serve),
Config: &http.Server{Handler: handler},
}
}
// Start starts a server from NewUnstartedServer.
func (s *Server) Start() {
if s.URL != "" {
panic("Server already started")
}
if s.client == nil {
s.client = &http.Client{Transport: &http.Transport{}}
}
s.URL = "http://" + s.Listener.Addr().String()
s.wrap()
s.goServe()
}
// StartTLS starts TLS on a server from NewUnstartedServer.
func (s *Server) StartTLS() {
if s.URL != "" {
panic("Server already started")
}
if s.client == nil {
s.client = &http.Client{Transport: &http.Transport{}}
}
cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey)
if err != nil {
panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
}
existingConfig := s.TLS
if existingConfig != nil {
s.TLS = existingConfig.Clone()
} else {
s.TLS = new(tls.Config)
}
if s.TLS.NextProtos == nil {
s.TLS.NextProtos = []string{"http/1.1"}
}
if len(s.TLS.Certificates) == 0 {
s.TLS.Certificates = []tls.Certificate{cert}
}
s.certificate, err = x509.ParseCertificate(s.TLS.Certificates[0].Certificate[0])
if err != nil {
panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
}
certpool := x509.NewCertPool()
certpool.AddCert(s.certificate)
s.client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certpool,
},
}
s.Listener = tls.NewListener(s.Listener, s.TLS)
s.URL = "https://" + s.Listener.Addr().String()
s.wrap()
s.goServe()
}
// NewTLSServer starts and returns a new Server using TLS.
// The caller should call Close when finished, to shut it down.
func NewTLSServer(handler http.Handler) *Server {
ts := NewUnstartedServer(handler, "")
ts.StartTLS()
return ts
}
type closeIdleTransport interface {
CloseIdleConnections()
}
// Close shuts down the server and blocks until all outstanding
// requests on this server have completed.
func (s *Server) Close() {
s.mu.Lock()
if !s.closed {
s.closed = true
s.Listener.Close()
s.Config.SetKeepAlivesEnabled(false)
for c, st := range s.conns {
// Force-close any idle connections (those between
// requests) and new connections (those which connected
// but never sent a request). StateNew connections are
// super rare and have only been seen (in
// previously-flaky tests) in the case of
// socket-late-binding races from the http Client
// dialing this server and then getting an idle
// connection before the dial completed. There is thus
// a connected connection in StateNew with no
// associated Request. We only close StateIdle and
// StateNew because they're not doing anything. It's
// possible StateNew is about to do something in a few
// milliseconds, but a previous CL to check again in a
// few milliseconds wasn't liked (early versions of
// https://golang.org/cl/15151) so now we just
// forcefully close StateNew. The docs for Server.Close say
// we wait for "outstanding requests", so we don't close things
// in StateActive.
if st == http.StateIdle || st == http.StateNew {
s.closeConn(c)
}
}
// If this server doesn't shut down in 5 seconds, tell the user why.
t := time.AfterFunc(5*time.Second, s.logCloseHangDebugInfo)
defer t.Stop()
}
s.mu.Unlock()
// Not part of httptest.Server's correctness, but assume most
// users of httptest.Server will be using the standard
// transport, so help them out and close any idle connections for them.
if t, ok := http.DefaultTransport.(closeIdleTransport); ok {
t.CloseIdleConnections()
}
// Also close the client idle connections.
if s.client != nil {
if t, ok := s.client.Transport.(closeIdleTransport); ok {
t.CloseIdleConnections()
}
}
s.wg.Wait()
}
func (s *Server) logCloseHangDebugInfo() {
s.mu.Lock()
defer s.mu.Unlock()
var buf strings.Builder
buf.WriteString("httptest.Server blocked in Close after 5 seconds, waiting for connections:\n")
for c, st := range s.conns {
fmt.Fprintf(&buf, " %T %p %v in state %v\n", c, c, c.RemoteAddr(), st)
}
log.Print(buf.String())
}
// CloseClientConnections closes any open HTTP connections to the test Server.
func (s *Server) CloseClientConnections() {
s.mu.Lock()
nconn := len(s.conns)
ch := make(chan struct{}, nconn)
for c := range s.conns {
go s.closeConnChan(c, ch)
}
s.mu.Unlock()
// Wait for outstanding closes to finish.
//
// Out of paranoia for making a late change in Go 1.6, we
// bound how long this can wait, since golang.org/issue/14291
// isn't fully understood yet. At least this should only be used
// in tests.
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
for i := 0; i < nconn; i++ {
select {
case <-ch:
case <-timer.C:
// Too slow. Give up.
return
}
}
}
// Certificate returns the certificate used by the server, or nil if
// the server doesn't use TLS.
func (s *Server) Certificate() *x509.Certificate {
return s.certificate
}
// Client returns an HTTP client configured for making requests to the server.
// It is configured to trust the server's TLS test certificate and will
// close its idle connections on Server.Close.
func (s *Server) Client() *http.Client {
return s.client
}
func (s *Server) goServe() {
s.wg.Add(1)
go func() {
defer s.wg.Done()
s.Config.Serve(s.Listener)
}()
}
// wrap installs the connection state-tracking hook to know which
// connections are idle.
func (s *Server) wrap() {
oldHook := s.Config.ConnState
s.Config.ConnState = func(c net.Conn, cs http.ConnState) {
s.mu.Lock()
defer s.mu.Unlock()
switch cs {
case http.StateNew:
s.wg.Add(1)
if _, exists := s.conns[c]; exists {
panic("invalid state transition")
}
if s.conns == nil {
s.conns = make(map[net.Conn]http.ConnState)
}
s.conns[c] = cs
if s.closed {
// Probably just a socket-late-binding dial from
// the default transport that lost the race (and
// thus this connection is now idle and will
// never be used).
s.closeConn(c)
}
case http.StateActive:
if oldState, ok := s.conns[c]; ok {
if oldState != http.StateNew && oldState != http.StateIdle {
panic("invalid state transition")
}
s.conns[c] = cs
}
case http.StateIdle:
if oldState, ok := s.conns[c]; ok {
if oldState != http.StateActive {
panic("invalid state transition")
}
s.conns[c] = cs
}
if s.closed {
s.closeConn(c)
}
case http.StateHijacked, http.StateClosed:
s.forgetConn(c)
}
if oldHook != nil {
oldHook(c, cs)
}
}
}
// closeConn closes c.
// s.mu must be held.
func (s *Server) closeConn(c net.Conn) { s.closeConnChan(c, nil) }
// closeConnChan is like closeConn, but takes an optional channel to receive a value
// when the goroutine closing c is done.
func (s *Server) closeConnChan(c net.Conn, done chan<- struct{}) {
c.Close()
if done != nil {
done <- struct{}{}
}
}
// forgetConn removes c from the set of tracked conns and decrements it from the
// waitgroup, unless it was previously removed.
// s.mu must be held.
func (s *Server) forgetConn(c net.Conn) {
if _, ok := s.conns[c]; ok {
delete(s.conns, c)
s.wg.Done()
}
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2014-2022 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 internal
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
//
// Please note the certificate was updated to 2048 bits due to macOS now
// requiring RSA keys of at least 2048 bits. For more information, please see:
// https://developer.apple.com/documentation/security/preventing_insecure_network_connections
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIIDOjCCAiKgAwIBAgIRAK6d/JpGL75P2wOSYc6WalEwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAK9lInM4OAKI4z+wDNkvcZC6S6exFSOysp7NPJyaEAhW93kPY7gO
f6H5aP3V3YU0vYpCSnz/UhyDD+/knBof1J3Do7FVwYtC293vrtXffNtAvygfJodW
1dPllp17ZJbq76ei9oWq1Y5Hox/sVYmNVNztvBfK1mtpS8z8Qrk1LWCyLiDHkvDA
hCy2OjuaopxC6qQejdWT1PxwbqptuLVakQmecpiFrupy8DTG0x0rxxdMdAATywhY
Gm49A/FroagZ6HMz3bm39we/w6VIx3pX1lbUUyrfjvBgfUlRwxyZABBj2STGsOQJ
a451eEcESXcSEWzjGjUQ1Wf+zzxr2GAHmI8CAwEAAaOBiDCBhTAOBgNVHQ8BAf8E
BAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUjtR2VSuxchTxe0UNDVqWDNMR37AwLgYDVR0RBCcwJYILZXhhbXBsZS5j
b22HBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQADggEBACK7
1L15IeYPiQHFDml3EgDoRnd/tAaZP9nUZIIPLRgUnQITNAtjFgBvqneQZwlQtco2
s8YXSivBQiATlBEtGBzVxv36R4tTXldIgJxaCUxxZtqALLwyGqSaI/cwE0pWa6Z0
Op2wkzUmoQ5rRrJfRM+C6HR/+lWkNtHRzaUFOSlxNJbPo53K53OoDriwEc1PvEYP
wFeUXwTzCZ68pAlWUmDKCyp+lPhjIt2Gznig+BSPCNJqmwKM76oFyywi3HIP56rD
/cwUtoplF68uVuD8HXb1ggGsqtGiAT4GLT8tU5w+BtK8ZIs/LK7mdi7W8aIOhUUH
l1lgeV3oEQue3A7SogA=
-----END CERTIFICATE-----`)
// LocalhostKey is the private key for localhostCert.
var LocalhostKey = []byte(`-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvZSJzODgCiOM/
sAzZL3GQukunsRUjsrKezTycmhAIVvd5D2O4Dn+h+Wj91d2FNL2KQkp8/1Icgw/v
5JwaH9Sdw6OxVcGLQtvd767V33zbQL8oHyaHVtXT5Zade2SW6u+novaFqtWOR6Mf
7FWJjVTc7bwXytZraUvM/EK5NS1gsi4gx5LwwIQstjo7mqKcQuqkHo3Vk9T8cG6q
bbi1WpEJnnKYha7qcvA0xtMdK8cXTHQAE8sIWBpuPQPxa6GoGehzM925t/cHv8Ol
SMd6V9ZW1FMq347wYH1JUcMcmQAQY9kkxrDkCWuOdXhHBEl3EhFs4xo1ENVn/s88
a9hgB5iPAgMBAAECggEAEpeS3knQThx6kk60HfWUgTXuPRldV0pi+shgq2z9VBT7
6J5EAMewqdfJVFbuQ2eCy/wY70UVTCZscw51qaNEI3EQkgS4Hm345n64tr0Y/BjR
6ovaxq/ivLJyk8D3ubOvscJphWPFfW6EkSa5LnqHy197972tmvcvbMw0unMzmzM7
DenXdoIJQu1SqLiLUiDXEfkvCReekqhe1jATCwTzIBTCnTWxgI4Ox2qsBaxuwrnl
D1GpWy4sh8NpDB0EBwdrjAOmLDOyvsy2X65DIlHS/k7901tvzyNjRrsr2Ig0sAz4
w0ke6CUKQ2B+Pqn3p6bvxRYMP08+ZjlQpPuU4RrxGQKBgQDd3HCrZCgUJAGcfzYX
ZzSmSoxB9+sEuVUZGU+ICMPlG0Dd8aEkXIyDjGMWsLFMIvzNBf4wB1FwdLaCJu6y
0PbX3KVfg/Yc4lvYUuQ+1nD/3gm2hE46lZuSfbmExH5SQVLSbSQf9S/5BTHAWQO9
PNie71AZ8fO5YDBM18tq2V7dBQKBgQDKYk1+Zup5p0BeRyCNnVYnpngO+pAZZmld
gYiRn8095QJ/Y+yV0kYc2+0+5f6St462E+PVH3tX1l9OG3ujVQnWfu2iSsRJRMUf
0blxqTWvqdcGi8SLpVjkrHn30scFNWmojhJv3k42H3nUMC1+WU3rp2f7+W58afyd
NY9x4sqzgwKBgQCoeMq9+3JLyQPIOPl0UBS06gsT1RUMI0gxpPy1yiInich6QRAi
snypMCPWiRo5PKBHd/OLuSLoiFhHARVliDTJum2B2I09Zc5kuJ1F8kUgpxUtGc7l
wdG/LeWAok1iXORtkh9KfT+Ok5kx/OZP/zJnjkZ/TTHMZPSIhZ2cZ7AXmQKBgHMP
HjWNtyKApsSytVwtpgyWxMznQMNgCOkjOoxoCJx2tUvNeHTY/glsM14+DdRFzTnQ
5weEhXAzrS1PzKPYNeafdOR+k0eAdH2Zk09+PspmyZusHIqz72zabeEqEQHyEubE
FtFI1rhIfs/WsBaUGQuvuhtz/I95BiguiiXaJRmXAoGADwcO6YXoWXga07gGRwZP
LYKwt5wBh13LAGbSsUyCSK5FG6ZrTmzaFdAGV1U4wc/wgiIgv33m8BG4Ikxvpa0r
Wg3dbhBx9Oya8QWIMBPk72KKEzsSDfi+Cn52ZmxTkWbBDCnkRhG77Ooi8vJ3dhq4
fHeAu1F9OwF83SBi1oNySd8=
-----END PRIVATE KEY-----`)

View File

@@ -0,0 +1,73 @@
/*
Copyright (c) 2014-2022 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 internal
import (
"reflect"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
)
// Minimal set of internal types and methods:
// - Fetch() - used by ovftool to collect various managed object properties
// - RetrieveInternalContent() - used by ovftool to obtain a reference to NfcService (which it does not use by default)
func init() {
types.Add("Fetch", reflect.TypeOf((*Fetch)(nil)).Elem())
}
type Fetch struct {
This types.ManagedObjectReference `xml:"_this"`
Prop string `xml:"prop"`
}
type FetchResponse struct {
Returnval types.AnyType `xml:"returnval,omitempty,typeattr"`
}
type FetchBody struct {
Res *FetchResponse `xml:"FetchResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *FetchBody) Fault() *soap.Fault { return b.Fault_ }
func init() {
types.Add("RetrieveInternalContent", reflect.TypeOf((*RetrieveInternalContent)(nil)).Elem())
}
type RetrieveInternalContent struct {
This types.ManagedObjectReference `xml:"_this"`
}
type RetrieveInternalContentResponse struct {
Returnval InternalServiceInstanceContent `xml:"returnval"`
}
type RetrieveInternalContentBody struct {
Res *RetrieveInternalContentResponse `xml:"RetrieveInternalContentResponse,omitempty"`
Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
}
func (b *RetrieveInternalContentBody) Fault() *soap.Fault { return b.Fault_ }
type InternalServiceInstanceContent struct {
types.DynamicData
NfcService types.ManagedObjectReference `xml:"nfcService"`
}