Merge pull request #1440 from swordqiu/hotfix/qj-esxi-resource-pool-tags

feature: 1. esxi vm add resource pool metadata 2. esxicli support
This commit is contained in:
yunion-ci-robot
2019-07-01 10:03:50 +08:00
committed by GitHub
32 changed files with 618 additions and 131 deletions
+5 -3
View File
@@ -100,9 +100,11 @@ func newClient(options *BaseOptions) (*azure.SRegion, error) {
return nil, fmt.Errorf("Missing Cloud Environment")
}
account := fmt.Sprintf("%s/%s", options.DirectoryID, options.SubscriptionID)
secret := fmt.Sprintf("%s/%s", options.ApplicationID, options.ApplicationKey)
cli, err := azure.NewAzureClient("", "", account, secret, options.CloudEnv, options.Debug)
cli, err := azure.NewAzureClient("", "", options.CloudEnv,
options.DirectoryID,
options.ApplicationID, options.ApplicationKey,
options.SubscriptionID,
options.Debug)
if err != nil {
return nil, err
}
+21
View File
@@ -15,6 +15,8 @@
package shell
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -187,4 +189,23 @@ func init() {
printObject(result)
return nil
})
type CloudproviderClientRCOptions struct {
ID string `help:"ID or name of cloud provider"`
}
R(&CloudproviderClientRCOptions{}, "cloud-provider-clirc", "Get client RC file of the cloud provider", func(s *mcclient.ClientSession, args *CloudproviderClientRCOptions) error {
result, err := modules.Cloudproviders.GetSpecific(s, args.ID, "clirc", nil)
if err != nil {
return err
}
rc := make(map[string]string)
err = result.Unmarshal(&rc)
if err != nil {
return err
}
for k, v := range rc {
fmt.Printf("export %s='%s'\n", k, v)
}
return nil
})
}
+3 -8
View File
@@ -86,14 +86,9 @@ func newClient(options *BaseOptions) (*huawei.SRegion, error) {
return nil, fmt.Errorf("Missing secret")
}
account := ""
if len(options.ProjectId) > 0 {
account = options.AccessKey + "/" + options.ProjectId
} else {
account = options.AccessKey
}
cli, err := huawei.NewHuaweiClient("", "", options.CloudEnv, account, options.Secret, options.Debug)
cli, err := huawei.NewHuaweiClient("", "", options.CloudEnv,
options.AccessKey, options.Secret, options.ProjectId,
options.Debug)
if err != nil {
return nil, err
}
+5 -6
View File
@@ -85,12 +85,11 @@ func newClient(options *BaseOptions) (*qcloud.SRegion, error) {
return nil, fmt.Errorf("Missing SecretID")
}
account := options.SecretID
if len(options.AppID) > 0 {
account = fmt.Sprintf("%s/%s", account, options.AppID)
}
if cli, err := qcloud.NewQcloudClient("", "", account, options.SecretKey, options.Debug); err != nil {
if cli, err := qcloud.NewQcloudClient("", "",
options.SecretID,
options.SecretKey,
options.AppID,
options.Debug); err != nil {
return nil, err
} else if region := cli.GetRegion(options.RegionId); region == nil {
return nil, fmt.Errorf("No such region %s", options.RegionId)
+5 -8
View File
@@ -86,14 +86,11 @@ func newClient(options *BaseOptions) (*ucloud.SRegion, error) {
return nil, fmt.Errorf("Missing secret")
}
account := ""
if len(options.ProjectId) > 0 {
account = options.AccessKey + "::" + options.ProjectId
} else {
account = options.AccessKey
}
cli, err := ucloud.NewUcloudClient("", "", account, options.Secret, options.Debug)
cli, err := ucloud.NewUcloudClient("", "",
options.AccessKey,
options.Secret,
options.ProjectId,
options.Debug)
if err != nil {
return nil, err
}
+5 -4
View File
@@ -38,8 +38,9 @@ const (
CLOUD_TAG_PREFIX = "ext:"
USER_TAG_PREFIX = "user:"
TAG_DELETE_RANGE_USER = "user"
TAG_DELETE_RANGE_CLOUD = "cloud"
// TAG_DELETE_RANGE_USER = "user"
// TAG_DELETE_RANGE_CLOUD = CLOUD_TAG_PREFIX // "cloud"
TAG_DELETE_RANGE_ALL = "all"
)
@@ -332,9 +333,9 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
records := []SMetadata{}
q := manager.Query().Equals("id", idStr).NotLike("key", `\_\_%`) //避免删除系统内置的metadata, _ 在mysql里面有特殊含义,需要转义
switch delRange {
case TAG_DELETE_RANGE_USER:
case USER_TAG_PREFIX:
q = q.Like("key", USER_TAG_PREFIX+"%")
case TAG_DELETE_RANGE_CLOUD:
case CLOUD_TAG_PREFIX:
q = q.Like("key", CLOUD_TAG_PREFIX+"%")
}
q = q.Filter(sqlchemy.NOT(sqlchemy.In(q.Field("key"), keys)))
+6 -2
View File
@@ -258,7 +258,11 @@ func (model *SStandaloneResourceBase) SetUserMetadataValues(ctx context.Context,
}
func (model *SStandaloneResourceBase) SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetAll(ctx, model, dictstore, userCred, "user")
return Metadata.SetAll(ctx, model, dictstore, userCred, USER_TAG_PREFIX)
}
func (model *SStandaloneResourceBase) SetCloudMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
return Metadata.SetAll(ctx, model, dictstore, userCred, CLOUD_TAG_PREFIX)
}
func (model *SStandaloneResourceBase) RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error {
@@ -343,7 +347,7 @@ func (model *SStandaloneResourceBase) PerformSetUserMetadata(ctx context.Context
}
dictStore := make(map[string]interface{})
for k, v := range dictMap {
dictStore["user:"+k], _ = v.GetString()
dictStore[USER_TAG_PREFIX+k], _ = v.GetString()
}
err = model.SetUserMetadataAll(ctx, dictStore, userCred)
return nil, err
+14 -4
View File
@@ -16,18 +16,18 @@ package cloudprovider
import (
"context"
"errors"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
var (
ErrNoSuchProvder = errors.New("no such provider")
const (
ErrNoSuchProvder = errors.Error("no such provider")
)
type SCloudaccount struct {
@@ -38,6 +38,8 @@ type SCloudaccount struct {
type ICloudProviderFactory interface {
GetProvider(providerId, providerName, url, account, secret string) (ICloudProvider, error)
GetClientRC(url, account, secret string) (map[string]string, error)
GetId() string
GetName() string
@@ -103,11 +105,19 @@ func GetRegistedProviderIds() []string {
func GetProvider(providerId, providerName, accessUrl, account, secret, provider string) (ICloudProvider, error) {
driver, err := GetProviderFactory(provider)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "GetProviderFactory")
}
return driver.GetProvider(providerId, providerName, accessUrl, account, secret)
}
func GetClientRC(accessUrl, account, secret, provider string) (map[string]string, error) {
driver, err := GetProviderFactory(provider)
if err != nil {
return nil, errors.Wrap(err, "GetProviderFactory")
}
return driver.GetClientRC(accessUrl, account, secret)
}
func IsSupported(provider string) bool {
_, ok := providerTable[provider]
return ok
+21
View File
@@ -1222,3 +1222,24 @@ func (manager *SCloudproviderManager) initAllRecords() {
})
}
}
func (provider *SCloudprovider) AllowGetDetailsClirc(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return db.IsAdminAllowGetSpec(userCred, provider, "client-rc")
}
func (provider *SCloudprovider) GetDetailsClirc(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
accessUrl := provider.getAccessUrl()
passwd, err := provider.getPassword()
if err != nil {
return nil, err
}
rc, err := cloudprovider.GetClientRC(accessUrl, provider.Account, passwd, provider.Provider)
if err != nil {
return nil, err
}
return jsonutils.Marshal(rc), nil
}
func (manager *SCloudproviderManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeDomain
}
+9 -3
View File
@@ -21,11 +21,13 @@ import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
)
type IMetadataSetter interface {
SetAllMetadata(ctx context.Context, meta map[string]interface{}, userCred mcclient.TokenCredential) error
SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error
// SetAllMetadata(ctx context.Context, meta map[string]interface{}, userCred mcclient.TokenCredential) error
// SetMetadata(ctx context.Context, key string, value interface{}, userCred mcclient.TokenCredential) error
SetCloudMetadataAll(ctx context.Context, meta map[string]interface{}, userCred mcclient.TokenCredential) error
}
func syncMetadata(ctx context.Context, userCred mcclient.TokenCredential, model IMetadataSetter, remote cloudprovider.ICloudResource) error {
@@ -37,9 +39,13 @@ func syncMetadata(ctx context.Context, userCred mcclient.TokenCredential, model
log.Errorf("Get VM Metadata error: %v", err)
return err
}
store := make(map[string]interface{}, 0)
for key, value := range meta {
model.SetMetadata(ctx, "ext:"+key, value, userCred)
store[db.CLOUD_TAG_PREFIX + key] = value
}
// model.SetMetadata(ctx, "ext:"+key, value, userCred)
// replace all ext keys
model.SetCloudMetadataAll(ctx, store, userCred)
}
return nil
}
+7 -1
View File
@@ -56,7 +56,13 @@ type SAliyunClient struct {
}
func NewAliyunClient(providerId string, providerName string, accessKey string, secret string, isDebug bool) (*SAliyunClient, error) {
client := SAliyunClient{providerId: providerId, providerName: providerName, accessKey: accessKey, secret: secret, Debug: isDebug}
client := SAliyunClient{
providerId: providerId,
providerName: providerName,
accessKey: accessKey,
secret: secret,
Debug: isDebug,
}
err := client.fetchRegions()
if err != nil {
return nil, err
+8
View File
@@ -80,6 +80,14 @@ func (self *SAliyunProviderFactory) GetProvider(providerId, providerName, url, a
}, nil
}
func (self *SAliyunProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
return map[string]string{
"ALIYUN_ACCESS_KEY": account,
"ALIYUN_SECRET": secret,
"ALIYUN_REGION": aliyun.ALIYUN_DEFAULT_REGION,
}, nil
}
func init() {
factory := SAliyunProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+11 -4
View File
@@ -30,6 +30,9 @@ const (
CLOUD_PROVIDER_AWS = api.CLOUD_PROVIDER_AWS
CLOUD_PROVIDER_AWS_CN = "AWS"
AWS_INTERNATIONAL_CLOUDENV = "InternationalCloud"
AWS_CHINA_CLOUDENV = "ChinaCloud"
AWS_INTERNATIONAL_DEFAULT_REGION = "us-west-1"
AWS_CHINA_DEFAULT_REGION = "cn-north-1"
AWS_API_VERSION = "2018-10-10"
@@ -54,18 +57,22 @@ func NewAwsClient(providerId string, providerName string, accessUrl string, acce
return &client, nil
}
func (self *SAwsClient) getDefaultRegionId() string {
func GetDefaultRegionId(accessUrl string) string {
defaultRegion := AWS_INTERNATIONAL_DEFAULT_REGION
switch self.accessUrl {
case "InternationalCloud":
switch accessUrl {
case AWS_INTERNATIONAL_CLOUDENV:
defaultRegion = AWS_INTERNATIONAL_DEFAULT_REGION
case "ChinaCloud":
case AWS_CHINA_CLOUDENV:
defaultRegion = AWS_CHINA_DEFAULT_REGION
}
return defaultRegion
}
func (self *SAwsClient) getDefaultRegionId() string {
return GetDefaultRegionId(self.accessUrl)
}
func (self *SAwsClient) getDefaultSession() (*session.Session, error) {
defaultRegion := self.getDefaultRegionId()
return session.NewSession(&sdk.Config{
+9
View File
@@ -88,6 +88,15 @@ func (self *SAwsProviderFactory) GetProvider(providerId, providerName, url, acco
}, nil
}
func (self *SAwsProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
return map[string]string{
"AWS_ACCESS_URL": url,
"AWS_ACCESS_KEY": account,
"AWS_SECRET": secret,
"AWS_REGION": aws.GetDefaultRegionId(url),
}, nil
}
func init() {
factory := SAwsProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+28 -35
View File
@@ -31,7 +31,7 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
// "yunion.io/x/onecloud/pkg/httperrors"
)
const (
@@ -42,16 +42,16 @@ const (
)
type SAzureClient struct {
client autorest.Client
providerId string
providerName string
subscriptionId string
tenantId string
clientId string
clientScret string
domain string
baseUrl string
secret string
client autorest.Client
providerId string
providerName string
subscriptionId string
tenantId string
clientId string
clientScret string
domain string
baseUrl string
// secret string
envName string
ressourceGroups []SResourceGroup
fetchResourceGroups bool
@@ -87,29 +87,22 @@ var DEFAULT_API_VERSION = map[string]string{
"Microsoft.Compute/locations": "2018-06-01",
}
func NewAzureClient(providerId string, providerName string, accessKey string, secret string, envName string, debug bool) (*SAzureClient, error) {
clientInfo := strings.Split(secret, "/")
accountInfo := strings.Split(accessKey, "/")
if len(clientInfo) >= 2 && len(accountInfo) >= 1 {
client := SAzureClient{
providerId: providerId,
providerName: providerName,
secret: secret,
envName: envName,
debug: debug,
}
client.clientId, client.clientScret = clientInfo[0], strings.Join(clientInfo[1:], "/")
client.tenantId = accountInfo[0]
if len(accountInfo) == 2 {
client.subscriptionId = accountInfo[1]
}
err := client.fetchRegions()
if err != nil {
return nil, err
}
return &client, nil
func NewAzureClient(providerId string, providerName string, envName, tenantId, clientId, clientSecret, subscriptionId string, debug bool) (*SAzureClient, error) {
client := SAzureClient{
providerId: providerId,
providerName: providerName,
envName: envName,
tenantId: tenantId,
clientId: clientId,
clientScret: clientSecret,
subscriptionId: subscriptionId,
debug: debug,
}
return nil, httperrors.NewUnauthorizedError("clientId、clientScret or subscriptId input error")
err := client.fetchRegions()
if err != nil {
return nil, err
}
return &client, nil
}
func (self *SAzureClient) getDefaultClient() (*autorest.Client, error) {
@@ -678,7 +671,7 @@ func _jsonRequest(client *autorest.Client, method, domain, baseURL, body string)
return jsonutils.Parse([]byte(_data))
}
func (self *SAzureClient) UpdateAccount(tenantId, secret, envName string) error {
/*func (self *SAzureClient) UpdateAccount(envName, tenantId, appId, appKey, subscriptionId string) error {
if self.tenantId != tenantId || self.secret != secret || self.envName != envName {
if clientInfo, accountInfo := strings.Split(secret, "/"), strings.Split(tenantId, "/"); len(clientInfo) >= 2 && len(accountInfo) >= 1 {
self.clientId, self.clientScret = clientInfo[0], strings.Join(clientInfo[1:], "/")
@@ -696,7 +689,7 @@ func (self *SAzureClient) UpdateAccount(tenantId, secret, envName string) error
}
}
return nil
}
}*/
func (self *SAzureClient) fetchRegions() error {
if len(self.subscriptionId) > 0 {
+29 -2
View File
@@ -17,6 +17,7 @@ package provider
import (
"context"
"fmt"
"strings"
"yunion.io/x/jsonutils"
@@ -25,7 +26,6 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/azure"
// "yunion.io/x/log"
)
type SAzureProviderFactory struct {
@@ -87,8 +87,23 @@ func (self *SAzureProviderFactory) ValidateUpdateCloudaccountCredential(ctx cont
return account, nil
}
func parseAccount(account, secret string) (tenantId string, appId string, appKey string, subId string) {
clientInfo := strings.Split(secret, "/")
accountInfo := strings.Split(account, "/")
tenantId = accountInfo[0]
if len(accountInfo) > 1 {
subId = strings.Join(accountInfo[1:], "/")
}
appId = clientInfo[0]
if len(clientInfo) > 1 {
appKey = strings.Join(clientInfo[1:], "/")
}
return
}
func (self *SAzureProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) {
if client, err := azure.NewAzureClient(providerId, providerName, account, secret, url, false); err != nil {
tenantId, appId, appKey, subId := parseAccount(account, secret)
if client, err := azure.NewAzureClient(providerId, providerName, url, tenantId, appId, appKey, subId, false); err != nil {
return nil, err
} else {
return &SAzureProvider{
@@ -98,6 +113,18 @@ func (self *SAzureProviderFactory) GetProvider(providerId, providerName, url, ac
}
}
func (self *SAzureProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
tenantId, appId, appKey, subId := parseAccount(account, secret)
return map[string]string{
"AZURE_DIRECTORY_ID": tenantId,
"AZURE_SUBSCRIPTION_ID": subId,
"AZURE_APPLICATION_ID": appId,
"AZURE_APPLICATION_KEY": appKey,
"AZURE_REGION_ID": "",
"AZURE_CLOUD_ENV": url,
}, nil
}
func init() {
factory := SAzureProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+41 -9
View File
@@ -21,7 +21,6 @@ import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
@@ -35,6 +34,7 @@ type SDatacenter struct {
ihosts []cloudprovider.ICloudHost
istorages []cloudprovider.ICloudStorage
inetworks []IVMNetwork
Name string
}
@@ -58,7 +58,7 @@ func (dc *SDatacenter) scanHosts() error {
var hosts []mo.HostSystem
err := dc.manager.scanMObjects(dc.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
if err != nil {
return err
return errors.Wrap(err, "dc.manager.scanMObjects")
}
dc.ihosts = make([]cloudprovider.ICloudHost, len(hosts))
for i := 0; i < len(hosts); i += 1 {
@@ -71,7 +71,7 @@ func (dc *SDatacenter) scanHosts() error {
func (dc *SDatacenter) GetIHosts() ([]cloudprovider.ICloudHost, error) {
err := dc.scanHosts()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "dc.scanHosts")
}
return dc.ihosts, nil
}
@@ -83,8 +83,7 @@ func (dc *SDatacenter) scanDatastores() error {
if dsList != nil {
err := dc.manager.references2Objects(dsList, DATASTORE_PROPS, &stores)
if err != nil {
log.Errorf("references2Objects dsList fail %s", err)
return err
return errors.Wrap(err, "dc.manager.references2Objects")
}
}
dc.istorages = make([]cloudprovider.ICloudStorage, 0)
@@ -110,7 +109,7 @@ func (dc *SDatacenter) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
func (dc *SDatacenter) GetIHostByMoId(idstr string) (cloudprovider.ICloudHost, error) {
ihosts, err := dc.GetIHosts()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "dc.GetIHosts")
}
for i := 0; i < len(ihosts); i += 1 {
if ihosts[i].GetId() == idstr {
@@ -123,7 +122,7 @@ func (dc *SDatacenter) GetIHostByMoId(idstr string) (cloudprovider.ICloudHost, e
func (dc *SDatacenter) GetIStorageByMoId(idstr string) (cloudprovider.ICloudStorage, error) {
istorages, err := dc.GetIStorages()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "dc.GetIStorages")
}
for i := 0; i < len(istorages); i += 1 {
if istorages[i].GetId() == idstr {
@@ -142,8 +141,7 @@ func (dc *SDatacenter) fetchVms(vmRefs []types.ManagedObjectReference, all bool)
if vmRefs != nil {
err := dc.manager.references2Objects(vmRefs, VIRTUAL_MACHINE_PROPS, &vms)
if err != nil {
log.Errorf("references2Objects fail %s", err)
return nil, err
return nil, errors.Wrap(err, "dc.manager.references2Objects")
}
}
@@ -155,3 +153,37 @@ func (dc *SDatacenter) fetchVms(vmRefs []types.ManagedObjectReference, all bool)
}
return retVms, nil
}
func (dc *SDatacenter) scanNetworks() error {
if dc.inetworks == nil {
dc.inetworks = make([]IVMNetwork, 0)
netMOBs := dc.getDatacenter().Network
for i := range netMOBs {
dvport := mo.DistributedVirtualPortgroup{}
err := dc.manager.reference2Object(netMOBs[i], DVPORTGROUP_PROPS, &dvport)
if err == nil {
net := NewDistributedVirtualPortgroup(dc.manager, &dvport, dc)
dc.inetworks = append(dc.inetworks, net)
} else {
net := mo.Network{}
err = dc.manager.reference2Object(netMOBs[i], NETWORK_PROPS, &net)
if err == nil {
vnet := NewNetwork(dc.manager, &net, dc)
dc.inetworks = append(dc.inetworks, vnet)
} else {
return errors.Wrap(err, "dc.manager.reference2Object")
}
}
}
}
return nil
}
func (dc *SDatacenter) GetNetworks() ([]IVMNetwork, error) {
err := dc.scanNetworks()
if err != nil {
return nil, errors.Wrap(err, "dc.scanNetworks")
}
return dc.inetworks, nil
}
+2 -2
View File
@@ -31,6 +31,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
@@ -229,8 +230,7 @@ func (cli *SESXiClient) reference2Object(ref types.ManagedObjectReference, props
pc := property.DefaultCollector(cli.client.Client)
err := pc.RetrieveOne(cli.context, ref, props, dst)
if err != nil {
log.Errorf("pc.RetrieveOne fail %s", err)
return err
return errors.Wrap(err, "pc.RetrieveOne")
}
return nil
}
+144
View File
@@ -0,0 +1,144 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package esxi
import (
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type IVMNetwork interface {
GetId() string
GetName() string
GetVlanId() int32
GetNumPorts() int32
GetActivePorts() []string
GetType() string
}
const (
NET_TYPE_NETWORK = "network"
NET_TYPE_DVPORTGROUP = "dvportgroup"
VLAN_MODE_NONE = "none"
VLAN_MODE_VLAN = "vlan"
VLAN_MODE_PVLAN = "pvlan"
VLAN_MODE_TRUNK = "trunk"
)
var NETWORK_PROPS = []string{"name", "parent", "summary", "host", "vm"}
var DVPORTGROUP_PROPS = []string{"name", "parent", "summary", "host", "vm", "config"}
type SNetwork struct {
SManagedObject
}
type SDistributedVirtualPortgroup struct {
SManagedObject
}
func NewNetwork(manager *SESXiClient, net *mo.Network, dc *SDatacenter) *SNetwork {
return &SNetwork{SManagedObject: newManagedObject(manager, net, dc)}
}
func NewDistributedVirtualPortgroup(manager *SESXiClient, net *mo.DistributedVirtualPortgroup, dc *SDatacenter) *SDistributedVirtualPortgroup {
return &SDistributedVirtualPortgroup{SManagedObject: newManagedObject(manager, net, dc)}
}
func (net *SNetwork) getMONetwork() *mo.Network {
return net.object.(*mo.Network)
}
func (net *SNetwork) GetName() string {
return net.getMONetwork().Name
}
func (net *SNetwork) GetType() string {
return NET_TYPE_NETWORK
}
func (net *SNetwork) GetVlanId() int32 {
return -1
}
func (net *SNetwork) GetVlanMode() string {
return VLAN_MODE_NONE
}
func (net *SNetwork) GetNumPorts() int32 {
return -1
}
func (net *SNetwork) GetActivePorts() []string {
return nil
}
func (net *SDistributedVirtualPortgroup) getMODVPortgroup() *mo.DistributedVirtualPortgroup {
return net.object.(*mo.DistributedVirtualPortgroup)
}
func (net *SDistributedVirtualPortgroup) GetName() string {
return net.getMODVPortgroup().Name
}
func (net *SDistributedVirtualPortgroup) GetType() string {
return NET_TYPE_DVPORTGROUP
}
func (net *SDistributedVirtualPortgroup) GetVlanId() int32 {
dvpg := net.getMODVPortgroup()
switch conf := dvpg.Config.DefaultPortConfig.(type) {
case *types.VMwareDVSPortSetting:
switch vlanConf := conf.Vlan.(type) {
case *types.VmwareDistributedVirtualSwitchTrunkVlanSpec:
return -1
case *types.VmwareDistributedVirtualSwitchPvlanSpec:
return vlanConf.PvlanId
case *types.VmwareDistributedVirtualSwitchVlanIdSpec:
return vlanConf.VlanId
}
}
return -1
}
func (net *SDistributedVirtualPortgroup) GetVlanMode() string {
dvpg := net.getMODVPortgroup()
switch conf := dvpg.Config.DefaultPortConfig.(type) {
case *types.VMwareDVSPortSetting:
switch conf.Vlan.(type) {
case *types.VmwareDistributedVirtualSwitchTrunkVlanSpec:
return VLAN_MODE_TRUNK
case *types.VmwareDistributedVirtualSwitchPvlanSpec:
return VLAN_MODE_PVLAN
case *types.VmwareDistributedVirtualSwitchVlanIdSpec:
return VLAN_MODE_VLAN
}
}
return VLAN_MODE_NONE
}
func (net *SDistributedVirtualPortgroup) GetNumPorts() int32 {
dvpg := net.getMODVPortgroup()
return dvpg.Config.NumPorts
}
func (net *SDistributedVirtualPortgroup) GetActivePorts() []string {
dvpg := net.getMODVPortgroup()
switch conf := dvpg.Config.DefaultPortConfig.(type) {
case *types.VMwareDVSPortSetting:
return conf.UplinkTeamingPolicy.UplinkPortOrder.ActiveUplinkPort
}
return nil
}
+18
View File
@@ -125,6 +125,24 @@ func (self *SESXiProviderFactory) GetProvider(providerId, providerName, urlStr,
}, nil
}
func (self *SESXiProviderFactory) GetClientRC(urlStr, account, secret string) (map[string]string, error) {
parts, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
host, port, err := parseHostPort(parts.Host, 443)
if err != nil {
return nil, err
}
return map[string]string{
"VMWARE_HOST": host,
"VMWARE_PORT": fmt.Sprintf("%d", port),
"VMWARE_ACCOUNT": account,
"VMWARE_PASSWORD": secret,
}, nil
}
func init() {
factory := SESXiProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+27
View File
@@ -0,0 +1,27 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package esxi
import "github.com/vmware/govmomi/vim25/mo"
var RESOURCEPOOL_PROPS = []string{"name", "parent"}
type SResourcePool struct {
SManagedObject
}
func NewResourcePool(manager *SESXiClient, rp *mo.ResourcePool, dc *SDatacenter) *SResourcePool {
return &SResourcePool{SManagedObject: newManagedObject(manager, rp, dc)}
}
+38
View File
@@ -0,0 +1,38 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/util/esxi"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type NetworkListOptions struct {
DATACENTER string `help:"List datastores in datacenter"`
}
shellutils.R(&NetworkListOptions{}, "network-list", "List networks in datacenter", func(cli *esxi.SESXiClient, args *NetworkListOptions) error {
dc, err := cli.FindDatacenterByMoId(args.DATACENTER)
if err != nil {
return err
}
nets, err := dc.GetNetworks()
if err != nil {
return err
}
printList(nets, nil)
return nil
})
}
+31 -2
View File
@@ -31,6 +31,7 @@ import (
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/pkg/util/regutils"
"github.com/pkg/errors"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -38,7 +39,7 @@ import (
"yunion.io/x/onecloud/pkg/util/billing"
)
var VIRTUAL_MACHINE_PROPS = []string{"name", "parent", "runtime", "summary", "config", "guest"}
var VIRTUAL_MACHINE_PROPS = []string{"name", "parent", "runtime", "summary", "config", "guest", "resourcePool"}
type SVirtualMachine struct {
SManagedObject
@@ -64,7 +65,24 @@ func (self *SVirtualMachine) GetSecurityGroupIds() ([]string, error) {
}
func (self *SVirtualMachine) GetMetadata() *jsonutils.JSONDict {
return nil
meta := jsonutils.NewDict()
meta.Set("datacenter", jsonutils.NewString(self.GetDatacenterPathString()))
rp, _ := self.getResourcePool()
if rp != nil {
rpPath := rp.GetPath()
rpOffset := -1
for i := range rpPath {
if rpPath[i] == "Resources" {
if i > 0 {
meta.Set("cluster", jsonutils.NewString(rpPath[i-1]))
rpOffset = i
}
} else if rpOffset >= 0 && i > rpOffset {
meta.Set(fmt.Sprintf("pool%d", i-rpOffset-1), jsonutils.NewString(rpPath[i]))
}
}
}
return meta
}
func (self *SVirtualMachine) getVirtualMachine() *mo.VirtualMachine {
@@ -797,3 +815,14 @@ func (self *SVirtualMachine) GetProjectId() string {
func (self *SVirtualMachine) GetError() error {
return nil
}
func (self *SVirtualMachine) getResourcePool() (*SResourcePool, error) {
vm := self.getVirtualMachine()
morp := mo.ResourcePool{}
err := self.manager.reference2Object(*vm.ResourcePool, RESOURCEPOOL_PROPS, &morp)
if err != nil {
return nil, errors.Wrap(err, "self.manager.reference2Object")
}
rp := NewResourcePool(self.manager, &morp, self.datacenter)
return rp, nil
}
+1 -15
View File
@@ -55,25 +55,11 @@ type SHuaweiClient struct {
iregions []cloudprovider.ICloudRegion
}
func parseAccount(account string) (accessKey string, projectId string) {
segs := strings.Split(account, "/")
if len(segs) == 2 {
accessKey = segs[0]
projectId = segs[1]
} else {
accessKey = account
projectId = ""
}
return
}
// 进行资源操作时参数account 对应数据库cloudprovider表中的account字段,由accessKey和projectID两部分组成,通过"/"分割。
// 初次导入Subaccount时,参数account对应cloudaccounts表中的account字段,即accesskey。此时projectID为空,
// 只能进行同步子账号、查询region列表等projectId无关的操作。
// todo: 通过accessurl支持国际站。目前暂时未支持国际站
func NewHuaweiClient(providerId, providerName, accessurl, account, secret string, debug bool) (*SHuaweiClient, error) {
accessKey, projectId := parseAccount(account)
func NewHuaweiClient(providerId, providerName, accessurl, accessKey, secret, projectId string, debug bool) (*SHuaweiClient, error) {
client := SHuaweiClient{
providerId: providerId,
providerName: providerName,
+27 -1
View File
@@ -16,6 +16,7 @@ package provider
import (
"context"
"strings"
"yunion.io/x/jsonutils"
@@ -73,8 +74,22 @@ func (self *SHuaweiProviderFactory) ValidateUpdateCloudaccountCredential(ctx con
return account, nil
}
func parseAccount(account string) (accessKey string, projectId string) {
segs := strings.Split(account, "/")
if len(segs) == 2 {
accessKey = segs[0]
projectId = segs[1]
} else {
accessKey = account
projectId = ""
}
return
}
func (self *SHuaweiProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) {
client, err := huawei.NewHuaweiClient(providerId, providerName, url, account, secret, false)
accessKey, projectId := parseAccount(account)
client, err := huawei.NewHuaweiClient(providerId, providerName, url, accessKey, secret, projectId, false)
if err != nil {
return nil, err
}
@@ -84,6 +99,17 @@ func (self *SHuaweiProviderFactory) GetProvider(providerId, providerName, url, a
}, nil
}
func (self *SHuaweiProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
accessKey, projectId := parseAccount(account)
return map[string]string{
"HUAWEI_CLOUD_ENV": url,
"HUAWEI_ACCESS_KEY": accessKey,
"HUAWEI_SECRET": secret,
"HUAWEI_REGION": huawei.HUAWEI_DEFAULT_REGION,
"HUAWEI_PROJECT": projectId,
}, nil
}
func init() {
factory := SHuaweiProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+22
View File
@@ -126,6 +126,28 @@ func (self *SOpenStackProviderFactory) GetProvider(providerId, providerName, url
}, nil
}
func (self *SOpenStackProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
accountInfo := strings.Split(account, "/")
if len(accountInfo) < 2 {
return nil, fmt.Errorf("Missing username or project name %s", account)
}
project, username, endpointType, domainName, projectDomainName := accountInfo[0], accountInfo[1], "internal", "Default", "Default"
if len(accountInfo) == 3 {
domainName, projectDomainName = accountInfo[2], accountInfo[2]
}
return map[string]string{
"OPENSTACK_AUTH_URL": url,
"OPENSTACK_USERNAME": username,
"OPENSTACK_PASSWORD": secret,
"OPENSTACK_PROJECT": project,
"OPENSTACK_ENDPOINT_TYPE": endpointType,
"OPENSTACK_DOMAIN_NAME": domainName,
"OPENSTACK_PROJECT_DOMAIN": projectDomainName,
"OPENSTACK_REGION_ID": openstack.OPENSTACK_DEFAULT_REGION,
}, nil
}
func init() {
factory := SOpenStackProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pinyinutils // import "yunion.io/x/onecloud/pkg/util/pinyinutils"
+22 -1
View File
@@ -90,7 +90,13 @@ func (self *SQcloudProviderFactory) ValidateUpdateCloudaccountCredential(ctx con
}
func (self *SQcloudProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) {
client, err := qcloud.NewQcloudClient(providerId, providerName, account, secret, false)
secretId := account
appId := ""
if tmp := strings.Split(account, "/"); len(tmp) == 2 {
secretId = tmp[0]
appId = tmp[1]
}
client, err := qcloud.NewQcloudClient(providerId, providerName, secretId, secret, appId, false)
if err != nil {
return nil, err
}
@@ -100,6 +106,21 @@ func (self *SQcloudProviderFactory) GetProvider(providerId, providerName, url, a
}, nil
}
func (self *SQcloudProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
secretId := account
appId := ""
if tmp := strings.Split(account, "/"); len(tmp) == 2 {
secretId = tmp[0]
appId = tmp[1]
}
return map[string]string{
"QCLOUD_APPID": appId,
"QCLOUD_SECRET_ID": secretId,
"QCLOUD_SECRET_KEY": secret,
"QCLOUD_REGION": qcloud.QCLOUD_DEFAULT_REGION,
}, nil
}
func init() {
factory := SQcloudProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+8 -5
View File
@@ -54,11 +54,14 @@ type SQcloudClient struct {
Debug bool
}
func NewQcloudClient(providerId string, providerName string, secretID string, secretKey string, isDebug bool) (*SQcloudClient, error) {
client := SQcloudClient{providerId: providerId, providerName: providerName, SecretID: secretID, SecretKey: secretKey, Debug: isDebug}
if account := strings.Split(secretID, "/"); len(account) == 2 {
client.SecretID = account[0]
client.AppID = account[1]
func NewQcloudClient(providerId string, providerName string, secretID string, secretKey string, appID string, isDebug bool) (*SQcloudClient, error) {
client := SQcloudClient{
providerId: providerId,
providerName: providerName,
SecretID: secretID,
SecretKey: secretKey,
AppID: appID,
Debug: isDebug,
}
err := client.fetchRegions()
if err != nil {
+26 -1
View File
@@ -16,6 +16,7 @@ package provider
import (
"context"
"strings"
"yunion.io/x/jsonutils"
@@ -70,8 +71,22 @@ func (self *SUcloudProviderFactory) ValidateUpdateCloudaccountCredential(ctx con
return account, nil
}
func parseAccount(account string) (accessKey string, projectId string) {
segs := strings.Split(account, "::")
if len(segs) == 2 {
accessKey = segs[0]
projectId = segs[1]
} else {
accessKey = account
projectId = ""
}
return
}
func (self *SUcloudProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) {
client, err := ucloud.NewUcloudClient(providerId, providerName, account, secret, false)
accessKey, projectId := parseAccount(account)
client, err := ucloud.NewUcloudClient(providerId, providerName, accessKey, secret, projectId, false)
if err != nil {
return nil, err
}
@@ -81,6 +96,16 @@ func (self *SUcloudProviderFactory) GetProvider(providerId, providerName, url, a
}, nil
}
func (self *SUcloudProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
accessKey, projectId := parseAccount(account)
return map[string]string{
"UCLOUD_ACCESS_KEY": accessKey,
"UCLOUD_SECRET": secret,
"UCLOUD_REGION": ucloud.UCLOUD_DEFAULT_REGION,
"UCLOUD_PROJECT": projectId,
}, nil
}
func init() {
factory := SUcloudProviderFactory{}
cloudprovider.RegisterFactory(&factory)
+1 -15
View File
@@ -65,23 +65,9 @@ type SUcloudClient struct {
Debug bool
}
func parseAccount(account string) (accessKey string, projectId string) {
segs := strings.Split(account, "::")
if len(segs) == 2 {
accessKey = segs[0]
projectId = segs[1]
} else {
accessKey = account
projectId = ""
}
return
}
// 进行资源操作时参数account 对应数据库cloudprovider表中的account字段,由accessKey和projectID两部分组成,通过"/"分割。
// 初次导入Subaccount时,参数account对应cloudaccounts表中的account字段,即accesskey。此时projectID为空,只能进行同步子账号(项目)、查询region列表等projectId无关的操作。
func NewUcloudClient(providerId string, providerName string, account string, secret string, isDebug bool) (*SUcloudClient, error) {
accessKey, projectId := parseAccount(account)
func NewUcloudClient(providerId string, providerName string, accessKey string, secret string, projectId string, isDebug bool) (*SUcloudClient, error) {
client := SUcloudClient{
providerId: providerId,
providerName: providerName,
+9
View File
@@ -88,6 +88,15 @@ func (self *SZStackProviderFactory) GetProvider(providerId, providerName, url, u
}, nil
}
func (self *SZStackProviderFactory) GetClientRC(url, account, secret string) (map[string]string, error) {
return map[string]string{
"ZSTACK_AUTH_URL": url,
"ZSTACK_USERNAME": account,
"ZSTACK_PASSWORD": secret,
"ZSTACK_REGION_ID": zstack.ZSTACK_DEFAULT_REGION,
}, nil
}
func init() {
factory := SZStackProviderFactory{}
cloudprovider.RegisterFactory(&factory)