client.go 3.5 KB

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