改进:1. 增加vmware cloud provider driver初步实现 2. 增加vmware vnc信息获取的支持

This commit is contained in:
Qiu Jian
2018-08-07 15:19:19 +08:00
parent ab44a1f547
commit 9eb41b392f
47 changed files with 1760 additions and 99 deletions
Generated
+24 -1
View File
@@ -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
+5
View File
@@ -52,3 +52,8 @@
[prune]
go-tests = true
unused-packages = true
[[constraint]]
branch = "master"
name = "github.com/vmware/govmomi"
+5 -3
View File
@@ -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 -4
View File
@@ -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)
}
+118
View File
@@ -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)
}
}
}
}
+2
View File
@@ -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")
+1 -1
View File
@@ -130,7 +130,7 @@ type ICloudVM interface {
GetEIP() ICloudEIP
// GetStatus() string
GetRemoteStatus() string
// GetRemoteStatus() string
GetVcpuCount() int8
GetVmemSizeMB() int //MB
-22
View File
@@ -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
}
-9
View File
@@ -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
}
+24 -1
View File
@@ -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
}
+49 -11
View File
@@ -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)
}
+1
View File
@@ -7,6 +7,7 @@ import (
func InitDB() error {
for _, manager := range []db.IModelManager{
CloudproviderManager,
CloudregionManager,
ZoneManager,
VpcManager,
+2 -1
View File
@@ -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"
+6 -3
View File
@@ -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 -1
View File
@@ -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
+3 -2
View File
@@ -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)
})
}
+7 -6
View File
@@ -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
+3 -2
View File
@@ -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
+3 -2
View File
@@ -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
+7 -6
View File
@@ -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
+11
View File
@@ -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 -1
View File
@@ -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 -2
View File
@@ -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
+3 -2
View File
@@ -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
+5 -2
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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
+78
View File
@@ -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
}
+360
View File
@@ -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
}
+226
View File
@@ -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)
}
+22
View File
@@ -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())
}
}
}
+124
View File
@@ -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:]
}
+14
View File
@@ -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)
}
+119
View File
@@ -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
}
+19
View File
@@ -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
})
}
+36
View File
@@ -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
})
}
+24
View File
@@ -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
})
}
+12
View File
@@ -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)
}
+59
View File
@@ -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
})
}
+89
View File
@@ -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
}
+208
View File
@@ -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
}
+60
View File
@@ -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{}