diff --git a/cmd/climc/shell/cloudaccounts.go b/cmd/climc/shell/cloudaccounts.go index 1d744f6ceb..9c9369875a 100644 --- a/cmd/climc/shell/cloudaccounts.go +++ b/cmd/climc/shell/cloudaccounts.go @@ -34,7 +34,7 @@ func init() { NAME string `help:"Name of cloud account"` ACCOUNT string `help:"Account to access the cloud account"` SECRET string `help:"Secret to access the cloud account, clientId/clientScret for Azure"` - PROVIDER string `help:"Driver for cloud account" choices:"VMware|Aliyun|Azure|Qcloud|OpenStack"` + PROVIDER string `help:"Driver for cloud account" choices:"VMware|Aliyun|Azure|Qcloud|OpenStack|Huawei"` AccessURL string `helo:"hello" metavar:"Azure choices: "` Desc string `help:"Description"` Enabled bool `help:"Enabled the account automatically"` diff --git a/pkg/util/huawei/client/clients.go b/pkg/util/huawei/client/clients.go index 3d031a8ea1..6e561e4d2b 100644 --- a/pkg/util/huawei/client/clients.go +++ b/pkg/util/huawei/client/clients.go @@ -12,21 +12,22 @@ type Client struct { domainId string projectId string - Bandwidths *modules.SBandwidthManager - Disks *modules.SDiskManager - Eips *modules.SEipManager - Images *modules.SImageManager - Interface *modules.SInterfaceManager - Keypairs *modules.SKeypairManager - Port *modules.SPortManager - Projects *modules.SProjectManager - Regions *modules.SRegionManager - SecurityGroups *modules.SSecurityGroupManager - Servers *modules.SServerManager - Snapshots *modules.SSnapshotManager - Subnets *modules.SSubnetManager - Vpcs *modules.SVpcManager - Zones *modules.SZoneManager + Bandwidths *modules.SBandwidthManager + Disks *modules.SDiskManager + Eips *modules.SEipManager + Images *modules.SImageManager + Interface *modules.SInterfaceManager + Keypairs *modules.SKeypairManager + Port *modules.SPortManager + Projects *modules.SProjectManager + Regions *modules.SRegionManager + SecurityGroupRules *modules.SSecgroupRuleManager + SecurityGroups *modules.SSecurityGroupManager + Servers *modules.SServerManager + Snapshots *modules.SSnapshotManager + Subnets *modules.SSubnetManager + Vpcs *modules.SVpcManager + Zones *modules.SZoneManager } func (self *Client) Init() error { @@ -101,6 +102,10 @@ func (self *Client) initManagers() { self.Keypairs = modules.NewKeypairManager(self.regionId, self.projectId, self.signer) } + if self.SecurityGroupRules == nil { + self.SecurityGroupRules = modules.NewSecgroupRuleManager(self.regionId, self.projectId, self.signer) + } + if self.SecurityGroups == nil { self.SecurityGroups = modules.NewSecurityGroupManager(self.regionId, self.projectId, self.signer) } diff --git a/pkg/util/huawei/client/modules/manager_base.go b/pkg/util/huawei/client/modules/manager_base.go index 61b6cdc809..7d6091a2bb 100644 --- a/pkg/util/huawei/client/modules/manager_base.go +++ b/pkg/util/huawei/client/modules/manager_base.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "strconv" + "yunion.io/x/jsonutils" "yunion.io/x/onecloud/pkg/util/httputils" "yunion.io/x/onecloud/pkg/util/huawei/client/auth" diff --git a/pkg/util/huawei/client/modules/mod_secgroup_rules.go b/pkg/util/huawei/client/modules/mod_secgroup_rules.go index 382057c367..e0e463b288 100644 --- a/pkg/util/huawei/client/modules/mod_secgroup_rules.go +++ b/pkg/util/huawei/client/modules/mod_secgroup_rules.go @@ -17,8 +17,8 @@ func NewSecgroupRuleManager(regionId string, projectId string, signer auth.Signe Region: regionId, ProjectId: projectId, version: "v1", - Keyword: "security-group-rule", - KeywordPlural: "security-group-rules", + Keyword: "security_group_rule", + KeywordPlural: "security_group_rules", ResourceKeyword: "security-group-rules", }} diff --git a/pkg/util/huawei/huawei.go b/pkg/util/huawei/huawei.go index e3583e9440..d9e2105627 100644 --- a/pkg/util/huawei/huawei.go +++ b/pkg/util/huawei/huawei.go @@ -31,6 +31,7 @@ type SHuaweiClient struct { providerId string providerName string projectId string // 华为云项目ID. + accessUrl string // 服务区域 ChinaCloud | InternationalCloud accessKey string secret string iregions []cloudprovider.ICloudRegion @@ -52,7 +53,8 @@ func parseAccount(account string) (accessKey string, projectId string) { // 进行资源操作时参数account 对应数据库cloudprovider表中的account字段,由accessKey和projectID两部分组成,通过"/"分割。 // 初次导入Subaccount时,参数account对应cloudaccounts表中的account字段,即accesskey。此时projectID为空, // 只能进行同步子账号、查询region列表等projectId无关的操作。 -func NewHuaweiClient(providerId string, providerName string, account string, secret string) (*SHuaweiClient, error) { +// todo: 通过accessurl支持国际站。目前暂时未支持国际站 +func NewHuaweiClient(providerId, providerName, accessurl, account, secret string) (*SHuaweiClient, error) { accessKey, projectId := parseAccount(account) client := SHuaweiClient{ providerId: providerId, @@ -137,9 +139,13 @@ func (self *SHuaweiClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) } // https://support.huaweicloud.com/api-iam/zh-cn_topic_0074171149.html - subAccounts := make([]cloudprovider.SSubAccount, len(projects)) + subAccounts := make([]cloudprovider.SSubAccount, 0) for i := range projects { project := projects[i] + // name 为MOS的project是华为云内部的一个特殊project。不需要同步到本地 + if strings.ToLower(project.Name) == "mos" { + continue + } s := cloudprovider.SSubAccount{ Name: project.Name, State: models.CLOUD_PROVIDER_CONNECTED, diff --git a/pkg/util/huawei/project.go b/pkg/util/huawei/project.go index 58993dba81..48f7d6b7b5 100644 --- a/pkg/util/huawei/project.go +++ b/pkg/util/huawei/project.go @@ -37,11 +37,7 @@ func (self *SHuaweiClient) fetchProjects() ([]SProject, error) { huawei, _ := clients.NewClientWithAccessKey("", "", self.accessKey, self.secret) projects := make([]SProject, 0) err := DoList(huawei.Projects.List, nil, &projects) - if err != nil { - return nil, err - } - - return projects, nil + return projects, err } func (self *SHuaweiClient) GetProjectById(projectId string) (SProject, error) { diff --git a/pkg/util/huawei/provider/provider.go b/pkg/util/huawei/provider/provider.go index d7800d4b3e..954be702ad 100644 --- a/pkg/util/huawei/provider/provider.go +++ b/pkg/util/huawei/provider/provider.go @@ -15,7 +15,7 @@ func (self *SHuaweiProviderFactory) ValidateChangeBandwidth(instanceId string, b } func (self *SHuaweiProviderFactory) GetProvider(providerId, providerName, url, account, secret string) (cloudprovider.ICloudProvider, error) { - client, err := huawei.NewHuaweiClient(providerId, providerName, account, secret) + client, err := huawei.NewHuaweiClient(providerId, providerName, url, account, secret) if err != nil { return nil, err } diff --git a/pkg/util/huawei/securitygroup.go b/pkg/util/huawei/securitygroup.go index 62a1aff3a6..8349b67958 100644 --- a/pkg/util/huawei/securitygroup.go +++ b/pkg/util/huawei/securitygroup.go @@ -20,12 +20,12 @@ import ( ) type SecurityGroupRule struct { - Direction string `json:"direction"` - Ethertype string `json:"ethertype"` - ID string `json:"id"` - Description string `json:"description"` - SecurityGroupID string `json:"security_group_id"` - RemoteGroupID *string `json:"remote_group_id,omitempty"` + Direction string `json:"direction"` + Ethertype string `json:"ethertype"` + ID string `json:"id"` + Description string `json:"description"` + SecurityGroupID string `json:"security_group_id"` + RemoteGroupID string `json:"remote_group_id"` } type SecurityGroupRuleDetail struct { @@ -59,6 +59,11 @@ func (self *SSecurityGroup) GetId() string { } func (self *SSecurityGroup) GetVpcId() string { + // 无vpc关联的安全组统一返回normal + if len(self.VpcID) == 0 { + return "normal" + } + return self.VpcID } @@ -101,6 +106,11 @@ func (self *SSecurityGroup) GetDescription() string { func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) { rules := make([]secrules.SecurityRule, 0) for _, r := range self.SecurityGroupRules { + // 忽略了源地址是安全组的规则 + if len(r.RemoteGroupID) > 0 { + continue + } + rule, err := self.GetSecurityRule(r.ID) if err != nil { return rules, err @@ -114,7 +124,7 @@ func (self *SSecurityGroup) GetRules() ([]secrules.SecurityRule, error) { func (self *SSecurityGroup) GetSecurityRule(ruleId string) (secrules.SecurityRule, error) { remoteRule := SecurityGroupRuleDetail{} - err := DoGet(self.vpc.region.ecsClient.SecurityGroups.Get, ruleId, nil, &remoteRule) + err := DoGet(self.vpc.region.ecsClient.SecurityGroupRules.Get, ruleId, nil, &remoteRule) if err != nil { return secrules.SecurityRule{}, err } @@ -126,6 +136,11 @@ func (self *SSecurityGroup) GetSecurityRule(ruleId string) (secrules.SecurityRul direction = secrules.SecurityRuleEgress } + protocol := "any" + if remoteRule.Protocol != "" { + protocol = remoteRule.Protocol + } + // todo: 没考虑ipv6。可能报错 ipNet := &net.IPNet{} if len(remoteRule.RemoteIPPrefix) > 0 { @@ -136,7 +151,7 @@ func (self *SSecurityGroup) GetSecurityRule(ruleId string) (secrules.SecurityRul Priority: 0, Action: secrules.SecurityRuleAllow, IPNet: ipNet, - Protocol: remoteRule.Protocol, + Protocol: protocol, Direction: direction, PortStart: int(remoteRule.PortRangeMin), PortEnd: int(remoteRule.PortRangeMax), diff --git a/pkg/util/huawei/vpc.go b/pkg/util/huawei/vpc.go index a9907e4525..c32cf0b4c4 100644 --- a/pkg/util/huawei/vpc.go +++ b/pkg/util/huawei/vpc.go @@ -69,12 +69,14 @@ func (self *SVpc) fetchNetworks() error { return nil } +// 华为云安全组可以被同region的VPC使用 func (self *SVpc) fetchSecurityGroups() error { limit := 100 marker := "" secgroups := make([]SSecurityGroup, 0) for { - parts, count, err := self.region.GetSecurityGroups(self.GetId(), limit, marker) + // todo: vpc 和 安全组的关联关系还需要进一步确认。 + parts, count, err := self.region.GetSecurityGroups("", limit, marker) if err != nil { return err }