esxlib/esx/client.go

156 lines
3.2 KiB
Go
Raw Normal View History

2023-06-24 19:57:08 +00:00
package esx
import (
"context"
"fmt"
"regexp"
"esxlib/pkg/sshutil"
"richat/pkg/utils"
"github.com/vmware/govmomi/session/cache"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
)
var diskRegexp = regexp.MustCompile("\\[(.*?)\\] (.*)")
type Option func(c *Client)
type Client struct {
sshAuth *sshutil.Auth
vim *vim25.Client
props *HostProperties
VirtualMachines VirtualMachines
Networks Networks
}
type ClientRef interface {
VIM() *vim25.Client
hostExec(ctx context.Context, cmd string) error
hostProperties() *HostProperties
}
func (c *Client) VIM() *vim25.Client {
return c.vim
}
// hostExec runs a vim command using on the specific ssh host.
// Workaround: if you are running the FREE license of ESX, the power management API is not available to you
// IE: ServerFaultCode: Current license or ESXi version prohibits execution of the requested operation
// so as an alternative you can provide the SSH auth to the server and we do it the gross way
func (c *Client) hostExec(_ context.Context, cmd string) error {
if c.sshAuth == nil {
return fmt.Errorf("unsupported")
}
_, err := sshutil.CombinedOutput(sshutil.Auth{
User: c.sshAuth.User,
Password: c.sshAuth.Password,
Host: c.sshAuth.Host,
}, cmd)
if err != nil {
fmt.Printf("cmd: %s err:%s\n", cmd, err.Error())
return err
}
fmt.Printf("cmd: %s OK\n", cmd)
return nil
}
func (c *Client) hostProperties() *HostProperties {
return c.props
}
func WithSSH(host, user, password string) Option {
return func(c *Client) {
c.sshAuth = &sshutil.Auth{
Host: host,
User: user,
Password: password,
}
}
}
func WithHostProperties(props *HostProperties) Option {
return func(c *Client) {
c.props = props
}
}
func NewClient(ctx context.Context, url string, insecure bool, opts ...Option) (*Client, error) {
// Parse URL from string
u, err := soap.ParseURL(url)
if err != nil {
return nil, err
}
// Share govc's session cache
s := &cache.Session{
URL: u,
Insecure: insecure,
}
c := new(vim25.Client)
err = s.Login(ctx, c, nil)
if err != nil {
return nil, err
}
client := &Client{
vim: c,
props: &DefaultHostProperties,
}
for _, opt := range opts {
opt(client)
}
client.VirtualMachines.ClientRef = client
return client, nil
}
func NewClientFromConfigFile(configFile string) (*Client, error) {
config := &Config{}
err := utils.UnmarshalFromFile(configFile, config)
if err != nil {
return nil, err
}
return NewClientFromConfig(config)
}
func NewClientFromConfig(config *Config) (*Client, error) {
vimURL, err := soap.ParseURL(fmt.Sprintf("https://%s:%s@%s", config.User, config.Password, config.Host))
if err != nil {
return nil, err
}
sessionCache := &cache.Session{
URL: vimURL,
Insecure: true,
}
c := new(vim25.Client)
err = sessionCache.Login(context.Background(), c, nil)
if err != nil {
return nil, err
}
client := &Client{
vim: c,
sshAuth: &sshutil.Auth{
Host: fmt.Sprintf("%s:22", config.Host),
User: config.User,
Password: config.Password,
},
props: &config.HostDefaults,
}
client.VirtualMachines.ClientRef = client
client.Networks.ClientRef = client
return client, nil
}