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
|
2023-09-02 17:53:56 +00:00
|
|
|
session *cache.Session
|
2023-06-24 19:57:08 +00:00
|
|
|
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 {
|
2023-09-02 17:53:56 +00:00
|
|
|
vim := new(vim25.Client)
|
|
|
|
|
|
|
|
err := c.session.Login(context.Background(), vim, nil)
|
|
|
|
if err != nil {
|
|
|
|
return vim
|
|
|
|
}
|
|
|
|
|
|
|
|
return vim
|
2023-06-24 19:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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{
|
2023-09-02 17:53:56 +00:00
|
|
|
session: s,
|
|
|
|
props: &DefaultHostProperties,
|
2023-06-24 19:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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{
|
2023-09-02 17:53:56 +00:00
|
|
|
session: sessionCache,
|
2023-06-24 19:57:08 +00:00
|
|
|
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
|
|
|
|
}
|