github.com/vmware/govmomi@v0.43.0/vim25/client.go (about) 1 /* 2 Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vim25 18 19 import ( 20 "context" 21 "encoding/json" 22 "strings" 23 24 "github.com/vmware/govmomi/vim25/methods" 25 "github.com/vmware/govmomi/vim25/soap" 26 "github.com/vmware/govmomi/vim25/types" 27 ) 28 29 const ( 30 Namespace = "vim25" 31 Version = "8.0.3.0" 32 Path = "/sdk" 33 ) 34 35 var ( 36 ServiceInstance = types.ManagedObjectReference{ 37 Type: "ServiceInstance", 38 Value: "ServiceInstance", 39 } 40 ) 41 42 // Client is a tiny wrapper around the vim25/soap Client that stores session 43 // specific state (i.e. state that only needs to be retrieved once after the 44 // client has been created). This means the client can be reused after 45 // serialization without performing additional requests for initialization. 46 type Client struct { 47 *soap.Client 48 49 ServiceContent types.ServiceContent 50 51 // RoundTripper is a separate field such that the client's implementation of 52 // the RoundTripper interface can be wrapped by separate implementations for 53 // extra functionality (for example, reauthentication on session timeout). 54 RoundTripper soap.RoundTripper 55 } 56 57 // NewClient creates and returns a new client with the ServiceContent field 58 // filled in. 59 func NewClient(ctx context.Context, rt soap.RoundTripper) (*Client, error) { 60 c := Client{ 61 RoundTripper: rt, 62 } 63 64 // Set client if it happens to be a soap.Client 65 if sc, ok := rt.(*soap.Client); ok { 66 c.Client = sc 67 68 if c.Namespace == "" { 69 c.Namespace = "urn:" + Namespace 70 } else if !strings.Contains(c.Namespace, ":") { 71 c.Namespace = "urn:" + c.Namespace // ensure valid URI format 72 } 73 if c.Version == "" { 74 c.Version = Version 75 } 76 } 77 78 var err error 79 c.ServiceContent, err = methods.GetServiceContent(ctx, rt) 80 if err != nil { 81 return nil, err 82 } 83 84 return &c, nil 85 } 86 87 // RoundTrip dispatches to the RoundTripper field. 88 func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { 89 return c.RoundTripper.RoundTrip(ctx, req, res) 90 } 91 92 type marshaledClient struct { 93 SoapClient *soap.Client 94 ServiceContent types.ServiceContent 95 } 96 97 func (c *Client) MarshalJSON() ([]byte, error) { 98 m := marshaledClient{ 99 SoapClient: c.Client, 100 ServiceContent: c.ServiceContent, 101 } 102 103 return json.Marshal(m) 104 } 105 106 func (c *Client) UnmarshalJSON(b []byte) error { 107 var m marshaledClient 108 109 err := json.Unmarshal(b, &m) 110 if err != nil { 111 return err 112 } 113 114 *c = Client{ 115 Client: m.SoapClient, 116 ServiceContent: m.ServiceContent, 117 RoundTripper: m.SoapClient, 118 } 119 120 return nil 121 } 122 123 // Valid returns whether or not the client is valid and ready for use. 124 // This should be called after unmarshalling the client. 125 func (c *Client) Valid() bool { 126 if c == nil { 127 return false 128 } 129 130 if c.Client == nil { 131 return false 132 } 133 134 // Use arbitrary pointer field in the service content. 135 // Doesn't matter which one, as long as it is populated by default. 136 if c.ServiceContent.SessionManager == nil { 137 return false 138 } 139 140 return true 141 } 142 143 // Path returns vim25.Path (see cache.Client) 144 func (c *Client) Path() string { 145 return Path 146 } 147 148 // IsVC returns true if we are connected to a vCenter 149 func (c *Client) IsVC() bool { 150 return c.ServiceContent.About.ApiType == "VirtualCenter" 151 }