mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #10677 from ioito/automated-cherry-pick-of-#10666-upstream-release-3.7
Automated cherry pick of #10666: feat: add nas sync
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.AccessGroupCaches).WithKeyword("access-group-cache")
|
||||
cmd.List(&compute.AccessGroupCacheListOptions{})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.AccessGroupRules).WithKeyword("access-group-rule")
|
||||
cmd.List(&compute.AccessGroupRuleListOptions{})
|
||||
cmd.Delete(&options.BaseIdOptions{})
|
||||
cmd.Create(&compute.AccessRuleCreateOptions{})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.AccessGroups).WithKeyword("access-group")
|
||||
cmd.List(&compute.AccessGroupListOptions{})
|
||||
cmd.Delete(&options.BaseIdOptions{})
|
||||
cmd.Create(&options.BaseCreateOptions{})
|
||||
cmd.Perform("syncstatus", &options.BaseIdOptions{})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.FileSystems).WithKeyword("file-system")
|
||||
cmd.List(&compute.FileSystemListOptions{})
|
||||
cmd.Show(&options.BaseIdOptions{})
|
||||
cmd.Delete(&options.BaseIdOptions{})
|
||||
cmd.Create(&compute.FileSystemCreateOptions{})
|
||||
cmd.Perform("syncstatus", &compute.FileSystemIdOption{})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.MountTargets).WithKeyword("mount-target")
|
||||
cmd.Show(&options.BaseIdOptions{})
|
||||
cmd.Delete(&options.BaseIdOptions{})
|
||||
cmd.List(&compute.MountTargetListOptions{})
|
||||
cmd.Create(&compute.MountTargetCreateOptions{})
|
||||
cmd.Perform("syncstatus", &options.BaseIdOptions{})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/cmd/climc/shell"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options/compute"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := shell.NewResourceCmd(&modules.NasSkus).WithKeyword("nas-sku")
|
||||
cmd.List(&compute.NasSkuListOption{})
|
||||
cmd.Show(&compute.NasSkuIdOption{})
|
||||
cmd.PerformClass("sync-skus", &options.SkuSyncOptions{})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type AccessGroupCacheListInput struct {
|
||||
apis.StatusStandaloneResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
ManagedResourceListInput
|
||||
RegionalFilterListInput
|
||||
|
||||
AccessGroupFilterListInput
|
||||
}
|
||||
|
||||
type AccessGroupCacheDetails struct {
|
||||
apis.StatusStandaloneResourceDetails
|
||||
apis.DomainizedResourceInfo
|
||||
ManagedResourceInfo
|
||||
CloudregionResourceInfo
|
||||
AccessGroupResourceInfo
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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 compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type AccessGroupRuleListInput struct {
|
||||
apis.ResourceBaseListInput
|
||||
|
||||
AccessGroupFilterListInput
|
||||
}
|
||||
|
||||
type AccessGroupRuleDetails struct {
|
||||
apis.ResourceBaseDetails
|
||||
|
||||
AccessGroupResourceInfo
|
||||
}
|
||||
|
||||
type AccessGroupRuleCreateInput struct {
|
||||
apis.ResourceBaseCreateInput
|
||||
|
||||
Priority int
|
||||
Source string
|
||||
RWAccessType string
|
||||
UserAccessType string
|
||||
Description string
|
||||
AccessGroupId string
|
||||
}
|
||||
|
||||
type AccessGroupRuleUpdateInput struct {
|
||||
Priority *int
|
||||
Source string
|
||||
RWAccessType string
|
||||
UserAccessType string
|
||||
Description string
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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 compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
DEFAULT_ACCESS_GROUP = "default"
|
||||
|
||||
ACCESS_GROUP_STATUS_AVAILABLE = "available"
|
||||
ACCESS_GROUP_STATUS_DELETING = "deleting"
|
||||
ACCESS_GROUP_STATUS_DELETE_FAILED = "delete_failed"
|
||||
ACCESS_GROUP_STATUS_CREATING = "creating"
|
||||
ACCESS_GROUP_STATUS_SYNC_RULES = "sync_rules"
|
||||
ACCESS_GROUP_STATUS_SYNC_RULES_FAILED = "sync_rules_failed"
|
||||
ACCESS_GROUP_STATUS_UNKNOWN = "unknown"
|
||||
)
|
||||
|
||||
type AccessGroupListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
}
|
||||
|
||||
type AccessGroupDetails struct {
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
}
|
||||
|
||||
type AccessGroupResourceInfo struct {
|
||||
// 权限组名称
|
||||
AccessGroup string `json:"access_group"`
|
||||
}
|
||||
|
||||
type AccessGroupFilterListInput struct {
|
||||
// 权限组Id
|
||||
AccessGroupId string `json:"access_group_id"`
|
||||
|
||||
// 以权限组排序
|
||||
OrderByAccessGroup string `json:"order_by_access_group"`
|
||||
}
|
||||
|
||||
type AccessGroupCreateInput struct {
|
||||
apis.StatusInfrasResourceBaseCreateInput
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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 compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
// 可用
|
||||
NAS_STATUS_AVAILABLE = "available"
|
||||
// 不可用
|
||||
NAS_STATUS_UNAVAILABLE = "unavailable"
|
||||
// 扩容中
|
||||
NAS_STATUS_EXTENDING = "extending"
|
||||
// 创建中
|
||||
NAS_STATUS_CREATING = "creating"
|
||||
// 创建失败
|
||||
NAS_STATUS_CREATE_FAILED = "create_failed"
|
||||
// 未知
|
||||
NAS_STATUS_UNKNOWN = "unknown"
|
||||
// 删除中
|
||||
NAS_STATUS_DELETING = "deleting"
|
||||
NAS_STATUS_DELETE_FAILED = "delete_failed"
|
||||
)
|
||||
|
||||
type FileSystemListInput struct {
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
ManagedResourceListInput
|
||||
|
||||
RegionalFilterListInput
|
||||
}
|
||||
|
||||
type FileSystemCreateInput struct {
|
||||
apis.StatusInfrasResourceBaseCreateInput
|
||||
// 协议类型
|
||||
// enum: NFS, SMB, CPFS
|
||||
Protocol string `json:"protocol"`
|
||||
|
||||
// 文件系统类型
|
||||
// enmu: extreme, standard, cpfs
|
||||
FileSystemType string `json:"file_system_type"`
|
||||
|
||||
// 容量大小
|
||||
Capacity int64 `json:"capacity"`
|
||||
|
||||
// IP子网Id
|
||||
NetworkId string `json:"network_id"`
|
||||
|
||||
// 存储类型
|
||||
// enmu: performance, capacity, standard, advance, advance_100, advance_200
|
||||
StorageType string `json:"storage_type"`
|
||||
|
||||
// 可用区Id, 若不指定IP子网,此参数必填
|
||||
ZoneId string `json:"zone_id"`
|
||||
|
||||
//swagger:ignore
|
||||
CloudregionId string `json:"cloudregion_id"`
|
||||
|
||||
// 订阅Id, 若传入network_id此参数可忽略
|
||||
ManagerId string `json:"manager_id"`
|
||||
}
|
||||
|
||||
type FileSystemSyncstatusInput struct {
|
||||
}
|
||||
|
||||
type FileSystemDetails struct {
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
ManagedResourceInfo
|
||||
CloudregionResourceInfo
|
||||
|
||||
Vpc string
|
||||
Network string
|
||||
Zone string
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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 compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
MOUNT_TARGET_STATUS_AVAILABLE = "available"
|
||||
MOUNT_TARGET_STATUS_UNAVAILABLE = "unavailable"
|
||||
MOUNT_TARGET_STATUS_CREATING = "creating"
|
||||
MOUNT_TARGET_STATUS_CREATE_FAILED = "create_failed"
|
||||
MOUNT_TARGET_STATUS_DELETING = "deleting"
|
||||
MOUNT_TARGET_STATUS_DELETE_FAILED = "delete_failed"
|
||||
MOUNT_TARGET_STATUS_UNKNOWN = "unknown"
|
||||
)
|
||||
|
||||
type MountTargetListInput struct {
|
||||
apis.StatusStandaloneResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
AccessGroupFilterListInput
|
||||
VpcFilterListInput
|
||||
NetworkFilterListInput
|
||||
|
||||
// 文件系统Id
|
||||
FileSystemId string `json:"file_system_id"`
|
||||
}
|
||||
|
||||
type MountTargetDetails struct {
|
||||
apis.StatusStandaloneResourceDetails
|
||||
AccessGroupResourceInfo
|
||||
VpcResourceInfo
|
||||
NetworkResourceInfo
|
||||
|
||||
FileSystem string
|
||||
}
|
||||
|
||||
type MountTargetCreateInput struct {
|
||||
apis.StatusStandaloneResourceCreateInput
|
||||
|
||||
// 网络类型
|
||||
// enmu: vpc, classic
|
||||
// default: vpc
|
||||
NetworkType string `json:"network_type"`
|
||||
|
||||
// 文件系统Id
|
||||
// required: true
|
||||
FileSystemId string `json:"file_system_id"`
|
||||
|
||||
// Ip子网名称或Id, network_type == vpc时有效
|
||||
// required: true
|
||||
NetworkId string `json:"network_id"`
|
||||
// swagger:ignore
|
||||
Network string `json:"network" yunion-deprecated-by:"network_id"`
|
||||
|
||||
// swagger:ignore
|
||||
VpcId string `json:"vpc_id"`
|
||||
|
||||
// 权限组Id
|
||||
AccessGroupId string `json:"access_group_id"`
|
||||
}
|
||||
|
||||
type MountTargetSyncstatusInput struct {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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 compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
const (
|
||||
NAS_SKU_AVAILABLE = "available"
|
||||
NAS_SKU_SOLDOUT = "soldout"
|
||||
)
|
||||
|
||||
type NasSkuListInput struct {
|
||||
apis.EnabledStatusStandaloneResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
RegionalFilterListInput
|
||||
|
||||
PostpaidStatus string `json:"postpaid_stauts"`
|
||||
PrepaidStatus string `json:"prepaid_status"`
|
||||
|
||||
Providers []string `json:"providers"`
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
Provider []string `json:"provider" yunion-deprecated-by:"providers"`
|
||||
}
|
||||
|
||||
type NasSkuDetails struct {
|
||||
apis.EnabledStatusStandaloneResourceDetails
|
||||
|
||||
CloudregionResourceInfo
|
||||
}
|
||||
@@ -18,6 +18,11 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
NETWORK_TYPE_VPC = "vpc"
|
||||
NETWORK_TYPE_CLASSIC = "classic"
|
||||
)
|
||||
|
||||
type WireResourceInput struct {
|
||||
// 二层网络(ID或Name)的资源
|
||||
WireId string `json:"wire_id"`
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
// 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 cloudprovider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
type SAccessGroup struct {
|
||||
Name string
|
||||
NetworkType string
|
||||
FileSystemType string
|
||||
Desc string
|
||||
}
|
||||
|
||||
type TRWAccessType string
|
||||
type TUserAccessType string
|
||||
|
||||
const (
|
||||
RWAccessTypeRW = TRWAccessType("RW")
|
||||
RWAccessTypeR = TRWAccessType("R")
|
||||
|
||||
UserAccessTypeNoRootSquash = TUserAccessType("no_root_squash")
|
||||
UserAccessTypeRootSquash = TUserAccessType("root_squash")
|
||||
UserAccessTypeAllSquash = TUserAccessType("all_squash")
|
||||
)
|
||||
|
||||
func GetAccessGroupRuleInfo(group ICloudAccessGroup) (AccessGroupRuleInfo, error) {
|
||||
ret := AccessGroupRuleInfo{
|
||||
MinPriority: group.GetMinPriority(),
|
||||
MaxPriority: group.GetMaxPriority(),
|
||||
SupportedUserAccessType: group.GetSupporedUserAccessTypes(),
|
||||
}
|
||||
var err error
|
||||
ret.Rules, err = group.GetRules()
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "GetRules")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type AccessGroupRule struct {
|
||||
Id string
|
||||
ExternalId string
|
||||
Priority int
|
||||
RWAccessType TRWAccessType
|
||||
UserAccessType TUserAccessType
|
||||
Source string
|
||||
}
|
||||
|
||||
func (self AccessGroupRule) String() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.RWAccessType, self.UserAccessType, self.Source)
|
||||
}
|
||||
|
||||
type AccessGroupRuleSet []AccessGroupRule
|
||||
|
||||
func (srs AccessGroupRuleSet) Len() int {
|
||||
return len(srs)
|
||||
}
|
||||
|
||||
func (srs AccessGroupRuleSet) Swap(i, j int) {
|
||||
srs[i], srs[j] = srs[j], srs[i]
|
||||
}
|
||||
|
||||
func (srs AccessGroupRuleSet) Less(i, j int) bool {
|
||||
return srs[i].Priority < srs[j].Priority || (srs[i].Priority == srs[j].Priority && srs[i].String() < srs[j].String())
|
||||
}
|
||||
|
||||
type AccessGroupRuleInfo struct {
|
||||
MaxPriority int
|
||||
MinPriority int
|
||||
SupportedUserAccessType []TUserAccessType
|
||||
Rules AccessGroupRuleSet
|
||||
}
|
||||
|
||||
func (self *AccessGroupRuleInfo) Sort() {
|
||||
if self.MinPriority < self.MaxPriority {
|
||||
sort.Sort(self.Rules)
|
||||
return
|
||||
}
|
||||
sort.Sort(sort.Reverse(self.Rules))
|
||||
}
|
||||
|
||||
func CompareAccessGroupRules(src, dest AccessGroupRuleInfo, debug bool) (common, added, removed AccessGroupRuleSet) {
|
||||
src.Sort()
|
||||
dest.Sort()
|
||||
var addPriority = func(init int, min, max int) int {
|
||||
inc := 1
|
||||
if max < min {
|
||||
max, min, inc = min, max, -1
|
||||
}
|
||||
if init >= max || init <= min {
|
||||
return init
|
||||
}
|
||||
return init + inc
|
||||
}
|
||||
i, j, priority := 0, 0, (dest.MinPriority-1+dest.MaxPriority)/2
|
||||
for i < len(src.Rules) || j < len(dest.Rules) {
|
||||
if i < len(src.Rules) && j < len(dest.Rules) {
|
||||
destRuleStr := dest.Rules[j].String()
|
||||
srcRuleStr := src.Rules[i].String()
|
||||
if debug {
|
||||
log.Debugf("compare src %s priority(%d) %s -> dest %s priority(%d) %s\n",
|
||||
src.Rules[i].ExternalId, src.Rules[i].Priority, src.Rules[i].String(),
|
||||
dest.Rules[j].ExternalId, dest.Rules[j].Priority, dest.Rules[j].String())
|
||||
}
|
||||
cmp := strings.Compare(destRuleStr, srcRuleStr)
|
||||
if cmp == 0 {
|
||||
dest.Rules[j].Id = src.Rules[i].Id
|
||||
common = append(common, dest.Rules[j])
|
||||
priority = dest.Rules[j].Priority
|
||||
i++
|
||||
j++
|
||||
} else if cmp < 0 {
|
||||
removed = append(removed, dest.Rules[j])
|
||||
j++
|
||||
} else {
|
||||
if isIn, _ := utils.InArray(src.Rules[i].UserAccessType, dest.SupportedUserAccessType); isIn {
|
||||
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority)
|
||||
src.Rules[i].Priority = priority
|
||||
added = append(added, src.Rules[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
} else if i >= len(src.Rules) {
|
||||
removed = append(removed, dest.Rules[j])
|
||||
j++
|
||||
} else if j >= len(dest.Rules) {
|
||||
if isIn, _ := utils.InArray(src.Rules[i].UserAccessType, dest.SupportedUserAccessType); isIn {
|
||||
priority = addPriority(priority, dest.MinPriority, dest.MaxPriority)
|
||||
src.Rules[i].Priority = priority
|
||||
added = append(added, src.Rules[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
return common, added, removed
|
||||
}
|
||||
@@ -55,6 +55,7 @@ const (
|
||||
CLOUD_CAPABILITY_INTERVPCNETWORK = "intervpcnetwork"
|
||||
CLOUD_CAPABILITY_SAML_AUTH = "saml_auth" // 是否支持SAML 2.0
|
||||
CLOUD_CAPABILITY_NAT = "nat" // NAT网关
|
||||
CLOUD_CAPABILITY_NAS = "nas" // NAS
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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 cloudprovider
|
||||
|
||||
type SMountTargetCreateOptions struct {
|
||||
AccessGroupId string
|
||||
NetworkType string
|
||||
VpcId string
|
||||
NetworkId string
|
||||
FileSystemId string
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 cloudprovider
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/util/billing"
|
||||
|
||||
type FileSystemCraeteOptions struct {
|
||||
Name string
|
||||
Desc string
|
||||
VpcId string
|
||||
NetworkId string
|
||||
Capacity int64
|
||||
StorageType string
|
||||
Protocol string
|
||||
FileSystemType string
|
||||
ZoneId string
|
||||
|
||||
BillingCycle *billing.SBillingCycle
|
||||
}
|
||||
@@ -153,6 +153,15 @@ type ICloudRegion interface {
|
||||
GetCapabilities() []string
|
||||
|
||||
GetICloudQuotas() ([]ICloudQuota, error)
|
||||
|
||||
GetICloudFileSystems() ([]ICloudFileSystem, error)
|
||||
GetICloudFileSystemById(id string) (ICloudFileSystem, error)
|
||||
|
||||
CreateICloudFileSystem(opts *FileSystemCraeteOptions) (ICloudFileSystem, error)
|
||||
|
||||
GetICloudAccessGroups() ([]ICloudAccessGroup, error)
|
||||
CreateICloudAccessGroup(opts *SAccessGroup) (ICloudAccessGroup, error)
|
||||
GetICloudAccessGroupById(id string) (ICloudAccessGroup, error)
|
||||
}
|
||||
|
||||
type ICloudZone interface {
|
||||
@@ -1217,3 +1226,53 @@ type ICloudInterVpcNetworkRoute interface {
|
||||
GetEnabled() bool
|
||||
GetCidr() string
|
||||
}
|
||||
|
||||
type ICloudFileSystem interface {
|
||||
ICloudResource
|
||||
IBillingResource
|
||||
|
||||
GetFileSystemType() string
|
||||
GetStorageType() string
|
||||
GetProtocol() string
|
||||
GetCapacityGb() int64
|
||||
GetUsedCapacityGb() int64
|
||||
GetMountTargetCountLimit() int
|
||||
|
||||
GetZoneId() string
|
||||
|
||||
GetMountTargets() ([]ICloudMountTarget, error)
|
||||
CreateMountTarget(opts *SMountTargetCreateOptions) (ICloudMountTarget, error)
|
||||
|
||||
Delete() error
|
||||
}
|
||||
|
||||
type ICloudMountTarget interface {
|
||||
GetGlobalId() string
|
||||
GetName() string
|
||||
GetAccessGroupId() string
|
||||
GetDomainName() string
|
||||
GetNetworkType() string
|
||||
GetVpcId() string
|
||||
GetNetworkId() string
|
||||
GetStatus() string
|
||||
|
||||
Delete() error
|
||||
}
|
||||
|
||||
type ICloudAccessGroup interface {
|
||||
GetGlobalId() string
|
||||
GetName() string
|
||||
GetDesc() string
|
||||
IsDefault() bool
|
||||
GetMaxPriority() int
|
||||
GetMinPriority() int
|
||||
GetSupporedUserAccessTypes() []TUserAccessType
|
||||
GetNetworkType() string
|
||||
GetFileSystemType() string
|
||||
GetMountTargetCount() int
|
||||
|
||||
GetRules() ([]AccessGroupRule, error)
|
||||
SyncRules(common, added, removed AccessGroupRuleSet) error
|
||||
|
||||
Delete() error
|
||||
}
|
||||
|
||||
@@ -0,0 +1,628 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SAccessGroupCacheManager struct {
|
||||
db.SStatusStandaloneResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SManagedResourceBaseManager
|
||||
SCloudregionResourceBaseManager
|
||||
SAccessGroupResourceBaseManager
|
||||
}
|
||||
|
||||
var AccessGroupCacheManager *SAccessGroupCacheManager
|
||||
|
||||
func init() {
|
||||
AccessGroupCacheManager = &SAccessGroupCacheManager{
|
||||
SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
|
||||
SAccessGroupCache{},
|
||||
"access_group_caches_tbl",
|
||||
"access_group_cache",
|
||||
"access_group_caches",
|
||||
),
|
||||
}
|
||||
AccessGroupCacheManager.SetVirtualObject(AccessGroupCacheManager)
|
||||
}
|
||||
|
||||
type SAccessGroupCache struct {
|
||||
db.SStatusStandaloneResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SCloudregionResourceBase
|
||||
SManagedResourceBase
|
||||
SAccessGroupResourceBase
|
||||
|
||||
// 已关联的挂载点数量
|
||||
MountTargetCount int `nullable:"false" list:"user" json:"mount_target_count"`
|
||||
|
||||
FileSystemType string `width:"16" charset:"ascii" nullable:"false" index:"true" list:"user"`
|
||||
NetworkType string `width:"8" charset:"ascii" nullable:"false" index:"true" list:"user" default:"vpc"`
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowList(userCred, manager)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
||||
group, err := self.GetAccessGroup()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return group.AllowUpdateItem(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupCacheListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SManagedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SCloudregionResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.AccessGroupFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupCacheListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.AccessGroupFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAccessGroupResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SAccessGroupResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if userCred != nil {
|
||||
sq := AccessGroupManager.Query("id")
|
||||
if len(userCred.GetProjectDomainId()) > 0 {
|
||||
sq = sq.Equals("domain_id", userCred.GetProjectDomainId())
|
||||
return q.In("access_group_id", sq)
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.AccessGroupCacheDetails {
|
||||
rows := make([]api.AccessGroupCacheDetails, len(objs))
|
||||
|
||||
stdRows := manager.SStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
manRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
groupRows := manager.SAccessGroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.AccessGroupCacheDetails{
|
||||
StatusStandaloneResourceDetails: stdRows[i],
|
||||
ManagedResourceInfo: manRows[i],
|
||||
CloudregionResourceInfo: regRows[i],
|
||||
AccessGroupResourceInfo: groupRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
|
||||
if keys.ContainsAny(manager.SManagedResourceBaseManager.GetExportKeys()...) {
|
||||
q, err = manager.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
}
|
||||
|
||||
if keys.ContainsAny(manager.SCloudregionResourceBaseManager.GetExportKeys()...) {
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
}
|
||||
|
||||
if keys.ContainsAny(manager.SAccessGroupResourceBaseManager.GetExportKeys()...) {
|
||||
q, err = manager.SAccessGroupResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAccessGroupResourceBaseManager.ListItemExportKey")
|
||||
}
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SCloudregion) GetAccessGroupCaches() ([]SAccessGroupCache, error) {
|
||||
caches := []SAccessGroupCache{}
|
||||
q := AccessGroupCacheManager.Query().Equals("cloudregion_id", self.Id)
|
||||
err := db.FetchModelObjects(AccessGroupCacheManager, q, &caches)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return caches, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.SStatusStandaloneResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudregion) SyncAccessGroups(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, iAccessGroups []cloudprovider.ICloudAccessGroup) compare.SyncResult {
|
||||
lockman.LockRawObject(ctx, self.Id, "access_groups")
|
||||
defer lockman.ReleaseRawObject(ctx, self.Id, "access_groups")
|
||||
|
||||
result := compare.SyncResult{}
|
||||
|
||||
dbCaches, err := self.GetAccessGroupCaches()
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "self.GetAccessGroupCaches"))
|
||||
return result
|
||||
}
|
||||
|
||||
removed := make([]SAccessGroupCache, 0)
|
||||
commondb := make([]SAccessGroupCache, 0)
|
||||
commonext := make([]cloudprovider.ICloudAccessGroup, 0)
|
||||
added := make([]cloudprovider.ICloudAccessGroup, 0)
|
||||
err = compare.CompareSets(dbCaches, iAccessGroups, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "compare.CompareSets"))
|
||||
return result
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].syncWithAccessGroup(ctx, userCred, commonext[i])
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
result.Update()
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
err := provider.newFromCloudAccessGroup(ctx, userCred, self, added[i])
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
continue
|
||||
}
|
||||
result.Add()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) GetDomainAccessGroups() ([]SAccessGroup, error) {
|
||||
groups := []SAccessGroup{}
|
||||
q := AccessGroupManager.Query().Equals("domain_id", self.DomainId).NotEquals("id", api.DEFAULT_ACCESS_GROUP)
|
||||
err := db.FetchModelObjects(AccessGroupManager, q, &groups)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) init(iAccessGroup cloudprovider.ICloudAccessGroup) {
|
||||
self.Name = iAccessGroup.GetName()
|
||||
self.NetworkType = iAccessGroup.GetNetworkType()
|
||||
self.FileSystemType = iAccessGroup.GetFileSystemType()
|
||||
self.MountTargetCount = iAccessGroup.GetMountTargetCount()
|
||||
self.ExternalId = iAccessGroup.GetGlobalId()
|
||||
self.Description = iAccessGroup.GetDesc()
|
||||
self.Status = api.ACCESS_GROUP_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) newFromCloudAccessGroup(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, iAccessGroup cloudprovider.ICloudAccessGroup) error {
|
||||
if iAccessGroup.IsDefault() {
|
||||
cache := &SAccessGroupCache{}
|
||||
cache.SetModelManager(AccessGroupCacheManager, cache)
|
||||
cache.CloudregionId = region.Id
|
||||
cache.ManagerId = self.Id
|
||||
cache.AccessGroupId = api.DEFAULT_ACCESS_GROUP
|
||||
cache.init(iAccessGroup)
|
||||
return AccessGroupCacheManager.TableSpec().Insert(ctx, cache)
|
||||
}
|
||||
groups, err := self.GetDomainAccessGroups()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetDomainAccessGroups")
|
||||
}
|
||||
src, err := cloudprovider.GetAccessGroupRuleInfo(iAccessGroup)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroupRuleInfo")
|
||||
}
|
||||
for i := range groups {
|
||||
dest, err := groups[i].GetAccessGroupRuleInfo()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
_, added, removed := cloudprovider.CompareAccessGroupRules(src, dest, false)
|
||||
if len(added)+len(removed) == 0 {
|
||||
cache := &SAccessGroupCache{}
|
||||
cache.SetModelManager(AccessGroupCacheManager, cache)
|
||||
cache.Name = iAccessGroup.GetName()
|
||||
cache.AccessGroupId = groups[i].Id
|
||||
cache.ManagerId = self.Id
|
||||
cache.CloudregionId = region.Id
|
||||
cache.init(iAccessGroup)
|
||||
return AccessGroupCacheManager.TableSpec().Insert(ctx, cache)
|
||||
}
|
||||
}
|
||||
group := &SAccessGroup{}
|
||||
group.SetModelManager(AccessGroupManager, group)
|
||||
group.Name, _ = db.GenerateName(AccessGroupManager, self.GetOwnerId(), iAccessGroup.GetName())
|
||||
group.Status = api.ACCESS_GROUP_STATUS_AVAILABLE
|
||||
group.DomainId = self.DomainId
|
||||
err = AccessGroupManager.TableSpec().Insert(ctx, group)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "AccessGroupManager.Insert")
|
||||
}
|
||||
err = group.SyncRules(ctx, userCred, src)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetAccessGroupCaches() ([]SAccessGroupCache, error) {
|
||||
q := AccessGroupCacheManager.Query().Equals("access_group_id", self.Id)
|
||||
caches := []SAccessGroupCache{}
|
||||
err := db.FetchModelObjects(AccessGroupCacheManager, q, &caches)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return caches, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) removeRules(ctx context.Context, ruleIds []string) error {
|
||||
rules := []SAccessGroupRule{}
|
||||
q := AccessGroupRuleManager.Query().Equals("access_group_id", self.Id).In("id", ruleIds)
|
||||
err := db.FetchModelObjects(AccessGroupRuleManager, q, &rules)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
for i := range rules {
|
||||
rules[i].Delete(ctx, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) newAccessGroupRule(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.AccessGroupRule) error {
|
||||
rule := &SAccessGroupRule{}
|
||||
rule.SetModelManager(AccessGroupRuleManager, rule)
|
||||
rule.AccessGroupId = self.Id
|
||||
rule.Source = ext.Source
|
||||
rule.RWAccessType = string(ext.RWAccessType)
|
||||
rule.UserAccessType = string(ext.UserAccessType)
|
||||
rule.Priority = ext.Priority
|
||||
return AccessGroupRuleManager.TableSpec().Insert(ctx, rule)
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) SyncRules(ctx context.Context, userCred mcclient.TokenCredential, src cloudprovider.AccessGroupRuleInfo) error {
|
||||
dest, err := self.GetAccessGroupRuleInfo()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroupRuleInfo")
|
||||
}
|
||||
_, added, removed := cloudprovider.CompareAccessGroupRules(src, dest, false)
|
||||
removeIds := []string{}
|
||||
for i := range removed {
|
||||
if len(removed[i].ExternalId) > 0 {
|
||||
removeIds = append(removeIds, removed[i].ExternalId)
|
||||
}
|
||||
}
|
||||
self.removeRules(ctx, removeIds)
|
||||
for i := range added {
|
||||
self.newAccessGroupRule(ctx, userCred, added[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) syncAccessGroupBaseInfo(ctx context.Context, userCred mcclient.TokenCredential, iAccessGroup cloudprovider.ICloudAccessGroup) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.init(iAccessGroup)
|
||||
return nil
|
||||
})
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) syncWithAccessGroup(ctx context.Context, userCred mcclient.TokenCredential, iAccessGroup cloudprovider.ICloudAccessGroup) error {
|
||||
err := self.syncAccessGroupBaseInfo(ctx, userCred, iAccessGroup)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "syncAccessGroupBaseInfo")
|
||||
}
|
||||
if self.AccessGroupId == api.DEFAULT_ACCESS_GROUP {
|
||||
return nil
|
||||
}
|
||||
group, err := self.GetAccessGroup()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroup")
|
||||
}
|
||||
caches, err := group.GetAccessGroupCaches()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroupCaches")
|
||||
}
|
||||
if len(caches) > 1 {
|
||||
return nil
|
||||
}
|
||||
src, err := cloudprovider.GetAccessGroupRuleInfo(iAccessGroup)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cloudprovider.GetAccessGroupRuleInfo")
|
||||
}
|
||||
return group.SyncRules(ctx, userCred, src)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) GetRegion() (*SCloudregion, error) {
|
||||
region, err := CloudregionManager.FetchById(self.CloudregionId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CloudregionManager.FetchById(%s)", self.CloudregionId)
|
||||
}
|
||||
return region.(*SCloudregion), nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) GetIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
provider, err := self.GetDriver()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetDriver")
|
||||
}
|
||||
region, err := self.GetRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetRegion")
|
||||
}
|
||||
return provider.GetIRegionById(region.ExternalId)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) GetICloudAccessGroup() (cloudprovider.ICloudAccessGroup, error) {
|
||||
if len(self.ExternalId) == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
|
||||
}
|
||||
iRegion, err := self.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetIRegion")
|
||||
}
|
||||
iAccessGroup, err := iRegion.GetICloudAccessGroupById(self.ExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "iRegion.GetICloudAccessGroupById(%s)", self.ExternalId)
|
||||
}
|
||||
return iAccessGroup, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) SyncRules() error {
|
||||
group, err := self.GetAccessGroup()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroup")
|
||||
}
|
||||
src, err := group.GetAccessGroupRuleInfo()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroupRuleInfo")
|
||||
}
|
||||
|
||||
iAccessGroup, err := self.GetICloudAccessGroup()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetICloudAccessGroup")
|
||||
}
|
||||
|
||||
dest, err := cloudprovider.GetAccessGroupRuleInfo(iAccessGroup)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetAccessGroupRuleInfo")
|
||||
}
|
||||
|
||||
common, added, removed := cloudprovider.CompareAccessGroupRules(src, dest, false)
|
||||
return iAccessGroup.SyncRules(common, added, removed)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) CreateIAccessGroup() error {
|
||||
iRegion, err := self.GetIRegion()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "self.GetIRegion")
|
||||
}
|
||||
opts := &cloudprovider.SAccessGroup{
|
||||
Name: self.Name,
|
||||
NetworkType: self.NetworkType,
|
||||
FileSystemType: self.FileSystemType,
|
||||
Desc: self.Description,
|
||||
}
|
||||
iAccessGroup, err := iRegion.CreateICloudAccessGroup(opts)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "iRegion.CreateIAccessGroup")
|
||||
}
|
||||
_, err = db.Update(self, func() error {
|
||||
self.ExternalId = iAccessGroup.GetGlobalId()
|
||||
self.Status = api.ACCESS_GROUP_STATUS_AVAILABLE
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
return self.SyncRules()
|
||||
}
|
||||
|
||||
type SAccessGroupCacheRegisterInput struct {
|
||||
Name string
|
||||
Desc string
|
||||
ManagerId string
|
||||
CloudregionId string
|
||||
FileSystemType string
|
||||
NetworkType string
|
||||
AccessGroupId string
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) Register(ctx context.Context, opts *SAccessGroupCacheRegisterInput) (*SAccessGroupCache, error) {
|
||||
lockman.LockClass(ctx, manager, "")
|
||||
defer lockman.ReleaseClass(ctx, manager, "")
|
||||
|
||||
cache := &SAccessGroupCache{}
|
||||
cache.SetModelManager(manager, cache)
|
||||
cache.Name = opts.Name
|
||||
cache.Description = opts.Desc
|
||||
cache.Status = api.ACCESS_GROUP_STATUS_CREATING
|
||||
cache.ManagerId = opts.ManagerId
|
||||
cache.CloudregionId = opts.CloudregionId
|
||||
cache.FileSystemType = opts.FileSystemType
|
||||
cache.NetworkType = opts.NetworkType
|
||||
cache.AccessGroupId = opts.AccessGroupId
|
||||
err := manager.TableSpec().Insert(ctx, cache)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Insert")
|
||||
}
|
||||
return cache, cache.CreateIAccessGroup()
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.AccessGroupId == api.DEFAULT_ACCESS_GROUP {
|
||||
return httperrors.NewProtectedResourceError("not allow to delete default access group")
|
||||
}
|
||||
if self.MountTargetCount > 0 && self.Status != api.ACCESS_GROUP_STATUS_UNKNOWN {
|
||||
return httperrors.NewNotEmptyError("access group not empty, please delete mount target first")
|
||||
}
|
||||
return self.SStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
|
||||
return self.StartDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "AccessGroupCacheDeleteTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_DELETE_FAILED, err.Error())
|
||||
return nil
|
||||
}
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_DELETING, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) SyncStatus(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
iAccessGroup, err := self.GetICloudAccessGroup()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_CREATING, err.Error())
|
||||
return err
|
||||
}
|
||||
return self.syncAccessGroupBaseInfo(ctx, userCred, iAccessGroup)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) AllowPerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowPerform(userCred, self, "syncstatus")
|
||||
}
|
||||
|
||||
// 同步权限组缓存状态
|
||||
func (self *SAccessGroupCache) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.MountTargetSyncstatusInput) (jsonutils.JSONObject, error) {
|
||||
return nil, self.SyncStatus(ctx, userCred)
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/reflectutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SAccessGroupResourceBase struct {
|
||||
// 权限组Id
|
||||
AccessGroupId string `width:"36" charset:"ascii" nullable:"false" create:"required" index:"true" list:"user"`
|
||||
}
|
||||
|
||||
type SAccessGroupResourceBaseManager struct{}
|
||||
|
||||
func (self *SAccessGroupResourceBase) GetAccessGroup() (*SAccessGroup, error) {
|
||||
group, err := AccessGroupManager.FetchById(self.AccessGroupId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "AccessGroupManager.FetchById(%s)", self.AccessGroupId)
|
||||
}
|
||||
return group.(*SAccessGroup), nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.AccessGroupResourceInfo {
|
||||
rows := make([]api.AccessGroupResourceInfo, len(objs))
|
||||
groupIds := make([]string, len(objs))
|
||||
for i := range objs {
|
||||
var base *SAccessGroupResourceBase
|
||||
err := reflectutils.FindAnonymouStructPointer(objs[i], &base)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot find SAccessGroupResourceBase in object %s", objs[i])
|
||||
continue
|
||||
}
|
||||
groupIds[i] = base.AccessGroupId
|
||||
}
|
||||
groupNames, err := db.FetchIdNameMap2(AccessGroupManager, groupIds)
|
||||
if err != nil {
|
||||
return rows
|
||||
}
|
||||
for i := range rows {
|
||||
rows[i].AccessGroup, _ = groupNames[groupIds[i]]
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupFilterListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if len(query.AccessGroupId) > 0 {
|
||||
_, err := validators.ValidateModel(userCred, AccessGroupManager, &query.AccessGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q = q.Equals("access_group_id", query.AccessGroupId)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupFilterListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
|
||||
return q, nil
|
||||
}
|
||||
orderQ := AccessGroupManager.Query("id")
|
||||
orderSubQ := orderQ.SubQuery()
|
||||
orderQ, orders, fields := manager.GetOrderBySubQuery(orderQ, orderSubQ, orderQ.Field("id"), userCred, query, nil, nil)
|
||||
q = q.LeftJoin(orderSubQ, sqlchemy.Equals(q.Field("access_group_id"), orderSubQ.Field("id")))
|
||||
q = db.OrderByFields(q, orders, fields)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
if field == "access_group" {
|
||||
groupQuery := AccessGroupManager.Query("name", "id").Distinct().SubQuery()
|
||||
q.AppendField(groupQuery.Field("name", field))
|
||||
q = q.Join(groupQuery, sqlchemy.Equals(q.Field("access_group_id"), groupQuery.Field("id")))
|
||||
q.GroupBy(groupQuery.Field("name"))
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) GetOrderBySubQuery(
|
||||
q *sqlchemy.SQuery,
|
||||
subq *sqlchemy.SSubQuery,
|
||||
joinField sqlchemy.IQueryField,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupFilterListInput,
|
||||
orders []string,
|
||||
fields []sqlchemy.IQueryField,
|
||||
) (*sqlchemy.SQuery, []string, []sqlchemy.IQueryField) {
|
||||
if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
|
||||
return q, orders, fields
|
||||
}
|
||||
groupQ := AccessGroupManager.Query().SubQuery()
|
||||
q = q.LeftJoin(groupQ, sqlchemy.Equals(joinField, groupQ.Field("id")))
|
||||
q = q.AppendField(groupQ.Field("name").Label("access_group"))
|
||||
orders = append(orders, query.OrderByAccessGroup)
|
||||
fields = append(fields, subq.Field("access_group"))
|
||||
return q, orders, fields
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) GetOrderByFields(query api.AccessGroupFilterListInput) []string {
|
||||
return []string{query.OrderByAccessGroup}
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if keys.ContainsAny(manager.GetExportKeys()...) {
|
||||
subq := AccessGroupManager.Query("id", "name").SubQuery()
|
||||
q = q.LeftJoin(subq, sqlchemy.Equals(q.Field("access_group_id"), subq.Field("id")))
|
||||
q = q.AppendField(subq.Field("name", "access_group"))
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupResourceBaseManager) GetExportKeys() []string {
|
||||
return []string{"access_group"}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SAccessGroupRuleManager struct {
|
||||
db.SResourceBaseManager
|
||||
SAccessGroupResourceBaseManager
|
||||
}
|
||||
|
||||
var AccessGroupRuleManager *SAccessGroupRuleManager
|
||||
|
||||
func init() {
|
||||
AccessGroupRuleManager = &SAccessGroupRuleManager{
|
||||
SResourceBaseManager: db.NewResourceBaseManager(
|
||||
SAccessGroupRule{},
|
||||
"access_group_rules_tbl",
|
||||
"access_group_rule",
|
||||
"access_group_rules",
|
||||
),
|
||||
}
|
||||
AccessGroupRuleManager.SetVirtualObject(AccessGroupRuleManager)
|
||||
}
|
||||
|
||||
type SAccessGroupRule struct {
|
||||
db.SResourceBase
|
||||
SAccessGroupResourceBase
|
||||
|
||||
Id string `width:"128" charset:"ascii" primary:"true" list:"user"`
|
||||
Priority int `default:"1" list:"user" update:"user" list:"user"`
|
||||
Source string `width:"16" charset:"ascii" list:"user" update:"user" create:"required"`
|
||||
RWAccessType string `width:"16" charset:"ascii" list:"user" update:"user" create:"required"`
|
||||
UserAccessType string `width:"16" charset:"ascii" list:"user" update:"user" create:"required"`
|
||||
Description string `width:"256" charset:"utf8" list:"user" update:"user" create:"optional"`
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) BeforeInsert() {
|
||||
if len(self.Id) == 0 {
|
||||
self.Id = stringutils.UUID4()
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) GetId() string {
|
||||
return self.Id
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
|
||||
groupId, _ := data.GetString("access_group_id")
|
||||
return jsonutils.Marshal(map[string]string{"access_group_id": groupId})
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
|
||||
groupId, _ := values.GetString("access_group_id")
|
||||
if len(groupId) > 0 {
|
||||
q = q.Equals("access_group_id", groupId)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
|
||||
groupId, _ := data.GetString("access_group_id")
|
||||
if len(groupId) > 0 {
|
||||
accessGroup, err := db.FetchById(AccessGroupManager, groupId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchById(%s)", groupId)
|
||||
}
|
||||
return accessGroup.(*SAccessGroup).GetOwnerId(), nil
|
||||
}
|
||||
return db.FetchDomainInfo(ctx, data)
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
sq := AccessGroupManager.Query("id")
|
||||
sq = db.SharableManagerFilterByOwner(AccessGroupManager, sq, userCred, scope)
|
||||
return q.In("access_group_id", sq.SubQuery())
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowCreate(userCred, manager)
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowList(userCred, manager)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
||||
if self.AccessGroupId == api.DEFAULT_ACCESS_GROUP {
|
||||
return false
|
||||
}
|
||||
group, err := self.GetAccessGroup()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return group.AllowUpdateItem(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
group, err := self.GetAccessGroup()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return group.AllowDeleteItem(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
|
||||
return q.Equals("id", idStr)
|
||||
}
|
||||
|
||||
// 权限组规则列表
|
||||
func (manager *SAccessGroupRuleManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupRuleListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.AccessGroupFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.AccessGroupRuleDetails {
|
||||
rows := make([]api.AccessGroupRuleDetails, len(objs))
|
||||
bRows := manager.SResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
gRows := manager.SAccessGroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.AccessGroupRuleDetails{
|
||||
ResourceBaseDetails: bRows[i],
|
||||
AccessGroupResourceInfo: gRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupRuleListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
q, err = manager.SAccessGroupResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.AccessGroupFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
}
|
||||
|
||||
// 创建权限组规则
|
||||
func (manager *SAccessGroupRuleManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.AccessGroupRuleCreateInput) (api.AccessGroupRuleCreateInput, error) {
|
||||
if len(input.AccessGroupId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("access_group_id")
|
||||
}
|
||||
if input.AccessGroupId == api.DEFAULT_ACCESS_GROUP {
|
||||
return input, httperrors.NewNotSupportedError("can not add rule for default access group")
|
||||
}
|
||||
_ag, err := validators.ValidateModel(userCred, AccessGroupManager, &input.AccessGroupId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
ag := _ag.(*SAccessGroup)
|
||||
if !ag.IsOwner(userCred) && !userCred.HasSystemAdminPrivilege() {
|
||||
return input, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
if ag.Status != api.ACCESS_GROUP_STATUS_AVAILABLE {
|
||||
return input, httperrors.NewInvalidStatusError("access group %s status is not available", ag.Name)
|
||||
}
|
||||
if len(input.Source) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("source")
|
||||
}
|
||||
if !regutils.MatchCIDR(input.Source) && !regutils.MatchIP4Addr(input.Source) {
|
||||
return input, httperrors.NewInputParameterError("invalid source %s", input.Source)
|
||||
}
|
||||
if input.Priority < 1 || input.Priority > 100 {
|
||||
return input, httperrors.NewOutOfRangeError("Invalid priority %d, must be in range or 1 ~ 100", input.Priority)
|
||||
}
|
||||
if len(input.RWAccessType) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("rw_access_type")
|
||||
}
|
||||
if isIn, _ := utils.InArray(cloudprovider.TRWAccessType(input.RWAccessType), []cloudprovider.TRWAccessType{
|
||||
cloudprovider.RWAccessTypeR,
|
||||
cloudprovider.RWAccessTypeRW,
|
||||
}); !isIn {
|
||||
return input, httperrors.NewInputParameterError("invalid rw_access_type %s", input.RWAccessType)
|
||||
}
|
||||
if len(input.UserAccessType) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("user_access_type")
|
||||
}
|
||||
if isIn, _ := utils.InArray(cloudprovider.TUserAccessType(input.UserAccessType), []cloudprovider.TUserAccessType{
|
||||
cloudprovider.UserAccessTypeAllSquash,
|
||||
cloudprovider.UserAccessTypeRootSquash,
|
||||
cloudprovider.UserAccessTypeNoRootSquash,
|
||||
}); !isIn {
|
||||
return input, httperrors.NewInputParameterError("invalid user_access_type %s", input.UserAccessType)
|
||||
}
|
||||
|
||||
input.ResourceBaseCreateInput, err = manager.SResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.ResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
|
||||
log.Debugf("POST Create %s", data)
|
||||
|
||||
group, err := self.GetAccessGroup()
|
||||
if err == nil {
|
||||
logclient.AddSimpleActionLog(group, logclient.ACT_ALLOCATE, data, userCred, true)
|
||||
group.DoSync(ctx, userCred)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.AccessGroupRuleUpdateInput) (api.AccessGroupRuleUpdateInput, error) {
|
||||
if input.Priority != nil && *input.Priority < 1 || *input.Priority > 100 {
|
||||
return input, httperrors.NewOutOfRangeError("Invalid priority %d, must be in range or 1 ~ 100", input.Priority)
|
||||
}
|
||||
if len(input.Source) > 0 && !regutils.MatchCIDR(input.Source) {
|
||||
return input, httperrors.NewInputParameterError("invalid source %s", input.Source)
|
||||
}
|
||||
if isIn, _ := utils.InArray(cloudprovider.TRWAccessType(input.RWAccessType), []cloudprovider.TRWAccessType{
|
||||
cloudprovider.RWAccessTypeR,
|
||||
cloudprovider.RWAccessTypeRW,
|
||||
}); !isIn && len(input.RWAccessType) > 0 {
|
||||
return input, httperrors.NewInputParameterError("invalid rw_access_type %s", input.RWAccessType)
|
||||
}
|
||||
if isIn, _ := utils.InArray(cloudprovider.TUserAccessType(input.UserAccessType), []cloudprovider.TUserAccessType{
|
||||
cloudprovider.UserAccessTypeAllSquash,
|
||||
cloudprovider.UserAccessTypeRootSquash,
|
||||
cloudprovider.UserAccessTypeNoRootSquash,
|
||||
}); !isIn && len(input.UserAccessType) > 0 {
|
||||
return input, httperrors.NewInputParameterError("invalid user_access_type %s", input.UserAccessType)
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) GetOwnerId() mcclient.IIdentityProvider {
|
||||
group, err := self.GetAccessGroup()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return group.GetOwnerId()
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) PreDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
self.SResourceBase.PreDelete(ctx, userCred)
|
||||
|
||||
group, err := self.GetAccessGroup()
|
||||
if err == nil {
|
||||
logclient.AddSimpleActionLog(group, logclient.ACT_DELETE, jsonutils.Marshal(self), userCred, true)
|
||||
group.DoSync(ctx, userCred)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAccessGroupRule) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.AccessGroupId == api.DEFAULT_ACCESS_GROUP {
|
||||
return httperrors.NewProtectedResourceError("not allow to delete default access group rule")
|
||||
}
|
||||
return self.SResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupRuleManager) InitializeData() error {
|
||||
q := manager.Query().Equals("access_group_id", api.DEFAULT_ACCESS_GROUP)
|
||||
rules := []SAccessGroupRule{}
|
||||
err := db.FetchModelObjects(manager, q, &rules)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
if len(rules) == 0 {
|
||||
rule := &SAccessGroupRule{}
|
||||
rule.SetModelManager(manager, rule)
|
||||
rule.AccessGroupId = api.DEFAULT_ACCESS_GROUP
|
||||
rule.Source = "0.0.0.0/0"
|
||||
rule.RWAccessType = string(cloudprovider.RWAccessTypeRW)
|
||||
rule.UserAccessType = string(cloudprovider.UserAccessTypeNoRootSquash)
|
||||
err = manager.TableSpec().Insert(context.TODO(), rule)
|
||||
return errors.Wrapf(err, "Insert")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SAccessGroupManager struct {
|
||||
db.SStatusInfrasResourceBaseManager
|
||||
}
|
||||
|
||||
var AccessGroupManager *SAccessGroupManager
|
||||
|
||||
func init() {
|
||||
AccessGroupManager = &SAccessGroupManager{
|
||||
SStatusInfrasResourceBaseManager: db.NewStatusInfrasResourceBaseManager(
|
||||
SAccessGroup{},
|
||||
"access_groups_tbl",
|
||||
"access_group",
|
||||
"access_groups",
|
||||
),
|
||||
}
|
||||
AccessGroupManager.SetVirtualObject(AccessGroupManager)
|
||||
}
|
||||
|
||||
type SAccessGroup struct {
|
||||
db.SStatusInfrasResourceBase
|
||||
|
||||
IsDirty bool `nullable:"false" default:"false"`
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager SAccessGroupManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.AccessGroupDetails {
|
||||
rows := make([]api.AccessGroupDetails, len(objs))
|
||||
stdRows := manager.SStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.AccessGroupDetails{
|
||||
StatusInfrasResourceBaseDetails: stdRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusInfrasResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.AccessGroupListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusInfrasResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetChangeOwnerCandidateDomainIds() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetEmptyAccessGroupRuleInfo() cloudprovider.AccessGroupRuleInfo {
|
||||
return cloudprovider.AccessGroupRuleInfo{
|
||||
MinPriority: 1,
|
||||
MaxPriority: 100,
|
||||
Rules: cloudprovider.AccessGroupRuleSet{},
|
||||
SupportedUserAccessType: []cloudprovider.TUserAccessType{
|
||||
cloudprovider.UserAccessTypeRootSquash,
|
||||
cloudprovider.UserAccessTypeNoRootSquash,
|
||||
cloudprovider.UserAccessTypeAllSquash,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetAccessGroupRuleInfo() (cloudprovider.AccessGroupRuleInfo, error) {
|
||||
ret := self.GetEmptyAccessGroupRuleInfo()
|
||||
rules, err := self.GetAccessGroupRules()
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "GetAccessGroupRules")
|
||||
}
|
||||
for _, rule := range rules {
|
||||
userType := cloudprovider.TUserAccessType(rule.UserAccessType)
|
||||
if isIn, _ := utils.InArray(userType, ret.SupportedUserAccessType); !isIn {
|
||||
ret.SupportedUserAccessType = append(ret.SupportedUserAccessType, userType)
|
||||
}
|
||||
ret.Rules = append(ret.Rules, cloudprovider.AccessGroupRule{
|
||||
ExternalId: rule.Id,
|
||||
Source: rule.Source,
|
||||
RWAccessType: cloudprovider.TRWAccessType(rule.RWAccessType),
|
||||
UserAccessType: userType,
|
||||
Priority: rule.Priority,
|
||||
})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetAccessGroupRules() ([]SAccessGroupRule, error) {
|
||||
rules := []SAccessGroupRule{}
|
||||
q := AccessGroupRuleManager.Query().Equals("access_group_id", self.Id)
|
||||
err := db.FetchModelObjects(AccessGroupRuleManager, q, &rules)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) InitializeData() error {
|
||||
_, err := manager.FetchById(api.DEFAULT_ACCESS_GROUP)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != sql.ErrNoRows {
|
||||
return errors.Wrapf(err, "manager.FetchById(%s)", api.DEFAULT_ACCESS_GROUP)
|
||||
}
|
||||
log.Infof("Init default access group")
|
||||
accessGroup := &SAccessGroup{}
|
||||
accessGroup.SetModelManager(manager, accessGroup)
|
||||
accessGroup.Id = api.DEFAULT_ACCESS_GROUP
|
||||
accessGroup.Name = "Default"
|
||||
accessGroup.Status = api.ACCESS_GROUP_STATUS_AVAILABLE
|
||||
accessGroup.DomainId = auth.AdminCredential().GetProjectDomainId()
|
||||
accessGroup.IsPublic = true
|
||||
accessGroup.Deleted = false
|
||||
err = manager.TableSpec().InsertOrUpdate(context.TODO(), accessGroup)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "InsertOrUpdate default access group")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.AccessGroupCreateInput) (api.AccessGroupCreateInput, error) {
|
||||
var err error
|
||||
input.StatusInfrasResourceBaseCreateInput, err = manager.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
input.Status = api.ACCESS_GROUP_STATUS_AVAILABLE
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
|
||||
return self.StartDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "AccessGroupDeleteTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_DELETE_FAILED, err.Error())
|
||||
return nil
|
||||
}
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_DELETING, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetMountTargets() ([]SMountTarget, error) {
|
||||
mts := []SMountTarget{}
|
||||
q := MountTargetManager.Query().Equals("access_group_id", self.Id)
|
||||
err := db.FetchModelObjects(MountTargetManager, q, &mts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return mts, nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.SStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.Id == api.DEFAULT_ACCESS_GROUP {
|
||||
return httperrors.NewProtectedResourceError("not allow to delete default access group")
|
||||
}
|
||||
mts, err := self.GetMountTargets()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetMountTargets")
|
||||
}
|
||||
if len(mts) > 0 {
|
||||
return httperrors.NewNotEmptyError("access group not empty, please delete mount target first")
|
||||
}
|
||||
return self.SStatusInfrasResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) DoSync(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
if _, err := db.Update(self, func() error {
|
||||
self.IsDirty = true
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Errorf("Update Security Group error: %s", err.Error())
|
||||
}
|
||||
time.AfterFunc(10*time.Second, func() {
|
||||
AccessGroupManager.DelaySync(context.Background(), userCred, self.Id)
|
||||
})
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupManager) DelaySync(ctx context.Context, userCred mcclient.TokenCredential, idStr string) error {
|
||||
_group, err := manager.FetchById(idStr)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchById(%s)", idStr)
|
||||
}
|
||||
group := _group.(*SAccessGroup)
|
||||
needSync := false
|
||||
|
||||
func() {
|
||||
lockman.LockObject(ctx, group)
|
||||
defer lockman.ReleaseObject(ctx, group)
|
||||
|
||||
if group.IsDirty {
|
||||
if _, err := db.Update(group, func() error {
|
||||
group.IsDirty = false
|
||||
return nil
|
||||
}); err != nil {
|
||||
log.Errorf("Update Access Group error: %s", err.Error())
|
||||
}
|
||||
needSync = true
|
||||
}
|
||||
}()
|
||||
|
||||
if needSync {
|
||||
return group.StartSyncRulesTask(ctx, userCred, "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) StartSyncRulesTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "AccessGroupSyncRulesTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_SYNC_RULES_FAILED, err.Error())
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, api.ACCESS_GROUP_STATUS_SYNC_RULES, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) AllowPerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowPerform(userCred, self, "syncstatus")
|
||||
}
|
||||
|
||||
// 同步权限组状态
|
||||
func (self *SAccessGroup) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.MountTargetSyncstatusInput) (jsonutils.JSONObject, error) {
|
||||
return nil, self.StartSyncstatus(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
return StartResourceSyncStatusTask(ctx, userCred, self, "AccessGroupSyncstatusTask", parentTaskId)
|
||||
}
|
||||
@@ -53,6 +53,8 @@ type SCapabilities struct {
|
||||
DisabledSamlAuthBrands []string `json:",allowempty"`
|
||||
NatBrands []string `json:",allowempty"`
|
||||
DisabledNatBrands []string `json:",allowempty"`
|
||||
NasBrands []string `json:",allowempty"`
|
||||
DisabledNasBrands []string `json:",allowempty"`
|
||||
PublicIpBrands []string `json:",allowempty"`
|
||||
NetworkManageBrands []string `json:",allowempty"`
|
||||
DisabledNetworkManageBrands []string `json:",allowempty"`
|
||||
@@ -289,6 +291,7 @@ func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabi
|
||||
capa.LoadbalancerEngineBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_LOADBALANCER)
|
||||
capa.SamlAuthBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_SAML_AUTH)
|
||||
capa.NatBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_NAT)
|
||||
capa.NasBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_NAS)
|
||||
|
||||
if utils.IsInStringArray(api.HYPERVISOR_KVM, capa.Hypervisors) || utils.IsInStringArray(api.HYPERVISOR_BAREMETAL, capa.Hypervisors) {
|
||||
capa.Brands = append(capa.Brands, api.ONECLOUD_BRAND_ONECLOUD)
|
||||
@@ -309,6 +312,7 @@ func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabi
|
||||
capa.DisabledCloudIdBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_CLOUDID)
|
||||
capa.DisabledSamlAuthBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_SAML_AUTH)
|
||||
capa.DisabledNatBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_NAT)
|
||||
capa.DisabledNasBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_NAS)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2400,6 +2400,7 @@ func (account *SCloudaccount) PerformSyncSkus(ctx context.Context, userCred mccl
|
||||
ElasticcacheSkuManager.Keyword(),
|
||||
DBInstanceSkuManager.Keyword(),
|
||||
NatSkuManager.Keyword(),
|
||||
NasSkuManager.Keyword(),
|
||||
}) {
|
||||
return nil, httperrors.NewInputParameterError("invalid resource %s", input.Resource)
|
||||
}
|
||||
|
||||
@@ -1397,6 +1397,8 @@ func (self *SCloudprovider) RealDelete(ctx context.Context, userCred mcclient.To
|
||||
DBInstanceManager,
|
||||
DBInstanceBackupManager,
|
||||
ElasticcacheManager,
|
||||
AccessGroupCacheManager,
|
||||
FileSystemManager,
|
||||
VpcManager,
|
||||
ElasticipManager,
|
||||
NetworkInterfaceManager,
|
||||
|
||||
@@ -256,6 +256,63 @@ func syncRegionVPCs(ctx context.Context, userCred mcclient.TokenCredential, sync
|
||||
}
|
||||
}
|
||||
|
||||
func syncRegionAccessGroups(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) {
|
||||
accessGroups, err := remoteRegion.GetICloudAccessGroups()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported {
|
||||
return
|
||||
}
|
||||
log.Errorf("GetICloudFileSystems for region %s error: %v", localRegion.Name, err)
|
||||
return
|
||||
}
|
||||
|
||||
result := localRegion.SyncAccessGroups(ctx, userCred, provider, accessGroups)
|
||||
syncResults.Add(AccessGroupCacheManager, result)
|
||||
log.Infof("Sync Access Group Caches for region %s result: %s", localRegion.Name, result.Result())
|
||||
}
|
||||
|
||||
func syncRegionFileSystems(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *SSyncRange) {
|
||||
filesystems, err := remoteRegion.GetICloudFileSystems()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported {
|
||||
return
|
||||
}
|
||||
log.Errorf("GetICloudFileSystems for region %s error: %v", localRegion.Name, err)
|
||||
return
|
||||
}
|
||||
|
||||
localFSs, removeFSs, result := localRegion.SyncFileSystems(ctx, userCred, provider, filesystems)
|
||||
syncResults.Add(FileSystemManager, result)
|
||||
log.Infof("Sync FileSystem for region %s result: %s", localRegion.Name, result.Result())
|
||||
|
||||
for j := 0; j < len(localFSs); j += 1 {
|
||||
func() {
|
||||
// lock file system
|
||||
lockman.LockObject(ctx, &localFSs[j])
|
||||
defer lockman.ReleaseObject(ctx, &localFSs[j])
|
||||
|
||||
if localFSs[j].Deleted {
|
||||
return
|
||||
}
|
||||
|
||||
syncFileSystemMountTargets(ctx, userCred, &localFSs[j], removeFSs[j])
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func syncFileSystemMountTargets(ctx context.Context, userCred mcclient.TokenCredential, localFs *SFileSystem, remoteFs cloudprovider.ICloudFileSystem) {
|
||||
mountTargets, err := remoteFs.GetMountTargets()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported {
|
||||
return
|
||||
}
|
||||
log.Errorf("GetMountTargets for %s error: %v", localFs.Name, err)
|
||||
return
|
||||
}
|
||||
result := localFs.SyncMountTargets(ctx, userCred, mountTargets)
|
||||
log.Infof("SyncMountTargets for FileSystem %s result: %s", localFs.Name, result.Result())
|
||||
}
|
||||
|
||||
func syncVpcPeerConnections(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localVpc *SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *SSyncRange) {
|
||||
peerConnections, err := remoteVpc.GetICloudVpcPeeringConnections()
|
||||
if err != nil {
|
||||
@@ -1182,6 +1239,9 @@ func syncPublicCloudProviderInfo(
|
||||
syncRegionSnapshots(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
}
|
||||
|
||||
syncRegionAccessGroups(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
syncRegionFileSystems(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
|
||||
if cloudprovider.IsSupportLoadbalancer(driver) {
|
||||
syncRegionLoadbalancerAcls(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
syncRegionLoadbalancerCertificates(ctx, userCred, syncResults, provider, localRegion, remoteRegion, syncRange)
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SFileSystemManager struct {
|
||||
db.SStatusInfrasResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SManagedResourceBaseManager
|
||||
SCloudregionResourceBaseManager
|
||||
SZoneResourceBaseManager
|
||||
|
||||
SDeletePreventableResourceBaseManager
|
||||
}
|
||||
|
||||
var FileSystemManager *SFileSystemManager
|
||||
|
||||
func init() {
|
||||
FileSystemManager = &SFileSystemManager{
|
||||
SStatusInfrasResourceBaseManager: db.NewStatusInfrasResourceBaseManager(
|
||||
SFileSystem{},
|
||||
"file_systems_tbl",
|
||||
"file_system",
|
||||
"file_systems",
|
||||
),
|
||||
}
|
||||
FileSystemManager.SetVirtualObject(FileSystemManager)
|
||||
}
|
||||
|
||||
type SFileSystem struct {
|
||||
db.SStatusInfrasResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SManagedResourceBase
|
||||
SBillingResourceBase
|
||||
SCloudregionResourceBase
|
||||
SZoneResourceBase
|
||||
|
||||
SDeletePreventableResourceBase
|
||||
|
||||
// 文件系统类型
|
||||
// enmu: extreme, standard, cpfs
|
||||
FileSystemType string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
|
||||
// 存储类型
|
||||
// enmu: performance, capacity, standard, advance, advance_100, advance_200
|
||||
StorageType string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
// 协议类型
|
||||
// enum: NFS, SMB, cpfs
|
||||
Protocol string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
// 容量, 单位Gb
|
||||
Capacity int64 `nullable:"false" list:"user" create:"optional"`
|
||||
// 已使用容量, 单位Gb
|
||||
UsedCapacity int64 `nullable:"false" list:"user"`
|
||||
|
||||
// 最多支持挂载点数量, -1代表无限制
|
||||
MountTargetCountLimit int `nullable:"false" list:"user" default:"-1"`
|
||||
}
|
||||
|
||||
func (manager *SFileSystemManager) GetContextManagers() [][]db.IModelManager {
|
||||
return [][]db.IModelManager{
|
||||
{CloudregionManager},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetCloudproviderId() string {
|
||||
return self.ManagerId
|
||||
}
|
||||
|
||||
func (manager *SFileSystemManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.FileSystemListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SManagedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SCloudregionResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (man *SFileSystemManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.FileSystemCreateInput) (api.FileSystemCreateInput, error) {
|
||||
var err error
|
||||
if len(input.NetworkId) > 0 {
|
||||
net, err := validators.ValidateModel(userCred, NetworkManager, &input.NetworkId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
network := net.(*SNetwork)
|
||||
zone := network.GetZone()
|
||||
input.ManagerId = network.GetVpc().ManagerId
|
||||
input.ZoneId = zone.Id
|
||||
input.CloudregionId = zone.CloudregionId
|
||||
} else if len(input.ZoneId) > 0 {
|
||||
_zone, err := validators.ValidateModel(userCred, ZoneManager, &input.ZoneId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
zone := _zone.(*SZone)
|
||||
input.CloudregionId = zone.CloudregionId
|
||||
} else {
|
||||
return input, httperrors.NewMissingParameterError("zone_id")
|
||||
}
|
||||
if len(input.ManagerId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("manager_id")
|
||||
}
|
||||
input.StatusInfrasResourceBaseCreateInput, err = man.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
self.StartCreateTask(ctx, userCred, jsonutils.GetAnyString(data, []string{"network_id"}), "")
|
||||
}
|
||||
|
||||
func (self *SFileSystem) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, networkId string, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(networkId), "network_id")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "FileSystemCreateTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.NAS_STATUS_CREATE_FAILED, err.Error())
|
||||
return err
|
||||
}
|
||||
self.SetStatus(userCred, api.NAS_STATUS_CREATING, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager SFileSystemManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.FileSystemDetails {
|
||||
rows := make([]api.FileSystemDetails, len(objs))
|
||||
stdRows := manager.SStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
regionRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
mRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
zoneIds := make([]string, len(objs))
|
||||
for i := range rows {
|
||||
rows[i] = api.FileSystemDetails{
|
||||
StatusInfrasResourceBaseDetails: stdRows[i],
|
||||
CloudregionResourceInfo: regionRows[i],
|
||||
ManagedResourceInfo: mRows[i],
|
||||
}
|
||||
nas := objs[i].(*SFileSystem)
|
||||
zoneIds[i] = nas.ZoneId
|
||||
}
|
||||
|
||||
zoneMaps, err := db.FetchIdNameMap2(ZoneManager, zoneIds)
|
||||
if err != nil {
|
||||
return rows
|
||||
}
|
||||
for i := range rows {
|
||||
rows[i].Zone, _ = zoneMaps[zoneIds[i]]
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SFileSystemManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusInfrasResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SFileSystemManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SFileSystemManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.FileSystemListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusInfrasResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SManagedResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SCloudregion) GetFileSystems() ([]SFileSystem, error) {
|
||||
ret := []SFileSystem{}
|
||||
q := FileSystemManager.Query().Equals("cloudregion_id", self.Id)
|
||||
err := db.FetchModelObjects(FileSystemManager, q, &ret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SCloudregion) SyncFileSystems(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, filesystems []cloudprovider.ICloudFileSystem) ([]SFileSystem, []cloudprovider.ICloudFileSystem, compare.SyncResult) {
|
||||
lockman.LockRawObject(ctx, self.Id, "filesystems")
|
||||
defer lockman.ReleaseRawObject(ctx, self.Id, "filesystems")
|
||||
|
||||
result := compare.SyncResult{}
|
||||
|
||||
localFSs := []SFileSystem{}
|
||||
remoteFSs := []cloudprovider.ICloudFileSystem{}
|
||||
|
||||
dbFSs, err := self.GetFileSystems()
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "self.GetFileSystems"))
|
||||
return localFSs, remoteFSs, result
|
||||
}
|
||||
|
||||
removed := make([]SFileSystem, 0)
|
||||
commondb := make([]SFileSystem, 0)
|
||||
commonext := make([]cloudprovider.ICloudFileSystem, 0)
|
||||
added := make([]cloudprovider.ICloudFileSystem, 0)
|
||||
err = compare.CompareSets(dbFSs, filesystems, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "compare.CompareSets"))
|
||||
return localFSs, remoteFSs, result
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].syncRemove(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].SyncWithCloudFileSystem(ctx, userCred, commonext[i])
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
|
||||
localFSs = append(localFSs, commondb[i])
|
||||
remoteFSs = append(remoteFSs, commonext[i])
|
||||
result.Update()
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
newFs, err := self.newFromCloudFileSystem(ctx, userCred, provider, added[i])
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
continue
|
||||
}
|
||||
syncMetadata(ctx, userCred, newFs, added[i])
|
||||
localFSs = append(localFSs, *newFs)
|
||||
remoteFSs = append(remoteFSs, added[i])
|
||||
result.Add()
|
||||
}
|
||||
|
||||
return localFSs, remoteFSs, result
|
||||
}
|
||||
|
||||
func (self *SFileSystem) syncRemove(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
self.DeletePreventionOff(self, userCred)
|
||||
|
||||
err := self.ValidateDeleteCondition(ctx)
|
||||
if err != nil { // cannot delete
|
||||
return self.SetStatus(userCred, api.NAS_STATUS_UNKNOWN, "sync to delete")
|
||||
}
|
||||
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
|
||||
return self.StartDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SFileSystem) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "FileSystemDeleteTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.NAS_STATUS_DELETE_FAILED, err.Error())
|
||||
return nil
|
||||
}
|
||||
self.SetStatus(userCred, api.NAS_STATUS_DELETING, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
mts, err := self.GetMountTargets()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetMountTargets")
|
||||
}
|
||||
for i := range mts {
|
||||
err = mts[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "mount target %s real delete", mts[i].DomainName)
|
||||
}
|
||||
}
|
||||
return self.SInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.DisableDelete.IsTrue() {
|
||||
return httperrors.NewInvalidStatusError("FileSystem is locked, cannot delete")
|
||||
}
|
||||
return self.SStatusInfrasResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) SyncAllWithCloudFileSystem(ctx context.Context, userCred mcclient.TokenCredential, fs cloudprovider.ICloudFileSystem) error {
|
||||
syncFileSystemMountTargets(ctx, userCred, self, fs)
|
||||
return self.SyncWithCloudFileSystem(ctx, userCred, fs)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) SyncWithCloudFileSystem(ctx context.Context, userCred mcclient.TokenCredential, fs cloudprovider.ICloudFileSystem) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.Status = fs.GetStatus()
|
||||
self.StorageType = fs.GetStorageType()
|
||||
self.Protocol = fs.GetProtocol()
|
||||
self.Capacity = fs.GetCapacityGb()
|
||||
self.UsedCapacity = fs.GetUsedCapacityGb()
|
||||
self.FileSystemType = fs.GetFileSystemType()
|
||||
self.MountTargetCountLimit = fs.GetMountTargetCountLimit()
|
||||
if zoneId := fs.GetZoneId(); len(zoneId) > 0 {
|
||||
region, err := self.GetRegion()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "self.GetRegion")
|
||||
}
|
||||
self.ZoneId, _ = region.getZoneIdBySuffix(zoneId)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
|
||||
func (self *SCloudregion) getZoneIdBySuffix(zoneId string) (string, error) {
|
||||
zones, err := self.GetZones()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "region.GetZones")
|
||||
}
|
||||
for _, zone := range zones {
|
||||
if strings.HasSuffix(zone.ExternalId, zoneId) {
|
||||
return zone.Id, nil
|
||||
}
|
||||
}
|
||||
return "", errors.Wrapf(cloudprovider.ErrNotFound, zoneId)
|
||||
}
|
||||
|
||||
func (self *SCloudregion) newFromCloudFileSystem(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, fs cloudprovider.ICloudFileSystem) (*SFileSystem, error) {
|
||||
nas := SFileSystem{}
|
||||
nas.SetModelManager(FileSystemManager, &nas)
|
||||
var err error
|
||||
nas.Name, err = db.GenerateName(FileSystemManager, userCred, fs.GetName())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.GenerateName")
|
||||
}
|
||||
nas.ExternalId = fs.GetGlobalId()
|
||||
nas.CloudregionId = self.Id
|
||||
nas.ManagerId = provider.Id
|
||||
nas.Status = fs.GetStatus()
|
||||
nas.CreatedAt = fs.GetCreatedAt()
|
||||
nas.StorageType = fs.GetStorageType()
|
||||
nas.Protocol = fs.GetProtocol()
|
||||
nas.Capacity = fs.GetCapacityGb()
|
||||
nas.UsedCapacity = fs.GetCapacityGb()
|
||||
nas.FileSystemType = fs.GetFileSystemType()
|
||||
nas.MountTargetCountLimit = fs.GetMountTargetCountLimit()
|
||||
if zoneId := fs.GetZoneId(); len(zoneId) > 0 {
|
||||
nas.ZoneId, _ = self.getZoneIdBySuffix(zoneId)
|
||||
}
|
||||
return &nas, FileSystemManager.TableSpec().Insert(ctx, &nas)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) AllowPerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "syncstatus")
|
||||
}
|
||||
|
||||
// 同步NAS状态
|
||||
func (self *SFileSystem) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.FileSystemSyncstatusInput) (jsonutils.JSONObject, error) {
|
||||
var openTask = true
|
||||
count, err := taskman.TaskManager.QueryTasksOfObject(self, time.Now().Add(-3*time.Minute), &openTask).CountWithError()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, httperrors.NewBadRequestError("Nas has %d task active, can't sync status", count)
|
||||
}
|
||||
|
||||
return nil, self.StartSyncstatus(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SFileSystem) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
return StartResourceSyncStatusTask(ctx, userCred, self, "FileSystemSyncstatusTask", parentTaskId)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetRegion() (*SCloudregion, error) {
|
||||
region, err := CloudregionManager.FetchById(self.CloudregionId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CloudregionManager.FetchById")
|
||||
}
|
||||
return region.(*SCloudregion), nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
provider, err := self.GetDriver()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetDriver")
|
||||
}
|
||||
region, err := self.GetRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetRegion")
|
||||
}
|
||||
iRegion, err := provider.GetIRegionById(region.ExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "provider.GetIRegionById")
|
||||
}
|
||||
return iRegion, nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetICloudFileSystem() (cloudprovider.ICloudFileSystem, error) {
|
||||
if len(self.ExternalId) == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
|
||||
}
|
||||
iRegion, err := self.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "self.GetIRegion")
|
||||
}
|
||||
return iRegion.GetICloudFileSystemById(self.ExternalId)
|
||||
}
|
||||
@@ -69,6 +69,8 @@ func InitDB() error {
|
||||
DBInstanceDatabaseManager,
|
||||
|
||||
SnapshotPolicyDiskManager,
|
||||
AccessGroupManager,
|
||||
AccessGroupRuleManager,
|
||||
} {
|
||||
err := manager.InitializeData()
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SMountTargetManager struct {
|
||||
db.SStatusStandaloneResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SVpcResourceBaseManager
|
||||
SNetworkResourceBaseManager
|
||||
SAccessGroupResourceBaseManager
|
||||
}
|
||||
|
||||
var MountTargetManager *SMountTargetManager
|
||||
|
||||
func init() {
|
||||
MountTargetManager = &SMountTargetManager{
|
||||
SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
|
||||
SMountTarget{},
|
||||
"mount_targets_tbl",
|
||||
"mount_target",
|
||||
"mount_targets",
|
||||
),
|
||||
}
|
||||
MountTargetManager.SetVirtualObject(MountTargetManager)
|
||||
}
|
||||
|
||||
type SMountTarget struct {
|
||||
db.SStatusStandaloneResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SVpcResourceBase
|
||||
SNetworkResourceBase
|
||||
SAccessGroupResourceBase
|
||||
|
||||
NetworkType string `width:"8" charset:"ascii" nullable:"false" create:"required" index:"true" list:"user" default:"vpc"`
|
||||
DomainName string `charset:"utf8" nullable:"true" create:"optional" list:"user"`
|
||||
FileSystemId string `width:"36" charset:"ascii" nullable:"false" create:"required" index:"true" list:"user"`
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowCreate(userCred, manager)
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowList(userCred, manager)
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetFileSystem() (*SFileSystem, error) {
|
||||
fs, err := FileSystemManager.FetchById(self.FileSystemId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "FileSystemManager.FetchById(%s)", self.FileSystemId)
|
||||
}
|
||||
return fs.(*SFileSystem), nil
|
||||
}
|
||||
|
||||
func (self *SMountTarget) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
||||
fs, err := self.GetFileSystem()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return fs.AllowUpdateItem(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.MountTargetCreateInput) (api.MountTargetCreateInput, error) {
|
||||
if len(input.FileSystemId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("file_system_id")
|
||||
}
|
||||
_fs, err := validators.ValidateModel(userCred, FileSystemManager, &input.FileSystemId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
fs := _fs.(*SFileSystem)
|
||||
if fs.MountTargetCountLimit > -1 {
|
||||
mts, err := fs.GetMountTargets()
|
||||
if err != nil {
|
||||
return input, httperrors.NewGeneralError(errors.Wrapf(err, "fs.GetMountTargets"))
|
||||
}
|
||||
if len(mts) > fs.MountTargetCountLimit {
|
||||
return input, httperrors.NewOutOfLimitError("Mount target reached the upper limit")
|
||||
}
|
||||
}
|
||||
if len(input.NetworkType) == 0 {
|
||||
input.NetworkType = api.NETWORK_TYPE_VPC
|
||||
}
|
||||
if !utils.IsInStringArray(input.NetworkType, []string{api.NETWORK_TYPE_VPC, api.NETWORK_TYPE_CLASSIC}) {
|
||||
return input, httperrors.NewInputParameterError("invalid network type %s", input.NetworkType)
|
||||
}
|
||||
if input.NetworkType == api.NETWORK_TYPE_VPC {
|
||||
if len(input.NetworkId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("network_id")
|
||||
}
|
||||
_network, err := validators.ValidateModel(userCred, NetworkManager, &input.NetworkId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
network := _network.(*SNetwork)
|
||||
vpc := network.GetVpc()
|
||||
if vpc == nil {
|
||||
return input, httperrors.NewGeneralError(fmt.Errorf("failed to found vpc for network %s", input.NetworkId))
|
||||
}
|
||||
if vpc.ManagerId != fs.ManagerId {
|
||||
return input, httperrors.NewConflictError("network and filesystem do not belong to the same account")
|
||||
}
|
||||
if vpc.CloudregionId != fs.CloudregionId {
|
||||
return input, httperrors.NewConflictError("network and filesystem are not in the same region")
|
||||
}
|
||||
input.VpcId = vpc.Id
|
||||
}
|
||||
if len(input.AccessGroupId) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("access_group_id")
|
||||
}
|
||||
_, err = validators.ValidateModel(userCred, AccessGroupManager, &input.AccessGroupId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SMountTarget) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
if self.NetworkType == api.NETWORK_TYPE_CLASSIC {
|
||||
db.Update(self, func() error {
|
||||
self.VpcId = ""
|
||||
self.NetworkId = ""
|
||||
return nil
|
||||
})
|
||||
}
|
||||
self.StartCreateTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SMountTarget) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "MountTargetCreateTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.MOUNT_TARGET_STATUS_CREATE_FAILED, err.Error())
|
||||
return nil
|
||||
}
|
||||
self.SetStatus(userCred, api.MOUNT_TARGET_STATUS_CREATING, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.MountTargetListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.AccessGroupFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SVpcResourceBaseManager.ListItemFilter(ctx, q, userCred, query.VpcFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SVpcResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SNetworkResourceBaseManager.ListItemFilter(ctx, q, userCred, query.NetworkFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SNetworkResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if len(query.FileSystemId) > 0 {
|
||||
_, err := validators.ValidateModel(userCred, FileSystemManager, &query.FileSystemId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q = q.Equals("file_system_id", query.FileSystemId)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.MountTargetListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.AccessGroupFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SVpcResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.VpcFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SVpcResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SNetworkResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.NetworkFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SNetworkResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SVpcResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SNetworkResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) FilterByOwner(q *sqlchemy.SQuery, userCred mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if userCred != nil {
|
||||
sq := FileSystemManager.Query("id")
|
||||
if len(userCred.GetProjectDomainId()) > 0 {
|
||||
sq = sq.Equals("domain_id", userCred.GetProjectDomainId())
|
||||
return q.In("file_system_id", sq)
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.MountTargetDetails {
|
||||
rows := make([]api.MountTargetDetails, len(objs))
|
||||
stdRows := manager.SStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
vpcRows := manager.SVpcResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
netRows := manager.SNetworkResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
acRows := manager.SAccessGroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
fsIds := make([]string, len(objs))
|
||||
for i := range rows {
|
||||
rows[i] = api.MountTargetDetails{
|
||||
StatusStandaloneResourceDetails: stdRows[i],
|
||||
VpcResourceInfo: vpcRows[i],
|
||||
NetworkResourceInfo: netRows[i],
|
||||
AccessGroupResourceInfo: acRows[i],
|
||||
}
|
||||
mount := objs[i].(*SMountTarget)
|
||||
fsIds[i] = mount.FileSystemId
|
||||
}
|
||||
|
||||
fsMaps, err := db.FetchIdNameMap2(FileSystemManager, fsIds)
|
||||
if err != nil {
|
||||
return rows
|
||||
}
|
||||
for i := range rows {
|
||||
rows[i].FileSystem, _ = fsMaps[fsIds[i]]
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SMountTargetManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SVpcResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SVpcResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SNetworkResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SNetworkResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SAccessGroupResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SAccessGroupResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SMountTarget) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SMountTarget) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return self.SStatusStandaloneResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
// 删除挂载点
|
||||
func (self *SMountTarget) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query api.ServerDeleteInput, input api.NatgatewayDeleteInput) error {
|
||||
return self.StartDeleteTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SMountTarget) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
var err = func() error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "MountTargetDeleteTask", self, userCred, nil, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "NewTask")
|
||||
}
|
||||
return task.ScheduleRun(nil)
|
||||
}()
|
||||
if err != nil {
|
||||
self.SetStatus(userCred, api.MOUNT_TARGET_STATUS_DELETE_FAILED, err.Error())
|
||||
return err
|
||||
}
|
||||
return self.SetStatus(userCred, api.MOUNT_TARGET_STATUS_DELETING, "")
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetMountTargets() ([]SMountTarget, error) {
|
||||
mounts := []SMountTarget{}
|
||||
q := MountTargetManager.Query().Equals("file_system_id", self.Id)
|
||||
err := db.FetchModelObjects(MountTargetManager, q, &mounts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) SyncMountTargets(ctx context.Context, userCred mcclient.TokenCredential, extMounts []cloudprovider.ICloudMountTarget) compare.SyncResult {
|
||||
lockman.LockRawObject(ctx, self.Id, MountTargetManager.KeywordPlural())
|
||||
lockman.ReleaseRawObject(ctx, self.Id, MountTargetManager.KeywordPlural())
|
||||
|
||||
result := compare.SyncResult{}
|
||||
|
||||
dbMounts, err := self.GetMountTargets()
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "self.GetMountTargets"))
|
||||
return result
|
||||
}
|
||||
|
||||
removed := make([]SMountTarget, 0)
|
||||
commondb := make([]SMountTarget, 0)
|
||||
commonext := make([]cloudprovider.ICloudMountTarget, 0)
|
||||
added := make([]cloudprovider.ICloudMountTarget, 0)
|
||||
err = compare.CompareSets(dbMounts, extMounts, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
result.Error(errors.Wrapf(err, "compare.CompareSets"))
|
||||
return result
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
result.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].SyncWithMountTarget(ctx, userCred, self.ManagerId, commonext[i])
|
||||
if err != nil {
|
||||
result.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
result.Update()
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
err := self.newFromCloudMountTarget(ctx, userCred, added[i])
|
||||
if err != nil {
|
||||
result.AddError(err)
|
||||
continue
|
||||
}
|
||||
result.Add()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *SMountTarget) SyncWithMountTarget(ctx context.Context, userCred mcclient.TokenCredential, managerId string, m cloudprovider.ICloudMountTarget) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.Status = m.GetStatus()
|
||||
self.Name = m.GetName()
|
||||
self.DomainName = m.GetDomainName()
|
||||
self.ExternalId = m.GetGlobalId()
|
||||
if groupId := m.GetAccessGroupId(); len(groupId) > 0 {
|
||||
_cache, _ := db.FetchByExternalIdAndManagerId(AccessGroupCacheManager, groupId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("manager_id", managerId)
|
||||
})
|
||||
if _cache != nil {
|
||||
cache := _cache.(*SAccessGroupCache)
|
||||
self.AccessGroupId = cache.AccessGroupId
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return errors.Wrapf(err, "db.Update")
|
||||
}
|
||||
|
||||
func (self *SFileSystem) newFromCloudMountTarget(ctx context.Context, userCred mcclient.TokenCredential, m cloudprovider.ICloudMountTarget) error {
|
||||
mount := &SMountTarget{}
|
||||
mount.SetModelManager(MountTargetManager, mount)
|
||||
mount.FileSystemId = self.Id
|
||||
mount.Name = m.GetName()
|
||||
mount.Status = m.GetStatus()
|
||||
mount.ExternalId = m.GetGlobalId()
|
||||
mount.DomainName = m.GetDomainName()
|
||||
mount.NetworkType = m.GetNetworkType()
|
||||
if mount.NetworkType == api.NETWORK_TYPE_VPC {
|
||||
if vpcId := m.GetVpcId(); len(vpcId) > 0 {
|
||||
vpc, err := db.FetchByExternalIdAndManagerId(VpcManager, vpcId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("manager_id", self.ManagerId)
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("failed to found vpc for mount point %s by externalId: %s", mount.Name, vpcId)
|
||||
} else {
|
||||
mount.VpcId = vpc.GetId()
|
||||
}
|
||||
}
|
||||
if networkId := m.GetNetworkId(); len(networkId) > 0 {
|
||||
network, err := db.FetchByExternalIdAndManagerId(NetworkManager, networkId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
wire := WireManager.Query().SubQuery()
|
||||
vpc := VpcManager.Query().SubQuery()
|
||||
return q.Join(wire, sqlchemy.Equals(wire.Field("id"), q.Field("wire_id"))).
|
||||
Join(vpc, sqlchemy.Equals(vpc.Field("id"), wire.Field("vpc_id"))).
|
||||
Filter(sqlchemy.Equals(vpc.Field("manager_id"), self.ManagerId))
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("failed to found network for mount point %s by externalId: %s", mount.Name, networkId)
|
||||
} else {
|
||||
mount.NetworkId = network.GetId()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MountTargetManager.TableSpec().Insert(ctx, mount)
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetNetwork() (*SNetwork, error) {
|
||||
network, err := NetworkManager.FetchById(self.NetworkId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NetworkManager.FetchById(%s)", self.NetworkId)
|
||||
}
|
||||
return network.(*SNetwork), nil
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetVpc() (*SVpc, error) {
|
||||
vpc, err := VpcManager.FetchById(self.VpcId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "VpcManager.FetchById(%s)", self.VpcId)
|
||||
}
|
||||
return vpc.(*SVpc), nil
|
||||
}
|
||||
|
||||
func (self *SMountTarget) AllowPerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsDomainAllowPerform(userCred, self, "syncstatus")
|
||||
}
|
||||
|
||||
// 同步挂载点状态
|
||||
func (self *SMountTarget) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.MountTargetSyncstatusInput) (jsonutils.JSONObject, error) {
|
||||
return nil, self.StartSyncstatus(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (self *SMountTarget) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
return StartResourceSyncStatusTask(ctx, userCred, self, "MountTargetSyncstatusTask", parentTaskId)
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SNasSkuManager struct {
|
||||
db.SEnabledStatusStandaloneResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SCloudregionResourceBaseManager
|
||||
}
|
||||
|
||||
var NasSkuManager *SNasSkuManager
|
||||
|
||||
func init() {
|
||||
NasSkuManager = &SNasSkuManager{
|
||||
SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(
|
||||
SNasSku{},
|
||||
"nas_skus_tbl",
|
||||
"nas_sku",
|
||||
"nas_skus",
|
||||
),
|
||||
}
|
||||
NasSkuManager.NameRequireAscii = false
|
||||
NasSkuManager.SetVirtualObject(NasSkuManager)
|
||||
}
|
||||
|
||||
type SNasSku struct {
|
||||
db.SEnabledStatusStandaloneResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SCloudregionResourceBase
|
||||
|
||||
PrepaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 预付费资源状态 available|soldout
|
||||
PostpaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 按需付费资源状态 available|soldout
|
||||
|
||||
StorageType string `width:"32" index:"true" list:"user" create:"optional"`
|
||||
DiskSizeStep int `list:"user" default:"-1" create:"optional"` //步长
|
||||
MaxDiskSizeGb int `list:"user" create:"optional"`
|
||||
MinDiskSizeGb int `list:"user" create:"optional"`
|
||||
|
||||
NetworkTypes string `list:"user" create:"optional"`
|
||||
FileSystemType string `list:"user" create:"optional"`
|
||||
Protocol string `list:"user" create:"optional"`
|
||||
|
||||
Provider string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
ZoneIds string `charset:"utf8" nullable:"true" list:"user" update:"admin" create:"admin_optional" json:"zone_ids"`
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.NasSkuListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SExternalizedResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "SCloudregionResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if len(query.PostpaidStatus) > 0 {
|
||||
q = q.Equals("postpaid_status", query.PostpaidStatus)
|
||||
}
|
||||
if len(query.PrepaidStatus) > 0 {
|
||||
q = q.Equals("prepaid_status", query.PrepaidStatus)
|
||||
}
|
||||
if len(query.Providers) > 0 {
|
||||
q = q.In("provider", query.Providers)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.NasSkuDetails {
|
||||
rows := make([]api.NasSkuDetails, len(objs))
|
||||
|
||||
stdRows := manager.SEnabledStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.NasSkuDetails{
|
||||
EnabledStatusStandaloneResourceDetails: stdRows[i],
|
||||
CloudregionResourceInfo: regRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.NasSkuListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SCloudregion) GetNasSkus() ([]SNasSku, error) {
|
||||
skus := []SNasSku{}
|
||||
q := NasSkuManager.Query().Equals("cloudregion_id", self.Id)
|
||||
err := db.FetchModelObjects(NasSkuManager, q, &skus)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return skus, nil
|
||||
}
|
||||
|
||||
func (self SNasSku) GetGlobalId() string {
|
||||
return self.ExternalId
|
||||
}
|
||||
|
||||
func (self *SCloudregion) SyncNasSkus(ctx context.Context, userCred mcclient.TokenCredential, meta *SSkuResourcesMeta) compare.SyncResult {
|
||||
lockman.LockRawObject(ctx, self.Id, "nas-sku")
|
||||
defer lockman.ReleaseRawObject(ctx, self.Id, "nas-sku")
|
||||
|
||||
syncResult := compare.SyncResult{}
|
||||
|
||||
iskus, err := meta.GetNasSkusByRegionExternalId(self.ExternalId)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
dbSkus, err := self.GetNasSkus()
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
removed := make([]SNasSku, 0)
|
||||
commondb := make([]SNasSku, 0)
|
||||
commonext := make([]SNasSku, 0)
|
||||
added := make([]SNasSku, 0)
|
||||
|
||||
err = compare.CompareSets(dbSkus, iskus, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
syncResult.DeleteError(err)
|
||||
continue
|
||||
}
|
||||
syncResult.Delete()
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].syncWithCloudSku(ctx, userCred, commonext[i])
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
continue
|
||||
}
|
||||
syncResult.Update()
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
err = self.newFromCloudNasSku(ctx, userCred, added[i])
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
syncResult.Add()
|
||||
}
|
||||
}
|
||||
return syncResult
|
||||
}
|
||||
|
||||
func (self *SNasSku) syncWithCloudSku(ctx context.Context, userCred mcclient.TokenCredential, sku SNasSku) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
jsonutils.Update(self, sku)
|
||||
self.Status = api.NAS_SKU_AVAILABLE
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SCloudregion) newFromCloudNasSku(ctx context.Context, userCred mcclient.TokenCredential, isku SNasSku) error {
|
||||
sku := &isku
|
||||
sku.SetModelManager(NasSkuManager, sku)
|
||||
sku.Id = "" //避免使用yunion meta的id,导致出现duplicate entry问题
|
||||
sku.Status = api.NAS_SKU_AVAILABLE
|
||||
sku.SetEnabled(true)
|
||||
sku.CloudregionId = self.Id
|
||||
return NasSkuManager.TableSpec().Insert(ctx, sku)
|
||||
}
|
||||
|
||||
func SyncNasSkus(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
err := SyncRegionNasSkus(ctx, userCred, "", isStart)
|
||||
if err != nil {
|
||||
log.Errorf("SyncRegionNasSkus error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func SyncRegionNasSkus(ctx context.Context, userCred mcclient.TokenCredential, regionId string, isStart bool) error {
|
||||
if isStart {
|
||||
q := NasSkuManager.Query()
|
||||
if len(regionId) > 0 {
|
||||
q = q.Equals("cloudregion_id", regionId)
|
||||
}
|
||||
cnt, err := q.Limit(1).CountWithError()
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return errors.Wrapf(err, "SyncRegionNasSkus.QueryNasSku")
|
||||
}
|
||||
if cnt > 0 {
|
||||
log.Debugf("SyncRegionNasSkus synced skus, skip...")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
q := CloudregionManager.Query()
|
||||
q = q.In("provider", CloudproviderManager.GetPublicProviderProvidersQuery())
|
||||
if len(regionId) > 0 {
|
||||
q = q.Equals("id", regionId)
|
||||
}
|
||||
regions := []SCloudregion{}
|
||||
err := db.FetchModelObjects(CloudregionManager, q, ®ions)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
|
||||
meta, err := FetchSkuResourcesMeta()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "FetchSkuResourcesMeta")
|
||||
}
|
||||
|
||||
for i := range regions {
|
||||
if !regions[i].GetDriver().IsSupportedNas() {
|
||||
log.Infof("region %s(%s) not support nas, skip sync", regions[i].Name, regions[i].Id)
|
||||
continue
|
||||
}
|
||||
result := regions[i].SyncNasSkus(ctx, userCred, meta)
|
||||
msg := result.Result()
|
||||
notes := fmt.Sprintf("SyncNasSkus for region %s result: %s", regions[i].Name, msg)
|
||||
log.Infof(notes)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) AllowSyncSkus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, manager, "sync-skus")
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) PerformSyncSkus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SkuSyncInput) (jsonutils.JSONObject, error) {
|
||||
return PerformActionSyncSkus(ctx, userCred, manager.Keyword(), input)
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) AllowGetPropertySyncTasks(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowGetSpec(userCred, manager, "sync-tasks")
|
||||
}
|
||||
|
||||
func (manager *SNasSkuManager) GetPropertySyncTasks(ctx context.Context, userCred mcclient.TokenCredential, query api.SkuTaskQueryInput) (jsonutils.JSONObject, error) {
|
||||
return GetPropertySkusSyncTasks(ctx, userCred, query)
|
||||
}
|
||||
@@ -63,11 +63,6 @@ type SNatSku struct {
|
||||
PrepaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 预付费资源状态 available|soldout
|
||||
PostpaidStatus string `width:"32" charset:"utf8" nullable:"false" list:"user" create:"admin_optional" update:"admin" default:"available"` // 按需付费资源状态 available|soldout
|
||||
|
||||
Cps int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
Conns int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
Pps int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
Throughput int `nullable:"false" list:"user" create:"optional" update:"admin"`
|
||||
|
||||
Provider string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
ZoneIds string `charset:"utf8" nullable:"true" list:"user" update:"admin" create:"admin_optional" json:"zone_ids"`
|
||||
}
|
||||
|
||||
@@ -1789,6 +1789,54 @@ func (manager *SPolicyDefinitionManager) purgeAll(ctx context.Context, userCred
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAccessGroupCache) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SAccessGroupCacheManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
|
||||
caches := []SAccessGroupCache{}
|
||||
err := fetchByManagerId(manager, providerId, &caches)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetchByManagerId")
|
||||
}
|
||||
|
||||
for i := range caches {
|
||||
err := caches[i].purge(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cache purge")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SFileSystemManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
|
||||
files := []SFileSystem{}
|
||||
err := fetchByManagerId(manager, providerId, &files)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetchByManagerId")
|
||||
}
|
||||
|
||||
for i := range files {
|
||||
err := files[i].purge(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cache purge")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vpcPC *SVpcPeeringConnection) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, vpcPC)
|
||||
defer lockman.ReleaseObject(ctx, vpcPC)
|
||||
|
||||
@@ -177,6 +177,12 @@ type IDBInstanceDriver interface {
|
||||
INatGatewayDriver
|
||||
|
||||
IElasticIpDriver
|
||||
INasDriver
|
||||
}
|
||||
|
||||
type INasDriver interface {
|
||||
RequestSyncAccessGroup(ctx context.Context, userCred mcclient.TokenCredential, fs *SFileSystem, mt *SMountTarget, ag *SAccessGroup, task taskman.ITask) error
|
||||
IsSupportedNas() bool
|
||||
}
|
||||
|
||||
// NAT
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
@@ -19,7 +33,13 @@ import (
|
||||
)
|
||||
|
||||
func PerformActionSyncSkus(ctx context.Context, userCred mcclient.TokenCredential, resourceKey string, input apis.SkuSyncInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(resourceKey, []string{ServerSkuManager.Keyword(), ElasticcacheSkuManager.Keyword(), DBInstanceSkuManager.Keyword(), NatSkuManager.Keyword()}) {
|
||||
if !utils.IsInStringArray(resourceKey, []string{
|
||||
ServerSkuManager.Keyword(),
|
||||
ElasticcacheSkuManager.Keyword(),
|
||||
DBInstanceSkuManager.Keyword(),
|
||||
NatSkuManager.Keyword(),
|
||||
NasSkuManager.Keyword(),
|
||||
}) {
|
||||
return nil, httperrors.NewUnsupportOperationError("resource %s is not support sync skus", resourceKey)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ type SSkuResourcesMeta struct {
|
||||
ElasticCacheBase string `json:"elastic_cache_base"`
|
||||
ImageBase string `json:"image_base"`
|
||||
NatBase string `json:"nat_base"`
|
||||
NasBase string `json:"nas_base"`
|
||||
}
|
||||
|
||||
func (self *SSkuResourcesMeta) getZoneIdBySuffix(zoneMaps map[string]string, suffix string) string {
|
||||
@@ -161,6 +162,43 @@ func (self *SSkuResourcesMeta) GetNatSkusByRegionExternalId(regionExternalId str
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SSkuResourcesMeta) GetNasSkusByRegionExternalId(regionExternalId string) ([]SNasSku, error) {
|
||||
regionId, zoneMaps, err := self.GetRegionIdAndZoneMaps(regionExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetRegionIdAndZoneMaps")
|
||||
}
|
||||
result := []SNasSku{}
|
||||
objs, err := self.getObjsByRegion(self.NasBase, regionExternalId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "getSkusByRegion")
|
||||
}
|
||||
for _, obj := range objs {
|
||||
sku := SNasSku{}
|
||||
sku.SetModelManager(NasSkuManager, &sku)
|
||||
err = obj.Unmarshal(&sku)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "obj.Unmarshal")
|
||||
}
|
||||
if len(sku.ZoneIds) > 0 {
|
||||
zoneIds := []string{}
|
||||
for _, zoneExtId := range strings.Split(sku.ZoneIds, ",") {
|
||||
zoneId := self.getZoneIdBySuffix(zoneMaps, zoneExtId) // Huawei rds sku zone1 maybe is cn-north-4f
|
||||
if len(zoneId) == 0 {
|
||||
log.Warningf("invalid nat sku %s(%s) %s zone: %s", sku.Name, sku.Id, sku.CloudregionId, zoneExtId)
|
||||
continue
|
||||
}
|
||||
zoneIds = append(zoneIds, zoneId)
|
||||
}
|
||||
sku.ZoneIds = strings.Join(zoneIds, ",")
|
||||
}
|
||||
sku.Id = ""
|
||||
sku.CloudregionId = regionId
|
||||
|
||||
result = append(result, sku)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SSkuResourcesMeta) getCloudregion(regionExternalId string) (*SCloudregion, error) {
|
||||
region, err := db.FetchByExternalId(CloudregionManager, regionExternalId)
|
||||
if err != nil {
|
||||
|
||||
@@ -300,6 +300,18 @@ var (
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: api.SERVICE_TYPE,
|
||||
Resource: "nas_skus",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
{
|
||||
Service: api.SERVICE_TYPE,
|
||||
Resource: "nas_skus",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.Allow,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1474,3 +1474,56 @@ func (self *SAliyunRegionDriver) ValidateCreateNatGateway(ctx context.Context, u
|
||||
func (self *SAliyunRegionDriver) IsSupportedNatGateway() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) IsSupportedNas() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) RequestSyncAccessGroup(ctx context.Context, userCred mcclient.TokenCredential, fs *models.SFileSystem, mt *models.SMountTarget, ag *models.SAccessGroup, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
if mt.AccessGroupId == api.DEFAULT_ACCESS_GROUP {
|
||||
return jsonutils.Marshal(
|
||||
map[string]string{
|
||||
"access_group_id": fmt.Sprintf("DEFAULT_%s_GROUP_NAME", strings.ToUpper(mt.NetworkType)),
|
||||
}), nil
|
||||
}
|
||||
caches, err := ag.GetAccessGroupCaches()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ag.GetAccessGroupCaches")
|
||||
}
|
||||
for i := range caches {
|
||||
if caches[i].CloudregionId == fs.CloudregionId &&
|
||||
caches[i].ManagerId == fs.ManagerId &&
|
||||
caches[i].FileSystemType == fs.FileSystemType &&
|
||||
caches[i].NetworkType == mt.NetworkType {
|
||||
if len(caches[i].ExternalId) > 0 {
|
||||
err := caches[i].SyncRules()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cache.SyncRules")
|
||||
}
|
||||
return jsonutils.Marshal(map[string]string{"access_group_id": caches[i].ExternalId}), nil
|
||||
}
|
||||
err := caches[i].CreateIAccessGroup()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateIAccessGroup")
|
||||
}
|
||||
return jsonutils.Marshal(map[string]string{"access_group_id": caches[i].ExternalId}), nil
|
||||
}
|
||||
}
|
||||
opts := models.SAccessGroupCacheRegisterInput{
|
||||
Name: ag.Name,
|
||||
Desc: ag.Description,
|
||||
ManagerId: fs.ManagerId,
|
||||
CloudregionId: fs.CloudregionId,
|
||||
NetworkType: mt.NetworkType,
|
||||
FileSystemType: fs.FileSystemType,
|
||||
AccessGroupId: ag.Id,
|
||||
}
|
||||
cache, err := models.AccessGroupCacheManager.Register(ctx, &opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Register")
|
||||
}
|
||||
return jsonutils.Marshal(map[string]string{"access_group_id": cache.ExternalId}), nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -428,6 +428,10 @@ func (self *SBaseRegionDriver) IsSupportedNatGateway() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) IsSupportedNas() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) OnNatEntryDeleteComplete(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip) error {
|
||||
return nil
|
||||
}
|
||||
@@ -443,3 +447,7 @@ func (self *SBaseRegionDriver) IsSupportedNatAutoRenew() bool {
|
||||
func (self *SBaseRegionDriver) RequestAssociatEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error {
|
||||
return httperrors.NewNotImplementedError("RequestAssociatEip")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) RequestSyncAccessGroup(ctx context.Context, userCred mcclient.TokenCredential, fs *models.SFileSystem, mt *models.SMountTarget, ag *models.SAccessGroup, task taskman.ITask) error {
|
||||
return errors.Wrapf(cloudprovider.ErrNotImplemented, "RequestSyncAccessGroup")
|
||||
}
|
||||
|
||||
@@ -205,6 +205,13 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.InterVpcNetworkManager,
|
||||
|
||||
models.NatSkuManager,
|
||||
models.NasSkuManager,
|
||||
|
||||
models.FileSystemManager,
|
||||
models.AccessGroupManager,
|
||||
models.AccessGroupRuleManager,
|
||||
models.AccessGroupCacheManager,
|
||||
models.MountTargetManager,
|
||||
} {
|
||||
db.RegisterModelManager(manager)
|
||||
handler := db.NewModelHandler(manager)
|
||||
|
||||
@@ -153,6 +153,7 @@ func StartService() {
|
||||
cron.AddJobEveryFewDays("SyncSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncServerSkus, true)
|
||||
cron.AddJobEveryFewDays("SyncDBInstanceSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncDBInstanceSkus, true)
|
||||
cron.AddJobEveryFewDays("SyncNatSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncNatSkus, false)
|
||||
cron.AddJobEveryFewDays("SyncNasSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncNasSkus, false)
|
||||
cron.AddJobEveryFewDays("SyncElasticCacheSkus", opts.SyncSkusDay, opts.SyncSkusHour, 0, 0, models.SyncElasticCacheSkus, true)
|
||||
cron.AddJobEveryFewDays("StorageSnapshotsRecycle", 1, 2, 0, 0, models.StorageManager.StorageSnapshotsRecycle, false)
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 cachereed 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 langucachee governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type AccessGroupCacheDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(AccessGroupCacheDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *AccessGroupCacheDeleteTask) taskFailed(ctx context.Context, cache *models.SAccessGroupCache, err error) {
|
||||
cache.SetStatus(self.UserCred, api.ACCESS_GROUP_STATUS_DELETE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, cache, logclient.ACT_DELOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *AccessGroupCacheDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
cache := obj.(*models.SAccessGroupCache)
|
||||
|
||||
iAccessGroup, err := cache.GetICloudAccessGroup()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
self.taskComplete(ctx, cache)
|
||||
return
|
||||
}
|
||||
self.taskFailed(ctx, cache, errors.Wrapf(err, "GetICloudAccessGroup"))
|
||||
return
|
||||
}
|
||||
err = iAccessGroup.Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, cache, errors.Wrapf(err, "iAccessGroup.Delete"))
|
||||
return
|
||||
}
|
||||
self.taskComplete(ctx, cache)
|
||||
}
|
||||
|
||||
func (self *AccessGroupCacheDeleteTask) taskComplete(ctx context.Context, cache *models.SAccessGroupCache) {
|
||||
cache.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type AccessGroupDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(AccessGroupDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *AccessGroupDeleteTask) taskFailed(ctx context.Context, ag *models.SAccessGroup, cache *models.SAccessGroupCache, err error) {
|
||||
ag.SetStatus(self.UserCred, api.ACCESS_GROUP_STATUS_DELETE_FAILED, err.Error())
|
||||
if cache != nil {
|
||||
cache.SetStatus(self.UserCred, api.ACCESS_GROUP_STATUS_DELETE_FAILED, err.Error())
|
||||
}
|
||||
logclient.AddActionLogWithStartable(self, ag, logclient.ACT_DELOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *AccessGroupDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
ag := obj.(*models.SAccessGroup)
|
||||
|
||||
caches, err := ag.GetAccessGroupCaches()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, ag, nil, errors.Wrapf(err, "GetAccessGroupCaches"))
|
||||
return
|
||||
}
|
||||
for i := range caches {
|
||||
caches[i].SetStatus(self.GetUserCred(), api.ACCESS_GROUP_STATUS_DELETING, "")
|
||||
iAccessGroup, err := caches[i].GetICloudAccessGroup()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
caches[i].RealDelete(ctx, self.GetUserCred())
|
||||
continue
|
||||
}
|
||||
self.taskFailed(ctx, ag, &caches[i], errors.Wrapf(err, "cache.GetICloudAccessGroup"))
|
||||
return
|
||||
}
|
||||
err = iAccessGroup.Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, ag, &caches[i], errors.Wrapf(err, "iAccessGroup.Delete"))
|
||||
return
|
||||
}
|
||||
caches[i].RealDelete(ctx, self.GetUserCred())
|
||||
}
|
||||
self.taskComplete(ctx, ag)
|
||||
}
|
||||
|
||||
func (self *AccessGroupDeleteTask) taskComplete(ctx context.Context, ag *models.SAccessGroup) {
|
||||
ag.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type AccessGroupSyncRulesTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(AccessGroupSyncRulesTask{})
|
||||
}
|
||||
|
||||
func (self *AccessGroupSyncRulesTask) taskFail(ctx context.Context, ag *models.SAccessGroup, err error) {
|
||||
ag.SetStatus(self.GetUserCred(), api.ACCESS_GROUP_STATUS_AVAILABLE, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, ag, logclient.ACT_SYNC_CONF, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *AccessGroupSyncRulesTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
ag := obj.(*models.SAccessGroup)
|
||||
|
||||
caches, err := ag.GetAccessGroupCaches()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, ag, errors.Wrapf(err, "ag.GetAccessGroupCaches"))
|
||||
return
|
||||
}
|
||||
|
||||
for i := range caches {
|
||||
err := caches[i].SyncRules()
|
||||
if err != nil {
|
||||
caches[i].SetStatus(self.GetUserCred(), api.ACCESS_GROUP_STATUS_SYNC_RULES_FAILED, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
ag.SetStatus(self.GetUserCred(), api.ACCESS_GROUP_STATUS_AVAILABLE, "")
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type AccessGroupSyncstatusTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(AccessGroupSyncstatusTask{})
|
||||
}
|
||||
|
||||
func (self *AccessGroupSyncstatusTask) taskFail(ctx context.Context, ag *models.SAccessGroup, err error) {
|
||||
ag.SetStatus(self.GetUserCred(), api.ACCESS_GROUP_STATUS_AVAILABLE, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, ag, logclient.ACT_SYNC_STATUS, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *AccessGroupSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
ag := obj.(*models.SAccessGroup)
|
||||
|
||||
caches, err := ag.GetAccessGroupCaches()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, ag, errors.Wrapf(err, "ag.GetAccessGroupCaches"))
|
||||
return
|
||||
}
|
||||
|
||||
for i := range caches {
|
||||
caches[i].SyncStatus(ctx, self.GetUserCred())
|
||||
}
|
||||
|
||||
ag.SetStatus(self.GetUserCred(), api.ACCESS_GROUP_STATUS_AVAILABLE, "")
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -105,6 +105,9 @@ func (self *CloudAccountSyncSkusTask) OnInit(ctx context.Context, obj db.IStanda
|
||||
case models.NatSkuManager.Keyword():
|
||||
result := region.SyncNatSkus(ctx, self.GetUserCred(), meta)
|
||||
log.Infof("Sync %s %s skus for region %s result: %s", region.Provider, res, region.Name, result.Result())
|
||||
case models.NasSkuManager.Keyword():
|
||||
result := region.SyncNasSkus(ctx, self.GetUserCred(), meta)
|
||||
log.Infof("Sync %s %s skus for region %s result: %s", region.Provider, res, region.Name, result.Result())
|
||||
}
|
||||
|
||||
if syncFunc != nil {
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// 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 fsreed 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 langufse governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type FileSystemCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(FileSystemCreateTask{})
|
||||
}
|
||||
|
||||
func (self *FileSystemCreateTask) taskFailed(ctx context.Context, fs *models.SFileSystem, err error) {
|
||||
fs.SetStatus(self.UserCred, api.NAS_STATUS_CREATE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, fs, logclient.ACT_ALLOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *FileSystemCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
fs := obj.(*models.SFileSystem)
|
||||
|
||||
iRegion, err := fs.GetIRegion()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, fs, errors.Wrapf(err, "fs.GetIRegion"))
|
||||
return
|
||||
}
|
||||
|
||||
opts := &cloudprovider.FileSystemCraeteOptions{
|
||||
Name: fs.Name,
|
||||
Desc: fs.Description,
|
||||
Capacity: fs.Capacity,
|
||||
StorageType: fs.StorageType,
|
||||
Protocol: fs.Protocol,
|
||||
FileSystemType: fs.FileSystemType,
|
||||
ZoneId: strings.TrimPrefix(fs.GetZone().ExternalId, iRegion.GetGlobalId()+"/"),
|
||||
}
|
||||
|
||||
netId := jsonutils.GetAnyString(self.GetParams(), []string{"network_id"})
|
||||
if len(netId) > 0 {
|
||||
net, err := models.NetworkManager.FetchById(netId)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, fs, errors.Wrapf(err, "NetworkManager.FetchById(%s)", netId))
|
||||
return
|
||||
}
|
||||
network := net.(*models.SNetwork)
|
||||
opts.NetworkId = network.ExternalId
|
||||
opts.VpcId = network.GetVpc().ExternalId
|
||||
}
|
||||
|
||||
log.Infof("nas create params: %v", opts)
|
||||
|
||||
iFs, err := iRegion.CreateICloudFileSystem(opts)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, fs, errors.Wrapf(err, "iRegion.CreaetICloudFileSystem"))
|
||||
return
|
||||
}
|
||||
db.SetExternalId(fs, self.GetUserCred(), iFs.GetGlobalId())
|
||||
|
||||
cloudprovider.WaitStatus(iFs, api.NAS_STATUS_AVAILABLE, time.Second*5, time.Minute*3)
|
||||
|
||||
self.SetStage("OnSyncstatusComplete", nil)
|
||||
fs.StartSyncstatus(ctx, self.GetUserCred(), self.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *FileSystemCreateTask) OnSyncstatusComplete(ctx context.Context, fs *models.SFileSystem, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *FileSystemCreateTask) OnSyncstatusCompleteFailed(ctx context.Context, fs *models.SFileSystem, data jsonutils.JSONObject) {
|
||||
self.SetStageFailed(ctx, data)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// 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 fsreed 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 langufse governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type FileSystemDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(FileSystemDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *FileSystemDeleteTask) taskFailed(ctx context.Context, fs *models.SFileSystem, err error) {
|
||||
fs.SetStatus(self.UserCred, api.NAS_STATUS_DELETE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, fs, logclient.ACT_DELOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *FileSystemDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
fs := obj.(*models.SFileSystem)
|
||||
|
||||
if len(fs.ExternalId) == 0 {
|
||||
self.taskComplete(ctx, fs)
|
||||
return
|
||||
}
|
||||
|
||||
iFs, err := fs.GetICloudFileSystem()
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
self.taskComplete(ctx, fs)
|
||||
return
|
||||
}
|
||||
self.taskFailed(ctx, fs, errors.Wrapf(err, "fs.GetICloudFileSystem"))
|
||||
return
|
||||
}
|
||||
err = iFs.Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, fs, errors.Wrapf(err, "iFs.Delete"))
|
||||
return
|
||||
}
|
||||
cloudprovider.WaitDeleted(iFs, time.Second*10, time.Minute*5)
|
||||
self.taskComplete(ctx, fs)
|
||||
}
|
||||
|
||||
func (self *FileSystemDeleteTask) taskComplete(ctx context.Context, fs *models.SFileSystem) {
|
||||
fs.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type FileSystemSyncstatusTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(FileSystemSyncstatusTask{})
|
||||
}
|
||||
|
||||
func (self *FileSystemSyncstatusTask) taskFail(ctx context.Context, nas *models.SFileSystem, err error) {
|
||||
nas.SetStatus(self.GetUserCred(), api.NAS_STATUS_UNKNOWN, err.Error())
|
||||
db.OpsLog.LogEvent(nas, db.ACT_SYNC_STATUS, err, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, nas, logclient.ACT_SYNC_STATUS, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *FileSystemSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
nas := obj.(*models.SFileSystem)
|
||||
|
||||
iNas, err := nas.GetICloudFileSystem()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, nas, errors.Wrapf(err, "nas.GetICloudFileSystem"))
|
||||
return
|
||||
}
|
||||
|
||||
err = nas.SyncAllWithCloudFileSystem(ctx, self.GetUserCred(), iNas)
|
||||
if err != nil {
|
||||
self.taskFail(ctx, nas, errors.Wrapf(err, "nas.SyncAllWithCloudFileSystem"))
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"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/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type MountTargetCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(MountTargetCreateTask{})
|
||||
}
|
||||
|
||||
func (self *MountTargetCreateTask) taskFailed(ctx context.Context, mt *models.SMountTarget, err error) {
|
||||
mt.SetStatus(self.UserCred, api.MOUNT_TARGET_STATUS_CREATE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, mt, logclient.ACT_ALLOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *MountTargetCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
mt := obj.(*models.SMountTarget)
|
||||
|
||||
fs, err := mt.GetFileSystem()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "GetFileSystem"))
|
||||
return
|
||||
}
|
||||
region, err := fs.GetRegion()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "fs.GetRegion"))
|
||||
return
|
||||
}
|
||||
|
||||
ag, err := mt.GetAccessGroup()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "mt.GetAccessGroup"))
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStage("OnSyncAccessGroupComplete", nil)
|
||||
err = region.GetDriver().RequestSyncAccessGroup(ctx, self.GetUserCred(), fs, mt, ag, self)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "RequestSyncAccessGroup"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (self *MountTargetCreateTask) OnSyncAccessGroupCompleteFailed(ctx context.Context, mt *models.SMountTarget, data jsonutils.JSONObject) {
|
||||
self.taskFailed(ctx, mt, errors.Error(data.String()))
|
||||
}
|
||||
|
||||
func (self *MountTargetCreateTask) OnSyncAccessGroupComplete(ctx context.Context, mt *models.SMountTarget, data jsonutils.JSONObject) {
|
||||
opts := cloudprovider.SMountTargetCreateOptions{NetworkType: mt.NetworkType}
|
||||
data.Unmarshal(&opts)
|
||||
if len(opts.AccessGroupId) == 0 {
|
||||
self.taskFailed(ctx, mt, errors.Error("empty access_group_id after sync"))
|
||||
return
|
||||
}
|
||||
|
||||
fs, err := mt.GetFileSystem()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "GetFileSystem"))
|
||||
return
|
||||
}
|
||||
|
||||
iFs, err := fs.GetICloudFileSystem()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "fs.GetICloudFileSystem"))
|
||||
return
|
||||
}
|
||||
|
||||
if opts.NetworkType == api.NETWORK_TYPE_VPC {
|
||||
network, err := mt.GetNetwork()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "mt.GetNetwork"))
|
||||
return
|
||||
}
|
||||
opts.NetworkId = network.ExternalId
|
||||
vpc, err := mt.GetVpc()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "mt.GetVpc"))
|
||||
return
|
||||
}
|
||||
opts.VpcId = vpc.ExternalId
|
||||
}
|
||||
|
||||
opts.FileSystemId = fs.ExternalId
|
||||
|
||||
iMt, err := iFs.CreateMountTarget(&opts)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "iFs.CreateMountTarget"))
|
||||
return
|
||||
}
|
||||
|
||||
cloudprovider.Wait(time.Second*10, time.Minute*3, func() (bool, error) {
|
||||
mts, err := iFs.GetMountTargets()
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "iFs.GetMountTargets")
|
||||
}
|
||||
for i := range mts {
|
||||
if mts[i].GetGlobalId() == iMt.GetGlobalId() {
|
||||
status := mts[i].GetStatus()
|
||||
log.Infof("expect mount point status %s current is %s", api.MOUNT_TARGET_STATUS_AVAILABLE, status)
|
||||
if status == api.MOUNT_TARGET_STATUS_AVAILABLE {
|
||||
iMt = mts[i]
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
mt.SyncWithMountTarget(ctx, self.GetUserCred(), fs.ManagerId, iMt)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type MountTargetDeleteTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(MountTargetDeleteTask{})
|
||||
}
|
||||
|
||||
func (self *MountTargetDeleteTask) taskFailed(ctx context.Context, mt *models.SMountTarget, err error) {
|
||||
mt.SetStatus(self.UserCred, api.MOUNT_TARGET_STATUS_DELETE_FAILED, err.Error())
|
||||
logclient.AddActionLogWithStartable(self, mt, logclient.ACT_DELOCATE, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *MountTargetDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
mt := obj.(*models.SMountTarget)
|
||||
|
||||
if len(mt.ExternalId) == 0 {
|
||||
self.taskComplete(ctx, nil, mt)
|
||||
return
|
||||
}
|
||||
|
||||
fs, err := mt.GetFileSystem()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "GetFileSystem"))
|
||||
return
|
||||
}
|
||||
iFileSystem, err := fs.GetICloudFileSystem()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "GetICloudFileSystem"))
|
||||
return
|
||||
}
|
||||
iMountTargets, err := iFileSystem.GetMountTargets()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "GetMountTargets"))
|
||||
return
|
||||
}
|
||||
for i := range iMountTargets {
|
||||
if iMountTargets[i].GetGlobalId() == mt.ExternalId {
|
||||
err = iMountTargets[i].Delete()
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, mt, errors.Wrapf(err, "iMountTarget.Delete"))
|
||||
return
|
||||
}
|
||||
self.taskComplete(ctx, fs, mt)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
self.taskComplete(ctx, fs, mt)
|
||||
}
|
||||
|
||||
func (self *MountTargetDeleteTask) taskComplete(ctx context.Context, fs *models.SFileSystem, mt *models.SMountTarget) {
|
||||
if fs != nil {
|
||||
logclient.AddActionLogWithStartable(self, fs, logclient.ACT_DELOCATE, mt, self.UserCred, true)
|
||||
}
|
||||
mt.RealDelete(ctx, self.GetUserCred())
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type MountTargetSyncstatusTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(MountTargetSyncstatusTask{})
|
||||
}
|
||||
|
||||
func (self *MountTargetSyncstatusTask) taskFail(ctx context.Context, mt *models.SMountTarget, err error) {
|
||||
mt.SetStatus(self.GetUserCred(), api.MOUNT_TARGET_STATUS_UNKNOWN, err.Error())
|
||||
db.OpsLog.LogEvent(mt, db.ACT_SYNC_STATUS, err, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, mt, logclient.ACT_SYNC_STATUS, err, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, jsonutils.NewString(err.Error()))
|
||||
}
|
||||
|
||||
func (self *MountTargetSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
mt := obj.(*models.SMountTarget)
|
||||
|
||||
fs, err := mt.GetFileSystem()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, mt, errors.Wrapf(err, "GetFileSystem"))
|
||||
return
|
||||
}
|
||||
iFs, err := fs.GetICloudFileSystem()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, mt, errors.Wrapf(err, "fs.GetICloudFileSystem"))
|
||||
return
|
||||
}
|
||||
mts, err := iFs.GetMountTargets()
|
||||
if err != nil {
|
||||
self.taskFail(ctx, mt, errors.Wrapf(err, "iFs.GetMountTargets"))
|
||||
return
|
||||
}
|
||||
for i := range mts {
|
||||
if mts[i].GetGlobalId() == mt.ExternalId {
|
||||
mt.SyncWithMountTarget(ctx, self.GetUserCred(), fs.ManagerId, mts[i])
|
||||
self.SetStageComplete(ctx, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
self.taskFail(ctx, mt, errors.Wrapf(cloudprovider.ErrNotFound, mt.ExternalId))
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type AccessGroupCacheManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
AccessGroupCaches AccessGroupCacheManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
AccessGroupCaches = AccessGroupCacheManager{NewComputeManager("access_group_cache", "access_group_caches",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&AccessGroupCaches)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type AccessGroupRuleManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
AccessGroupRules AccessGroupRuleManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
AccessGroupRules = AccessGroupRuleManager{NewComputeManager("access_group_rule", "access_group_rules",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&AccessGroupRules)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type AccessGroupManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
AccessGroups AccessGroupManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
AccessGroups = AccessGroupManager{NewComputeManager("access_group", "access_groups",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&AccessGroups)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type FileSystemManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
FileSystems FileSystemManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
FileSystems = FileSystemManager{NewComputeManager("file_system", "file_systems",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&FileSystems)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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 modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
)
|
||||
|
||||
type MountTargetManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
MountTargets MountTargetManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
MountTargets = MountTargetManager{NewComputeManager("mount_target", "mount_targets",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&MountTargets)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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 modules
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
|
||||
type NasSkusManager struct {
|
||||
modulebase.ResourceManager
|
||||
}
|
||||
|
||||
var (
|
||||
NasSkus NasSkusManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
NasSkus = NasSkusManager{NewComputeManager("nas_sku", "nas_skus",
|
||||
[]string{},
|
||||
[]string{})}
|
||||
|
||||
registerCompute(&NasSkus)
|
||||
}
|
||||
@@ -375,6 +375,10 @@ type BaseCreateOptions struct {
|
||||
Desc string `metavar:"<DESCRIPTION>" help:"Description" json:"description"`
|
||||
}
|
||||
|
||||
func (opts *BaseCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type EnabledStatusCreateOptions struct {
|
||||
BaseCreateOptions
|
||||
Status string
|
||||
|
||||
@@ -840,7 +840,7 @@ func (opts *CloudaccountShareModeOptions) Params() (jsonutils.JSONObject, error)
|
||||
|
||||
type CloudaccountSyncSkusOptions struct {
|
||||
SCloudAccountIdOptions
|
||||
RESOURCE string `help:"Resource of skus" choices:"serversku|elasticcachesku|dbinstance_sku|nat_sku"`
|
||||
RESOURCE string `help:"Resource of skus" choices:"serversku|elasticcachesku|dbinstance_sku|nat_sku|nas_sku"`
|
||||
Force bool `help:"Force sync no matter what"`
|
||||
Cloudprovider string `help:"provider to sync"`
|
||||
Region string `help:"region to sync"`
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type AccessGroupCacheListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *AccessGroupCacheListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type AccessGroupCacheIdOption struct {
|
||||
ID string `help:"Access group cache Id"`
|
||||
}
|
||||
|
||||
func (opts *AccessGroupCacheIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *AccessGroupCacheIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type AccessGroupRuleListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *AccessGroupRuleListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type AccessGroupRuleIdOption struct {
|
||||
ID string `help:"Access group rule Id"`
|
||||
}
|
||||
|
||||
func (opts *AccessGroupRuleIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *AccessGroupRuleIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type AccessRuleCreateOptions struct {
|
||||
Priority int
|
||||
Source string
|
||||
RWAccessType string `choices:"rw|r"`
|
||||
UserAccessType string `choices:""`
|
||||
Description string
|
||||
AccessGroupId string
|
||||
}
|
||||
|
||||
func (opts *AccessRuleCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type AccessGroupListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *AccessGroupListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type AccessGroupIdOption struct {
|
||||
ID string `help:"Access group Id"`
|
||||
}
|
||||
|
||||
func (opts *AccessGroupIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *AccessGroupIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type FileSystemListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *FileSystemListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type FileSystemIdOption struct {
|
||||
ID string `help:"File system Id"`
|
||||
}
|
||||
|
||||
func (opts *FileSystemIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *FileSystemIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type FileSystemCreateOptions struct {
|
||||
NAME string
|
||||
Protocol string `choices:"NFS|SMB|CPFS"`
|
||||
FileSystemType string
|
||||
Capacity int64 `json:"capacity"`
|
||||
NetworkId string `json:"network_id"`
|
||||
StorageType string `json:"storage_type"`
|
||||
ZoneId string `json:"zone_id"`
|
||||
ManagerId string `json:"manager_id"`
|
||||
}
|
||||
|
||||
func (opts *FileSystemCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type MountTargetListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *MountTargetListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type MountTargetIdOption struct {
|
||||
ID string `help:"Mount Target Id"`
|
||||
}
|
||||
|
||||
func (opts *MountTargetIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
|
||||
func (opts *MountTargetIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type MountTargetCreateOptions struct {
|
||||
NAME string
|
||||
NetworkType string `choices:"vpc|classic"`
|
||||
FileSystemId string `json:"file_system_id"`
|
||||
NetworkId string `json:"network_id"`
|
||||
AccessGroupId string `json:"access_group_id"`
|
||||
}
|
||||
|
||||
func (opts *MountTargetCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type NasSkuListOption struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
|
||||
func (opts *NasSkuListOption) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(opts)
|
||||
}
|
||||
|
||||
type NasSkuIdOption struct {
|
||||
ID string `help:"Nas Id or name"`
|
||||
}
|
||||
|
||||
func (opts *NasSkuIdOption) Params() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (opts *NasSkuIdOption) GetId() string {
|
||||
return opts.ID
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
// 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 aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SAccessGroup struct {
|
||||
region *SRegion
|
||||
|
||||
RuleCount int
|
||||
AccessGroupType string
|
||||
Description string
|
||||
AccessGroupName string
|
||||
MountTargetCount int
|
||||
FileSystemType string
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetName() string {
|
||||
return self.AccessGroupName
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", self.GetFileSystemType(), self.AccessGroupName)
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetFileSystemType() string {
|
||||
return self.FileSystemType
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) IsDefault() bool {
|
||||
return self.AccessGroupName == "DEFAULT_CLASSIC_GROUP_NAME" || self.AccessGroupName == "DEFAULT_VPC_GROUP_NAME"
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetDesc() string {
|
||||
return self.Description
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetMountTargetCount() int {
|
||||
return self.MountTargetCount
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetNetworkType() string {
|
||||
return strings.ToLower(self.AccessGroupType)
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetMaxPriority() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetMinPriority() int {
|
||||
return 100
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) Delete() error {
|
||||
return self.region.DeleteAccessGroup(self.FileSystemType, self.AccessGroupName)
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetSupporedUserAccessTypes() []cloudprovider.TUserAccessType {
|
||||
return []cloudprovider.TUserAccessType{
|
||||
cloudprovider.UserAccessTypeAllSquash,
|
||||
cloudprovider.UserAccessTypeRootSquash,
|
||||
cloudprovider.UserAccessTypeNoRootSquash,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) GetRules() ([]cloudprovider.AccessGroupRule, error) {
|
||||
rules := []SAccessGroupRule{}
|
||||
num := 1
|
||||
for {
|
||||
part, total, err := self.region.GetAccessGroupRules(self.AccessGroupName, 50, num)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetAccessGroupRules")
|
||||
}
|
||||
rules = append(rules, part...)
|
||||
if len(rules) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
ret := []cloudprovider.AccessGroupRule{}
|
||||
for i := range rules {
|
||||
rule := cloudprovider.AccessGroupRule{
|
||||
ExternalId: rules[i].AccessRuleId,
|
||||
Priority: rules[i].Priority,
|
||||
Source: rules[i].SourceCidrIp,
|
||||
}
|
||||
switch rules[i].RWAccess {
|
||||
case "RDWR":
|
||||
rule.RWAccessType = cloudprovider.RWAccessTypeRW
|
||||
case "RDONLY":
|
||||
rule.RWAccessType = cloudprovider.RWAccessTypeR
|
||||
}
|
||||
switch rules[i].UserAccess {
|
||||
case "no_squash":
|
||||
rule.UserAccessType = cloudprovider.UserAccessTypeNoRootSquash
|
||||
case "root_squash":
|
||||
rule.UserAccessType = cloudprovider.UserAccessTypeRootSquash
|
||||
case "all_squash":
|
||||
rule.UserAccessType = cloudprovider.UserAccessTypeAllSquash
|
||||
}
|
||||
ret = append(ret, rule)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getAccessGroups(fsType string, pageSize, pageNum int) ([]SAccessGroup, int, error) {
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 50
|
||||
}
|
||||
if pageNum < 1 {
|
||||
pageNum = 1
|
||||
}
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"PageSize": fmt.Sprintf("%d", pageSize),
|
||||
"PageNumber": fmt.Sprintf("%d", pageNum),
|
||||
"FileSystemType": fsType,
|
||||
}
|
||||
resp, err := self.nasRequest("DescribeAccessGroups", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeAccessGroups")
|
||||
}
|
||||
|
||||
ret := struct {
|
||||
TotalCount int
|
||||
AccessGroups struct {
|
||||
AccessGroup []SAccessGroup
|
||||
}
|
||||
}{}
|
||||
err = resp.Unmarshal(&ret)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return ret.AccessGroups.AccessGroup, ret.TotalCount, nil
|
||||
}
|
||||
|
||||
type SAccessGroupRule struct {
|
||||
RWAccess string
|
||||
UserAccess string
|
||||
Priority int
|
||||
SourceCidrIp string
|
||||
AccessRuleId string
|
||||
}
|
||||
|
||||
func (self *SRegion) GetAccessGroupRules(groupName string, pageSize, pageNum int) ([]SAccessGroupRule, int, error) {
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 50
|
||||
}
|
||||
if pageNum < 1 {
|
||||
pageNum = 1
|
||||
}
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"AccessGroupName": groupName,
|
||||
"PageSize": fmt.Sprintf("%d", pageSize),
|
||||
"PageNumber": fmt.Sprintf("%d", pageNum),
|
||||
}
|
||||
resp, err := self.nasRequest("DescribeAccessRules", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeAccessRules")
|
||||
}
|
||||
ret := struct {
|
||||
TotalCount int
|
||||
AccessRules struct {
|
||||
AccessRule []SAccessGroupRule
|
||||
}
|
||||
}{}
|
||||
err = resp.Unmarshal(&ret)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return ret.AccessRules.AccessRule, ret.TotalCount, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetAccessGroups(fsType string) ([]SAccessGroup, error) {
|
||||
accessGroups := []SAccessGroup{}
|
||||
num := 1
|
||||
for {
|
||||
part, total, err := self.getAccessGroups(fsType, 50, num)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetAccessGroups")
|
||||
}
|
||||
for i := range part {
|
||||
part[i].FileSystemType = fsType
|
||||
accessGroups = append(accessGroups, part[i])
|
||||
}
|
||||
if len(accessGroups) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return accessGroups, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudAccessGroups() ([]cloudprovider.ICloudAccessGroup, error) {
|
||||
standardAccessGroups, err := self.GetAccessGroups("standard")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetAccessGroups")
|
||||
}
|
||||
extremeAccessGroups, err := self.GetAccessGroups("extreme")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetAccessGroups")
|
||||
}
|
||||
ret := []cloudprovider.ICloudAccessGroup{}
|
||||
for _, accessGroups := range [][]SAccessGroup{standardAccessGroups, extremeAccessGroups} {
|
||||
for i := range accessGroups {
|
||||
accessGroups[i].region = self
|
||||
ret = append(ret, &accessGroups[i])
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudAccessGroupById(id string) (cloudprovider.ICloudAccessGroup, error) {
|
||||
groups, err := self.GetICloudAccessGroups()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetICloudAccessGroups")
|
||||
}
|
||||
for i := range groups {
|
||||
if groups[i].GetGlobalId() == id {
|
||||
return groups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(err, "GetICloudAccessGroupById(%s)", id)
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateICloudAccessGroup(opts *cloudprovider.SAccessGroup) (cloudprovider.ICloudAccessGroup, error) {
|
||||
err := self.CreateAccessGroup(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateAccessGroup")
|
||||
}
|
||||
return self.GetICloudAccessGroupById(fmt.Sprintf("%s/%s", opts.FileSystemType, opts.Name))
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateAccessGroup(opts *cloudprovider.SAccessGroup) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"AccessGroupName": opts.Name,
|
||||
"AccessGroupType": opts.NetworkType,
|
||||
"FileSystemType": opts.FileSystemType,
|
||||
}
|
||||
_, err := self.nasRequest("CreateAccessGroup", params)
|
||||
return errors.Wrapf(err, "CreateAccessGroup")
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteAccessGroup(fsType, name string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"AccessGroupName": name,
|
||||
"FileSystemType": fsType,
|
||||
}
|
||||
_, err := self.nasRequest("DeleteAccessGroup", params)
|
||||
return errors.Wrapf(err, "DeleteAccessGroup")
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteAccessGroupRule(fsType, groupName, ruleId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"AccessRuleId": ruleId,
|
||||
"AccessGroupName": groupName,
|
||||
"FileSystemType": fsType,
|
||||
}
|
||||
_, err := self.nasRequest("DeleteAccessRule", params)
|
||||
return errors.Wrapf(err, "DeleteAccessRule")
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateAccessGroupRule(source, fsType, groupName string, rwType cloudprovider.TRWAccessType, userType cloudprovider.TUserAccessType, priority int) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"SourceCidrIp": source,
|
||||
"AccessGroupName": groupName,
|
||||
"Priority": fmt.Sprintf("%d", priority),
|
||||
"FileSystemType": fsType,
|
||||
}
|
||||
switch rwType {
|
||||
case cloudprovider.RWAccessTypeR:
|
||||
params["RWAccessType"] = "RDONLY"
|
||||
case cloudprovider.RWAccessTypeRW:
|
||||
params["RWAccessType"] = "RDWR"
|
||||
}
|
||||
switch userType {
|
||||
case cloudprovider.UserAccessTypeAllSquash:
|
||||
params["UserAccessType"] = "all_squash"
|
||||
case cloudprovider.UserAccessTypeRootSquash:
|
||||
params["UserAccessType"] = "root_squash"
|
||||
case cloudprovider.UserAccessTypeNoRootSquash:
|
||||
params["UserAccessType"] = "no_squash"
|
||||
}
|
||||
_, err := self.nasRequest("CreateAccessRule", params)
|
||||
return errors.Wrapf(err, "CreateAccessRule")
|
||||
}
|
||||
|
||||
func (self *SAccessGroup) SyncRules(common, added, removed cloudprovider.AccessGroupRuleSet) error {
|
||||
for _, rule := range removed {
|
||||
err := self.region.DeleteAccessGroupRule(self.FileSystemType, self.AccessGroupName, rule.ExternalId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DeleteAccessGroupRule")
|
||||
}
|
||||
}
|
||||
for _, rule := range added {
|
||||
err := self.region.CreateAccessGroupRule(rule.Source, self.FileSystemType, self.AccessGroupName, rule.RWAccessType, rule.UserAccessType, rule.Priority)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "CreateAccessGroupRule")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -64,6 +64,7 @@ const (
|
||||
ALIYUN_CBN_API_VERSION = "2017-09-12"
|
||||
ALIYUN_CDN_API_VERSION = "2018-05-10"
|
||||
ALIYUN_IMS_API_VERSION = "2019-08-15"
|
||||
ALIYUN_NAS_API_VERSION = "2017-06-26"
|
||||
|
||||
ALIYUN_SERVICE_ECS = "ecs"
|
||||
ALIYUN_SERVICE_VPC = "vpc"
|
||||
@@ -159,13 +160,21 @@ func jsonRequest(client *sdk.Client, domain, apiVersion, apiName string, params
|
||||
switch code {
|
||||
case "InvalidAccessKeyId.NotFound":
|
||||
return nil, err
|
||||
case "SignatureNonceUsed",
|
||||
"InvalidInstance.NotSupported",
|
||||
"BackendServer.configuring",
|
||||
"OperationUnsupported.EipNatBWPCheck":
|
||||
case "404 Not Found":
|
||||
return nil, errors.Wrap(cloudprovider.ErrNotFound, err.Error())
|
||||
case "InvalidInstance.NotSupported",
|
||||
"SignatureNonceUsed", // SignatureNonce 重复。每次请求的 SignatureNonce 在 15 分钟内不能重复。
|
||||
"BackendServer.configuring", // 负载均衡的前一个配置项正在配置中,请稍后再试。
|
||||
"Operation.Conflict", // 您当前的操作可能与其他人的操作产生了冲突,请稍后重试。
|
||||
"OperationDenied.ResourceControl", // 指定的区域处于资源控制中,请稍后再试。
|
||||
"ServiceIsStopping", // 监听正在停止,请稍后重试。
|
||||
"ProcessingSameRequest", // 正在处理相同的请求。请稍后再试。
|
||||
"ResourceInOperating", // 当前资源正在操作中,请求稍后重试。
|
||||
"InvalidFileSystemStatus.Ordering", // Message: The filesystem is ordering now, please check it later.
|
||||
"OperationUnsupported.EipNatBWPCheck": // create nat snat
|
||||
retry = true
|
||||
default:
|
||||
if strings.HasPrefix(code, "EntityNotExist") || strings.HasSuffix(code, "NotFound") {
|
||||
if strings.HasPrefix(code, "EntityNotExist.") || strings.HasSuffix(code, ".NotFound") {
|
||||
return nil, errors.Wrap(cloudprovider.ErrNotFound, err.Error())
|
||||
}
|
||||
return nil, err
|
||||
@@ -554,6 +563,7 @@ func (region *SAliyunClient) GetCapabilities() []string {
|
||||
cloudprovider.CLOUD_CAPABILITY_INTERVPCNETWORK,
|
||||
cloudprovider.CLOUD_CAPABILITY_SAML_AUTH,
|
||||
cloudprovider.CLOUD_CAPABILITY_NAT,
|
||||
cloudprovider.CLOUD_CAPABILITY_NAS,
|
||||
}
|
||||
return caps
|
||||
}
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
// 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 aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SupportedFeatures struct {
|
||||
SupportedFeature []string
|
||||
}
|
||||
|
||||
type MountTargets struct {
|
||||
MountTarget []SMountTarget
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
}
|
||||
|
||||
type Packages struct {
|
||||
Package []Package
|
||||
}
|
||||
|
||||
type SFileSystem struct {
|
||||
multicloud.SNasBase
|
||||
region *SRegion
|
||||
|
||||
Status string
|
||||
Description string
|
||||
StorageType string
|
||||
MountTargetCountLimit int
|
||||
Ldap string
|
||||
ZoneId string
|
||||
// 2021-03-22T10:08:15CST
|
||||
CreateTime string
|
||||
MeteredIASize int
|
||||
SupportedFeatures SupportedFeatures
|
||||
MountTargets MountTargets
|
||||
AutoSnapshotPolicyId string
|
||||
MeteredSize int64
|
||||
EncryptType int
|
||||
Capacity int64
|
||||
ProtocolType string
|
||||
ChargeType string
|
||||
Packages Packages
|
||||
ExpiredTime string
|
||||
FileSystemType string
|
||||
FileSystemId string
|
||||
RegionId string
|
||||
|
||||
Tags Tags
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetId() string {
|
||||
return self.FileSystemId
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetGlobalId() string {
|
||||
return self.FileSystemId
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetName() string {
|
||||
if len(self.Description) > 0 {
|
||||
return self.Description
|
||||
}
|
||||
return self.FileSystemId
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetFileSystemType() string {
|
||||
return self.FileSystemType
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetMountTargetCountLimit() int {
|
||||
return self.MountTargetCountLimit
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "", "Running":
|
||||
return api.NAS_STATUS_AVAILABLE
|
||||
case "Extending":
|
||||
return api.NAS_STATUS_EXTENDING
|
||||
case "Stopping", "Stopped":
|
||||
return api.NAS_STATUS_UNAVAILABLE
|
||||
case "Pending":
|
||||
return api.NAS_STATUS_CREATING
|
||||
default:
|
||||
return api.NAS_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetBillintType() string {
|
||||
if self.ChargeType == "PayAsYouGo" {
|
||||
return billing_api.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
return billing_api.BILLING_TYPE_PREPAID
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetStorageType() string {
|
||||
return strings.ToLower(self.StorageType)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetProtocol() string {
|
||||
return self.ProtocolType
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetCapacityGb() int64 {
|
||||
return self.Capacity
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetUsedCapacityGb() int64 {
|
||||
return self.MeteredSize
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetZoneId() string {
|
||||
return self.ZoneId
|
||||
}
|
||||
|
||||
func (self *SFileSystem) Delete() error {
|
||||
return self.region.DeleteFileSystem(self.FileSystemId)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetCreatedAt() time.Time {
|
||||
ret, _ := time.Parse("2006-01-02T15:04:05CST", self.CreateTime)
|
||||
if !ret.IsZero() {
|
||||
ret = ret.Add(time.Hour * 8)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetExpiredAt() time.Time {
|
||||
ret, _ := time.Parse("2006-01-02T15:04:05CST", self.ExpiredTime)
|
||||
if !ret.IsZero() {
|
||||
ret = ret.Add(time.Hour * 8)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SFileSystem) Refresh() error {
|
||||
fs, err := self.region.GetFileSystem(self.FileSystemId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetFileSystem(%s)", self.FileSystemId)
|
||||
}
|
||||
return jsonutils.Update(self, fs)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetTags() (map[string]string, error) {
|
||||
return self.Tags.GetTags()
|
||||
}
|
||||
|
||||
func (self *SRegion) GetFileSystems(id string, pageSize, pageNum int) ([]SFileSystem, int, error) {
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 50
|
||||
}
|
||||
if pageNum < 1 {
|
||||
pageNum = 1
|
||||
}
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"PageSize": fmt.Sprintf("%d", pageSize),
|
||||
"PageNumber": fmt.Sprintf("%d", pageNum),
|
||||
}
|
||||
if len(id) > 0 {
|
||||
params["FileSystemId"] = id
|
||||
}
|
||||
resp, err := self.nasRequest("DescribeFileSystems", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeFileSystems")
|
||||
}
|
||||
ret := struct {
|
||||
TotalCount int
|
||||
FileSystems struct {
|
||||
FileSystem []SFileSystem
|
||||
}
|
||||
}{}
|
||||
err = resp.Unmarshal(&ret)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return ret.FileSystems.FileSystem, ret.TotalCount, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudFileSystems() ([]cloudprovider.ICloudFileSystem, error) {
|
||||
nas := []SFileSystem{}
|
||||
num := 1
|
||||
for {
|
||||
part, total, err := self.GetFileSystems("", 100, num)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetFileSystems")
|
||||
}
|
||||
nas = append(nas, part...)
|
||||
if total <= len(nas) {
|
||||
break
|
||||
}
|
||||
num++
|
||||
}
|
||||
|
||||
ret := []cloudprovider.ICloudFileSystem{}
|
||||
for i := range nas {
|
||||
nas[i].region = self
|
||||
ret = append(ret, &nas[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetFileSystem(id string) (*SFileSystem, error) {
|
||||
if len(id) == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty id")
|
||||
}
|
||||
nas, total, err := self.GetFileSystems(id, 1, 1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetFileSystems")
|
||||
}
|
||||
if total == 1 {
|
||||
nas[0].region = self
|
||||
return &nas[0], nil
|
||||
}
|
||||
if total == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, id)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudFileSystemById(id string) (cloudprovider.ICloudFileSystem, error) {
|
||||
fs, err := self.GetFileSystem(id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetFileSystem")
|
||||
}
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateMountTarget(opts *cloudprovider.SMountTargetCreateOptions) (*SMountTarget, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"FileSystemId": opts.FileSystemId,
|
||||
"AccessGroupName": strings.TrimPrefix(strings.TrimPrefix(opts.AccessGroupId, "extreme/"), "standard/"),
|
||||
"NetworkType": opts.NetworkType,
|
||||
"VpcId": opts.VpcId,
|
||||
"VSwitchId": opts.NetworkId,
|
||||
}
|
||||
resp, err := self.nasRequest("CreateMountTarget", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateMountTarget")
|
||||
}
|
||||
ret := struct {
|
||||
MountTargetDomain string
|
||||
}{}
|
||||
err = resp.Unmarshal(&ret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
mts, _, err := self.GetMountTargets(opts.FileSystemId, ret.MountTargetDomain, 10, 1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.GetMountTargets")
|
||||
}
|
||||
for i := range mts {
|
||||
if mts[i].MountTargetDomain == ret.MountTargetDomain {
|
||||
return &mts[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "afeter create with mount domain %s", ret.MountTargetDomain)
|
||||
}
|
||||
|
||||
func (self *SFileSystem) CreateMountTarget(opts *cloudprovider.SMountTargetCreateOptions) (cloudprovider.ICloudMountTarget, error) {
|
||||
mt, err := self.region.CreateMountTarget(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateMountTarget")
|
||||
}
|
||||
mt.fs = self
|
||||
return mt, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteFileSystem(id string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"FileSystemId": id,
|
||||
}
|
||||
_, err := self.nasRequest("DeleteFileSystem", params)
|
||||
return errors.Wrapf(err, "DeleteFileSystem")
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateICloudFileSystem(opts *cloudprovider.FileSystemCraeteOptions) (cloudprovider.ICloudFileSystem, error) {
|
||||
fs, err := self.CreateFileSystem(opts)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "self.CreateFileSystem")
|
||||
}
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateFileSystem(opts *cloudprovider.FileSystemCraeteOptions) (*SFileSystem, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"ProtocolType": opts.Protocol,
|
||||
"ZoneId": opts.ZoneId,
|
||||
"EncryptType": "0",
|
||||
"FileSystemType": opts.FileSystemType,
|
||||
"StorageType": opts.StorageType,
|
||||
"ClientToken": utils.GenRequestId(20),
|
||||
"Description": opts.Name,
|
||||
}
|
||||
switch opts.FileSystemType {
|
||||
case "standard":
|
||||
params["StorageType"] = utils.Capitalize(opts.StorageType)
|
||||
case "cpfs":
|
||||
params["ProtocolType"] = "cpfs"
|
||||
switch opts.StorageType {
|
||||
case "advance_100":
|
||||
params["Bandwidth"] = "100"
|
||||
case "advance_200":
|
||||
params["Bandwidth"] = "200"
|
||||
}
|
||||
case "extreme":
|
||||
params["Capacity"] = fmt.Sprintf("%d", opts.Capacity)
|
||||
}
|
||||
if len(opts.VpcId) > 0 {
|
||||
params["VpcId"] = opts.VpcId
|
||||
}
|
||||
if len(opts.NetworkId) > 0 {
|
||||
params["VSwitchId"] = opts.NetworkId
|
||||
}
|
||||
resp, err := self.nasRequest("CreateFileSystem", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "CreateFileSystem")
|
||||
}
|
||||
fsId, _ := resp.GetString("FileSystemId")
|
||||
return self.GetFileSystem(fsId)
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
// 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 aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type ClientMasterNode struct {
|
||||
EcsIp string
|
||||
EcsId string
|
||||
DefaultPasswd string
|
||||
}
|
||||
|
||||
type ClientMasterNodes struct {
|
||||
ClientMasterNode []ClientMasterNode
|
||||
}
|
||||
|
||||
type SMountTarget struct {
|
||||
fs *SFileSystem
|
||||
|
||||
Status string
|
||||
NetworkType string
|
||||
VswId string
|
||||
VpcId string
|
||||
MountTargetDomain string
|
||||
AccessGroup string
|
||||
ClientMasterNodes ClientMasterNodes
|
||||
Tags Tags
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetGlobalId() string {
|
||||
return self.MountTargetDomain
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetName() string {
|
||||
return self.MountTargetDomain
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetNetworkType() string {
|
||||
return strings.ToLower(self.NetworkType)
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "Active":
|
||||
return api.MOUNT_TARGET_STATUS_AVAILABLE
|
||||
case "Inactive":
|
||||
return api.MOUNT_TARGET_STATUS_UNAVAILABLE
|
||||
case "Pending":
|
||||
return api.MOUNT_TARGET_STATUS_CREATING
|
||||
case "Deleting":
|
||||
return api.MOUNT_TARGET_STATUS_DELETING
|
||||
default:
|
||||
return strings.ToLower(self.Status)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetVpcId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetNetworkId() string {
|
||||
return self.VswId
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetDomainName() string {
|
||||
return self.MountTargetDomain
|
||||
}
|
||||
|
||||
func (self *SMountTarget) GetAccessGroupId() string {
|
||||
return fmt.Sprintf("%s/%s", self.fs.FileSystemType, self.AccessGroup)
|
||||
}
|
||||
|
||||
func (self *SMountTarget) Delete() error {
|
||||
return self.fs.region.DeleteMountTarget(self.fs.FileSystemId, self.MountTargetDomain)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetMountTargets(fsId, domainName string, pageSize, pageNum int) ([]SMountTarget, int, error) {
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 50
|
||||
}
|
||||
if pageNum < 1 {
|
||||
pageNum = 1
|
||||
}
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"FileSystemId": fsId,
|
||||
"PageSize": fmt.Sprintf("%d", pageSize),
|
||||
"PageNumber": fmt.Sprintf("%d", pageNum),
|
||||
}
|
||||
if len(domainName) > 0 {
|
||||
params["MountTargetDomain"] = domainName
|
||||
}
|
||||
resp, err := self.nasRequest("DescribeMountTargets", params)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "DescribeMountTargets")
|
||||
}
|
||||
ret := struct {
|
||||
TotalCount int
|
||||
MountTargets struct {
|
||||
MountTarget []SMountTarget
|
||||
}
|
||||
}{}
|
||||
err = resp.Unmarshal(&ret)
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
|
||||
}
|
||||
return ret.MountTargets.MountTarget, ret.TotalCount, nil
|
||||
}
|
||||
|
||||
func (self *SFileSystem) GetMountTargets() ([]cloudprovider.ICloudMountTarget, error) {
|
||||
targets := []SMountTarget{}
|
||||
num := 1
|
||||
for {
|
||||
part, total, err := self.region.GetMountTargets(self.FileSystemId, "", 50, num)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetMountTargets")
|
||||
}
|
||||
targets = append(targets, part...)
|
||||
if len(part) >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
ret := []cloudprovider.ICloudMountTarget{}
|
||||
for i := range targets {
|
||||
targets[i].fs = self
|
||||
ret = append(ret, &targets[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteMountTarget(fsId, id string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"FileSystemId": fsId,
|
||||
"MountTargetDomain": id,
|
||||
}
|
||||
_, err := self.nasRequest("DeleteMountTarget", params)
|
||||
return errors.Wrapf(err, "DeleteMountTarget")
|
||||
}
|
||||
@@ -153,6 +153,15 @@ func (self *SRegion) vpcRequest(action string, params map[string]string) (jsonut
|
||||
return jsonRequest(client, "vpc.aliyuncs.com", ALIYUN_API_VERSION_VPC, action, params, self.client.debug)
|
||||
}
|
||||
|
||||
func (self *SRegion) nasRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
client, err := self.getSdkClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return jsonRequest(client, "nas.aliyuncs.com", ALIYUN_NAS_API_VERSION, action, params, self.client.debug)
|
||||
}
|
||||
|
||||
func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
client, err := self.getSdkClient()
|
||||
if err != nil {
|
||||
|
||||
@@ -66,6 +66,14 @@ type Tags struct {
|
||||
Tag []Tag
|
||||
}
|
||||
|
||||
func (t Tags) GetTags() (map[string]string, error) {
|
||||
ret := map[string]string{}
|
||||
for _, tag := range t.Tag {
|
||||
ret[tag.TagKey] = tag.TagValue
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
TagKey string
|
||||
TagValue string
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// 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/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type NasAccessGroupListOptions struct {
|
||||
FileSystemType string `choices:"standard|extreme" default:"standard"`
|
||||
}
|
||||
shellutils.R(&NasAccessGroupListOptions{}, "access-group-list", "List Nas AccessGroups", func(cli *aliyun.SRegion, args *NasAccessGroupListOptions) error {
|
||||
ags, err := cli.GetAccessGroups(args.FileSystemType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(ags, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&cloudprovider.SAccessGroup{}, "access-group-create", "Create Nas AccessGroup", func(cli *aliyun.SRegion, args *cloudprovider.SAccessGroup) error {
|
||||
return cli.CreateAccessGroup(args)
|
||||
})
|
||||
|
||||
type AccessGroupDeleteOptions struct {
|
||||
FileSystemType string
|
||||
NAME string
|
||||
}
|
||||
|
||||
shellutils.R(&AccessGroupDeleteOptions{}, "access-group-delete", "Delete AccessGroup", func(cli *aliyun.SRegion, args *AccessGroupDeleteOptions) error {
|
||||
return cli.DeleteAccessGroup(args.FileSystemType, args.NAME)
|
||||
})
|
||||
|
||||
type NasAccessGroupRuleListOptions struct {
|
||||
GROUP string
|
||||
PageSize int `help:"page size"`
|
||||
PageNum int `help:"page num"`
|
||||
}
|
||||
|
||||
shellutils.R(&NasAccessGroupRuleListOptions{}, "access-group-rule-list", "List Nas AccessGroup Rules", func(cli *aliyun.SRegion, args *NasAccessGroupRuleListOptions) error {
|
||||
rules, _, err := cli.GetAccessGroupRules(args.GROUP, args.PageSize, args.PageNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(rules, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type AccessRuleDeleteOptions struct {
|
||||
FileSystemType string
|
||||
GROUP string
|
||||
RULE_ID string
|
||||
}
|
||||
|
||||
shellutils.R(&AccessRuleDeleteOptions{}, "access-group-rule-delete", "Delete AccessGroup Rule", func(cli *aliyun.SRegion, args *AccessRuleDeleteOptions) error {
|
||||
return cli.DeleteAccessGroupRule(args.FileSystemType, args.GROUP, args.RULE_ID)
|
||||
})
|
||||
|
||||
type AccessRuleCreateOptions struct {
|
||||
SOURCE string
|
||||
FileSystemType string
|
||||
GroupName string
|
||||
RwType cloudprovider.TRWAccessType
|
||||
UserType cloudprovider.TUserAccessType
|
||||
Priority int
|
||||
}
|
||||
|
||||
shellutils.R(&AccessRuleCreateOptions{}, "access-group-rule-create", "Delete AccessGroup Rule", func(cli *aliyun.SRegion, args *AccessRuleCreateOptions) error {
|
||||
return cli.CreateAccessGroupRule(args.SOURCE, args.FileSystemType, args.GroupName, args.RwType, args.UserType, args.Priority)
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type FileSystemListOptions struct {
|
||||
Id string `help:"FileSystem Id"`
|
||||
PageSize int `help:"page size"`
|
||||
PageNum int `help:"page num"`
|
||||
}
|
||||
shellutils.R(&FileSystemListOptions{}, "file-system-list", "List FileSystem", func(cli *aliyun.SRegion, args *FileSystemListOptions) error {
|
||||
nas, _, err := cli.GetFileSystems(args.Id, args.PageSize, args.PageNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(nas, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type FileSystemDeleteOptions struct {
|
||||
ID string `help:"File System ID"`
|
||||
}
|
||||
shellutils.R(&FileSystemDeleteOptions{}, "file-system-delete", "Delete filesystem", func(cli *aliyun.SRegion, args *FileSystemDeleteOptions) error {
|
||||
return cli.DeleteFileSystem(args.ID)
|
||||
})
|
||||
|
||||
shellutils.R(&cloudprovider.FileSystemCraeteOptions{}, "file-system-create", "Create filesystem", func(cli *aliyun.SRegion, args *cloudprovider.FileSystemCraeteOptions) error {
|
||||
fs, err := cli.CreateFileSystem(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(fs)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type MountTargetListOptions struct {
|
||||
ID string `help:"Id"`
|
||||
DomainName string
|
||||
PageSize int `help:"page size"`
|
||||
PageNum int `help:"page num"`
|
||||
}
|
||||
shellutils.R(&MountTargetListOptions{}, "mount-target-list", "List MountTargets", func(cli *aliyun.SRegion, args *MountTargetListOptions) error {
|
||||
mounts, _, err := cli.GetMountTargets(args.ID, args.DomainName, args.PageSize, args.PageNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(mounts, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&cloudprovider.SMountTargetCreateOptions{}, "mount-target-create", "Create Nas MountTarget", func(cli *aliyun.SRegion, args *cloudprovider.SMountTargetCreateOptions) error {
|
||||
mt, err := cli.CreateMountTarget(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(mt)
|
||||
return nil
|
||||
})
|
||||
|
||||
type MountTargetDeleteOptions struct {
|
||||
FILE_SYSTEM_ID string
|
||||
MOUT_POINT_ID string
|
||||
}
|
||||
shellutils.R(&MountTargetDeleteOptions{}, "mount-target-delete", "Delete Nas MountTarget", func(cli *aliyun.SRegion, args *MountTargetDeleteOptions) error {
|
||||
return cli.DeleteMountTarget(args.FILE_SYSTEM_ID, args.MOUT_POINT_ID)
|
||||
})
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// 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 multicloud
|
||||
|
||||
type SNasBase struct {
|
||||
SResourceBase
|
||||
SBillingBase
|
||||
}
|
||||
@@ -149,3 +149,27 @@ func (self *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
|
||||
func (self *SRegion) CreateInternetGateway() (cloudprovider.ICloudInternetGateway, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "CreateInternetGateway")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudFileSystems() ([]cloudprovider.ICloudFileSystem, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetICloudFileSystems")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudFileSystemById(id string) (cloudprovider.ICloudFileSystem, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetICloudFileSystemById")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudAccessGroups() ([]cloudprovider.ICloudAccessGroup, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetICloudAccessGroups")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetICloudAccessGroupById(id string) (cloudprovider.ICloudAccessGroup, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetICloudAccessGroupById")
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateICloudAccessGroup(opts *cloudprovider.SAccessGroup) (cloudprovider.ICloudAccessGroup, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "CreateICloudAccessGroup")
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateICloudFileSystem(opts *cloudprovider.FileSystemCraeteOptions) (cloudprovider.ICloudFileSystem, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "CreateICloudFileSystem")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user