github.com/netdata/go.d.plugin@v0.58.1/modules/vsphere/client/client.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package client 4 5 import ( 6 "context" 7 "net/http" 8 "net/url" 9 "time" 10 11 "github.com/netdata/go.d.plugin/pkg/tlscfg" 12 13 "github.com/vmware/govmomi" 14 "github.com/vmware/govmomi/performance" 15 "github.com/vmware/govmomi/session" 16 "github.com/vmware/govmomi/view" 17 "github.com/vmware/govmomi/vim25" 18 "github.com/vmware/govmomi/vim25/mo" 19 "github.com/vmware/govmomi/vim25/soap" 20 "github.com/vmware/govmomi/vim25/types" 21 ) 22 23 const ( 24 datacenter = "Datacenter" 25 folder = "Folder" 26 computeResource = "ComputeResource" 27 hostSystem = "HostSystem" 28 virtualMachine = "VirtualMachine" 29 30 maxIdleConnections = 32 31 ) 32 33 type Config struct { 34 URL string 35 User string 36 Password string 37 tlscfg.TLSConfig 38 Timeout time.Duration 39 } 40 41 type Client struct { 42 client *govmomi.Client 43 root *view.ContainerView 44 perf *performance.Manager 45 } 46 47 func newSoapClient(config Config) (*soap.Client, error) { 48 soapURL, err := soap.ParseURL(config.URL) 49 if err != nil || soapURL == nil { 50 return nil, err 51 } 52 soapURL.User = url.UserPassword(config.User, config.Password) 53 soapClient := soap.NewClient(soapURL, config.TLSConfig.InsecureSkipVerify) 54 55 tlsConfig, err := tlscfg.NewTLSConfig(config.TLSConfig) 56 if err != nil { 57 return nil, err 58 } 59 if tlsConfig != nil && len(tlsConfig.Certificates) > 0 { 60 soapClient.SetCertificate(tlsConfig.Certificates[0]) 61 } 62 if config.TLSConfig.TLSCA != "" { 63 if err := soapClient.SetRootCAs(config.TLSConfig.TLSCA); err != nil { 64 return nil, err 65 } 66 } 67 68 if t, ok := soapClient.Transport.(*http.Transport); ok { 69 t.MaxIdleConnsPerHost = maxIdleConnections 70 t.TLSHandshakeTimeout = config.Timeout 71 } 72 soapClient.Timeout = config.Timeout 73 74 return soapClient, nil 75 } 76 77 func newContainerView(ctx context.Context, client *govmomi.Client) (*view.ContainerView, error) { 78 viewManager := view.NewManager(client.Client) 79 return viewManager.CreateContainerView(ctx, client.ServiceContent.RootFolder, []string{}, true) 80 } 81 82 func newPerformanceManager(client *vim25.Client) *performance.Manager { 83 perfManager := performance.NewManager(client) 84 perfManager.Sort = true 85 return perfManager 86 } 87 88 func New(config Config) (*Client, error) { 89 ctx := context.Background() 90 soapClient, err := newSoapClient(config) 91 if err != nil { 92 return nil, err 93 } 94 95 vimClient, err := vim25.NewClient(ctx, soapClient) 96 if err != nil { 97 return nil, err 98 } 99 100 vmomiClient := &govmomi.Client{ 101 Client: vimClient, 102 SessionManager: session.NewManager(vimClient), 103 } 104 105 userInfo := url.UserPassword(config.User, config.Password) 106 addKeepAlive(vmomiClient, userInfo) 107 108 err = vmomiClient.Login(ctx, userInfo) 109 if err != nil { 110 return nil, err 111 } 112 113 containerView, err := newContainerView(ctx, vmomiClient) 114 if err != nil { 115 return nil, err 116 } 117 118 perfManager := newPerformanceManager(vimClient) 119 120 client := &Client{ 121 client: vmomiClient, 122 perf: perfManager, 123 root: containerView, 124 } 125 126 return client, nil 127 } 128 129 func (c *Client) IsSessionActive() (bool, error) { 130 return c.client.SessionManager.SessionIsActive(context.Background()) 131 } 132 133 func (c *Client) Version() string { 134 return c.client.ServiceContent.About.Version 135 } 136 137 func (c *Client) Login(userinfo *url.Userinfo) error { 138 return c.client.Login(context.Background(), userinfo) 139 } 140 141 func (c *Client) Logout() error { 142 return c.client.Logout(context.Background()) 143 } 144 145 func (c *Client) PerformanceMetrics(pqs []types.PerfQuerySpec) ([]performance.EntityMetric, error) { 146 metrics, err := c.perf.Query(context.Background(), pqs) 147 if err != nil { 148 return nil, err 149 } 150 return c.perf.ToMetricSeries(context.Background(), metrics) 151 } 152 153 func (c *Client) Datacenters(pathSet ...string) (dcs []mo.Datacenter, err error) { 154 err = c.root.Retrieve(context.Background(), []string{datacenter}, pathSet, &dcs) 155 return 156 } 157 158 func (c *Client) Folders(pathSet ...string) (folders []mo.Folder, err error) { 159 err = c.root.Retrieve(context.Background(), []string{folder}, pathSet, &folders) 160 return 161 } 162 163 func (c *Client) ComputeResources(pathSet ...string) (computes []mo.ComputeResource, err error) { 164 err = c.root.Retrieve(context.Background(), []string{computeResource}, pathSet, &computes) 165 return 166 } 167 168 func (c *Client) Hosts(pathSet ...string) (hosts []mo.HostSystem, err error) { 169 err = c.root.Retrieve(context.Background(), []string{hostSystem}, pathSet, &hosts) 170 return 171 } 172 173 func (c *Client) VirtualMachines(pathSet ...string) (vms []mo.VirtualMachine, err error) { 174 err = c.root.Retrieve(context.Background(), []string{virtualMachine}, pathSet, &vms) 175 return 176 } 177 178 func (c *Client) CounterInfoByName() (map[string]*types.PerfCounterInfo, error) { 179 return c.perf.CounterInfoByName(context.Background()) 180 }