HEX
Server: Apache/2.4.54 (Win64) OpenSSL/1.1.1p PHP/7.4.30
System: Windows NT website-api 10.0 build 20348 (Windows Server 2016) AMD64
User: SYSTEM (0)
PHP: 7.4.30
Disabled: NONE
Upload Files
File: C:/github_repos/casibase_customer_0058/pkgmachine/vmware.go
// Copyright 2025 The Casibase Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pkgmachine

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"

	"github.com/casibase/casibase/i18n"
)

type MachineVmwareClient struct {
	hostname     string
	basicAuthKey string
}

type VirtualMachine struct {
	ID     string `json:"id"`
	Cpu    Cpu    `json:"cpu"`
	Memory int    `json:"memory"`
}

type VirtualMachinePath struct {
	ID   string `json:"id"`
	Path string `json:"path"`
}

type Cpu struct {
	Processors int `json:"processors"`
}

// hostname is the IP address of the target host and the configured port format is {IP}:{port}
// basicAuthKey is the credential for VMware Workstation Pro REST service, in the form of {username}:{password}
func newMachineVmwareClient(hostname string, basicAuthKey string) (*MachineVmwareClient, error) {
	client := MachineVmwareClient{
		hostname,
		basicAuthKey,
	}
	return &client, nil
}

func (client MachineVmwareClient) sendRequest(method, path string, lang string) ([]byte, error) {
	url := fmt.Sprintf("http://%s/api%s", client.hostname, path)
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Accept", "application/vnd.vmware.vmw.rest-v1+json")
	encodedAuth := base64.StdEncoding.EncodeToString([]byte(client.basicAuthKey))
	req.Header.Add("Authorization", "Basic "+encodedAuth)

	c := http.Client{}
	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	type Message struct {
		Code    int    `json:"Code"`
		Message string `json:"Message"`
	}
	var message Message
	err = json.Unmarshal(body, &message)
	if err == nil {
		if message.Code == 100 {
			return nil, nil
		} else if message.Code != 0 {
			return nil, fmt.Errorf(i18n.Translate(lang, "pkgmachine:VMware API error, code = %d, message = %s"), message.Code, message.Message)
		}
	}

	return body, nil
}

func (client MachineVmwareClient) GetMachines(lang string) ([]*Machine, error) {
	body, err := client.sendRequest("GET", "/vms", lang)
	if err != nil {
		return nil, err
	}

	var vmList []VirtualMachinePath
	err = json.Unmarshal(body, &vmList)
	if err != nil {
		return nil, err
	}

	machines := []*Machine{}
	var wg sync.WaitGroup
	var mu sync.Mutex
	errChan := make(chan error, len(vmList))
	for _, vm := range vmList {
		wg.Add(1)
		go func(vm VirtualMachinePath) {
			defer wg.Done()
			machine, err2 := client.GetMachine(vm.ID, lang)
			if err2 != nil {
				errChan <- err2
				return
			}

			mu.Lock()
			machines = append(machines, machine)
			mu.Unlock()
		}(vm)
	}

	wg.Wait()
	close(errChan)
	for err := range errChan {
		return nil, err
	}

	return machines, nil
}

func (client MachineVmwareClient) GetMachine(name string, lang string) (*Machine, error) {
	body, err := client.sendRequest("GET", fmt.Sprintf("/vms/%s", name), lang)
	if err != nil {
		return nil, err
	}
	if body == nil {
		return nil, nil
	}

	var vm VirtualMachine
	err = json.Unmarshal(body, &vm)
	if err != nil {
		return nil, err
	}

	machine := &Machine{
		Name:    name,
		Id:      vm.ID,
		CpuSize: fmt.Sprintf("%d", vm.Cpu.Processors),
		MemSize: fmt.Sprintf("%d", vm.Memory),
	}
	return machine, nil
}

func (client MachineVmwareClient) UpdateMachineState(name string, state string, lang string) (bool, string, error) {
	return false, "", fmt.Errorf(i18n.Translate(lang, "pkgmachine:Not implemented"))
}