vSphere Cloud Provider: update vmware/gomvomi godeps
This commit is contained in:
184
vendor/github.com/vmware/govmomi/simulator/simulator.go
generated
vendored
184
vendor/github.com/vmware/govmomi/simulator/simulator.go
generated
vendored
@@ -21,6 +21,7 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
@@ -35,6 +37,7 @@ import (
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/find"
|
||||
@@ -51,15 +54,17 @@ var Trace = false
|
||||
|
||||
// Method encapsulates a decoded SOAP client request
|
||||
type Method struct {
|
||||
Name string
|
||||
This types.ManagedObjectReference
|
||||
Body types.AnyType
|
||||
Name string
|
||||
This types.ManagedObjectReference
|
||||
Header soap.Header
|
||||
Body types.AnyType
|
||||
}
|
||||
|
||||
// Service decodes incoming requests and dispatches to a Handler
|
||||
type Service struct {
|
||||
client *vim25.Client
|
||||
sm *SessionManager
|
||||
sdk map[string]*Registry
|
||||
|
||||
readAll func(io.Reader) ([]byte, error)
|
||||
|
||||
@@ -70,7 +75,8 @@ type Service struct {
|
||||
// Server provides a simulator Service over HTTP
|
||||
type Server struct {
|
||||
*httptest.Server
|
||||
URL *url.URL
|
||||
URL *url.URL
|
||||
Tunnel int
|
||||
|
||||
caFile string
|
||||
}
|
||||
@@ -80,6 +86,7 @@ func New(instance *ServiceInstance) *Service {
|
||||
s := &Service{
|
||||
readAll: ioutil.ReadAll,
|
||||
sm: Map.SessionManager(),
|
||||
sdk: make(map[string]*Registry),
|
||||
}
|
||||
|
||||
s.client, _ = vim25.NewClient(context.Background(), s)
|
||||
@@ -110,12 +117,12 @@ func Fault(msg string, fault types.BaseMethodFault) *soap.Fault {
|
||||
}
|
||||
|
||||
func (s *Service) call(ctx *Context, method *Method) soap.HasFault {
|
||||
handler := Map.Get(method.This)
|
||||
handler := ctx.Map.Get(method.This)
|
||||
session := ctx.Session
|
||||
|
||||
if session == nil {
|
||||
switch method.Name {
|
||||
case "RetrieveServiceContent", "Login", "RetrieveProperties", "RetrievePropertiesEx", "CloneSession":
|
||||
case "RetrieveServiceContent", "List", "Login", "LoginByToken", "LoginExtensionByCertificate", "RetrieveProperties", "RetrievePropertiesEx", "CloneSession":
|
||||
// ok for now, TODO: authz
|
||||
default:
|
||||
fault := &types.NotAuthenticated{
|
||||
@@ -170,7 +177,7 @@ func (s *Service) call(ctx *Context, method *Method) soap.HasFault {
|
||||
args = append(args, reflect.ValueOf(ctx))
|
||||
}
|
||||
args = append(args, reflect.ValueOf(method.Body))
|
||||
Map.WithLock(handler, func() {
|
||||
ctx.Map.WithLock(handler, func() {
|
||||
res = m.Call(args)
|
||||
})
|
||||
|
||||
@@ -197,6 +204,7 @@ func (s *Service) RoundTrip(ctx context.Context, request, response soap.HasFault
|
||||
}
|
||||
|
||||
res := s.call(&Context{
|
||||
Map: Map,
|
||||
Context: ctx,
|
||||
Session: internalContext.Session,
|
||||
}, method)
|
||||
@@ -281,6 +289,16 @@ func (s *Service) About(w http.ResponseWriter, r *http.Request) {
|
||||
_ = enc.Encode(&about)
|
||||
}
|
||||
|
||||
// RegisterSDK adds an HTTP handler for the Registry's Path and Namespace.
|
||||
func (s *Service) RegisterSDK(r *Registry) {
|
||||
if s.ServeMux == nil {
|
||||
s.ServeMux = http.NewServeMux()
|
||||
}
|
||||
|
||||
s.sdk[r.Path] = r
|
||||
s.ServeMux.HandleFunc(r.Path, s.ServeSDK)
|
||||
}
|
||||
|
||||
// ServeSDK implements the http.Handler interface
|
||||
func (s *Service) ServeSDK(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
@@ -305,17 +323,19 @@ func (s *Service) ServeSDK(w http.ResponseWriter, r *http.Request) {
|
||||
res: w,
|
||||
m: s.sm,
|
||||
|
||||
Map: s.sdk[r.URL.Path],
|
||||
Context: context.Background(),
|
||||
}
|
||||
Map.WithLock(s.sm, ctx.mapSession)
|
||||
ctx.Map.WithLock(s.sm, ctx.mapSession)
|
||||
|
||||
var res soap.HasFault
|
||||
var soapBody interface{}
|
||||
|
||||
method, err := UnmarshalBody(body)
|
||||
method, err := UnmarshalBody(ctx.Map.typeFunc, body)
|
||||
if err != nil {
|
||||
res = serverFault(err.Error())
|
||||
} else {
|
||||
ctx.Header = method.Header
|
||||
res = s.call(ctx, method)
|
||||
}
|
||||
|
||||
@@ -447,15 +467,10 @@ func (*Service) ServiceVersions(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// NewServer returns an http Server instance for the given service
|
||||
func (s *Service) NewServer() *Server {
|
||||
s.RegisterSDK(Map)
|
||||
|
||||
mux := s.ServeMux
|
||||
if mux == nil {
|
||||
mux = http.NewServeMux()
|
||||
}
|
||||
|
||||
path := "/sdk"
|
||||
|
||||
mux.HandleFunc(path, s.ServeSDK)
|
||||
mux.HandleFunc(path+"/vimServiceVersions.xml", s.ServiceVersions)
|
||||
mux.HandleFunc(Map.Path+"/vimServiceVersions.xml", s.ServiceVersions)
|
||||
mux.HandleFunc(folderPrefix, s.ServeDatastore)
|
||||
mux.HandleFunc("/about", s.About)
|
||||
|
||||
@@ -466,7 +481,7 @@ func (s *Service) NewServer() *Server {
|
||||
u := &url.URL{
|
||||
Scheme: "http",
|
||||
Host: ts.Listener.Addr().String(),
|
||||
Path: path,
|
||||
Path: Map.Path,
|
||||
User: url.UserPassword("user", "pass"),
|
||||
}
|
||||
|
||||
@@ -478,14 +493,31 @@ func (s *Service) NewServer() *Server {
|
||||
_ = f.Value.Set("")
|
||||
}
|
||||
|
||||
cert := ""
|
||||
if s.TLS == nil {
|
||||
ts.Start()
|
||||
} else {
|
||||
ts.TLS = s.TLS
|
||||
ts.TLS.ClientAuth = tls.RequestClientCert // Used by SessionManager.LoginExtensionByCertificate
|
||||
ts.StartTLS()
|
||||
u.Scheme += "s"
|
||||
|
||||
cert = base64.StdEncoding.EncodeToString(ts.TLS.Certificates[0].Certificate[0])
|
||||
}
|
||||
|
||||
// Add vcsim config to OptionManager for use by SDK handlers (see lookup/simulator for example)
|
||||
m := Map.OptionManager()
|
||||
m.Setting = append(m.Setting,
|
||||
&types.OptionValue{
|
||||
Key: "vcsim.server.url",
|
||||
Value: ts.URL,
|
||||
},
|
||||
&types.OptionValue{
|
||||
Key: "vcsim.server.cert",
|
||||
Value: cert,
|
||||
},
|
||||
)
|
||||
|
||||
return &Server{
|
||||
Server: ts,
|
||||
URL: u,
|
||||
@@ -525,6 +557,60 @@ func (s *Server) CertificateFile() (string, error) {
|
||||
return s.caFile, pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
|
||||
}
|
||||
|
||||
// proxy tunnels SDK requests
|
||||
func (s *Server) proxy(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodConnect {
|
||||
http.Error(w, "", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
dst, err := net.Dial("tcp", s.URL.Host)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
src, _, err := w.(http.Hijacker).Hijack()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
go io.Copy(src, dst)
|
||||
go func() {
|
||||
_, _ = io.Copy(dst, src)
|
||||
_ = dst.Close()
|
||||
_ = src.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// StartTunnel runs an HTTP proxy for tunneling SDK requests that require TLS client certificate authentication.
|
||||
func (s *Server) StartTunnel() error {
|
||||
tunnel := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", s.URL.Hostname(), s.Tunnel),
|
||||
Handler: http.HandlerFunc(s.proxy),
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", tunnel.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.Tunnel == 0 {
|
||||
s.Tunnel = l.Addr().(*net.TCPAddr).Port
|
||||
}
|
||||
|
||||
// Set client proxy port (defaults to vCenter host port 80 in real life)
|
||||
q := s.URL.Query()
|
||||
q.Set("GOVMOMI_TUNNEL_PROXY_PORT", strconv.Itoa(s.Tunnel))
|
||||
s.URL.RawQuery = q.Encode()
|
||||
|
||||
go tunnel.Serve(l)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close shuts down the server and blocks until all outstanding
|
||||
// requests on this server have completed.
|
||||
func (s *Server) Close() {
|
||||
@@ -536,7 +622,6 @@ func (s *Server) Close() {
|
||||
|
||||
var (
|
||||
vim25MapType = types.TypeFunc()
|
||||
typeFunc = defaultMapType
|
||||
)
|
||||
|
||||
func defaultMapType(name string) (reflect.Type, bool) {
|
||||
@@ -552,14 +637,39 @@ func defaultMapType(name string) (reflect.Type, bool) {
|
||||
return typ, ok
|
||||
}
|
||||
|
||||
// UnmarshalBody extracts the Body from a soap.Envelope and unmarshals to the corresponding govmomi type
|
||||
func UnmarshalBody(data []byte) (*Method, error) {
|
||||
body := struct {
|
||||
// Element can be used to defer decoding of an XML node.
|
||||
type Element struct {
|
||||
start xml.StartElement
|
||||
inner struct {
|
||||
Content string `xml:",innerxml"`
|
||||
}{}
|
||||
}
|
||||
typeFunc func(string) (reflect.Type, bool)
|
||||
}
|
||||
|
||||
func (e *Element) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
e.start = start
|
||||
|
||||
return d.DecodeElement(&e.inner, &start)
|
||||
}
|
||||
|
||||
func (e *Element) decoder() *xml.Decoder {
|
||||
decoder := xml.NewDecoder(strings.NewReader(e.inner.Content))
|
||||
decoder.TypeFunc = e.typeFunc // required to decode interface types
|
||||
return decoder
|
||||
}
|
||||
|
||||
func (e *Element) Decode(val interface{}) error {
|
||||
return e.decoder().DecodeElement(val, &e.start)
|
||||
}
|
||||
|
||||
// UnmarshalBody extracts the Body from a soap.Envelope and unmarshals to the corresponding govmomi type
|
||||
func UnmarshalBody(typeFunc func(string) (reflect.Type, bool), data []byte) (*Method, error) {
|
||||
body := &Element{typeFunc: typeFunc}
|
||||
req := soap.Envelope{
|
||||
Body: &body,
|
||||
Header: &soap.Header{
|
||||
Security: new(Element),
|
||||
},
|
||||
Body: body,
|
||||
}
|
||||
|
||||
err := xml.Unmarshal(data, &req)
|
||||
@@ -567,40 +677,38 @@ func UnmarshalBody(data []byte) (*Method, error) {
|
||||
return nil, fmt.Errorf("xml.Unmarshal: %s", err)
|
||||
}
|
||||
|
||||
decoder := xml.NewDecoder(bytes.NewReader([]byte(body.Content)))
|
||||
decoder.TypeFunc = typeFunc // required to decode interface types
|
||||
|
||||
var start *xml.StartElement
|
||||
var start xml.StartElement
|
||||
var ok bool
|
||||
decoder := body.decoder()
|
||||
|
||||
for {
|
||||
tok, derr := decoder.Token()
|
||||
if derr != nil {
|
||||
return nil, fmt.Errorf("decoding body: %s", err)
|
||||
return nil, fmt.Errorf("decoding: %s", derr)
|
||||
}
|
||||
if t, ok := tok.(xml.StartElement); ok {
|
||||
start = &t
|
||||
if start, ok = tok.(xml.StartElement); ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
kind := start.Name.Local
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("decoding: method token not found")
|
||||
}
|
||||
|
||||
kind := start.Name.Local
|
||||
rtype, ok := typeFunc(kind)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no vmomi type defined for '%s'", kind)
|
||||
}
|
||||
|
||||
var val interface{}
|
||||
if rtype != nil {
|
||||
val = reflect.New(rtype).Interface()
|
||||
}
|
||||
val := reflect.New(rtype).Interface()
|
||||
|
||||
err = decoder.DecodeElement(val, start)
|
||||
err = decoder.DecodeElement(val, &start)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decoding %s: %s", kind, err)
|
||||
}
|
||||
|
||||
method := &Method{Name: kind, Body: val}
|
||||
method := &Method{Name: kind, Header: *req.Header, Body: val}
|
||||
|
||||
field := reflect.ValueOf(val).Elem().FieldByName("This")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user