// © Broadcom. All Rights Reserved. // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. // SPDX-License-Identifier: Apache-2.0 package vim25 import ( "context" "encoding/json" "strings" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" ) const ( Namespace = "vim25" Version = "9.0.0.0" Path = "/sdk" ) var ( ServiceInstance = types.ManagedObjectReference{ Type: "ServiceInstance", Value: "ServiceInstance", } ) // Client is a tiny wrapper around the vim25/soap Client that stores session // specific state (i.e. state that only needs to be retrieved once after the // client has been created). This means the client can be reused after // serialization without performing additional requests for initialization. type Client struct { *soap.Client ServiceContent types.ServiceContent // RoundTripper is a separate field such that the client's implementation of // the RoundTripper interface can be wrapped by separate implementations for // extra functionality (for example, reauthentication on session timeout). RoundTripper soap.RoundTripper } // NewClient creates and returns a new client with the ServiceContent field // filled in. func NewClient(ctx context.Context, rt soap.RoundTripper) (*Client, error) { c := Client{ RoundTripper: rt, } // Set client if it happens to be a soap.Client if sc, ok := rt.(*soap.Client); ok { c.Client = sc if c.Namespace == "" { c.Namespace = "urn:" + Namespace } else if !strings.Contains(c.Namespace, ":") { c.Namespace = "urn:" + c.Namespace // ensure valid URI format } if c.Version == "" { c.Version = Version } } var err error c.ServiceContent, err = methods.GetServiceContent(ctx, rt) if err != nil { return nil, err } return &c, nil } // RoundTrip dispatches to the RoundTripper field. func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { return c.RoundTripper.RoundTrip(ctx, req, res) } type marshaledClient struct { SoapClient *soap.Client ServiceContent types.ServiceContent } func (c *Client) MarshalJSON() ([]byte, error) { m := marshaledClient{ SoapClient: c.Client, ServiceContent: c.ServiceContent, } return json.Marshal(m) } func (c *Client) UnmarshalJSON(b []byte) error { var m marshaledClient err := json.Unmarshal(b, &m) if err != nil { return err } *c = Client{ Client: m.SoapClient, ServiceContent: m.ServiceContent, RoundTripper: m.SoapClient, } return nil } // Valid returns whether or not the client is valid and ready for use. // This should be called after unmarshalling the client. func (c *Client) Valid() bool { if c == nil { return false } if c.Client == nil { return false } // Use arbitrary pointer field in the service content. // Doesn't matter which one, as long as it is populated by default. if c.ServiceContent.SessionManager == nil { return false } return true } // Path returns vim25.Path (see cache.Client) func (c *Client) Path() string { return Path } // IsVC returns true if we are connected to a vCenter func (c *Client) IsVC() bool { return c.ServiceContent.About.ApiType == "VirtualCenter" }