mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
改进:1. 增加vmware cloud provider driver初步实现 2. 增加vmware vnc信息获取的支持
This commit is contained in:
Generated
+24
-1
@@ -258,6 +258,29 @@
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/vmware/govmomi"
|
||||
packages = [
|
||||
".",
|
||||
"nfc",
|
||||
"object",
|
||||
"property",
|
||||
"session",
|
||||
"task",
|
||||
"view",
|
||||
"vim25",
|
||||
"vim25/debug",
|
||||
"vim25/methods",
|
||||
"vim25/mo",
|
||||
"vim25/progress",
|
||||
"vim25/soap",
|
||||
"vim25/types",
|
||||
"vim25/xml"
|
||||
]
|
||||
revision = "bbd99532a768d2fe369079ceda730e30726ae1a6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/yunionio/jsonutils"
|
||||
packages = ["."]
|
||||
revision = "6dd39f8579af6c6b61b971eb3a1ccf55e724b0ca"
|
||||
@@ -369,6 +392,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "7b33757daccd7b7b9fc876fd74890fc9c7e638b9ee0f68d665559165716eb70d"
|
||||
inputs-digest = "66245a09bfe41c9921a519539ddf9c585a75079e1ed418a90a0f075b0e097805"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
@@ -52,3 +52,8 @@
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/vmware/govmomi"
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
"github.com/yunionio/log"
|
||||
"github.com/yunionio/structarg"
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun/shell"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
|
||||
_ "github.com/yunionio/onecloud/pkg/util/aliyun/shell"
|
||||
)
|
||||
|
||||
type BaseOptions struct {
|
||||
@@ -35,7 +37,7 @@ func getSubcommandParser() (*structarg.ArgumentParser, error) {
|
||||
type HelpOptions struct {
|
||||
SUBCOMMAND string `help:"sub-command name"`
|
||||
}
|
||||
shell.R(&HelpOptions{}, "help", "Show help of a subcommand", func(args *HelpOptions) error {
|
||||
shellutils.R(&HelpOptions{}, "help", "Show help of a subcommand", func(args *HelpOptions) error {
|
||||
helpstr, e := subcmd.SubHelpString(args.SUBCOMMAND)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -44,7 +46,7 @@ func getSubcommandParser() (*structarg.ArgumentParser, error) {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
for _, v := range shell.CommandTable {
|
||||
for _, v := range shellutils.CommandTable {
|
||||
_, e := subcmd.AddSubParser(v.Options, v.Command, v.Desc, v.Callback)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
|
||||
@@ -4,17 +4,17 @@ import (
|
||||
"github.com/yunionio/jsonutils"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/mcclient/modules"
|
||||
"github.com/yunionio/onecloud/pkg/util/printjson"
|
||||
"github.com/yunionio/onecloud/pkg/util/printutils"
|
||||
)
|
||||
|
||||
func printList(list *modules.ListResult, columns []string) {
|
||||
printjson.PrintList(list, columns)
|
||||
printutils.PrintJSONList(list, columns)
|
||||
}
|
||||
|
||||
func printObject(obj jsonutils.JSONObject) {
|
||||
printjson.PrintObject(obj)
|
||||
printutils.PrintJSONObject(obj)
|
||||
}
|
||||
|
||||
func printBatchResults(results []modules.SubmitResult, columns []string) {
|
||||
printjson.PrintBatchResults(results, columns)
|
||||
printutils.PrintJSONBatchResults(results, columns)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yunionio/log"
|
||||
"github.com/yunionio/structarg"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/util/esxi"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
|
||||
_ "github.com/yunionio/onecloud/pkg/util/esxi/shell"
|
||||
)
|
||||
|
||||
type BaseOptions struct {
|
||||
Help bool `help:"Show help"`
|
||||
Host string `help:"Host IP or NAME" default:"$VMWARE_HOST"`
|
||||
Port int `help:"Service port" default:"$VMWARE_PORT"`
|
||||
Account string `help:"VCenter or ESXi Account" default:"$VMWARE_ACCOUNT"`
|
||||
Password string `help:"Password" default:"$VMWARE_PASSWORD"`
|
||||
SUBCOMMAND string `help:"aliyuncli subcommand" subcommand:"true"`
|
||||
}
|
||||
|
||||
func getSubcommandParser() (*structarg.ArgumentParser, error) {
|
||||
parse, e := structarg.NewArgumentParser(&BaseOptions{},
|
||||
"govmcli",
|
||||
"Command-line interface to VMware VSphere Webservice API.",
|
||||
`See "govmcli help COMMAND" for help on a specific command.`)
|
||||
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
subcmd := parse.GetSubcommand()
|
||||
if subcmd == nil {
|
||||
return nil, fmt.Errorf("No subcommand argument.")
|
||||
}
|
||||
type HelpOptions struct {
|
||||
SUBCOMMAND string `help:"sub-command name"`
|
||||
}
|
||||
shellutils.R(&HelpOptions{}, "help", "Show help of a subcommand", func(args *HelpOptions) error {
|
||||
helpstr, e := subcmd.SubHelpString(args.SUBCOMMAND)
|
||||
if e != nil {
|
||||
return e
|
||||
} else {
|
||||
fmt.Print(helpstr)
|
||||
return nil
|
||||
}
|
||||
})
|
||||
for _, v := range shellutils.CommandTable {
|
||||
_, e := subcmd.AddSubParser(v.Options, v.Command, v.Desc, v.Callback)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
return parse, nil
|
||||
}
|
||||
|
||||
func showErrorAndExit(e error) {
|
||||
log.Errorf("%s", e)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func newClient(options *BaseOptions) (*esxi.SESXiClient, error) {
|
||||
if len(options.Host) == 0 {
|
||||
return nil, fmt.Errorf("Missing host")
|
||||
}
|
||||
|
||||
if len(options.Account) == 0 {
|
||||
return nil, fmt.Errorf("Missing account")
|
||||
}
|
||||
|
||||
if len(options.Password) == 0 {
|
||||
return nil, fmt.Errorf("Missing password")
|
||||
}
|
||||
|
||||
return esxi.NewESXiClient("", "", options.Host, options.Port, options.Account, options.Password)
|
||||
}
|
||||
|
||||
func main() {
|
||||
parser, e := getSubcommandParser()
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
e = parser.ParseArgs(os.Args[1:], false)
|
||||
options := parser.Options().(*BaseOptions)
|
||||
|
||||
if options.Help {
|
||||
fmt.Print(parser.HelpString())
|
||||
} else {
|
||||
subcmd := parser.GetSubcommand()
|
||||
subparser := subcmd.GetSubParser()
|
||||
if e != nil {
|
||||
if subparser != nil {
|
||||
fmt.Print(subparser.Usage())
|
||||
} else {
|
||||
fmt.Print(parser.Usage())
|
||||
}
|
||||
showErrorAndExit(e)
|
||||
} else {
|
||||
suboptions := subparser.Options()
|
||||
if options.SUBCOMMAND == "help" {
|
||||
e = subcmd.Invoke(suboptions)
|
||||
} else {
|
||||
var esxicli *esxi.SESXiClient
|
||||
esxicli, e = newClient(options)
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
e = subcmd.Invoke(esxicli, suboptions)
|
||||
}
|
||||
if e != nil {
|
||||
showErrorAndExit(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,3 +15,5 @@ var ErrNotFound = errors.New("id not found")
|
||||
var ErrDuplicateId = errors.New("duplicate id")
|
||||
var ErrInvalidStatus = errors.New("invalid status")
|
||||
var ErrTimeout = errors.New("timeout")
|
||||
var ErrNotImplemented = errors.New("Not implemented")
|
||||
var ErrNotSupported = errors.New("Not supported")
|
||||
|
||||
@@ -130,7 +130,7 @@ type ICloudVM interface {
|
||||
GetEIP() ICloudEIP
|
||||
|
||||
// GetStatus() string
|
||||
GetRemoteStatus() string
|
||||
// GetRemoteStatus() string
|
||||
|
||||
GetVcpuCount() int8
|
||||
GetVmemSizeMB() int //MB
|
||||
|
||||
@@ -240,25 +240,3 @@ func (self *SAliyunGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Contex
|
||||
guest.SaveDeployInfo(ctx, task.GetUserCred(), data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) GetGuestVncInfo(userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) (*jsonutils.JSONDict, error) {
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iVM, err := ihost.GetIVMById(guest.ExternalId)
|
||||
if err != nil {
|
||||
log.Errorf("cannot find vm %s %s", iVM, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := iVM.GetVNCInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dataDict := data.(*jsonutils.JSONDict)
|
||||
|
||||
return dataDict, nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package guestdrivers
|
||||
|
||||
import (
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/onecloud/pkg/mcclient"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
@@ -19,9 +16,3 @@ func init() {
|
||||
func (self *SESXiGuestDriver) GetHypervisor() string {
|
||||
return models.HYPERVISOR_ESXI
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) GetGuestVncInfo(userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) (*jsonutils.JSONDict, error) {
|
||||
data := jsonutils.NewDict()
|
||||
// TODO
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -112,6 +112,29 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncstatusOnHost(ctx context.
|
||||
return nil, err
|
||||
}
|
||||
body := jsonutils.NewDict()
|
||||
body.Add(jsonutils.NewString(ivm.GetRemoteStatus()), "status")
|
||||
body.Add(jsonutils.NewString(ivm.GetStatus()), "status")
|
||||
return body, nil
|
||||
}
|
||||
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) GetGuestVncInfo(userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) (*jsonutils.JSONDict, error) {
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iVM, err := ihost.GetIVMById(guest.ExternalId)
|
||||
if err != nil {
|
||||
log.Errorf("cannot find vm %s %s", iVM, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := iVM.GetVNCInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dataDict := data.(*jsonutils.JSONDict)
|
||||
|
||||
return dataDict, nil
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
"database/sql"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/log"
|
||||
@@ -24,8 +25,8 @@ const (
|
||||
CLOUD_PROVIDER_START_SYNC = "start_sync"
|
||||
CLOUD_PROVIDER_SYNCING = "syncing"
|
||||
|
||||
CLOUD_PROVIDER_DRIVER_VMWARE = "VMware"
|
||||
CLOUD_PROVIDER_DRIVER_ALIYUN = "Aliyun"
|
||||
CLOUD_PROVIDER_VMWARE = "VMware"
|
||||
CLOUD_PROVIDER_ALIYUN = "Aliyun"
|
||||
)
|
||||
|
||||
type SCloudproviderManager struct {
|
||||
@@ -187,10 +188,9 @@ func (self *SCloudprovider) PerformUpdateCredential(ctx context.Context, userCre
|
||||
q := self.GetModelManager().Query()
|
||||
q = q.Equals("access_url", accessUrl)
|
||||
q = q.Equals("account", account)
|
||||
q = q.Equals("secret", secret)
|
||||
q = q.NotEquals("id", self.Id)
|
||||
if q.Count() > 0 {
|
||||
return nil, httperrors.NewConflictError("Access url and account and ")
|
||||
return nil, httperrors.NewConflictError("Access url and account conflict")
|
||||
}
|
||||
}
|
||||
if len(secret) > 0 {
|
||||
@@ -284,13 +284,6 @@ func (manager *SCloudproviderManager) FetchCloudproviderByIdOrName(providerId st
|
||||
return providerObj.(*SCloudprovider)
|
||||
}
|
||||
|
||||
/*func (manager *SCloudproviderManager) GetDriverByManagerId(managerId string) (cloudprovider.ICloudProvider, error) {
|
||||
provider := manager.FetchCloudproviderById(managerId)
|
||||
if provider == nil {
|
||||
return nil, fmt.Errorf("no valid cloud provider")
|
||||
}
|
||||
return provider.GetDriver()
|
||||
}*/
|
||||
|
||||
type SCloudproviderUsage struct {
|
||||
HostCount int
|
||||
@@ -339,3 +332,48 @@ func (self *SCloudprovider) GetExtraDetails(ctx context.Context, userCred mcclie
|
||||
extra := self.SEnabledStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
|
||||
return self.getMoreDetails(extra)
|
||||
}
|
||||
|
||||
func (manager *SCloudproviderManager) InitializeData() error {
|
||||
// move vmware info from vcenter to cloudprovider
|
||||
vcenters := make([]SVCenter, 0)
|
||||
q := VCenterManager.Query()
|
||||
err := db.FetchModelObjects(manager, q, &vcenters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, vc := range vcenters {
|
||||
_, err := CloudproviderManager.FetchById(vc.Id)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
err = manager.migrateVCenterInfo(&vc)
|
||||
if err != nil {
|
||||
log.Errorf("migrateVcenterInfo fail %s", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Errorf("fetch cloudprovider fail %s", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Debugf("vcenter info has been migrate into cloudprovider")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SCloudproviderManager) migrateVCenterInfo(vc *SVCenter) error {
|
||||
cp := SCloudprovider{}
|
||||
cp.SetModelManager(manager)
|
||||
|
||||
cp.Id = vc.Id
|
||||
cp.Name = db.GenerateName(manager, "", vc.Name)
|
||||
cp.Status = vc.Status
|
||||
cp.AccessUrl = fmt.Sprintf("https://%s:%d", vc.Hostname, vc.Password)
|
||||
cp.Account = vc.Account
|
||||
cp.Secret = vc.Password
|
||||
cp.LastSync = vc.LastSync
|
||||
cp.Sysinfo = vc.Sysinfo
|
||||
cp.Provider = CLOUD_PROVIDER_VMWARE
|
||||
|
||||
return manager.TableSpec().Insert(&cp)
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
func InitDB() error {
|
||||
for _, manager := range []db.IModelManager{
|
||||
CloudproviderManager,
|
||||
CloudregionManager,
|
||||
ZoneManager,
|
||||
VpcManager,
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/log"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
const (
|
||||
CLOUD_PROVIDER_ALIYUN = "Aliyun"
|
||||
CLOUD_PROVIDER_ALIYUN = models.CLOUD_PROVIDER_ALIYUN
|
||||
CLOUD_PROVIDER_ALIYUN_CN = "阿里云"
|
||||
|
||||
ALIYUN_DEFAULT_REGION = "cn-hangzhou"
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"fmt"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/log"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
"github.com/yunionio/pkg/util/osprofile"
|
||||
"github.com/yunionio/pkg/util/seclib"
|
||||
"github.com/yunionio/pkg/utils"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -291,6 +292,7 @@ func (self *SInstance) Refresh() error {
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
/*
|
||||
func (self *SInstance) GetRemoteStatus() string {
|
||||
// Running:运行中
|
||||
//Starting:启动中
|
||||
@@ -309,6 +311,7 @@ func (self *SInstance) GetRemoteStatus() string {
|
||||
return cloudprovider.CloudVMStatusOther
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func (self *SInstance) GetHypervisor() string {
|
||||
return models.HYPERVISOR_ALIYUN
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -12,7 +13,7 @@ func init() {
|
||||
Offset int `help:"List offset"`
|
||||
Limit int `help:"List limit"`
|
||||
}
|
||||
R(&DiskListOptions{}, "disk-list", "List disks", func(cli *aliyun.SRegion, args *DiskListOptions) error {
|
||||
shellutils.R(&DiskListOptions{}, "disk-list", "List disks", func(cli *aliyun.SRegion, args *DiskListOptions) error {
|
||||
disks, total, e := cli.GetDisks(args.Instance, args.Zone, args.Category, nil, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -13,7 +14,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&ImageListOptions{}, "image-list", "List images", func(cli *aliyun.SRegion, args *ImageListOptions) error {
|
||||
shellutils.R(&ImageListOptions{}, "image-list", "List images", func(cli *aliyun.SRegion, args *ImageListOptions) error {
|
||||
images, total, e := cli.GetImages(aliyun.ImageStatusType(args.Status), aliyun.ImageOwnerType(args.Owner), args.Id, args.Name, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -25,7 +26,7 @@ func init() {
|
||||
type ImageDeleteOptions struct {
|
||||
ID string `help:"ID or Name to delete"`
|
||||
}
|
||||
R(&ImageDeleteOptions{}, "image-delete", "Delete image", func(cli *aliyun.SRegion, args *ImageDeleteOptions) error {
|
||||
shellutils.R(&ImageDeleteOptions{}, "image-delete", "Delete image", func(cli *aliyun.SRegion, args *ImageDeleteOptions) error {
|
||||
return cli.DeleteImage(args.ID)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package shell
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -12,7 +13,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&InstanceListOptions{}, "instance-list", "List intances", func(cli *aliyun.SRegion, args *InstanceListOptions) error {
|
||||
shellutils.R(&InstanceListOptions{}, "instance-list", "List intances", func(cli *aliyun.SRegion, args *InstanceListOptions) error {
|
||||
instances, total, e := cli.GetInstances(args.Zone, args.Id, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -32,7 +33,7 @@ func init() {
|
||||
PASSWD string `help:"password"`
|
||||
PublicKey string `help:"PublicKey"`
|
||||
}
|
||||
R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *aliyun.SRegion, args *InstanceCrateOptions) error {
|
||||
shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *aliyun.SRegion, args *InstanceCrateOptions) error {
|
||||
instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.CPU, args.MEMORYGB, args.STORAGE, args.Disk, args.VSWITCH, args.PASSWD, args.PublicKey)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -44,7 +45,7 @@ func init() {
|
||||
type InstanceOperationOptions struct {
|
||||
ID string `help:"instance ID"`
|
||||
}
|
||||
R(&InstanceOperationOptions{}, "instance-start", "Start a instance", func(cli *aliyun.SRegion, args *InstanceOperationOptions) error {
|
||||
shellutils.R(&InstanceOperationOptions{}, "instance-start", "Start a instance", func(cli *aliyun.SRegion, args *InstanceOperationOptions) error {
|
||||
err := cli.StartVM(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -52,7 +53,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&InstanceOperationOptions{}, "instance-vnc", "Get a instance VNC url", func(cli *aliyun.SRegion, args *InstanceOperationOptions) error {
|
||||
shellutils.R(&InstanceOperationOptions{}, "instance-vnc", "Get a instance VNC url", func(cli *aliyun.SRegion, args *InstanceOperationOptions) error {
|
||||
url, err := cli.GetInstanceVNCUrl(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -65,14 +66,14 @@ func init() {
|
||||
ID string `help:"instance ID"`
|
||||
Force bool `help:"Force stop instance"`
|
||||
}
|
||||
R(&InstanceStopOptions{}, "instance-stop", "Stop a instance", func(cli *aliyun.SRegion, args *InstanceStopOptions) error {
|
||||
shellutils.R(&InstanceStopOptions{}, "instance-stop", "Stop a instance", func(cli *aliyun.SRegion, args *InstanceStopOptions) error {
|
||||
err := cli.StopVM(args.ID, args.Force)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
R(&InstanceOperationOptions{}, "instance-delete", "Delete a instance", func(cli *aliyun.SRegion, args *InstanceOperationOptions) error {
|
||||
shellutils.R(&InstanceOperationOptions{}, "instance-delete", "Delete a instance", func(cli *aliyun.SRegion, args *InstanceOperationOptions) error {
|
||||
err := cli.DeleteVM(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -2,12 +2,13 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type InstanceTypeListOptions struct {
|
||||
}
|
||||
R(&InstanceTypeListOptions{}, "instance-type-list", "List intance types", func(cli *aliyun.SRegion, args *InstanceTypeListOptions) error {
|
||||
shellutils.R(&InstanceTypeListOptions{}, "instance-type-list", "List intance types", func(cli *aliyun.SRegion, args *InstanceTypeListOptions) error {
|
||||
instanceTypes, e := cli.GetInstanceTypes()
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
GPU int `help:"GPU size"`
|
||||
Zone string `help:"Test in zone"`
|
||||
}
|
||||
R(&InstanceMatchOptions{}, "instance-type-select", "Select matching instance types", func(cli *aliyun.SRegion, args *InstanceMatchOptions) error {
|
||||
shellutils.R(&InstanceMatchOptions{}, "instance-type-select", "Select matching instance types", func(cli *aliyun.SRegion, args *InstanceMatchOptions) error {
|
||||
instanceTypes, e := cli.GetMatchInstanceTypes(args.CPU, args.MEM, args.GPU, args.Zone)
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -9,7 +10,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&KeyPairListOptions{}, "keypair-list", "List keypairs", func(cli *aliyun.SRegion, args *KeyPairListOptions) error {
|
||||
shellutils.R(&KeyPairListOptions{}, "keypair-list", "List keypairs", func(cli *aliyun.SRegion, args *KeyPairListOptions) error {
|
||||
keypairs, total, e := cli.GetKeypairs("", "", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
NAME string `help:"Name of new keypair"`
|
||||
PUBKEY string `help:"Public key string"`
|
||||
}
|
||||
R(&KeyPairImportOptions{}, "keypair-import", "Import a keypair", func(cli *aliyun.SRegion, args *KeyPairImportOptions) error {
|
||||
shellutils.R(&KeyPairImportOptions{}, "keypair-import", "Import a keypair", func(cli *aliyun.SRegion, args *KeyPairImportOptions) error {
|
||||
keypair, err := cli.ImportKeypair(args.NAME, args.PUBKEY)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
osslib "github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
type progressListener struct {
|
||||
@@ -40,7 +41,7 @@ func str2AclType(aclStr string) osslib.ACLType {
|
||||
func init() {
|
||||
type OssListOptions struct {
|
||||
}
|
||||
R(&OssListOptions{}, "oss-list", "List OSS buckets", func(cli *aliyun.SRegion, args *OssListOptions) error {
|
||||
shellutils.R(&OssListOptions{}, "oss-list", "List OSS buckets", func(cli *aliyun.SRegion, args *OssListOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -57,7 +58,7 @@ func init() {
|
||||
BUCKET string `help:"bucket name"`
|
||||
}
|
||||
|
||||
R(&OssListBucketOptions{}, "oss-list-bucket", "List content of a OSS bucket", func(cli *aliyun.SRegion, args *OssListBucketOptions) error {
|
||||
shellutils.R(&OssListBucketOptions{}, "oss-list-bucket", "List content of a OSS bucket", func(cli *aliyun.SRegion, args *OssListBucketOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -74,7 +75,7 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&OssListBucketOptions{}, "oss-create-bucket", "Create a OSS bucket", func(cli *aliyun.SRegion, args *OssListBucketOptions) error {
|
||||
shellutils.R(&OssListBucketOptions{}, "oss-create-bucket", "Create a OSS bucket", func(cli *aliyun.SRegion, args *OssListBucketOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -93,7 +94,7 @@ func init() {
|
||||
Progress bool `help:"show progress"`
|
||||
Acl string `help:"Object ACL" choices:"private|public-read|public-rw"`
|
||||
}
|
||||
R(&OssUploadOptions{}, "oss-upload", "Upload a file to a OSS bucket", func(cli *aliyun.SRegion, args *OssUploadOptions) error {
|
||||
shellutils.R(&OssUploadOptions{}, "oss-upload", "Upload a file to a OSS bucket", func(cli *aliyun.SRegion, args *OssUploadOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -120,7 +121,7 @@ func init() {
|
||||
KEY string `help:"object key"`
|
||||
ACL string `help:"ACL" choices:"private|public-read|public-rw"`
|
||||
}
|
||||
R(&OssObjectAclOptions{}, "oss-set-acl", "Set acl for a object", func(cli *aliyun.SRegion, args *OssObjectAclOptions) error {
|
||||
shellutils.R(&OssObjectAclOptions{}, "oss-set-acl", "Set acl for a object", func(cli *aliyun.SRegion, args *OssObjectAclOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -138,7 +139,7 @@ func init() {
|
||||
KEY string `help:"Object key"`
|
||||
}
|
||||
|
||||
R(&OssDeleteOptions{}, "oss-delete", "Delete a file from a OSS bucket", func(cli *aliyun.SRegion, args *OssDeleteOptions) error {
|
||||
shellutils.R(&OssDeleteOptions{}, "oss-delete", "Delete a file from a OSS bucket", func(cli *aliyun.SRegion, args *OssDeleteOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package shell
|
||||
|
||||
import "github.com/yunionio/onecloud/pkg/util/printutils"
|
||||
|
||||
func printList(data interface{}, total, offset, limit int, columns []string) {
|
||||
printutils.PrintInterfaceList(data, total, offset, limit, columns)
|
||||
}
|
||||
|
||||
func printObject(obj interface{}) {
|
||||
printutils.PrintInterfaceObject(obj)
|
||||
}
|
||||
@@ -2,12 +2,13 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type RegionListOptions struct {
|
||||
}
|
||||
R(&RegionListOptions{}, "region-list", "List regions", func(cli *aliyun.SRegion, args *RegionListOptions) error {
|
||||
shellutils.R(&RegionListOptions{}, "region-list", "List regions", func(cli *aliyun.SRegion, args *RegionListOptions) error {
|
||||
regions := cli.GetClient().GetRegions()
|
||||
printList(regions, 0, 0, 0, nil)
|
||||
return nil
|
||||
|
||||
@@ -3,6 +3,7 @@ package shell
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -10,7 +11,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&RouteTableListOptions{}, "routetable-list", "List routetables", func(cli *aliyun.SRegion, args *RouteTableListOptions) error {
|
||||
shellutils.R(&RouteTableListOptions{}, "routetable-list", "List routetables", func(cli *aliyun.SRegion, args *RouteTableListOptions) error {
|
||||
routetables, total, e := cli.GetRouteTables(nil, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
type RouteTableShowOptions struct {
|
||||
ID string `help:"ID or name of routetable"`
|
||||
}
|
||||
R(&RouteTableShowOptions{}, "routetable-show", "Show routetable", func(cli *aliyun.SRegion, args *RouteTableShowOptions) error {
|
||||
shellutils.R(&RouteTableShowOptions{}, "routetable-show", "Show routetable", func(cli *aliyun.SRegion, args *RouteTableShowOptions) error {
|
||||
routetables, _, e := cli.GetRouteTables([]string{args.ID}, 0, 1)
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -10,7 +11,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&SecurityGroupListOptions{}, "security-group-list", "List security group", func(cli *aliyun.SRegion, args *SecurityGroupListOptions) error {
|
||||
shellutils.R(&SecurityGroupListOptions{}, "security-group-list", "List security group", func(cli *aliyun.SRegion, args *SecurityGroupListOptions) error {
|
||||
secgrps, total, e := cli.GetSecurityGroups(args.VpcId, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -22,7 +23,7 @@ func init() {
|
||||
type SecurityGroupShowOptions struct {
|
||||
ID string `help:"ID or name of security group"`
|
||||
}
|
||||
R(&SecurityGroupShowOptions{}, "security-group-show", "Show details of a security group", func(cli *aliyun.SRegion, args *SecurityGroupShowOptions) error {
|
||||
shellutils.R(&SecurityGroupShowOptions{}, "security-group-show", "Show details of a security group", func(cli *aliyun.SRegion, args *SecurityGroupShowOptions) error {
|
||||
secgrp, err := cli.GetSecurityGroupDetails(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package shell
|
||||
|
||||
import "github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type TaskListOptions struct {
|
||||
@@ -9,7 +12,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&TaskListOptions{}, "task-list", "List tasks", func(cli *aliyun.SRegion, args *TaskListOptions) error {
|
||||
shellutils.R(&TaskListOptions{}, "task-list", "List tasks", func(cli *aliyun.SRegion, args *TaskListOptions) error {
|
||||
tasks, total, err := cli.GetTasks(aliyun.TaskActionType(args.TYPE), args.Task, args.Offset, args.Limit)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -9,7 +10,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&VpcListOptions{}, "vpc-list", "List vpcs", func(cli *aliyun.SRegion, args *VpcListOptions) error {
|
||||
shellutils.R(&VpcListOptions{}, "vpc-list", "List vpcs", func(cli *aliyun.SRegion, args *VpcListOptions) error {
|
||||
vpcs, total, e := cli.GetVpcs(nil, args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -9,7 +10,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&VRouterListOptions{}, "vrouter-list", "List vrouters", func(cli *aliyun.SRegion, args *VRouterListOptions) error {
|
||||
shellutils.R(&VRouterListOptions{}, "vrouter-list", "List vrouters", func(cli *aliyun.SRegion, args *VRouterListOptions) error {
|
||||
vrouters, total, e := cli.GetVRouters(args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -9,7 +10,7 @@ func init() {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
R(&VSwitchListOptions{}, "vswitch-list", "List vswitches", func(cli *aliyun.SRegion, args *VSwitchListOptions) error {
|
||||
shellutils.R(&VSwitchListOptions{}, "vswitch-list", "List vswitches", func(cli *aliyun.SRegion, args *VSwitchListOptions) error {
|
||||
vswitches, total, e := cli.GetVSwitches(nil, "", args.Offset, args.Limit)
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -2,6 +2,7 @@ package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/aliyun"
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -10,7 +11,7 @@ func init() {
|
||||
// ChargeType string `help:"charge type" choices:"PrePaid|PostPaid" default:"PrePaid"`
|
||||
// SpotStrategy string `help:"Spot strategy, NoSpot|SpotWithPriceLimit|SpotAsPriceGo" choices:"NoSpot|SpotWithPriceLimit|SpotAsPriceGo" default:"NoSpot"`
|
||||
}
|
||||
R(&ZoneListOptions{}, "zone-list", "List zones", func(cli *aliyun.SRegion, args *ZoneListOptions) error {
|
||||
shellutils.R(&ZoneListOptions{}, "zone-list", "List zones", func(cli *aliyun.SRegion, args *ZoneListOptions) error {
|
||||
zones, e := cli.GetIZones()
|
||||
if e != nil {
|
||||
return e
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
var DATACENTER_PROPS = []string {"name", "parent", "datastore"}
|
||||
|
||||
type SDatacenter struct {
|
||||
SManagedObject
|
||||
|
||||
ihosts []cloudprovider.ICloudHost
|
||||
istorages []cloudprovider.ICloudStorage
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
func newDatacenter(manager *SESXiClient, dc *mo.Datacenter) *SDatacenter {
|
||||
obj := SDatacenter{SManagedObject: newManagedObject(manager, dc, nil)}
|
||||
obj.datacenter = &obj
|
||||
return &obj
|
||||
}
|
||||
|
||||
func (dc *SDatacenter) getDatacenter() *mo.Datacenter {
|
||||
return dc.object.(*mo.Datacenter)
|
||||
}
|
||||
|
||||
func (dc *SDatacenter) scanHosts() error {
|
||||
if dc.ihosts == nil {
|
||||
var hosts []mo.HostSystem
|
||||
err := dc.manager.scanMObjects(dc.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dc.ihosts = make([]cloudprovider.ICloudHost, len(hosts))
|
||||
for i := 0; i < len(hosts); i += 1 {
|
||||
dc.ihosts[i] = NewHost(dc.manager, &hosts[i], dc)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dc *SDatacenter) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
err := dc.scanHosts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dc.ihosts, nil
|
||||
}
|
||||
|
||||
func (dc *SDatacenter) scanDatastores() error {
|
||||
if dc.istorages == nil {
|
||||
stores := make([]mo.Datastore, 0)
|
||||
dsList := dc.getDatacenter().Datastore
|
||||
for i := 0; i < len(dsList); i += 1 {
|
||||
var ds mo.Datastore
|
||||
err := dc.manager.reference2Object(dsList[i], DATASTORE_PROPS, &ds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stores = append(stores, ds)
|
||||
}
|
||||
dc.istorages = make([]cloudprovider.ICloudStorage, len(stores))
|
||||
for i := 0; i < len(stores); i += 1 {
|
||||
dc.istorages[i] = NewDatastore(dc.manager, &stores[i], dc)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dc *SDatacenter) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
err := dc.scanDatastores()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dc.istorages, nil
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/yunionio/pkg/util/netutils"
|
||||
"github.com/yunionio/log"
|
||||
)
|
||||
|
||||
var HOST_SYSTEM_PROPS = []string {"name", "parent", "summary", "config", "hardware", "vm"}
|
||||
|
||||
type SHostNicInfo struct {
|
||||
Dev string
|
||||
Driver string
|
||||
Mac string
|
||||
Index int
|
||||
LinkUp bool
|
||||
IpAddr string
|
||||
Mtu int
|
||||
NicType string
|
||||
}
|
||||
|
||||
type SHostStorageAdapterInfo struct {
|
||||
Device string
|
||||
Model string
|
||||
Driver string
|
||||
Pci string
|
||||
Drivers []SHostStorageDriverInfo
|
||||
Enclosure int
|
||||
}
|
||||
|
||||
type SHostStorageDriverInfo struct {
|
||||
CN string
|
||||
Name string
|
||||
Model string
|
||||
Vendor string
|
||||
Revision string
|
||||
Status string
|
||||
SSD bool
|
||||
Dev string
|
||||
Size int
|
||||
}
|
||||
|
||||
type SHostStorageEnclosureInfo struct {
|
||||
CN string
|
||||
Name string
|
||||
Model string
|
||||
Vendor string
|
||||
Revision string
|
||||
Status string
|
||||
}
|
||||
|
||||
type SHost struct {
|
||||
SManagedObject
|
||||
|
||||
nicInfo []SHostNicInfo
|
||||
storageInfo []SHostStorageAdapterInfo
|
||||
|
||||
vms []cloudprovider.ICloudVM
|
||||
}
|
||||
|
||||
func NewHost(manager *SESXiClient, host *mo.HostSystem, dc *SDatacenter) *SHost {
|
||||
return &SHost{SManagedObject: newManagedObject(manager, host, dc)}
|
||||
}
|
||||
|
||||
func (self *SHost) getHostSystem() *mo.HostSystem {
|
||||
return self.object.(*mo.HostSystem)
|
||||
}
|
||||
|
||||
|
||||
func (self *SHost) GetGlobalId() string {
|
||||
return self.GetAccessIp()
|
||||
}
|
||||
|
||||
func (self *SHost) GetStatus() string {
|
||||
/*
|
||||
HostSystemPowerStatePoweredOn = HostSystemPowerState("poweredOn")
|
||||
HostSystemPowerStatePoweredOff = HostSystemPowerState("poweredOff")
|
||||
HostSystemPowerStateStandBy = HostSystemPowerState("standBy")
|
||||
HostSystemPowerStateUnknown = HostSystemPowerState("unknown")
|
||||
*/
|
||||
switch self.getHostSystem().Summary.Runtime.PowerState {
|
||||
case types.HostSystemPowerStatePoweredOn:
|
||||
return models.HOST_STATUS_RUNNING
|
||||
case types.HostSystemPowerStatePoweredOff:
|
||||
return models.HOST_STATUS_READY
|
||||
default:
|
||||
return models.HOST_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SHost) Refresh() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SHost) fetchVMs() error {
|
||||
if self.vms != nil {
|
||||
return nil
|
||||
}
|
||||
var vms []mo.VirtualMachine
|
||||
err := self.manager.references2Objects(self.getHostSystem().Vm, VIRTUAL_MACHINE_PROPS, &vms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dc, err := self.GetDatacenter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.vms = make([]cloudprovider.ICloudVM, len(vms))
|
||||
for i := 0; i < len(vms); i += 1 {
|
||||
self.vms[i] = NewVirtualMachine(self.manager, &vms[i], dc, self)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
err := self.fetchVMs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return self.vms, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
|
||||
vms, err := self.GetIVMs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(vms); i += 1 {
|
||||
if vms[i].GetGlobalId() == id {
|
||||
return vms[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostStatus() string {
|
||||
/*
|
||||
HostSystemConnectionStateConnected = HostSystemConnectionState("connected")
|
||||
HostSystemConnectionStateNotResponding = HostSystemConnectionState("notResponding")
|
||||
HostSystemConnectionStateDisconnected = HostSystemConnectionState("disconnected")
|
||||
*/
|
||||
switch self.getHostSystem().Summary.Runtime.ConnectionState {
|
||||
case types.HostSystemConnectionStateConnected:
|
||||
return models.HOST_ONLINE
|
||||
default:
|
||||
return models.HOST_OFFLINE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func findHostNicByMac(nicInfoList []SHostNicInfo, mac string) *SHostNicInfo {
|
||||
for i := 0; i < len(nicInfoList); i += 1 {
|
||||
if nicInfoList[i].Mac == mac {
|
||||
return &nicInfoList[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) getAdminNic() *SHostNicInfo {
|
||||
nics := self.getNicInfo()
|
||||
for i := 0; i < len(nics); i += 1 {
|
||||
if nics[i].NicType == models.NIC_TYPE_ADMIN {
|
||||
return &nics[i]
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(nics); i += 1 {
|
||||
if len(nics[i].IpAddr) > 0 {
|
||||
return &nics[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) getNicInfo() []SHostNicInfo {
|
||||
if self.nicInfo == nil {
|
||||
self.nicInfo = self.fetchNicInfo()
|
||||
}
|
||||
return self.nicInfo
|
||||
}
|
||||
|
||||
func (self *SHost) fetchNicInfo() []SHostNicInfo {
|
||||
moHost := self.getHostSystem()
|
||||
|
||||
nicInfoList := make([]SHostNicInfo, 0)
|
||||
|
||||
for i, nic := range moHost.Config.Network.Pnic {
|
||||
info := SHostNicInfo{}
|
||||
info.Dev = nic.Device
|
||||
info.Driver = nic.Driver
|
||||
info.Mac = netutils.FormatMacAddr(nic.Mac)
|
||||
info.Index = i
|
||||
info.LinkUp = false
|
||||
nicInfoList = append(nicInfoList, info)
|
||||
}
|
||||
|
||||
for _, nic := range moHost.Config.Network.Vnic {
|
||||
mac := netutils.FormatMacAddr(nic.Spec.Mac)
|
||||
pnic := findHostNicByMac(nicInfoList, mac)
|
||||
if pnic != nil {
|
||||
pnic.IpAddr = nic.Spec.Ip.IpAddress
|
||||
if nic.Spec.Portgroup == "Management Network" {
|
||||
pnic.NicType = models.NIC_TYPE_ADMIN
|
||||
}
|
||||
pnic.LinkUp = true
|
||||
}
|
||||
}
|
||||
|
||||
return nicInfoList
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessIp() string {
|
||||
adminNic := self.getAdminNic()
|
||||
if adminNic != nil {
|
||||
return adminNic.IpAddr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessMac() string {
|
||||
adminNic := self.getAdminNic()
|
||||
if adminNic != nil {
|
||||
return adminNic.Mac
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type SSysInfo struct {
|
||||
Manufacture string
|
||||
Model string
|
||||
SerialNumber string
|
||||
}
|
||||
|
||||
func (self *SHost) GetSysInfo() jsonutils.JSONObject {
|
||||
sysinfo := SSysInfo{}
|
||||
sysinfo.Manufacture = self.getHostSystem().Summary.Hardware.Vendor
|
||||
sysinfo.Model = self.getHostSystem().Summary.Hardware.Model
|
||||
sysinfo.SerialNumber = self.getHostSystem().Hardware.SystemInfo.SerialNumber
|
||||
return jsonutils.Marshal(&sysinfo)
|
||||
}
|
||||
|
||||
func (self *SHost) GetSN() string {
|
||||
return self.getHostSystem().Hardware.SystemInfo.SerialNumber
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuCount() int8 {
|
||||
return int8(self.getHostSystem().Summary.Hardware.NumCpuThreads)
|
||||
}
|
||||
|
||||
func (self *SHost) GetNodeCount() int8 {
|
||||
return int8(self.getHostSystem().Summary.Hardware.NumCpuPkgs)
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuDesc() string {
|
||||
return self.getHostSystem().Summary.Hardware.CpuModel
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuMhz() int {
|
||||
return int(self.getHostSystem().Summary.Hardware.CpuMhz)
|
||||
}
|
||||
|
||||
func (self *SHost) GetMemSizeMB() int {
|
||||
return int(self.getHostSystem().Summary.Hardware.MemorySize/1024/1024)
|
||||
}
|
||||
|
||||
/*func (self *SHost) fetchStorageInfo() {
|
||||
adapterList := make([]SHostStorageAdapterInfo, 0)
|
||||
driversTable := make(map[string]SHostStorageDriverInfo, 0)
|
||||
enclosuresTable := make(map[string]SHostStorageEnclosureInfo, 0)
|
||||
moHost := self.getHostSystem()
|
||||
|
||||
for i, ad := range moHost.Config.StorageDevice.HostBusAdapter {
|
||||
adinfo := ad.GetHostHostBusAdapter()
|
||||
if adinfo == nil {
|
||||
log.Errorf("Fail to GetHostHostBusAdapter")
|
||||
continue
|
||||
}
|
||||
info := SHostStorageAdapterInfo{}
|
||||
info.Device = adinfo.Device
|
||||
info.Model = adinfo.Model
|
||||
info.Driver = adinfo.Driver
|
||||
info.Pci = adinfo.Pci
|
||||
info.Drivers = make([]SHostStorageDriverInfo, 0)
|
||||
info.Enclosure = -1
|
||||
adapterList = append(adapterList, info)
|
||||
}
|
||||
|
||||
for i, drv := range moHost.Config.StorageDevice.ScsiLun {
|
||||
lunInfo := drv.GetScsiLun()
|
||||
if lunInfo == nil {
|
||||
log.Errorf("fail to GetScsiLun")
|
||||
continue
|
||||
}
|
||||
if lunInfo.DeviceType == "disk" {
|
||||
info := SHostStorageDriverInfo{}
|
||||
info.CN = lunInfo.CanonicalName
|
||||
info.Name = lunInfo.DisplayName
|
||||
info.Model = lunInfo.Model
|
||||
info.Vendor = lunInfo.Vendor
|
||||
info.Revision = lunInfo.Revision
|
||||
info.Status = lunInfo.OperationalState[0]
|
||||
// info.SSD = lunInfo.
|
||||
// info.Dev =
|
||||
// info.Size = lunInfo.S
|
||||
} else if lunInfo.DeviceType == "enclosure" {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func (self *SHost) GetStorageSizeMB() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostType() string {
|
||||
return models.HOST_TYPE_ESXI
|
||||
}
|
||||
|
||||
func (self *SHost) GetManagerId() string {
|
||||
return self.manager.providerId
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, vswitchId string, ipAddr string, desc string,
|
||||
passwd string, storageType string, diskSizes []int, publicKey string) (cloudprovider.ICloudVM, error) {
|
||||
log.Debugf("CreateVM")
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/view"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/object"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/log"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/vmware/govmomi/session"
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
const (
|
||||
CLOUD_PROVIDER_VMWARE = models.CLOUD_PROVIDER_VMWARE
|
||||
)
|
||||
|
||||
type SESXiClient struct {
|
||||
providerId string
|
||||
providerName string
|
||||
host string
|
||||
port int
|
||||
account string
|
||||
password string
|
||||
client *govmomi.Client
|
||||
context context.Context
|
||||
|
||||
datacenters []*SDatacenter
|
||||
}
|
||||
|
||||
func NewESXiClient(providerId string, providerName string, host string, port int, account string, passwd string) (*SESXiClient, error) {
|
||||
cli := &SESXiClient{providerId: providerId, providerName: providerName,
|
||||
host: host, port: port, account: account, password: passwd, context: context.Background()}
|
||||
|
||||
err := cli.connect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) url() string {
|
||||
if cli.port == 443 || cli.port == 0 {
|
||||
return fmt.Sprintf("https://%s/sdk", cli.host)
|
||||
} else {
|
||||
return fmt.Sprintf("https://%s:%d/sdk", cli.host, cli.port)
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) connect() error {
|
||||
u, err := url.Parse(cli.url())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Illegal url %s: %s", cli.url(), err)
|
||||
}
|
||||
|
||||
govmcli, err := govmomi.NewClient(cli.context, u, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userinfo := url.UserPassword(cli.account, cli.password)
|
||||
|
||||
err = govmcli.Login(cli.context, userinfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cli.client = govmcli
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) disconnect() error {
|
||||
if cli.client != nil {
|
||||
return cli.client.Logout(cli.context)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) About() jsonutils.JSONObject {
|
||||
return jsonutils.Marshal(&cli.client.ServiceContent.About)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) GetUUID() string {
|
||||
about := cli.client.ServiceContent.About
|
||||
return about.InstanceUuid
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) fetchDatacenters() error {
|
||||
var dcs []mo.Datacenter
|
||||
err := cli.scanAllMObjects(DATACENTER_PROPS, &dcs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cli.datacenters = make([]*SDatacenter, len(dcs))
|
||||
for i := 0; i < len(dcs); i += 1 {
|
||||
cli.datacenters[i] = newDatacenter(cli, &dcs[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanAllMObjects(props []string, dst interface{}) error {
|
||||
return cli.scanMObjects(cli.client.ServiceContent.RootFolder, props, dst)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanMObjects(folder types.ManagedObjectReference, props []string, dst interface{}) error {
|
||||
dstValue := reflect.Indirect(reflect.ValueOf(dst))
|
||||
dstType := dstValue.Type()
|
||||
dstEleType := dstType.Elem()
|
||||
|
||||
resType := dstEleType.Name()
|
||||
m := view.NewManager(cli.client.Client)
|
||||
|
||||
v, err := m.CreateContainerView(cli.context, folder, []string{resType}, true)
|
||||
if err != nil {
|
||||
log.Fatalf("%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer v.Destroy(cli.context)
|
||||
|
||||
err = v.Retrieve(cli.context, []string{resType}, props, dst)
|
||||
if err != nil {
|
||||
log.Fatalf("%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func getStructFields(dst interface{}) []string {
|
||||
dataValue := reflect.Indirect(reflect.ValueOf(dst))
|
||||
dataType := dataValue.Type()
|
||||
if dataType.Kind() != reflect.Struct {
|
||||
log.Warningf("GetStructFeilds for non-struct data")
|
||||
return nil
|
||||
}
|
||||
return _getStructFields(dataType)
|
||||
}
|
||||
|
||||
func _getStructFields(dataType reflect.Type) []string {
|
||||
ret := make([]string, 0)
|
||||
for i := 1; i < dataType.NumField(); i += 1 {
|
||||
field := dataType.Field(i)
|
||||
if field.Type.Kind() == reflect.Struct && field.Anonymous {
|
||||
subfields := _getStructFields(field.Type)
|
||||
ret = append(ret, subfields...)
|
||||
} else if gotypes.IsFieldExportable(field.Name) {
|
||||
log.Debugf("%s: %s", field.Name, field.Type.Name())
|
||||
ret = append(ret, utils.CamelSplit(field.Name, "_"))
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
*/
|
||||
|
||||
func (cli *SESXiClient) references2Objects(refs []types.ManagedObjectReference, props []string, dst interface{}) error {
|
||||
pc := property.DefaultCollector(cli.client.Client)
|
||||
err := pc.Retrieve(cli.context, refs, []string{"name", "config", "summary"}, dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) reference2Object(ref types.ManagedObjectReference, props []string, dst interface{}) error {
|
||||
pc := property.DefaultCollector(cli.client.Client)
|
||||
return pc.RetrieveOne(cli.context, ref, props, dst)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) GetDatacenters() ([]*SDatacenter, error) {
|
||||
if cli.datacenters == nil {
|
||||
err := cli.fetchDatacenters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cli.datacenters, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) FindDatacenterById(dcId string) (*SDatacenter, error) {
|
||||
dcs, err := cli.GetDatacenters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(dcs); i += 1 {
|
||||
if dcs[i].GetId() == dcId {
|
||||
return dcs[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) FindHostByIp(hostIp string) (*SHost, error) {
|
||||
searchIndex := object.NewSearchIndex(cli.client.Client)
|
||||
hostRef, err := searchIndex.FindByIp(cli.context, nil, hostIp, false)
|
||||
if err != nil {
|
||||
log.Errorf("searchIndex.FindByIp fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var host mo.HostSystem
|
||||
err = cli.reference2Object(hostRef.Reference(), HOST_SYSTEM_PROPS, &host)
|
||||
if err != nil {
|
||||
log.Errorf("reference2Object fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewHost(cli, &host, nil), nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) acquireCloneTicket() (string, error) {
|
||||
manager := session.NewManager(cli.client.Client)
|
||||
return manager.AcquireCloneTicket(cli.context)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package esxi
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
cli, err := NewESXiClient("", "", "10.168.222.104", 443, "root", "123@Vmware")
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("%s", err)
|
||||
} else {
|
||||
t.Logf("%s", cli.About())
|
||||
|
||||
cli.fetchDatacenters()
|
||||
|
||||
host, err := cli.FindHostByIp("10.168.222.104")
|
||||
if err != nil {
|
||||
t.Errorf("find_host_by_ip %s", err)
|
||||
} else {
|
||||
t.Logf("host %s %s", host.GetAccessIp(), host.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/yunionio/log"
|
||||
"reflect"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SManagedObject struct {
|
||||
manager *SESXiClient
|
||||
datacenter *SDatacenter
|
||||
object mo.Entity
|
||||
|
||||
path []string
|
||||
}
|
||||
|
||||
func newManagedObject(manager *SESXiClient, moobj mo.Entity, dc *SDatacenter) SManagedObject {
|
||||
return SManagedObject{manager: manager, object: moobj, datacenter: dc}
|
||||
}
|
||||
|
||||
func (self *SManagedObject) GetName() string {
|
||||
return self.object.Entity().Name
|
||||
}
|
||||
|
||||
func (self *SManagedObject) GetId() string {
|
||||
return self.object.Entity().Self.Value
|
||||
}
|
||||
|
||||
func (self *SManagedObject) GetType() string {
|
||||
return self.object.Entity().Self.Type
|
||||
}
|
||||
|
||||
func (self *SManagedObject) getCurrentParentEntity() *mo.ManagedEntity {
|
||||
return self.getParentEntity(self.object.Entity())
|
||||
}
|
||||
|
||||
func (self *SManagedObject) getParentEntity(obj *mo.ManagedEntity) *mo.ManagedEntity {
|
||||
parent := obj.Parent
|
||||
if parent != nil {
|
||||
var entity mo.ManagedEntity
|
||||
err := self.manager.reference2Object(*parent, []string{"name", "parent"}, &entity)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return nil
|
||||
}
|
||||
log.Debugf("getParentEntity %s %s %s", entity.Self.Type, entity.Self.Value, entity.Name)
|
||||
return &entity
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func reverseArray(array interface{}) {
|
||||
arrayValue := reflect.Indirect(reflect.ValueOf(array))
|
||||
if arrayValue.Kind() != reflect.Slice && arrayValue.Kind() != reflect.Array {
|
||||
log.Errorf("reverse non array or slice")
|
||||
return
|
||||
}
|
||||
tmp := reflect.Indirect(reflect.New(arrayValue.Type().Elem()))
|
||||
for i, j := 0, arrayValue.Len() - 1; i < j; i, j = i + 1, j - 1 {
|
||||
tmpi := arrayValue.Index(i)
|
||||
tmpj := arrayValue.Index(j)
|
||||
tmp.Set(tmpi)
|
||||
tmpi.Set(tmpj)
|
||||
tmpj.Set(tmp)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SManagedObject) fetchPath() []string {
|
||||
path := make([]string, 0)
|
||||
obj := self.object.Entity()
|
||||
for obj != nil {
|
||||
path = append(path, obj.Name)
|
||||
obj = self.getParentEntity(obj)
|
||||
}
|
||||
reverseArray(path)
|
||||
return path
|
||||
}
|
||||
|
||||
func (self *SManagedObject) GetPath() []string {
|
||||
if self.path == nil {
|
||||
self.path = self.fetchPath()
|
||||
}
|
||||
return self.path
|
||||
}
|
||||
|
||||
func (self *SManagedObject) findInParents(objType string) *mo.ManagedEntity {
|
||||
obj := self.object.Entity()
|
||||
|
||||
for obj != nil && obj.Self.Type != objType {
|
||||
obj = self.getParentEntity(obj)
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *SManagedObject) fetchDatacenter() (*SDatacenter, error) {
|
||||
me := self.findInParents("Datacenter")
|
||||
if me == nil {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return self.manager.FindDatacenterById(me.Self.Value)
|
||||
}
|
||||
|
||||
func (self *SManagedObject) GetDatacenter() (*SDatacenter, error) {
|
||||
if self.datacenter == nil {
|
||||
dc, err := self.fetchDatacenter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
self.datacenter = dc
|
||||
}
|
||||
return self.datacenter, nil
|
||||
}
|
||||
|
||||
func (self *SManagedObject) GetDatacenterPath() []string {
|
||||
dc, err := self.GetDatacenter()
|
||||
if err != nil {
|
||||
log.Errorf("cannot find datacenter")
|
||||
return nil
|
||||
}
|
||||
path := dc.GetPath()
|
||||
return path[1:]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package esxi
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestReverseArray(t *testing.T) {
|
||||
a := []int{1, 2, 3, 4, 5}
|
||||
|
||||
reverseArray(a)
|
||||
t.Logf("%#v", a)
|
||||
|
||||
b := []string{"1", "2", "3", "4", "5"}
|
||||
reverseArray(b)
|
||||
t.Logf("%#v", b)
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"strconv"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/log"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/util/esxi"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
|
||||
)
|
||||
|
||||
type SESXiProviderFactory struct {
|
||||
providerTable map[string]*SESXiProvider
|
||||
}
|
||||
|
||||
func (self *SESXiProviderFactory) GetId() string {
|
||||
return esxi.CLOUD_PROVIDER_VMWARE
|
||||
}
|
||||
|
||||
func parseHostPort(host string, defPort int) (string, int, error) {
|
||||
colonPos := strings.IndexByte(host, ':')
|
||||
if colonPos > 0 {
|
||||
h := host[:colonPos]
|
||||
p, err := strconv.Atoi(host[colonPos+1:])
|
||||
if err != nil {
|
||||
log.Errorf("Invalid host %s", host)
|
||||
return "", 0, err
|
||||
}
|
||||
if p == 0 {
|
||||
p = defPort
|
||||
}
|
||||
return h, p, nil
|
||||
} else {
|
||||
return host, defPort, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SESXiProviderFactory) GetProvider(providerId, providerName, urlStr, account, secret string) (cloudprovider.ICloudProvider, error) {
|
||||
provider, ok := self.providerTable[providerId]
|
||||
if ok {
|
||||
return provider, nil
|
||||
}
|
||||
parts, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
host, port, err := parseHostPort(parts.Host, 443)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := esxi.NewESXiClient(providerId, providerName, host, port, account, secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
self.providerTable[providerId] = &SESXiProvider{client: client}
|
||||
return self.providerTable[providerId], nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
factory := SESXiProviderFactory{
|
||||
providerTable: make(map[string]*SESXiProvider),
|
||||
}
|
||||
cloudprovider.RegisterFactory(&factory)
|
||||
}
|
||||
|
||||
type SESXiProvider struct {
|
||||
client *esxi.SESXiClient
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) IsPublicCloud() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetId() string {
|
||||
return esxi.CLOUD_PROVIDER_VMWARE
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetName() string {
|
||||
return esxi.CLOUD_PROVIDER_VMWARE
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetSysInfo() (jsonutils.JSONObject, error) {
|
||||
return self.client.About(), nil
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetIRegions() []cloudprovider.ICloudRegion {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
host, err := self.client.FindHostByIp(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return host, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SESXiProvider) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
"github.com/yunionio/onecloud/pkg/util/esxi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DatacenterListOptions struct {
|
||||
}
|
||||
shellutils.R(&DatacenterListOptions{}, "dc-list", "List all datacenters", func(cli *esxi.SESXiClient, args *DatacenterListOptions) error {
|
||||
dcs, err := cli.GetDatacenters()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(dcs, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
"github.com/yunionio/onecloud/pkg/util/esxi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type HostListOptions struct {
|
||||
DATACENTER string `help:"List hosts in datacenter"`
|
||||
}
|
||||
shellutils.R(&HostListOptions{}, "host-list", "List hosts in datacenter", func(cli *esxi.SESXiClient, args *HostListOptions) error {
|
||||
dc, err := cli.FindDatacenterById(args.DATACENTER)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hosts, err := dc.GetIHosts()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(hosts, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type HostShowOptions struct {
|
||||
IP string `help:"Host IP"`
|
||||
}
|
||||
shellutils.R(&HostShowOptions{}, "host-show", "Show details of a host by IP", func(cli *esxi.SESXiClient, args *HostShowOptions) error {
|
||||
host, err := cli.FindHostByIp(args.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(host)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
"github.com/yunionio/onecloud/pkg/util/esxi"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DatastoreListOptions struct {
|
||||
DATACENTER string `help:"List datastores in datacenter"`
|
||||
}
|
||||
shellutils.R(&DatastoreListOptions{}, "ds-list", "List datastores in datacenter", func(cli *esxi.SESXiClient, args *DatastoreListOptions) error {
|
||||
dc, err := cli.FindDatacenterById(args.DATACENTER)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ds, err := dc.GetIStorages()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(ds, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package shell
|
||||
|
||||
import "github.com/yunionio/onecloud/pkg/util/printutils"
|
||||
|
||||
|
||||
func printList(data interface{}, columns []string) {
|
||||
printutils.PrintGetterList(data, columns)
|
||||
}
|
||||
|
||||
func printObject(obj interface{}) {
|
||||
printutils.PrintGetterObject(obj)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"github.com/yunionio/onecloud/pkg/util/shellutils"
|
||||
"github.com/yunionio/onecloud/pkg/util/esxi"
|
||||
"github.com/yunionio/onecloud/pkg/util/printutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type VirtualMachineListOptions struct {
|
||||
HOSTIP string `help:"Host IP"`
|
||||
}
|
||||
shellutils.R(&VirtualMachineListOptions{}, "vm-list", "List vms of a host", func(cli *esxi.SESXiClient, args *VirtualMachineListOptions) error {
|
||||
host, err := cli.FindHostByIp(args.HOSTIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vms, err := host.GetIVMs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(vms, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type VirtualMachineShowOptions struct {
|
||||
HOSTIP string `help:"Host IP"`
|
||||
VMID string `help:"VM ID"`
|
||||
}
|
||||
shellutils.R(&VirtualMachineShowOptions{}, "vm-show", "Show vm details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
|
||||
host, err := cli.FindHostByIp(args.HOSTIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vm, err := host.GetIVMById(args.VMID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(vm)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&VirtualMachineShowOptions{}, "vm-vnc", "Show vm VNC details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
|
||||
host, err := cli.FindHostByIp(args.HOSTIP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vm, err := host.GetIVMById(args.VMID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := vm.GetVNCInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printutils.PrintJSONObject(info)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
var DATASTORE_PROPS = []string {"name", "parent"}
|
||||
|
||||
|
||||
type SDatastore struct {
|
||||
SManagedObject
|
||||
}
|
||||
|
||||
func NewDatastore(manager *SESXiClient, ds *mo.Datastore, dc *SDatacenter) *SDatastore {
|
||||
return &SDatastore{SManagedObject: newManagedObject(manager, ds, dc)}
|
||||
}
|
||||
|
||||
func (self *SDatastore) getDatastore() *mo.Datastore {
|
||||
return self.object.(*mo.Datastore)
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetGlobalId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetStatus() string {
|
||||
if self.getDatastore().Summary.Accessible {
|
||||
return models.STORAGE_ONLINE
|
||||
} else {
|
||||
return models.STORAGE_OFFLINE
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDatastore) Refresh() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDatastore) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDatastore) getVolumeId() string {
|
||||
return self.getDatastore().Summary.Type
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetIZone() cloudprovider.ICloudZone {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetStorageType() string {
|
||||
return self.getDatastore().Summary.Type
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetMediumType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetCapacityMB() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetStorageConf() jsonutils.JSONObject {
|
||||
conf := jsonutils.NewDict()
|
||||
return conf
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SDatastore) GetManagerId() string {
|
||||
return self.manager.providerId
|
||||
}
|
||||
|
||||
func (self *SDatastore) CreateIDisk(name string, sizeGb int, desc string) (cloudprovider.ICloudDisk, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/cloudprovider"
|
||||
"github.com/yunionio/onecloud/pkg/compute/models"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var VIRTUAL_MACHINE_PROPS = []string{"name", "parent", "runtime", "summary"}
|
||||
|
||||
type SVirtualMachine struct {
|
||||
SManagedObject
|
||||
|
||||
host *SHost
|
||||
}
|
||||
|
||||
func NewVirtualMachine(manager *SESXiClient, vm *mo.VirtualMachine, dc *SDatacenter, host *SHost) *SVirtualMachine {
|
||||
return &SVirtualMachine{SManagedObject: newManagedObject(manager, vm, dc), host: host}
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) getVirtualMachine() *mo.VirtualMachine {
|
||||
return self.object.(*mo.VirtualMachine)
|
||||
}
|
||||
|
||||
|
||||
func (self *SVirtualMachine) GetGlobalId() string {
|
||||
return self.getUuid()
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetStatus() string {
|
||||
vm := object.NewVirtualMachine(self.manager.client.Client, self.getVirtualMachine().Self)
|
||||
state, err := vm.PowerState(self.manager.context)
|
||||
if err != nil {
|
||||
return models.VM_UNKNOWN
|
||||
}
|
||||
switch state {
|
||||
case types.VirtualMachinePowerStatePoweredOff:
|
||||
return models.VM_READY
|
||||
case types.VirtualMachinePowerStatePoweredOn:
|
||||
return models.VM_RUNNING
|
||||
case types.VirtualMachinePowerStateSuspended:
|
||||
return models.VM_SUSPEND
|
||||
default:
|
||||
return models.VM_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) Refresh() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) getUuid() string {
|
||||
return self.getVirtualMachine().Summary.Config.Uuid
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetCreateTime() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetIHost() cloudprovider.ICloudHost {
|
||||
return self.host
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetINics() ([]cloudprovider.ICloudNic, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetEIP() cloudprovider.ICloudEIP {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetVcpuCount() int8 {
|
||||
// ret = self.obj.summary.config.numCpu
|
||||
return int8(self.getVirtualMachine().Summary.Config.NumCpu)
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetVmemSizeMB() int {
|
||||
// self.obj.summary.config.memorySizeMB
|
||||
return int(self.getVirtualMachine().Summary.Config.MemorySizeMB)
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetBootOrder() string {
|
||||
return "cdn"
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetVga() string {
|
||||
return "vga"
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetVdi() string {
|
||||
return "vmrc"
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetOSType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetOSName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetBios() string {
|
||||
// self.obj.config.firmware
|
||||
switch self.getVirtualMachine().Config.Firmware {
|
||||
case "efi":
|
||||
return "UEFI"
|
||||
case "bios":
|
||||
return "BIOS"
|
||||
default:
|
||||
return "BIOS"
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetMachine() string {
|
||||
return "pc"
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetHypervisor() string {
|
||||
return models.HYPERVISOR_ESXI
|
||||
}
|
||||
|
||||
// GetSecurityGroup() ICloudSecurityGroup
|
||||
|
||||
func (self *SVirtualMachine) StartVM() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) StopVM(isForce bool) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) DeleteVM() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) GetVNCInfo() (jsonutils.JSONObject, error) {
|
||||
info, err := self.acquireWebmksTicket("webmks")
|
||||
if err != nil {
|
||||
info, err = self.acquireVmrcUrl()
|
||||
}
|
||||
return info, err
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) acquireWebmksTicket(ticketType string) (jsonutils.JSONObject, error) {
|
||||
vm := object.NewVirtualMachine(self.manager.client.Client, self.getVirtualMachine().Self)
|
||||
ticket, err := vm.AcquireTicket(self.manager.context, ticketType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := jsonutils.NewDict()
|
||||
|
||||
host := ticket.Host
|
||||
if len(host) == 0 {
|
||||
host = self.manager.host
|
||||
}
|
||||
port := ticket.Port
|
||||
if port == 0 {
|
||||
port = int32(self.manager.port)
|
||||
}
|
||||
if port == 0 {
|
||||
port = 443
|
||||
}
|
||||
/*
|
||||
ret.Add(jsonutils.NewString(ticketType), "type")
|
||||
ret.Add(jsonutils.NewString(ticket.Host), "host")
|
||||
ret.Add(jsonutils.NewInt(int64(ticket.Port)), "port")
|
||||
ret.Add(jsonutils.NewString(ticket.Ticket), "ticket")
|
||||
ret.Add(jsonutils.NewString(ticket.SslThumbprint), "slThumbprint")
|
||||
ret.Add(jsonutils.NewString(ticket.CfgFile), "cfgFile")
|
||||
*/
|
||||
url := fmt.Sprintf("wss://%s:%d/ticket/%s", host, port, ticket.Ticket)
|
||||
ret.Add(jsonutils.NewString("wmks"), "protocol")
|
||||
ret.Add(jsonutils.NewString(url), "url")
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SVirtualMachine) acquireVmrcUrl() (jsonutils.JSONObject, error) {
|
||||
ticket, err := self.manager.acquireCloneTicket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := jsonutils.NewDict()
|
||||
ret.Add(jsonutils.NewString("vmrc"), "protocol")
|
||||
port := self.manager.port
|
||||
if port == 0 {
|
||||
port = 443
|
||||
}
|
||||
url := fmt.Sprintf("vmrc://clone:%s@%s:%d/?moid=%s", ticket, self.manager.host, port, self.GetId())
|
||||
ret.Add(jsonutils.NewString(url), "url")
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package printutils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"fmt"
|
||||
|
||||
"github.com/yunionio/jsonutils"
|
||||
"github.com/yunionio/pkg/utils"
|
||||
"github.com/yunionio/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
func getter2json(obj interface{}) jsonutils.JSONObject {
|
||||
jsonDict := jsonutils.NewDict()
|
||||
|
||||
objValue := reflect.ValueOf(obj)
|
||||
objType := reflect.TypeOf(obj)
|
||||
|
||||
// log.Debugf("getter2json %d", objValue.NumMethod())
|
||||
|
||||
for i := 0; i < objValue.NumMethod(); i += 1 {
|
||||
methodValue := objValue.Method(i)
|
||||
method := objType.Method(i)
|
||||
methodName := method.Name
|
||||
methodType := methodValue.Type()
|
||||
|
||||
if strings.HasPrefix(methodName, "Get") && methodType.NumIn() == 0 && methodType.NumOut() == 1 {
|
||||
fieldName := utils.CamelSplit(methodName[3:], "_")
|
||||
out := methodValue.Call([]reflect.Value{})
|
||||
if len(out) == 1 {
|
||||
jsonDict.Add(jsonutils.Marshal(out[0].Interface()), fieldName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jsonDict
|
||||
}
|
||||
|
||||
func PrintGetterList(data interface{}, columns []string) {
|
||||
dataValue := reflect.ValueOf(data)
|
||||
if dataValue.Kind() != reflect.Slice {
|
||||
fmt.Println("Invalid list data")
|
||||
return
|
||||
}
|
||||
jsonList := make([]jsonutils.JSONObject, dataValue.Len())
|
||||
for i := 0; i < dataValue.Len(); i += 1 {
|
||||
jsonList[i] = getter2json(dataValue.Index(i).Interface())
|
||||
}
|
||||
list := &modules.ListResult{
|
||||
Data: jsonList,
|
||||
Total: dataValue.Len(),
|
||||
Limit: 0,
|
||||
Offset: 0,
|
||||
}
|
||||
PrintJSONList(list, columns)
|
||||
}
|
||||
|
||||
func PrintGetterObject(obj interface{}) {
|
||||
PrintJSONObject(getter2json(obj))
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package printjson
|
||||
package printutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/yunionio/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
func PrintList(list *modules.ListResult, columns []string) {
|
||||
func PrintJSONList(list *modules.ListResult, columns []string) {
|
||||
colsWithData := make([]string, 0)
|
||||
if columns == nil || len(columns) == 0 {
|
||||
colsWithDataMap := make(map[string]bool)
|
||||
@@ -75,7 +75,7 @@ func PrintList(list *modules.ListResult, columns []string) {
|
||||
fmt.Println("*** ", title, " ***")
|
||||
}
|
||||
|
||||
func PrintObject(obj jsonutils.JSONObject) {
|
||||
func PrintJSONObject(obj jsonutils.JSONObject) {
|
||||
dict, ok := obj.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
fmt.Println("Not a valid JSON object:", obj.String())
|
||||
@@ -98,7 +98,7 @@ func PrintObject(obj jsonutils.JSONObject) {
|
||||
fmt.Println(pt.GetString(rows))
|
||||
}
|
||||
|
||||
func PrintBatchResults(results []modules.SubmitResult, columns []string) {
|
||||
func PrintJSONBatchResults(results []modules.SubmitResult, columns []string) {
|
||||
objs := make([]jsonutils.JSONObject, 0)
|
||||
errs := make([]jsonutils.JSONObject, 0)
|
||||
for _, r := range results {
|
||||
@@ -113,9 +113,9 @@ func PrintBatchResults(results []modules.SubmitResult, columns []string) {
|
||||
}
|
||||
}
|
||||
if len(objs) > 0 {
|
||||
PrintList(&modules.ListResult{Data: objs}, columns)
|
||||
PrintJSONList(&modules.ListResult{Data: objs}, columns)
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
PrintList(&modules.ListResult{Data: errs}, []string{"status", "id", "error"})
|
||||
PrintJSONList(&modules.ListResult{Data: errs}, []string{"status", "id", "error"})
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package shell
|
||||
package printutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -7,10 +7,9 @@ import (
|
||||
"github.com/yunionio/jsonutils"
|
||||
|
||||
"github.com/yunionio/onecloud/pkg/mcclient/modules"
|
||||
"github.com/yunionio/onecloud/pkg/util/printjson"
|
||||
)
|
||||
|
||||
func printList(data interface{}, total, offset, limit int, columns []string) {
|
||||
func PrintInterfaceList(data interface{}, total, offset, limit int, columns []string) {
|
||||
dataValue := reflect.ValueOf(data)
|
||||
if dataValue.Kind() != reflect.Slice {
|
||||
fmt.Println("Invalid list data")
|
||||
@@ -29,9 +28,9 @@ func printList(data interface{}, total, offset, limit int, columns []string) {
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
}
|
||||
printjson.PrintList(list, columns)
|
||||
PrintJSONList(list, columns)
|
||||
}
|
||||
|
||||
func printObject(obj interface{}) {
|
||||
printjson.PrintObject(jsonutils.Marshal(obj))
|
||||
func PrintInterfaceObject(obj interface{}) {
|
||||
PrintJSONObject(jsonutils.Marshal(obj))
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package shell
|
||||
package shellutils
|
||||
|
||||
type CMD struct {
|
||||
Options interface{}
|
||||
Reference in New Issue
Block a user