mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-29 03:51:54 +08:00
feature: system resource domainize
This commit is contained in:
@@ -76,7 +76,7 @@ install: prepare_dir
|
||||
|
||||
|
||||
gencopyright:
|
||||
@sh scripts/gencopyright.sh pkg cmd
|
||||
@bash scripts/gencopyright.sh pkg cmd
|
||||
|
||||
test:
|
||||
@go test $(GO_BUILD_FLAGS) $(shell go list ./... | egrep -v 'host-image|hostimage')
|
||||
|
||||
@@ -988,4 +988,22 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ClouaccountChangeOwnerOptions struct {
|
||||
ID string `help:"ID or name of cloudaccount" json:"-"`
|
||||
ProjectDomain string `json:"project_domain" help:"target domain"`
|
||||
}
|
||||
R(&ClouaccountChangeOwnerOptions{}, "cloud-account-change-owner", "Change owner domain of cloudaccount", func(s *mcclient.ClientSession, args *ClouaccountChangeOwnerOptions) error {
|
||||
if len(args.ProjectDomain) == 0 {
|
||||
return fmt.Errorf("empty project_domain")
|
||||
}
|
||||
params := jsonutils.Marshal(args)
|
||||
ret, err := modules.Cloudaccounts.PerformAction(s, args.ID, "change-owner", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -706,4 +706,21 @@ func init() {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type HostChangeOwnerOptions struct {
|
||||
ID string `help:"ID or name of host" json:"-"`
|
||||
ProjectDomain string `json:"project_domain" help:"target domain"`
|
||||
}
|
||||
R(&HostChangeOwnerOptions{}, "host-change-owner", "Change owner domain of host", func(s *mcclient.ClientSession, args *HostChangeOwnerOptions) error {
|
||||
if len(args.ProjectDomain) == 0 {
|
||||
return fmt.Errorf("empty project_domain")
|
||||
}
|
||||
params := jsonutils.Marshal(args)
|
||||
ret, err := modules.Hosts.PerformAction(s, args.ID, "change-owner", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(ret)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 billing
|
||||
|
||||
import "time"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cloudnet // import "yunion.io/x/onecloud/pkg/apis/cloudnet"
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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 cloudnet
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type RouterUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
|
||||
User string `json:"user"`
|
||||
|
||||
Host string `json:"host"`
|
||||
|
||||
Port *int `json:"port"`
|
||||
|
||||
PrivateKey string `json:"private_key"`
|
||||
|
||||
RealizeWgIfaces *bool `json:"realize_wg_ifaces"`
|
||||
|
||||
RealizeRoutes *bool `json:"realize_routes"`
|
||||
|
||||
RealizeRules *bool `json:"realize_rules"`
|
||||
|
||||
OldEndpoint string `json:"_old_endpoint"`
|
||||
}
|
||||
|
||||
type RouteUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
|
||||
Network string `json:"network"`
|
||||
|
||||
Gateway string `json:"gateway"`
|
||||
}
|
||||
|
||||
type RuleUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
|
||||
Prio int `json:"prio"`
|
||||
|
||||
MatchSrcNet string `json:"match_src_net"`
|
||||
|
||||
MatchDestNet string `json:"match_dest_net"`
|
||||
|
||||
MatchProto string `json:"match_proto"`
|
||||
|
||||
MatchSrcPort int `json:"match_src_port"`
|
||||
|
||||
MatchDestPort int `json:"match_dest_port"`
|
||||
|
||||
MatchInIfname string `json:"match_in_ifname"`
|
||||
|
||||
MatchOutIfname string `json:"match_out_ifname"`
|
||||
|
||||
Action string `json:"action"`
|
||||
|
||||
ActionOptions string `json:"action_options"`
|
||||
}
|
||||
@@ -22,3 +22,25 @@ type BaremetalagentDetails struct {
|
||||
|
||||
SBaremetalagent
|
||||
}
|
||||
|
||||
type BaremetalagentCreateInput struct {
|
||||
apis.StandaloneResourceCreateInput
|
||||
|
||||
ZoneResourceInput
|
||||
|
||||
AccessIp string `json:"access_ip"`
|
||||
ManagerUri string `json:"manager_uri"`
|
||||
AgentType string `json:"agent_type"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type BaremetalagentUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
|
||||
ZoneResourceInput
|
||||
|
||||
AccessIp string `json:"access_ip"`
|
||||
ManagerUri string `json:"manager_uri"`
|
||||
AgentType string `json:"agent_type"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
@@ -116,3 +116,7 @@ type BucketListInput struct {
|
||||
|
||||
type BucketSyncstatusInput struct {
|
||||
}
|
||||
|
||||
type BucketUpdateInput struct {
|
||||
apis.VirtualResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ type CloudaccountResourceInfo struct {
|
||||
}
|
||||
|
||||
type CloudaccountCreateInput struct {
|
||||
apis.EnabledStatusDomainLevelResourceCreateInput
|
||||
apis.EnabledStatusInfrasResourceBaseCreateInput
|
||||
|
||||
// 指定云平台
|
||||
// Qcloud: 腾讯云
|
||||
@@ -183,7 +183,7 @@ type CloudaccountCreateInput struct {
|
||||
AutoCreateProject bool `json:"auto_create_project"`
|
||||
|
||||
// 额外信息,例如账单的access key
|
||||
Options *jsonutils.JSONObject `json:"options"`
|
||||
Options *jsonutils.JSONDict `json:"options"`
|
||||
|
||||
// 代理配置
|
||||
ProxySettingId string `json:"proxy_setting_id"`
|
||||
@@ -209,7 +209,7 @@ func (i CloudaccountShareModeInput) Validate() error {
|
||||
}
|
||||
|
||||
type CloudaccountListInput struct {
|
||||
apis.EnabledStatusDomainLevelResourceListInput
|
||||
apis.EnabledStatusInfrasResourceBaseListInput
|
||||
|
||||
ManagedResourceListInput
|
||||
|
||||
@@ -235,7 +235,7 @@ type ProviderProject struct {
|
||||
}
|
||||
|
||||
type CloudaccountDetail struct {
|
||||
apis.EnabledStatusDomainLevelResourceDetails
|
||||
apis.EnabledStatusInfrasResourceBaseDetails
|
||||
SCloudaccount
|
||||
|
||||
// 子订阅项目信息
|
||||
@@ -295,3 +295,23 @@ type CloudaccountDetail struct {
|
||||
// example: 10
|
||||
StoragecacheCount int `json:"storagecache_count,allowempty"`
|
||||
}
|
||||
|
||||
type CloudaccountUpdateInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseUpdateInput
|
||||
|
||||
// 同步周期,单位为秒
|
||||
SyncIntervalSeconds *int64 `json:"sync_interval_seconds"`
|
||||
|
||||
// 待更新的options key/value
|
||||
Options *jsonutils.JSONDict `json:"options"`
|
||||
// 带删除的options key
|
||||
RemoveOptions []string `json:"remove_options"`
|
||||
}
|
||||
|
||||
type CloudaccountPerformPublicInput struct {
|
||||
apis.PerformPublicInput
|
||||
|
||||
// 共享模式,可能值为provider_domain, system
|
||||
// example: provider_domain
|
||||
ShareMode string `json:"share_mode"`
|
||||
}
|
||||
|
||||
@@ -139,10 +139,8 @@ type CloudproviderDetails struct {
|
||||
Brand string `json:"brand"`
|
||||
}
|
||||
|
||||
type ManagedResourceListInput struct {
|
||||
apis.DomainizedResourceListInput
|
||||
CloudenvResourceListInput
|
||||
|
||||
// 云订阅输入参数
|
||||
type CloudproviderResourceInput struct {
|
||||
// 列出关联指定云订阅(ID或Name)的资源
|
||||
Cloudprovider string `json:"cloudprovider"`
|
||||
// List objects belonging to the cloud provider
|
||||
@@ -158,6 +156,13 @@ type ManagedResourceListInput struct {
|
||||
// Deprecated
|
||||
// description: this param will be deprecate at 3.0
|
||||
CloudproviderId string `json:"cloudprovider_id" deprecated-by:"cloudprovider"`
|
||||
}
|
||||
|
||||
type ManagedResourceListInput struct {
|
||||
apis.DomainizedResourceListInput
|
||||
CloudenvResourceListInput
|
||||
|
||||
CloudproviderResourceInput
|
||||
|
||||
// 列出关联指定云账号(ID或Name)的资源
|
||||
Cloudaccount string `json:"cloudaccount"`
|
||||
@@ -235,3 +240,10 @@ type SyncableBaseResourceListInput struct {
|
||||
// 同步状态
|
||||
SyncStatus []string `json:"sync_status"`
|
||||
}
|
||||
|
||||
type CloudproviderUpdateInput struct {
|
||||
apis.EnabledStatusStandaloneResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type CloudproviderCreateInput struct {
|
||||
}
|
||||
|
||||
@@ -219,3 +219,10 @@ type DiskResourceInfo struct {
|
||||
|
||||
type DiskSyncstatusInput struct {
|
||||
}
|
||||
|
||||
type DiskUpdateInput struct {
|
||||
apis.VirtualResourceBaseUpdateInput
|
||||
|
||||
// 磁盘类型
|
||||
DiskType string `json:"disk_type"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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
|
||||
|
||||
type DnsRecordUpdateInput struct {
|
||||
}
|
||||
@@ -18,11 +18,8 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type RegionalFilterListInput struct {
|
||||
// 过滤位于指定城市区域的资源
|
||||
City string `json:"city"`
|
||||
|
||||
// 过滤处于指定区域内的资源
|
||||
type CloudregionResourceInput struct {
|
||||
// 区域名称或ID
|
||||
Cloudregion string `json:"cloudregion"`
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
@@ -36,6 +33,13 @@ type RegionalFilterListInput struct {
|
||||
// Deprecated
|
||||
// description: this param will be deprecate at 3.0
|
||||
RegionId string `json:"region_id" deprecated-by:"cloudregion"`
|
||||
}
|
||||
|
||||
type RegionalFilterListInput struct {
|
||||
// 过滤位于指定城市区域的资源
|
||||
City string `json:"city"`
|
||||
|
||||
CloudregionResourceInput
|
||||
|
||||
// 按区域名称过滤
|
||||
OrderByRegion string `json:"order_by_region"`
|
||||
|
||||
@@ -19,11 +19,11 @@ import (
|
||||
)
|
||||
|
||||
type GlobalVpcCreateInput struct {
|
||||
apis.EnabledStatusStandaloneResourceCreateInput
|
||||
apis.EnabledStatusInfrasResourceBaseCreateInput
|
||||
}
|
||||
|
||||
type GlobalVpcDetails struct {
|
||||
apis.EnabledStatusStandaloneResourceDetails
|
||||
apis.EnabledStatusInfrasResourceBaseDetails
|
||||
|
||||
SGlobalVpc
|
||||
}
|
||||
@@ -40,3 +40,11 @@ type GlobalVpcResourceListInput struct {
|
||||
// 以GlobalVpc的名称排序
|
||||
OrderByGlobalvpc string `json:"order_by_globalvpc"`
|
||||
}
|
||||
|
||||
type GlobalvpcUpdateInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type GlobalVpcListInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseListInput
|
||||
}
|
||||
|
||||
@@ -50,3 +50,19 @@ type GuestdiskListInput struct {
|
||||
|
||||
AioMode []string `json:"aio_mode"`
|
||||
}
|
||||
|
||||
type GuestdiskUpdateInput struct {
|
||||
GuestJointBaseUpdateInput
|
||||
|
||||
Driver string `json:"driver"`
|
||||
|
||||
CacheMode string `json:"cache_mode"`
|
||||
|
||||
AioMode string `json:"aio_mode"`
|
||||
|
||||
Iops *int `json:"iops"`
|
||||
|
||||
Bps *int `json:"bps"`
|
||||
|
||||
Index *int8 `json:"index"`
|
||||
}
|
||||
|
||||
@@ -53,3 +53,13 @@ type GuestnetworkListInput struct {
|
||||
|
||||
TeamWith []string `json:"team_with"`
|
||||
}
|
||||
|
||||
type GuestnetworkUpdateInput struct {
|
||||
GuestJointBaseUpdateInput
|
||||
|
||||
Driver string `json:"driver"`
|
||||
|
||||
BwLimit *int `json:"bw_limit"`
|
||||
|
||||
Index *int8 `json:"index"`
|
||||
}
|
||||
|
||||
@@ -285,3 +285,7 @@ type GuestFilterListInput struct {
|
||||
// pattern:asc|desc
|
||||
OrderByServer string `json:"order_by_server"`
|
||||
}
|
||||
|
||||
type GuestJointBaseUpdateInput struct {
|
||||
apis.VirtualJointResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type GuesttemplateCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
type GuesttemplateInput struct {
|
||||
// description: the content of guest template
|
||||
// required: true
|
||||
Content jsonutils.JSONObject `json:"content"`
|
||||
@@ -35,6 +33,18 @@ type GuesttemplateCreateInput struct {
|
||||
ImageId string `json:"image_id"`
|
||||
}
|
||||
|
||||
type GuesttemplateCreateInput struct {
|
||||
apis.SharableVirtualResourceCreateInput
|
||||
|
||||
GuesttemplateInput
|
||||
}
|
||||
|
||||
type GuesttemplateUpdateInput struct {
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
|
||||
GuesttemplateInput
|
||||
}
|
||||
|
||||
type GuesttemplateDetails struct {
|
||||
apis.SharableVirtualResourceDetails
|
||||
SGuestTemplate
|
||||
|
||||
@@ -47,7 +47,7 @@ type DiskSpec struct {
|
||||
}
|
||||
|
||||
type HostListInput struct {
|
||||
apis.EnabledStatusStandaloneResourceListInput
|
||||
apis.EnabledStatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
ManagedResourceListInput
|
||||
@@ -111,7 +111,7 @@ type HostListInput struct {
|
||||
}
|
||||
|
||||
type HostDetails struct {
|
||||
apis.EnabledStatusStandaloneResourceDetails
|
||||
apis.EnabledStatusInfrasResourceBaseDetails
|
||||
ManagedResourceInfo
|
||||
ZoneResourceInfo
|
||||
|
||||
@@ -226,3 +226,87 @@ type HostRegisterMetadata struct {
|
||||
OnKubernetes bool `json:"on_kubernetes"`
|
||||
Hostname string `json:"hostname"`
|
||||
}
|
||||
|
||||
type HostAccessAttributes struct {
|
||||
// 物理机管理URI
|
||||
ManagerUri string `json:"manager_uri"`
|
||||
|
||||
// 物理机管理口IP
|
||||
AccessIp string `json:"access_ip"`
|
||||
|
||||
// 物理机管理口MAC
|
||||
AccessMac string `json:"access_mac"`
|
||||
|
||||
// 物理机管理口IP子网
|
||||
AccessNet string `json:"access_net"`
|
||||
// 物理机管理口二次网络
|
||||
AccessWire string `json:"access_wire"`
|
||||
}
|
||||
|
||||
type HostSizeAttributes struct {
|
||||
// 内存大小(单位MB)
|
||||
MemSize string `json:"mem_size"`
|
||||
// 预留内存大小(单位MB)
|
||||
MemReserved string `json:"mem_reserved"`
|
||||
// CPU缓存大小(单位MB)
|
||||
CpuCache string `json:"cpu_cache"`
|
||||
}
|
||||
|
||||
type HostIpmiAttributes struct {
|
||||
// username
|
||||
IpmiUsername string `json:"ipmi_username"`
|
||||
// password
|
||||
IpmiPassword string `json:"ipmi_password"`
|
||||
// ip address
|
||||
IpmiIpAddr string `json:"ipmi_ip_addr"`
|
||||
// presence
|
||||
IpmiPresent *bool `json:"ipmi_present"`
|
||||
// lan channel
|
||||
IpmiLanChannel *int `json:"ipmi_lan_channel"`
|
||||
// verified
|
||||
IpmiVerified *bool `json:"ipmi_verified"`
|
||||
// Redfish API support
|
||||
IpmiRedfishApi *bool `json:"ipmi_redfish_api"`
|
||||
// Cdrom boot support
|
||||
IpmiCdromBoot *bool `json:"ipmi_cdrom_boot"`
|
||||
// ipmi_pxe_boot
|
||||
IpmiPxeBoot *bool `json:"ipmi_pxe_boot"`
|
||||
}
|
||||
|
||||
type HostCreateInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseCreateInput
|
||||
|
||||
ZoneResourceInput
|
||||
|
||||
HostAccessAttributes
|
||||
HostSizeAttributes
|
||||
HostIpmiAttributes
|
||||
|
||||
// 新建带IPMI信息的物理机时不进行IPMI信息探测
|
||||
NoProbe *bool `json:"no_probe"`
|
||||
|
||||
// host uuid
|
||||
Uuid string `json:"uuid"`
|
||||
|
||||
// Host类型
|
||||
HostType string `json:"host_type"`
|
||||
|
||||
// 是否为裸金属
|
||||
IsBaremetal *bool `json:"is_baremetal"`
|
||||
}
|
||||
|
||||
type HostUpdateInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseUpdateInput
|
||||
|
||||
HostAccessAttributes
|
||||
HostSizeAttributes
|
||||
HostIpmiAttributes
|
||||
|
||||
// IPMI info
|
||||
IpmiInfo jsonutils.JSONObject `json:"ipmi_info"`
|
||||
|
||||
// CPU超售比上限
|
||||
CpuCmtbound *float32 `json:"cpu_cmtbound"`
|
||||
// 内存超售比上限
|
||||
MemCmtbound *float32 `json:"mem_cmtbound"`
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ type ExternalProjectListInput struct {
|
||||
}
|
||||
|
||||
type RouteTableListInput struct {
|
||||
apis.VirtualResourceListInput
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
VpcFilterListInput
|
||||
@@ -94,7 +94,7 @@ type SnapshotPolicyCacheListInput struct {
|
||||
}
|
||||
|
||||
type NetworkInterfaceListInput struct {
|
||||
apis.StatusStandaloneResourceListInput
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
ManagedResourceListInput
|
||||
|
||||
@@ -65,7 +65,7 @@ type SimpleNetwork struct {
|
||||
}
|
||||
|
||||
type NatgatewayDetails struct {
|
||||
apis.StatusStandaloneResourceDetails
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
|
||||
VpcResourceInfo
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ const (
|
||||
)
|
||||
|
||||
type NatGetewayListInput struct {
|
||||
apis.StatusStandaloneResourceListInput
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
VpcFilterListInput
|
||||
@@ -48,7 +48,7 @@ type NatGetewayListInput struct {
|
||||
}
|
||||
|
||||
type NatEntryListInput struct {
|
||||
apis.StatusStandaloneResourceListInput
|
||||
apis.StatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
NatGatewayFilterListInput
|
||||
ManagedResourceListInput
|
||||
@@ -94,7 +94,7 @@ type NatGatewayFilterListInput struct {
|
||||
}
|
||||
|
||||
type NatEntryDetails struct {
|
||||
apis.StatusStandaloneResourceDetails
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
NatGatewayResourceInfo
|
||||
|
||||
// NAT ENTRY的真实名称??
|
||||
|
||||
+28
-19
@@ -18,25 +18,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type VpcFilterListInputBase struct {
|
||||
// 过滤关联此VPC(ID或Name)的资源
|
||||
Vpc string `json:"vpc"`
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
// filter by vpc Id
|
||||
VpcId string `json:"vpc_id" deprecated-by:"vpc"`
|
||||
|
||||
// 按VPC名称排序
|
||||
// pattern:asc|desc
|
||||
OrderByVpc string `json:"order_by_vpc"`
|
||||
}
|
||||
|
||||
type VpcFilterListInput struct {
|
||||
VpcFilterListInputBase
|
||||
RegionalFilterListInput
|
||||
ManagedResourceListInput
|
||||
}
|
||||
|
||||
type WireFilterListBase struct {
|
||||
// 过滤连接此二层网络(ID或Name)的资源
|
||||
Wire string `json:"wire"`
|
||||
@@ -278,3 +259,31 @@ type NetworkTryCreateNetworkInput struct {
|
||||
type NetworkSyncInput struct {
|
||||
apis.Meta
|
||||
}
|
||||
|
||||
type NetworkUpdateInput struct {
|
||||
apis.SharableVirtualResourceBaseUpdateInput
|
||||
|
||||
// 起始IP地址
|
||||
GuestIpStart string `json:"guest_ip_start"`
|
||||
// 接收IP地址
|
||||
GuestIpEnd string `json:"guest_ip_end"`
|
||||
// 掩码
|
||||
GuestIpMask *int8 `json:"guest_ip_mask"`
|
||||
// 网关地址
|
||||
GuestGateway string `json:"guest_gateway"`
|
||||
// DNS
|
||||
GuestDns string `json:"guest_dns"`
|
||||
// allow multiple dhcp, seperated by ","
|
||||
GuestDhcp string `json:"guest_dhcp"`
|
||||
|
||||
GuestDomain string `json:"guest_domain"`
|
||||
|
||||
VlanId *int `json:"vlan_id"`
|
||||
|
||||
// 服务器类型
|
||||
// example: server
|
||||
ServerType string `json:"server_type"`
|
||||
|
||||
// 分配策略
|
||||
AllocPolicy string `json:"alloc_policy"`
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ type NetworkInterfaceNetworkInfo struct {
|
||||
}
|
||||
|
||||
type NetworkInterfaceDetails struct {
|
||||
apis.StatusStandaloneResourceDetails
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
ManagedResourceInfo
|
||||
CloudregionResourceInfo
|
||||
|
||||
|
||||
@@ -14,11 +14,101 @@
|
||||
|
||||
package compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
)
|
||||
|
||||
type RouteTableDetails struct {
|
||||
apis.VirtualResourceDetails
|
||||
apis.StatusInfrasResourceBaseDetails
|
||||
VpcResourceInfo
|
||||
|
||||
SRouteTable
|
||||
}
|
||||
|
||||
type SRoute struct {
|
||||
Type string `json:"type"`
|
||||
Cidr string `json:"cidr"`
|
||||
NextHopType string `json:"next_hop_type"`
|
||||
NextHopId string `json:"next_hop_id"`
|
||||
}
|
||||
|
||||
func (route *SRoute) Validate() error {
|
||||
if strings.Index(route.Cidr, "/") > 0 {
|
||||
_, ipNet, err := net.ParseCIDR(route.Cidr)
|
||||
if err != nil {
|
||||
return errors.Wrapf(httperrors.ErrInputParameter, "net.ParseCIDR %s", err)
|
||||
}
|
||||
// normalize from 192.168.1.3/24 to 192.168.1.0/24
|
||||
route.Cidr = ipNet.String()
|
||||
} else {
|
||||
ip := net.ParseIP(route.Cidr).To4()
|
||||
if ip == nil {
|
||||
return errors.Wrapf(httperrors.ErrInputParameter, "invalid addr %s", route.Cidr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SRoutes []*SRoute
|
||||
|
||||
func (routes SRoutes) String() string {
|
||||
return jsonutils.Marshal(routes).String()
|
||||
}
|
||||
|
||||
func (routes SRoutes) IsZero() bool {
|
||||
if len(routes) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (routes *SRoutes) Validate() error {
|
||||
if routes == nil {
|
||||
*routes = SRoutes{}
|
||||
return nil
|
||||
}
|
||||
|
||||
found := map[string]struct{}{}
|
||||
for _, route := range *routes {
|
||||
if err := route.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := found[route.Cidr]; ok {
|
||||
// error so that the user has a chance to deal with comments
|
||||
return httperrors.NewInputParameterError("duplicate route cidr %s", route.Cidr)
|
||||
}
|
||||
// TODO aliyun: check overlap with System type route
|
||||
found[route.Cidr] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RouteTableCreateInput struct {
|
||||
apis.StatusInfrasResourceBaseCreateInput
|
||||
|
||||
VpcResourceInput
|
||||
|
||||
Type string `json:"type"`
|
||||
Routes *SRoutes `json:"routes"`
|
||||
}
|
||||
|
||||
type RouteTableUpdateInput struct {
|
||||
apis.StatusInfrasResourceBaseUpdateInput
|
||||
|
||||
Routes *SRoutes `json:"routes"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
gotypes.RegisterSerializable(reflect.TypeOf(&SRoutes{}), func() gotypes.ISerializable {
|
||||
return &SRoutes{}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
package compute
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type ServerSkuCreateInput struct {
|
||||
apis.StatusStandaloneResourceCreateInput
|
||||
@@ -139,3 +141,45 @@ type ServerSkuDetails struct {
|
||||
// 绑定云主机数量
|
||||
TotalGuestCount int `json:"total_guest_count"`
|
||||
}
|
||||
|
||||
type ServerSkuUpdateInput struct {
|
||||
apis.StatusStandaloneResourceBaseUpdateInput
|
||||
|
||||
InstanceTypeFamily string `json:"instance_type_family"`
|
||||
|
||||
InstanceTypeCategory string `json:"instance_type_category"`
|
||||
|
||||
LocalCategory string `json:"local_category"` // 记录本地分类
|
||||
|
||||
OsName string `json:"os_name"` // Windows|Linux|Any
|
||||
|
||||
SysDiskResizable *bool `json:"sys_disk_resizable"`
|
||||
|
||||
SysDiskType string `json:"sys_disk_type"`
|
||||
|
||||
SysDiskMinSizeGB *int `json:"sys_disk_min_size_gb"` // not required。 windows比较新的版本都是50G左右。
|
||||
|
||||
SysDiskMaxSizeGB *int `json:"sys_disk_max_size_gb"` // not required
|
||||
|
||||
AttachedDiskType string `json:"attached_disk_type"`
|
||||
|
||||
AttachedDiskSizeGB *int `json:"attached_disk_size_gb"`
|
||||
|
||||
AttachedDiskCount *int `json:"attached_disk_count"`
|
||||
|
||||
DataDiskTypes string `json:"data_disk_types"`
|
||||
|
||||
DataDiskMaxCount *int `json:"data_disk_max_count"`
|
||||
|
||||
NicType string `json:"nic_type"`
|
||||
|
||||
NicMaxCount *int `json:"nic_max_count"`
|
||||
|
||||
GpuAttachable *bool `json:"gpu_attachable"`
|
||||
|
||||
GpuSpec string `json:"gpu_spec"`
|
||||
|
||||
GpuCount *int `json:"gpu_count"`
|
||||
|
||||
GpuMaxCount *int `json:"gpu_max_count"`
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
)
|
||||
|
||||
type StorageCreateInput struct {
|
||||
apis.EnabledStatusStandaloneResourceCreateInput
|
||||
apis.EnabledStatusInfrasResourceBaseCreateInput
|
||||
|
||||
// 存储类型
|
||||
//
|
||||
@@ -49,12 +49,7 @@ type StorageCreateInput struct {
|
||||
// required: true
|
||||
MediumType string `json:"medium_type"`
|
||||
|
||||
// 可用区名称或ID, 建议使用ID
|
||||
// required: true
|
||||
Zone string `json:"zone"`
|
||||
|
||||
// swagger:ignore
|
||||
ZoneId string
|
||||
ZoneResourceInput
|
||||
|
||||
// ceph认证主机, storage_type为 rbd 时,此参数为必传项
|
||||
// 单个ip或以逗号分隔的多个ip具体可查询 /etc/ceph/ceph.conf 文件
|
||||
@@ -128,7 +123,7 @@ type SStorageCapacityInfo struct {
|
||||
}
|
||||
|
||||
type StorageDetails struct {
|
||||
apis.EnabledStatusStandaloneResourceDetails
|
||||
apis.EnabledStatusInfrasResourceBaseDetails
|
||||
ManagedResourceInfo
|
||||
ZoneResourceInfo
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ type StorageShareFilterListInput struct {
|
||||
}
|
||||
|
||||
type StorageListInput struct {
|
||||
apis.EnabledStatusStandaloneResourceListInput
|
||||
apis.EnabledStatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
ManagedResourceListInput
|
||||
|
||||
+37
-3
@@ -17,13 +17,13 @@ package compute
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type VpcDetails struct {
|
||||
SVpc
|
||||
|
||||
apis.EnabledStatusStandaloneResourceDetails
|
||||
apis.EnabledStatusInfrasResourceBaseDetails
|
||||
ManagedResourceInfo
|
||||
CloudregionResourceInfo
|
||||
GlobalVpcResourceInfo
|
||||
|
||||
SVpc
|
||||
|
||||
// 二层网络数量
|
||||
// example: 1
|
||||
WireCount int `json:"wire_count"`
|
||||
@@ -62,3 +62,37 @@ type VpcResourceInfo struct {
|
||||
|
||||
type VpcSyncstatusInput struct {
|
||||
}
|
||||
|
||||
type VpcCreateInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseCreateInput
|
||||
|
||||
CloudregionResourceInput
|
||||
|
||||
CloudproviderResourceInput
|
||||
|
||||
// CIDR_BLOCK
|
||||
CidrBlock string `json:"cidr_block"`
|
||||
}
|
||||
|
||||
type VpcResourceInput struct {
|
||||
// 关联VPC(ID或Name)
|
||||
Vpc string `json:"vpc"`
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
// filter by vpc Id
|
||||
VpcId string `json:"vpc_id" deprecated-by:"vpc"`
|
||||
}
|
||||
|
||||
type VpcFilterListInputBase struct {
|
||||
VpcResourceInput
|
||||
|
||||
// 按VPC名称排序
|
||||
// pattern:asc|desc
|
||||
OrderByVpc string `json:"order_by_vpc"`
|
||||
}
|
||||
|
||||
type VpcFilterListInput struct {
|
||||
VpcFilterListInputBase
|
||||
RegionalFilterListInput
|
||||
ManagedResourceListInput
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ type UsableVpcResourceListInput struct {
|
||||
}
|
||||
|
||||
type VpcListInput struct {
|
||||
apis.EnabledStatusStandaloneResourceListInput
|
||||
apis.EnabledStatusInfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
ManagedResourceListInput
|
||||
@@ -68,21 +68,6 @@ type VpcListInput struct {
|
||||
CidrBlock []string `json:"cidr_block"`
|
||||
}
|
||||
|
||||
type WireListInput struct {
|
||||
apis.StandaloneResourceListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
VpcFilterListInput
|
||||
|
||||
ZonalFilterListBase
|
||||
|
||||
HostResourceInput
|
||||
}
|
||||
|
||||
type GlobalVpcListInput struct {
|
||||
apis.EnabledStatusStandaloneResourceListInput
|
||||
}
|
||||
|
||||
const (
|
||||
VPC_PROVIDER_OVN = "ovn"
|
||||
)
|
||||
|
||||
+26
-13
@@ -17,7 +17,7 @@ package compute
|
||||
import "yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
type WireCreateInput struct {
|
||||
apis.StandaloneResourceCreateInput
|
||||
apis.InfrasResourceBaseCreateInput
|
||||
|
||||
// 带宽大小,单位: Mbps
|
||||
// default: 0
|
||||
@@ -29,22 +29,13 @@ type WireCreateInput struct {
|
||||
// default: 0
|
||||
Mtu int `json:"mtu"`
|
||||
|
||||
// vpc名称或Id
|
||||
// required: true
|
||||
Vpc string `json:"vpc"`
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
VpcId string `json:"vpc_id" deprecated-by:"vpc"`
|
||||
VpcResourceInput
|
||||
|
||||
// 可用区名称或Id
|
||||
// required: true
|
||||
Zone string `json:"zone"`
|
||||
// swagger:ignore
|
||||
ZoneId string
|
||||
ZoneResourceInput
|
||||
}
|
||||
|
||||
type WireDetails struct {
|
||||
apis.StandaloneResourceDetails
|
||||
apis.InfrasResourceBaseDetails
|
||||
VpcResourceInfo
|
||||
ZoneResourceInfoBase
|
||||
|
||||
@@ -75,3 +66,25 @@ type WireResourceInfo struct {
|
||||
// 可用区
|
||||
Zone string `json:"zone"`
|
||||
}
|
||||
|
||||
type WireUpdateInput struct {
|
||||
apis.InfrasResourceBaseUpdateInput
|
||||
|
||||
// bandwidth in MB
|
||||
Bandwidth int `json:"bandwidth"`
|
||||
|
||||
// MTU
|
||||
// example: 1500
|
||||
Mtu int `json:"mtu"`
|
||||
}
|
||||
|
||||
type WireListInput struct {
|
||||
apis.InfrasResourceBaseListInput
|
||||
apis.ExternalizedResourceBaseListInput
|
||||
|
||||
VpcFilterListInput
|
||||
|
||||
ZonalFilterListBase
|
||||
|
||||
HostResourceInput
|
||||
}
|
||||
|
||||
@@ -1585,14 +1585,6 @@ type SReservedip struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// SRoute is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SRoute.
|
||||
type SRoute struct {
|
||||
Type string `json:"type"`
|
||||
Cidr string `json:"cidr"`
|
||||
NextHopType string `json:"next_hop_type"`
|
||||
NextHopId string `json:"next_hop_id"`
|
||||
}
|
||||
|
||||
// SRouteTable is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SRouteTable.
|
||||
type SRouteTable struct {
|
||||
apis.SVirtualResourceBase
|
||||
@@ -1602,9 +1594,6 @@ type SRouteTable struct {
|
||||
Routes *SRoutes `json:"routes"`
|
||||
}
|
||||
|
||||
// SRoutes is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SRoutes.
|
||||
type SRoutes []*SRoute
|
||||
|
||||
// SSchedpolicy is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SSchedpolicy.
|
||||
type SSchedpolicy struct {
|
||||
apis.SStandaloneResourceBase
|
||||
|
||||
@@ -95,6 +95,7 @@ var (
|
||||
"enable_rbac",
|
||||
"non_default_domain_projects",
|
||||
"time_zone",
|
||||
"domainized_namespace",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -25,3 +25,10 @@ type CredentialDetails struct {
|
||||
Domain string `json:"domain"`
|
||||
DomainId string `json:"domain_id"`
|
||||
}
|
||||
|
||||
type CredentialUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
|
||||
// enabled
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
@@ -29,3 +29,9 @@ type DomainDetails struct {
|
||||
PolicyCount int `json:"policy_count"`
|
||||
IdpCount int `json:"idp_count"`
|
||||
}
|
||||
|
||||
type DomainUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package identity
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
@@ -335,3 +336,65 @@ type ServiceListInput struct {
|
||||
// 是否启用/禁用
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type IdentityBaseUpdateInput struct {
|
||||
apis.StandaloneResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type EnabledIdentityBaseUpdateInput struct {
|
||||
IdentityBaseUpdateInput
|
||||
|
||||
// 是否启用
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type GroupUpdateInput struct {
|
||||
IdentityBaseUpdateInput
|
||||
|
||||
// display name
|
||||
Displayname string `json:"displayname"`
|
||||
}
|
||||
|
||||
type IdentityProviderUpdateInput struct {
|
||||
apis.EnabledStatusStandaloneResourceBaseUpdateInput
|
||||
|
||||
TargetDomainId string `json:"target_domain_id"`
|
||||
|
||||
AutoCreateProject *bool `json:"auto_create_project"`
|
||||
|
||||
SyncIntervalSeconds *int `json:"sync_interval_seconds"`
|
||||
}
|
||||
|
||||
type PolicyUpdateInput struct {
|
||||
EnabledIdentityBaseUpdateInput
|
||||
|
||||
Type string `json:"type"`
|
||||
|
||||
Blob jsonutils.JSONObject `json:"blob"`
|
||||
}
|
||||
|
||||
type ProjectUpdateInput struct {
|
||||
IdentityBaseUpdateInput
|
||||
}
|
||||
|
||||
type RoleUpdateInput struct {
|
||||
IdentityBaseUpdateInput
|
||||
}
|
||||
|
||||
type UserUpdateInput struct {
|
||||
EnabledIdentityBaseUpdateInput
|
||||
|
||||
Email string `json:"email"`
|
||||
|
||||
Mobile string `json:"mobile"`
|
||||
|
||||
Displayname string `json:"displayname"`
|
||||
|
||||
IsSystemAccount *bool `json:"is_system_account"`
|
||||
|
||||
AllowWebConsole *bool `json:"allow_web_console"`
|
||||
|
||||
EnableMfa *bool `json:"enable_mfa"`
|
||||
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright 2019 Yunion
|
||||
// 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.
|
||||
|
||||
+23
-3
@@ -120,23 +120,26 @@ type StatusStandaloneResourceCreateInput struct {
|
||||
type StandaloneResourceCreateInput struct {
|
||||
ResourceBaseCreateInput
|
||||
|
||||
// 资源名称,如果generate_name为空,则为必填项
|
||||
// description: resource name, required if generated_name is not given
|
||||
// unique: true
|
||||
// required: true
|
||||
// example: test-network
|
||||
Name string `json:"name"`
|
||||
|
||||
// 生成资源名称的规则,如果name为空,则为必填项
|
||||
// description: generated resource name, given a pattern to generate name, required if name is not given
|
||||
// unique: false
|
||||
// required: false
|
||||
// example: test###
|
||||
GenerateName string `json:"generate_name"`
|
||||
|
||||
// description: resource description
|
||||
// 资源描述
|
||||
// required: false
|
||||
// example: test create network
|
||||
Description string `json:"description"`
|
||||
|
||||
// 资源是否为模拟资源
|
||||
// description: the resource is an emulated resource
|
||||
// required: false
|
||||
IsEmulated *bool `json:"is_emulated"`
|
||||
@@ -173,16 +176,19 @@ type GetDetailsStatusOutput struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type PerformProjectPublicInput struct {
|
||||
type PerformPublicInput struct {
|
||||
// 共享项目资源的共享范围,可能的值为:project, domain和system
|
||||
// pattern: project|domain|system
|
||||
Scope string `json:"scope"`
|
||||
|
||||
// 如果共享范围为项目,则在此列表中指定共享的目标项目
|
||||
SharedProjects []string `json:"shared_projects"`
|
||||
|
||||
// 如果共享范围为域,则在此列表中指定共享的目标域
|
||||
SharedDomains []string `json:"shared_domains"`
|
||||
}
|
||||
|
||||
type PerformProjectPrivateInput struct {
|
||||
type PerformPrivateInput struct {
|
||||
}
|
||||
|
||||
type PerformChangeProjectOwnerInput struct {
|
||||
@@ -198,3 +204,17 @@ type PerformEnableInput struct {
|
||||
|
||||
type PerformDisableInput struct {
|
||||
}
|
||||
|
||||
type InfrasResourceBaseCreateInput struct {
|
||||
DomainLevelResourceCreateInput
|
||||
}
|
||||
|
||||
type StatusInfrasResourceBaseCreateInput struct {
|
||||
InfrasResourceBaseCreateInput
|
||||
StatusBaseResourceCreateInput
|
||||
}
|
||||
|
||||
type EnabledStatusInfrasResourceBaseCreateInput struct {
|
||||
StatusInfrasResourceBaseCreateInput
|
||||
EnabledBaseResourceCreateInput
|
||||
}
|
||||
|
||||
@@ -199,6 +199,8 @@ type EnabledResourceBaseListInput struct {
|
||||
type SharableResourceBaseListInput struct {
|
||||
// 以资源是否共享过滤列表
|
||||
IsPublic *bool `json:"is_public"`
|
||||
// 根据资源的共享范围过滤列表,可能值为:system, domain, project
|
||||
PublicScope string `json:"public_scope"`
|
||||
}
|
||||
|
||||
type DomainLevelResourceListInput struct {
|
||||
@@ -247,3 +249,18 @@ type DeletePreventableResourceBaseListInput struct {
|
||||
type ScopedResourceBaseListInput struct {
|
||||
ProjectizedResourceListInput
|
||||
}
|
||||
|
||||
type InfrasResourceBaseListInput struct {
|
||||
DomainLevelResourceListInput
|
||||
SharableResourceBaseListInput
|
||||
}
|
||||
|
||||
type StatusInfrasResourceBaseListInput struct {
|
||||
InfrasResourceBaseListInput
|
||||
StatusResourceBaseListInput
|
||||
}
|
||||
|
||||
type EnabledStatusInfrasResourceBaseListInput struct {
|
||||
StatusInfrasResourceBaseListInput
|
||||
EnabledResourceBaseListInput
|
||||
}
|
||||
|
||||
@@ -112,10 +112,10 @@ type AlertCreateInput struct {
|
||||
}
|
||||
|
||||
type AlertUpdateInput struct {
|
||||
apis.Meta
|
||||
apis.VirtualResourceBaseUpdateInput
|
||||
|
||||
Message *string `json:"message"`
|
||||
|
||||
// 报警名称
|
||||
Name *string `json:"name"`
|
||||
// 报警执行频率
|
||||
Frequency *int64 `json:"frequency"`
|
||||
// 报警设置
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package monitor // import "yunion.io/x/onecloud/pkg/apis/monitor"
|
||||
|
||||
@@ -56,6 +56,8 @@ type MeterAlertDetails struct {
|
||||
}
|
||||
|
||||
type MeterAlertUpdateInput struct {
|
||||
V1AlertUpdateInput
|
||||
|
||||
// 比较运算符, 比如: >, <, >=, <=
|
||||
Comparator *string `json:"comparator"`
|
||||
// 报警阀值
|
||||
|
||||
@@ -180,6 +180,8 @@ type NodeAlertDetails struct {
|
||||
}
|
||||
|
||||
type NodeAlertUpdateInput struct {
|
||||
V1AlertUpdateInput
|
||||
|
||||
// 监控指标名称
|
||||
Metric *string `json:"metric"`
|
||||
// 监控资源类型, 比如: guest, host
|
||||
@@ -203,3 +205,7 @@ type NodeAlertUpdateInput struct {
|
||||
// 通知接受者
|
||||
Recipients *string `json:"recipients"`
|
||||
}
|
||||
|
||||
type V1AlertUpdateInput struct {
|
||||
AlertUpdateInput
|
||||
}
|
||||
|
||||
+29
-2
@@ -39,12 +39,26 @@ type ModelBaseShortDescDetail struct {
|
||||
type SharedProject struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
|
||||
DomainId string `json:"domain_id"`
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type SharedDomain struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type SharableResourceBaseInfo struct {
|
||||
// 共享的项目列表
|
||||
SharedProjects []SharedProject `json:"shared_projects"`
|
||||
// 共享的域列表
|
||||
SharedDomains []SharedDomain `json:"shared_domains"`
|
||||
}
|
||||
|
||||
type SharableVirtualResourceDetails struct {
|
||||
VirtualResourceDetails
|
||||
|
||||
SharedProjects []SharedProject `json:"shared_projects"`
|
||||
SharableResourceBaseInfo
|
||||
}
|
||||
|
||||
type AdminSharableVirtualResourceDetails struct {
|
||||
@@ -129,3 +143,16 @@ type ProjectizedResourceInfo struct {
|
||||
type ScopedResourceBaseInfo struct {
|
||||
ProjectizedResourceInfo
|
||||
}
|
||||
|
||||
type InfrasResourceBaseDetails struct {
|
||||
DomainLevelResourceDetails
|
||||
SharableResourceBaseInfo
|
||||
}
|
||||
|
||||
type StatusInfrasResourceBaseDetails struct {
|
||||
InfrasResourceBaseDetails
|
||||
}
|
||||
|
||||
type EnabledStatusInfrasResourceBaseDetails struct {
|
||||
StatusInfrasResourceBaseDetails
|
||||
}
|
||||
|
||||
@@ -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 apis
|
||||
|
||||
type ModelBaseUpdateInput struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
type ResourceBaseUpdateInput struct {
|
||||
ModelBaseUpdateInput
|
||||
}
|
||||
|
||||
type StandaloneResourceBaseUpdateInput struct {
|
||||
ResourceBaseUpdateInput
|
||||
|
||||
// 资源名称
|
||||
Name string `json:"name"`
|
||||
// 资源描述
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type StatusStandaloneResourceBaseUpdateInput struct {
|
||||
StandaloneResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type EnabledStatusStandaloneResourceBaseUpdateInput struct {
|
||||
StatusStandaloneResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type VirtualResourceBaseUpdateInput struct {
|
||||
StatusStandaloneResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type SharableVirtualResourceBaseUpdateInput struct {
|
||||
VirtualResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type AdminSharableVirtualResourceBaseUpdateInput struct {
|
||||
SharableVirtualResourceBaseUpdateInput
|
||||
|
||||
// 管理记录
|
||||
Records string `json:"records"`
|
||||
}
|
||||
|
||||
type DomainLevelResourceBaseUpdateInput struct {
|
||||
StandaloneResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type StatusDomainLevelResourceBaseUpdateInput struct {
|
||||
DomainLevelResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type EnabledStatusDomainLevelResourceBaseUpdateInput struct {
|
||||
StatusDomainLevelResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type JointResourceBaseUpdateInput struct {
|
||||
ResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type VirtualJointResourceBaseUpdateInput struct {
|
||||
JointResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type InfrasResourceBaseUpdateInput struct {
|
||||
DomainLevelResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type StatusInfrasResourceBaseUpdateInput struct {
|
||||
InfrasResourceBaseUpdateInput
|
||||
}
|
||||
|
||||
type EnabledStatusInfrasResourceBaseUpdateInput struct {
|
||||
StatusInfrasResourceBaseUpdateInput
|
||||
}
|
||||
@@ -1 +1,15 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package yunionconf // import "yunion.io/x/onecloud/pkg/apis/yunionconf"
|
||||
|
||||
@@ -31,6 +31,8 @@ var (
|
||||
|
||||
defaultPagingLimit int64 = 2048
|
||||
maxPagingLimit int64 = 2048
|
||||
|
||||
domainizedNamespace = true
|
||||
)
|
||||
|
||||
func SetRegion(region string) {
|
||||
@@ -72,3 +74,11 @@ func GetDefaultPagingLimit() int64 {
|
||||
func GetMaxPagingLimit() int64 {
|
||||
return maxPagingLimit
|
||||
}
|
||||
|
||||
func SetDomainizedNamespace(domainNS bool) {
|
||||
domainizedNamespace = domainNS
|
||||
}
|
||||
|
||||
func IsDomainizedNamespace() bool {
|
||||
return nonDefaultDomainProjects && domainizedNamespace
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
|
||||
type SAdminSharableVirtualResourceBase struct {
|
||||
SSharableVirtualResourceBase
|
||||
Records string `charset:"ascii" list:"user" create:"optional" update:"user"`
|
||||
Records string `charset:"utf8" list:"user" create:"optional" update:"user"`
|
||||
}
|
||||
|
||||
type SAdminSharableVirtualResourceBaseManager struct {
|
||||
@@ -226,3 +226,17 @@ func (manager *SAdminSharableVirtualResourceBaseManager) FetchCustomizeColumns(
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (model *SAdminSharableVirtualResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.AdminSharableVirtualResourceBaseUpdateInput,
|
||||
) (apis.AdminSharableVirtualResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.SharableVirtualResourceBaseUpdateInput, err = model.SSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.SharableVirtualResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SSharableVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"reflect"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
@@ -56,6 +58,50 @@ func call(obj interface{}, fName string, inputs ...interface{}) ([]reflect.Value
|
||||
return callObject(reflect.ValueOf(obj), fName, inputs...)
|
||||
}
|
||||
|
||||
func findFunc(modelVal reflect.Value, fName string) (reflect.Value, error) {
|
||||
funcVal := modelVal.MethodByName(fName)
|
||||
if !funcVal.IsValid() || funcVal.IsNil() {
|
||||
log.Debugf("find method %s for %s", fName, modelVal.Type())
|
||||
if modelVal.Kind() != reflect.Ptr {
|
||||
return funcVal, errors.Wrapf(httperrors.ErrNotImplemented, "%s not implemented", fName)
|
||||
}
|
||||
modelVal = modelVal.Elem()
|
||||
if modelVal.Kind() != reflect.Struct {
|
||||
return funcVal, errors.Wrapf(httperrors.ErrNotImplemented, "%s not implemented", fName)
|
||||
}
|
||||
modelType := modelVal.Type()
|
||||
for i := 0; i < modelType.NumField(); i += 1 {
|
||||
fieldType := modelType.Field(i)
|
||||
if fieldType.Anonymous {
|
||||
fieldValue := modelVal.Field(i)
|
||||
if fieldValue.Kind() != reflect.Ptr && fieldValue.CanAddr() {
|
||||
newFuncVal, err := findFunc(fieldValue.Addr(), fName)
|
||||
if err == nil {
|
||||
if !funcVal.IsValid() || funcVal.IsNil() {
|
||||
funcVal = newFuncVal
|
||||
} else {
|
||||
return funcVal, errors.Wrapf(httperrors.ErrConflict, "%s is ambiguous", fName)
|
||||
}
|
||||
}
|
||||
} else if fieldValue.Kind() == reflect.Ptr {
|
||||
newFuncVal, err := findFunc(fieldValue, fName)
|
||||
if err == nil {
|
||||
if !funcVal.IsValid() || funcVal.IsNil() {
|
||||
funcVal = newFuncVal
|
||||
} else {
|
||||
return funcVal, errors.Wrapf(httperrors.ErrConflict, "%s is ambiguous", fName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !funcVal.IsValid() || funcVal.IsNil() {
|
||||
return funcVal, errors.Wrapf(httperrors.ErrNotImplemented, "%s is not implemented", fName)
|
||||
}
|
||||
}
|
||||
return funcVal, nil
|
||||
}
|
||||
|
||||
func callObject(modelVal reflect.Value, fName string, inputs ...interface{}) ([]reflect.Value, error) {
|
||||
funcVal := modelVal.MethodByName(fName)
|
||||
return callFunc(funcVal, fName, inputs...)
|
||||
|
||||
@@ -16,6 +16,7 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -117,3 +118,83 @@ func Test_call(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type Embeded struct {
|
||||
}
|
||||
|
||||
func (e *Embeded) Method() {
|
||||
fmt.Println("Embeded Method")
|
||||
}
|
||||
|
||||
type Struct0 struct {
|
||||
Embeded
|
||||
}
|
||||
|
||||
type Struct1 struct {
|
||||
Embeded
|
||||
}
|
||||
|
||||
type Struct2 struct {
|
||||
}
|
||||
|
||||
func (e *Struct0) Method() {
|
||||
fmt.Println("Struct0 Method")
|
||||
}
|
||||
|
||||
type Top0 struct {
|
||||
Struct0
|
||||
Struct1
|
||||
Struct2
|
||||
}
|
||||
|
||||
type Top1 struct {
|
||||
Struct0
|
||||
Struct1
|
||||
Struct2
|
||||
}
|
||||
|
||||
func (e *Top1) Method() {
|
||||
fmt.Println("Top1 Method")
|
||||
}
|
||||
|
||||
func TestFindFunc(t *testing.T) {
|
||||
cases := []struct {
|
||||
obj interface{}
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
obj: &Embeded{},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
obj: &Struct0{},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
obj: &Struct1{},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
obj: &Struct2{},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
obj: &Top0{},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
obj: &Top1{},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Logf("%s is called", reflect.TypeOf(c.obj))
|
||||
funcVal, err := findFunc(reflect.ValueOf(c.obj), "Method")
|
||||
if funcVal.IsValid() {
|
||||
funcVal.Call(nil)
|
||||
}
|
||||
if (c.want && err != nil) || (!c.want && err == nil) {
|
||||
t.Errorf("%s want %v but err==nil %v", reflect.TypeOf(c.obj), c.want, err == nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1570,14 +1570,6 @@ func updateItem(manager IModelManager, item IModel, ctx context.Context, userCre
|
||||
return nil, httperrors.NewInternalServerError("Invalid data JSONObject")
|
||||
}
|
||||
|
||||
name, _ := data.GetString("name")
|
||||
if len(name) > 0 {
|
||||
err = alterNameValidator(item, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
dataDict, err = ValidateUpdateData(item, ctx, userCred, query, dataDict)
|
||||
if err != nil {
|
||||
errMsg := fmt.Sprintf("validate update data error: %s", err)
|
||||
|
||||
@@ -38,6 +38,14 @@ type SDomainizedResourceBase struct {
|
||||
DomainId string `width:"64" charset:"ascii" default:"default" nullable:"false" index:"true" list:"user" json:"domain_id"`
|
||||
}
|
||||
|
||||
func (manager *SDomainizedResourceBaseManager) NamespaceScope() rbacutils.TRbacScope {
|
||||
if consts.IsDomainizedNamespace() {
|
||||
return rbacutils.ScopeDomain
|
||||
} else {
|
||||
return rbacutils.ScopeSystem
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SDomainizedResourceBaseManager) ResourceScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeDomain
|
||||
}
|
||||
|
||||
@@ -151,6 +151,18 @@ func (model *SDomainLevelResourceBase) PerformChangeOwner(ctx context.Context, u
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// change domain, do check
|
||||
if managed, ok := model.GetIDomainLevelModel().(IManagedResoucceBase); ok {
|
||||
if !managed.CanShareToDomain(ownerId.GetProjectDomainId()) {
|
||||
return nil, errors.Wrap(httperrors.ErrForbidden, "cann't share across domain")
|
||||
}
|
||||
}
|
||||
|
||||
if !IsAdminAllowPerform(userCred, model, "change-owner") {
|
||||
return nil, errors.Wrap(httperrors.ErrNotSufficientPrivilege, "require system privileges")
|
||||
}
|
||||
|
||||
q := manager.Query().Equals("name", model.GetName())
|
||||
q = manager.FilterByOwner(q, ownerId, manager.NamespaceScope())
|
||||
q = manager.FilterBySystemAttributes(q, nil, nil, manager.ResourceScope())
|
||||
@@ -169,10 +181,12 @@ func (model *SDomainLevelResourceBase) PerformChangeOwner(ctx context.Context, u
|
||||
former = &formerObj
|
||||
}
|
||||
|
||||
// clean shared projects before update project id
|
||||
// if err := SharedResourceManager.CleanModelSharedProjects(ctx, userCred, model); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// clean shared projects before update domain id
|
||||
if sharedModel, ok := model.GetIDomainLevelModel().(ISharableBaseModel); ok {
|
||||
if err := SharedResourceManager.CleanModelShares(ctx, userCred, sharedModel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = Update(model, func() error {
|
||||
model.DomainId = ownerId.GetProjectDomainId()
|
||||
@@ -271,3 +285,17 @@ func (model *SDomainLevelResourceBase) SyncCloudDomainId(userCred mcclient.Token
|
||||
func (model *SDomainLevelResourceBase) GetIDomainLevelModel() IDomainLevelModel {
|
||||
return model.GetVirtualObject().(IDomainLevelModel)
|
||||
}
|
||||
|
||||
func (model *SDomainLevelResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.DomainLevelResourceBaseUpdateInput,
|
||||
) (apis.DomainLevelResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.StandaloneResourceBaseUpdateInput, err = model.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -146,3 +146,17 @@ func (model *SEnabledStatusDomainLevelResourceBase) GetExtraDetails(
|
||||
) (apis.EnabledStatusDomainLevelResourceDetails, error) {
|
||||
return apis.EnabledStatusDomainLevelResourceDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SEnabledStatusDomainLevelResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.EnabledStatusDomainLevelResourceBaseUpdateInput,
|
||||
) (apis.EnabledStatusDomainLevelResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.StatusDomainLevelResourceBaseUpdateInput, err = model.SStatusDomainLevelResourceBase.ValidateUpdateData(ctx, userCred, query, input.StatusDomainLevelResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStatusDomainLevelResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
// 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 db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SEnabledStatusInfrasResourceBase struct {
|
||||
SStatusInfrasResourceBase
|
||||
SEnabledResourceBase
|
||||
}
|
||||
|
||||
type SEnabledStatusInfrasResourceBaseManager struct {
|
||||
SStatusInfrasResourceBaseManager
|
||||
SEnabledResourceBaseManager
|
||||
}
|
||||
|
||||
func NewEnabledStatusInfrasResourceBaseManager(dt interface{}, tableName string, keyword string, keywordPlural string) SEnabledStatusInfrasResourceBaseManager {
|
||||
return SEnabledStatusInfrasResourceBaseManager{
|
||||
SStatusInfrasResourceBaseManager: NewStatusInfrasResourceBaseManager(dt, tableName, keyword, keywordPlural),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEnabledStatusInfrasResourceBase) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformEnableInput) bool {
|
||||
return IsDomainAllowPerform(userCred, self, "enable")
|
||||
}
|
||||
|
||||
func (self *SEnabledStatusInfrasResourceBase) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformEnableInput) (jsonutils.JSONObject, error) {
|
||||
err := EnabledPerformEnable(self, ctx, userCred, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "EnabledPerformEnable")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SEnabledStatusInfrasResourceBase) AllowPerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformDisableInput) bool {
|
||||
return IsDomainAllowPerform(userCred, self, "disable")
|
||||
}
|
||||
|
||||
func (self *SEnabledStatusInfrasResourceBase) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformDisableInput) (jsonutils.JSONObject, error) {
|
||||
err := EnabledPerformEnable(self, ctx, userCred, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "EnabledPerformEnable")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (manager *SEnabledStatusInfrasResourceBaseManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.EnabledStatusInfrasResourceBaseCreateInput,
|
||||
) (apis.EnabledStatusInfrasResourceBaseCreateInput, error) {
|
||||
var err error
|
||||
input.StatusInfrasResourceBaseCreateInput, err = manager.SStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStatusInfrasResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SEnabledStatusInfrasResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query apis.EnabledStatusInfrasResourceBaseListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SEnabledResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SEnabledStatusInfrasResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SEnabledStatusInfrasResourceBaseManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query apis.EnabledStatusInfrasResourceBaseListInput,
|
||||
) (*sqlchemy.SQuery, 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 (manager *SEnabledStatusInfrasResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []apis.EnabledStatusInfrasResourceBaseDetails {
|
||||
rows := make([]apis.EnabledStatusInfrasResourceBaseDetails, len(objs))
|
||||
domainRows := manager.SStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = apis.EnabledStatusInfrasResourceBaseDetails{
|
||||
StatusInfrasResourceBaseDetails: domainRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (model *SEnabledStatusInfrasResourceBase) GetExtraDetails(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
isList bool,
|
||||
) (apis.EnabledStatusInfrasResourceBaseDetails, error) {
|
||||
return apis.EnabledStatusInfrasResourceBaseDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SEnabledStatusInfrasResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.EnabledStatusInfrasResourceBaseUpdateInput,
|
||||
) (apis.EnabledStatusInfrasResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.StatusInfrasResourceBaseUpdateInput, err = model.SStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.StatusInfrasResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStatusInfrasResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -140,3 +140,17 @@ func (model *SEnabledStatusStandaloneResourceBase) GetExtraDetails(
|
||||
) (apis.EnabledStatusStandaloneResourceDetails, error) {
|
||||
return apis.EnabledStatusStandaloneResourceDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SEnabledStatusStandaloneResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.EnabledStatusStandaloneResourceBaseUpdateInput,
|
||||
) (apis.EnabledStatusStandaloneResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.StatusStandaloneResourceBaseUpdateInput, err = model.SStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StatusStandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStatusStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
// 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 db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"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 SInfrasResourceBaseManager struct {
|
||||
SDomainLevelResourceBaseManager
|
||||
SSharableBaseResourceManager
|
||||
}
|
||||
|
||||
func NewInfrasResourceBaseManager(
|
||||
dt interface{},
|
||||
tableName string,
|
||||
keyword string,
|
||||
keywordPlural string,
|
||||
) SInfrasResourceBaseManager {
|
||||
return SInfrasResourceBaseManager{
|
||||
SDomainLevelResourceBaseManager: NewDomainLevelResourceBaseManager(dt, tableName, keyword, keywordPlural),
|
||||
}
|
||||
}
|
||||
|
||||
type SInfrasResourceBase struct {
|
||||
SDomainLevelResourceBase
|
||||
SSharableBaseResource
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) GetIInfrasModelManager() IInfrasModelManager {
|
||||
return manager.GetVirtualObject().(IInfrasModelManager)
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
return SharableManagerFilterByOwner(manager.GetIInfrasModelManager(), q, owner, scope)
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return ((model.IsOwner(userCred) || model.IsSharable(userCred)) && IsAllowGet(rbacutils.ScopeDomain, userCred, model)) || IsAllowGet(rbacutils.ScopeSystem, userCred, model)
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) IsSharable(reqUsrId mcclient.IIdentityProvider) bool {
|
||||
return SharableModelIsSharable(model.GetIInfrasModel(), reqUsrId)
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) IsShared() bool {
|
||||
return SharableModelIsShared(model)
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicInput) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicInput) (jsonutils.JSONObject, error) {
|
||||
err := SharablePerformPublic(model, ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SharablePerformPublic")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
|
||||
err := SharablePerformPrivate(model, ctx, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SharablePerformPrivate")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) GetIInfrasModel() IInfrasModel {
|
||||
return model.GetVirtualObject().(IInfrasModel)
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.InfrasResourceBaseCreateInput,
|
||||
) (apis.InfrasResourceBaseCreateInput, error) {
|
||||
var err error
|
||||
input.DomainLevelResourceCreateInput, err = manager.SDomainLevelResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.DomainLevelResourceCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "manager.SDomainLevelResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query apis.InfrasResourceBaseListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SDomainLevelResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DomainLevelResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SDomainLevelResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SSharableBaseResourceManager.ListItemFilter(ctx, q, userCred, query.SharableResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SSharableBaseResourceManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SDomainLevelResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) OrderByExtraFields(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query apis.InfrasResourceBaseListInput) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SDomainLevelResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DomainLevelResourceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SDomainLevelResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (apis.InfrasResourceBaseDetails, error) {
|
||||
return apis.InfrasResourceBaseDetails{}, nil
|
||||
}
|
||||
|
||||
func (manager *SInfrasResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []apis.InfrasResourceBaseDetails {
|
||||
rows := make([]apis.InfrasResourceBaseDetails, len(objs))
|
||||
|
||||
domainRows := manager.SDomainLevelResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
shareRows := manager.SSharableBaseResourceManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = apis.InfrasResourceBaseDetails{
|
||||
DomainLevelResourceDetails: domainRows[i],
|
||||
SharableResourceBaseInfo: shareRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.InfrasResourceBaseUpdateInput,
|
||||
) (apis.InfrasResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.DomainLevelResourceBaseUpdateInput, err = model.SDomainLevelResourceBase.ValidateUpdateData(ctx, userCred, query, input.DomainLevelResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SDomainLevelResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) GetSharedDomains() []string {
|
||||
return SharableGetSharedProjects(model, SharedTargetDomain)
|
||||
}
|
||||
|
||||
func (model *SInfrasResourceBase) PerformChangeOwner(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.PerformChangeDomainOwnerInput,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
if model.IsShared() {
|
||||
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "cannot change owner when shared!")
|
||||
}
|
||||
return model.SDomainLevelResourceBase.PerformChangeOwner(ctx, userCred, query, input)
|
||||
}
|
||||
@@ -276,13 +276,15 @@ type IStandaloneModel interface {
|
||||
RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error
|
||||
RemoveAllMetadata(ctx context.Context, userCred mcclient.TokenCredential) error
|
||||
GetAllMetadata(userCred mcclient.TokenCredential) (map[string]string, error)
|
||||
|
||||
IsShared() bool
|
||||
}
|
||||
|
||||
type IDomainLevelModelManager interface {
|
||||
IStandaloneModelManager
|
||||
|
||||
GetIDomainLevelModelManager() IDomainLevelModelManager
|
||||
GetResourceCount() ([]SProjectResourceCount, error)
|
||||
GetResourceCount() ([]SDomainResourceCount, error)
|
||||
}
|
||||
|
||||
type IDomainLevelModel interface {
|
||||
@@ -295,6 +297,20 @@ type IDomainLevelModel interface {
|
||||
GetIDomainLevelModel() IDomainLevelModel
|
||||
}
|
||||
|
||||
type IInfrasModelManager interface {
|
||||
IDomainLevelModelManager
|
||||
|
||||
GetIInfrasModelManager() IInfrasModelManager
|
||||
}
|
||||
|
||||
type IInfrasModel interface {
|
||||
IDomainLevelModel
|
||||
ISharableBase
|
||||
|
||||
GetIInfrasModel() IInfrasModel
|
||||
GetSharedDomains() []string
|
||||
}
|
||||
|
||||
type IVirtualModelManager interface {
|
||||
IStandaloneModelManager
|
||||
|
||||
@@ -322,9 +338,11 @@ type ISharableVirtualModelManager interface {
|
||||
|
||||
type ISharableVirtualModel interface {
|
||||
IVirtualModel
|
||||
ISharableBase
|
||||
|
||||
GetISharableVirtualModel() ISharableVirtualModel
|
||||
GetSharedProjects() []string
|
||||
GetSharedDomains() []string
|
||||
}
|
||||
|
||||
type IAdminSharableVirtualModelManager interface {
|
||||
|
||||
@@ -282,3 +282,17 @@ func (manager *SJointResourceBaseManager) OrderByExtraFields(
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (model *SJointResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.JointResourceBaseUpdateInput,
|
||||
) (apis.JointResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.ResourceBaseUpdateInput, err = model.SResourceBase.ValidateUpdateData(ctx, userCred, query, input.ResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// 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 db
|
||||
|
||||
type IManagedResoucceBase interface {
|
||||
CanShareToDomain(domainId string) bool
|
||||
}
|
||||
@@ -508,8 +508,8 @@ func (model *SModelBase) AllowUpdateItem(ctx context.Context, userCred mcclient.
|
||||
return false
|
||||
}
|
||||
|
||||
func (model *SModelBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return data, nil
|
||||
func (model *SModelBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.ModelBaseUpdateInput) (apis.ModelBaseUpdateInput, error) {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SModelBase) PreUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -49,6 +49,9 @@ const (
|
||||
ACT_DETACH_FAIL = "detach_fail"
|
||||
ACT_DELETE_FAIL = "delete_fail"
|
||||
|
||||
ACT_PUBLIC = "public"
|
||||
ACT_PRIVATE = "private"
|
||||
|
||||
ACT_SYNC_UPDATE = "sync_update"
|
||||
ACT_SYNC_CREATE = "sync_create"
|
||||
|
||||
|
||||
@@ -176,3 +176,12 @@ func (manager *SResourceBaseManager) FetchCustomizeColumns(
|
||||
func (model *SResourceBase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, isList bool) (apis.ResourceBaseDetails, error) {
|
||||
return apis.ResourceBaseDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SResourceBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.ResourceBaseUpdateInput) (apis.ResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.ModelBaseUpdateInput, err = model.SModelBase.ValidateUpdateData(ctx, userCred, query, input.ModelBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SModelBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
@@ -26,105 +28,11 @@ import (
|
||||
"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 SSharableBaseResourceManager struct{}
|
||||
|
||||
func (manager *SSharableBaseResourceManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if owner != nil {
|
||||
switch scope {
|
||||
case rbacutils.ScopeProject, rbacutils.ScopeDomain:
|
||||
if len(owner.GetProjectDomainId()) > 0 {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
type SSharableBaseResource struct {
|
||||
IsPublic bool `default:"false" nullable:"false" list:"user"`
|
||||
}
|
||||
|
||||
type ISharableBase interface {
|
||||
IModel
|
||||
SetIsPublic(pub bool)
|
||||
GetIsPublic() bool
|
||||
}
|
||||
|
||||
func (m *SSharableBaseResource) IsSharable(ownerId mcclient.IIdentityProvider) bool {
|
||||
return m.IsPublic
|
||||
}
|
||||
|
||||
func (m *SSharableBaseResource) SetIsPublic(pub bool) {
|
||||
m.IsPublic = pub
|
||||
}
|
||||
|
||||
func (m SSharableBaseResource) GetIsPublic() bool {
|
||||
return m.IsPublic
|
||||
}
|
||||
|
||||
func SharableAllowPerformPublic(model ISharableBase, userCred mcclient.TokenCredential) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "public")
|
||||
}
|
||||
|
||||
func SharablePerformPublic(model ISharableBase, ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if model.GetIsPublic() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
|
||||
/*ownerId := model.GetOwnerId()
|
||||
if userCred.GetProjectDomainId() != ownerId.GetProjectDomainId() {
|
||||
return nil, httperrors.NewForbiddenError("not owner")
|
||||
}*/
|
||||
|
||||
diff, err := Update(model, func() error {
|
||||
model.SetIsPublic(true)
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
OpsLog.LogEvent(model, ACT_UPDATE, diff, userCred)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func SharableAllowPerformPrivate(model ISharableBase, userCred mcclient.TokenCredential) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "private")
|
||||
}
|
||||
|
||||
func SharablePerformPrivate(model ISharableBase, ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if !model.GetIsPublic() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
|
||||
/*ownerId := model.GetOwnerId()
|
||||
if userCred.GetProjectDomainId() != ownerId.GetProjectDomainId() {
|
||||
return nil, httperrors.NewForbiddenError("not owner")
|
||||
}*/
|
||||
|
||||
diff, err := Update(model, func() error {
|
||||
model.SetIsPublic(false)
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
OpsLog.LogEvent(model, ACT_UPDATE, diff, userCred)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (manager *SSharableBaseResourceManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
@@ -138,5 +46,337 @@ func (manager *SSharableBaseResourceManager) ListItemFilter(
|
||||
q = q.IsFalse("is_public")
|
||||
}
|
||||
}
|
||||
if len(query.PublicScope) > 0 {
|
||||
q = q.Equals("public_scope", query.PublicScope)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SSharableBaseResourceManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []apis.SharableResourceBaseInfo {
|
||||
rows := make([]apis.SharableResourceBaseInfo, len(objs))
|
||||
|
||||
var resType string
|
||||
resIds := make([]string, len(rows))
|
||||
var sharedTarget string
|
||||
for i := range rows {
|
||||
if model, ok := objs[i].(ISharableBaseModel); ok {
|
||||
if len(resType) == 0 {
|
||||
resType = model.Keyword()
|
||||
}
|
||||
if len(sharedTarget) == 0 {
|
||||
sharedTarget = string(model.GetModelManager().ResourceScope())
|
||||
}
|
||||
resIds[i] = model.GetId()
|
||||
}
|
||||
}
|
||||
|
||||
q := SharedResourceManager.Query()
|
||||
q = q.Equals("resource_type", resType)
|
||||
q = q.Equals("target_type", sharedTarget)
|
||||
|
||||
sharedResourceMap := make(map[string][]SSharedResource)
|
||||
err := FetchQueryObjectsByIds(q, "resource_id", resIds, &sharedResourceMap)
|
||||
if err != nil {
|
||||
log.Errorf("FetchQueryObjectsByIds for shared resource fail %s", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
targetIds := stringutils2.NewSortedStrings([]string{})
|
||||
|
||||
for _, srs := range sharedResourceMap {
|
||||
for _, sr := range srs {
|
||||
targetIds = stringutils2.Append(targetIds, sr.TargetProjectId)
|
||||
}
|
||||
}
|
||||
|
||||
if len(targetIds) == 0 {
|
||||
return rows
|
||||
}
|
||||
|
||||
tenantMap := make(map[string]STenant)
|
||||
var subq *sqlchemy.SQuery
|
||||
switch sharedTarget {
|
||||
case SharedTargetProject:
|
||||
subq = TenantCacheManager.GetTenantQuery()
|
||||
case SharedTargetDomain:
|
||||
subq = TenantCacheManager.GetDomainQuery()
|
||||
}
|
||||
|
||||
err = FetchQueryObjectsByIds(subq, "id", targetIds, &tenantMap)
|
||||
if err != nil {
|
||||
log.Errorf("FetchQueryObjectsByIds for tenant_cache fail %s", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
for i := range rows {
|
||||
resId := resIds[i]
|
||||
if srs, ok := sharedResourceMap[resId]; ok {
|
||||
switch sharedTarget {
|
||||
case SharedTargetProject:
|
||||
projects := make([]apis.SharedProject, len(srs))
|
||||
for si, sr := range srs {
|
||||
projects[si].Id = sr.TargetProjectId
|
||||
if tenant, ok := tenantMap[sr.TargetProjectId]; ok {
|
||||
projects[si].Name = tenant.Name
|
||||
projects[si].Domain = tenant.Domain
|
||||
projects[si].DomainId = tenant.DomainId
|
||||
}
|
||||
}
|
||||
rows[i].SharedProjects = projects
|
||||
case SharedTargetDomain:
|
||||
domains := make([]apis.SharedDomain, len(srs))
|
||||
for si, sr := range srs {
|
||||
domains[si].Id = sr.TargetProjectId
|
||||
if tenant, ok := tenantMap[sr.TargetProjectId]; ok {
|
||||
domains[si].Name = tenant.Name
|
||||
}
|
||||
}
|
||||
rows[i].SharedDomains = domains
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func SharableManagerFilterByOwner(manager IStandaloneModelManager, q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if owner != nil {
|
||||
resScope := manager.ResourceScope()
|
||||
if resScope == rbacutils.ScopeProject && scope == rbacutils.ScopeProject {
|
||||
ownerProjectId := owner.GetProjectId()
|
||||
if len(ownerProjectId) > 0 {
|
||||
subq := SharedResourceManager.Query("resource_id")
|
||||
subq = subq.Equals("resource_type", manager.Keyword())
|
||||
subq = subq.Equals("target_project_id", ownerProjectId)
|
||||
subq = subq.Equals("target_type", SharedTargetProject)
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("tenant_id"), ownerProjectId),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
|
||||
),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeDomain),
|
||||
sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
|
||||
),
|
||||
sqlchemy.In(q.Field("id"), subq.SubQuery()),
|
||||
))
|
||||
}
|
||||
} else if (resScope == rbacutils.ScopeDomain && (scope == rbacutils.ScopeProject || scope == rbacutils.ScopeDomain)) || (resScope == rbacutils.ScopeProject && scope == rbacutils.ScopeDomain) {
|
||||
ownerDomainId := owner.GetProjectDomainId()
|
||||
if len(ownerDomainId) > 0 {
|
||||
subq := SharedResourceManager.Query("resource_id")
|
||||
subq = subq.Equals("resource_type", manager.Keyword())
|
||||
subq = subq.Equals("target_project_id", ownerDomainId)
|
||||
subq = subq.Equals("target_type", SharedTargetDomain)
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("domain_id"), ownerDomainId),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
|
||||
),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.In(q.Field("id"), subq.SubQuery()),
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
type SSharableBaseResource struct {
|
||||
// 是否共享
|
||||
IsPublic bool `default:"false" nullable:"false" list:"user"`
|
||||
// 默认共享范围
|
||||
PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" list:"user"`
|
||||
}
|
||||
|
||||
type ISharableBaseModel interface {
|
||||
IStandaloneModel
|
||||
ISharableBase
|
||||
}
|
||||
|
||||
type ISharableBase interface {
|
||||
SetShare(pub bool, scoe rbacutils.TRbacScope)
|
||||
GetIsPublic() bool
|
||||
GetPublicScope() rbacutils.TRbacScope
|
||||
}
|
||||
|
||||
func SharableModelIsSharable(model ISharableBaseModel, reqUsrId mcclient.IIdentityProvider) bool {
|
||||
if model.GetIsPublic() && model.GetPublicScope() == rbacutils.ScopeSystem {
|
||||
return true
|
||||
}
|
||||
ownerId := model.GetOwnerId()
|
||||
if model.GetIsPublic() && model.GetPublicScope() == rbacutils.ScopeDomain {
|
||||
if ownerId != nil && ownerId.GetProjectDomainId() == reqUsrId.GetProjectDomainId() {
|
||||
return true
|
||||
}
|
||||
q := SharedResourceManager.Query().Equals("resource_id", model.GetId())
|
||||
q = q.Equals("resource_type", model.Keyword())
|
||||
q = q.Equals("target_project_id", reqUsrId.GetProjectDomainId())
|
||||
q = q.Equals("target_type", SharedTargetDomain)
|
||||
cnt, _ := q.CountWithError()
|
||||
if cnt > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if model.GetPublicScope() == rbacutils.ScopeProject {
|
||||
if ownerId != nil && ownerId.GetProjectId() == reqUsrId.GetProjectId() {
|
||||
return true
|
||||
}
|
||||
q := SharedResourceManager.Query().Equals("resource_id", model.GetId())
|
||||
q = q.Equals("resource_type", model.Keyword())
|
||||
q = q.Equals("target_project_id", reqUsrId.GetProjectId())
|
||||
q = q.Equals("target_type", SharedTargetProject)
|
||||
cnt, _ := q.CountWithError()
|
||||
if cnt > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *SSharableBaseResource) SetShare(pub bool, scope rbacutils.TRbacScope) {
|
||||
m.IsPublic = pub
|
||||
m.PublicScope = string(scope)
|
||||
}
|
||||
|
||||
func (m SSharableBaseResource) GetIsPublic() bool {
|
||||
return m.IsPublic
|
||||
}
|
||||
|
||||
func (m SSharableBaseResource) GetPublicScope() rbacutils.TRbacScope {
|
||||
return rbacutils.String2Scope(m.PublicScope)
|
||||
}
|
||||
|
||||
func SharablePerformPublic(model ISharableBaseModel, ctx context.Context, userCred mcclient.TokenCredential, input apis.PerformPublicInput) error {
|
||||
var err error
|
||||
|
||||
resourceScope := model.GetModelManager().ResourceScope()
|
||||
targetScope := rbacutils.String2ScopeDefault(input.Scope, rbacutils.ScopeSystem)
|
||||
if resourceScope.HigherThan(targetScope) {
|
||||
return errors.Wrapf(httperrors.ErrNotSupported, "cannot share %s resource to %s", resourceScope, targetScope)
|
||||
}
|
||||
|
||||
shareResult := apis.PerformPublicInput{
|
||||
Scope: string(targetScope),
|
||||
}
|
||||
|
||||
switch targetScope {
|
||||
case rbacutils.ScopeProject:
|
||||
if len(input.SharedProjects) == 0 {
|
||||
return errors.Wrap(httperrors.ErrEmptyRequest, "empty shared target project list")
|
||||
}
|
||||
shareResult.SharedProjects, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetProject, input.SharedProjects)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "shareToTarget")
|
||||
}
|
||||
case rbacutils.ScopeDomain:
|
||||
_, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetProject, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "shareToTarget clean projects")
|
||||
}
|
||||
shareResult.SharedDomains, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetDomain, input.SharedDomains)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "shareToTarget add domains")
|
||||
}
|
||||
case rbacutils.ScopeSystem:
|
||||
_, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetProject, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "shareToTarget clean projects")
|
||||
}
|
||||
_, err = SharedResourceManager.shareToTarget(ctx, userCred, model, SharedTargetDomain, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "shareToTarget clean domainss")
|
||||
}
|
||||
}
|
||||
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
if targetScope.HigherThan(allowScope) {
|
||||
return errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", targetScope, allowScope)
|
||||
}
|
||||
|
||||
_, err = Update(model, func() error {
|
||||
model.SetShare(true, targetScope)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Update")
|
||||
}
|
||||
|
||||
OpsLog.LogEvent(model, ACT_PUBLIC, shareResult, userCred)
|
||||
|
||||
model.GetIStandaloneModel().ClearSchedDescCache()
|
||||
return nil
|
||||
}
|
||||
|
||||
func SharablePerformPrivate(model ISharableBaseModel, ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
if !model.GetIsPublic() {
|
||||
return nil
|
||||
}
|
||||
|
||||
requireScope := model.GetPublicScope()
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
|
||||
if requireScope.HigherThan(allowScope) {
|
||||
return errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", requireScope, allowScope)
|
||||
}
|
||||
|
||||
err := SharedResourceManager.CleanModelShares(ctx, userCred, model)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "CleanModelShares")
|
||||
}
|
||||
|
||||
diff, err := Update(model, func() error {
|
||||
model.SetShare(false, rbacutils.ScopeNone)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Update")
|
||||
}
|
||||
|
||||
OpsLog.LogEvent(model, ACT_PRIVATE, diff, userCred)
|
||||
|
||||
model.GetIStandaloneModel().ClearSchedDescCache()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SharableGetSharedProjects(model ISharableBaseModel, targetType string) []string {
|
||||
sharedResources := make([]SSharedResource, 0)
|
||||
q := SharedResourceManager.Query()
|
||||
q = q.Equals("resource_type", model.Keyword())
|
||||
q = q.Equals("resource_id", model.GetId())
|
||||
q = q.Equals("target_type", targetType)
|
||||
err := q.All(&sharedResources)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
res := make([]string, len(sharedResources))
|
||||
for i := range sharedResources {
|
||||
res[i] = sharedResources[i].TargetProjectId
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func SharableModelIsShared(model ISharableBaseModel) bool {
|
||||
q := SharedResourceManager.Query()
|
||||
q = q.Equals("resource_type", model.Keyword())
|
||||
q = q.Equals("resource_id", model.GetId())
|
||||
cnt, _ := q.CountWithError()
|
||||
if cnt > 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -18,14 +18,10 @@ import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
@@ -34,13 +30,14 @@ import (
|
||||
|
||||
type SSharableVirtualResourceBase struct {
|
||||
SVirtualResourceBase
|
||||
|
||||
IsPublic bool `default:"false" nullable:"false" create:"domain_optional" list:"user" json:"is_public"`
|
||||
PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" create:"domain_optional" list:"user" json:"public_scope"`
|
||||
SSharableBaseResource
|
||||
// IsPublic bool `default:"false" nullable:"false" create:"domain_optional" list:"user" json:"is_public"`
|
||||
// PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" create:"domain_optional" list:"user" json:"public_scope"`
|
||||
}
|
||||
|
||||
type SSharableVirtualResourceBaseManager struct {
|
||||
SVirtualResourceBaseManager
|
||||
SSharableBaseResourceManager
|
||||
}
|
||||
|
||||
func NewSharableVirtualResourceBaseManager(dt interface{}, tableName string, keyword string, keywordPlural string) SSharableVirtualResourceBaseManager {
|
||||
@@ -52,196 +49,42 @@ func (manager *SSharableVirtualResourceBaseManager) GetISharableVirtualModelMana
|
||||
}
|
||||
|
||||
func (manager *SSharableVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
if owner != nil {
|
||||
switch scope {
|
||||
case rbacutils.ScopeProject:
|
||||
ownerProjectid := owner.GetProjectId()
|
||||
if len(ownerProjectid) > 0 {
|
||||
subq := SharedResourceManager.Query("resource_id")
|
||||
subq = subq.Equals("resource_type", manager.Keyword())
|
||||
subq = subq.Equals("target_project_id", ownerProjectid)
|
||||
subq = subq.Equals("owner_project_id", q.Field("tenant_id"))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("tenant_id"), ownerProjectid),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
|
||||
),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeDomain),
|
||||
sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
|
||||
),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsFalse(q.Field("is_public")),
|
||||
sqlchemy.In(q.Field("id"), subq.SubQuery()),
|
||||
),
|
||||
))
|
||||
}
|
||||
case rbacutils.ScopeDomain:
|
||||
if len(owner.GetProjectDomainId()) > 0 {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
|
||||
sqlchemy.AND(
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
return SharableManagerFilterByOwner(manager.GetISharableVirtualModelManager(), q, owner, scope)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return model.IsOwner(userCred) || model.IsPublic || IsAllowGet(rbacutils.ScopeSystem, userCred, model)
|
||||
return model.IsOwner(userCred) || model.IsSharable(userCred) || IsAllowGet(rbacutils.ScopeSystem, userCred, model)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) IsSharable(reqUsrId mcclient.IIdentityProvider) bool {
|
||||
if model.IsPublic {
|
||||
switch rbacutils.String2Scope(model.PublicScope) {
|
||||
case rbacutils.ScopeSystem:
|
||||
return true
|
||||
case rbacutils.ScopeDomain:
|
||||
ownerId := model.GetOwnerId()
|
||||
if ownerId != nil && ownerId.GetProjectDomainId() == reqUsrId.GetProjectDomainId() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
return SharableModelIsSharable(model.GetISharableVirtualModel(), reqUsrId)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformProjectPublicInput) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "public")
|
||||
func (model *SSharableVirtualResourceBase) IsShared() bool {
|
||||
return SharableModelIsShared(model)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformProjectPublicInput) (jsonutils.JSONObject, error) {
|
||||
targetScope := rbacutils.String2ScopeDefault(input.Scope, rbacutils.ScopeSystem)
|
||||
if targetScope == rbacutils.ScopeProject {
|
||||
if len(input.SharedProjects) > 0 {
|
||||
delProjects := make([]*SSharedResource, 0)
|
||||
addProjects := make([]string, 0)
|
||||
ops := make(map[string]*SSharedResource, 0)
|
||||
nps := make([]string, 0)
|
||||
srs := make([]SSharedResource, 0)
|
||||
q := SharedResourceManager.Query()
|
||||
err := q.Filter(sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("owner_project_id"), model.ProjectId),
|
||||
sqlchemy.Equals(q.Field("resource_id"), model.GetId()),
|
||||
sqlchemy.Equals(q.Field("resource_type"), model.GetModelManager().Keyword()),
|
||||
)).All(&srs)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("Fetch project error %s", err)
|
||||
}
|
||||
for i := 0; i < len(srs); i++ {
|
||||
ops[srs[i].TargetProjectId] = &srs[i]
|
||||
}
|
||||
for i := 0; i < len(input.SharedProjects); i++ {
|
||||
sharedProject := input.SharedProjects[i]
|
||||
tenant, err := TenantCacheManager.FetchTenantByIdOrName(ctx, sharedProject)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewBadRequestError("fetch tenant %s error %s", sharedProject, err)
|
||||
}
|
||||
if tenant.DomainId != model.DomainId {
|
||||
return nil, httperrors.NewBadRequestError("can't shared project to other domain")
|
||||
}
|
||||
if tenant.GetId() == model.ProjectId {
|
||||
return nil, httperrors.NewBadRequestError("Can't share project to yourself")
|
||||
}
|
||||
nps = append(nps, tenant.GetId())
|
||||
if _, ok := ops[tenant.GetId()]; !ok {
|
||||
addProjects = append(addProjects, tenant.GetId())
|
||||
}
|
||||
}
|
||||
for k, v := range ops {
|
||||
if !utils.IsInStringArray(k, nps) {
|
||||
delProjects = append(delProjects, v)
|
||||
}
|
||||
}
|
||||
func (model *SSharableVirtualResourceBase) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicInput) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
for i := 0; i < len(addProjects); i++ {
|
||||
sharedResource := new(SSharedResource)
|
||||
sharedResource.ResourceType = model.GetModelManager().Keyword()
|
||||
sharedResource.ResourceId = model.Id
|
||||
sharedResource.OwnerProjectId = model.ProjectId
|
||||
sharedResource.TargetProjectId = addProjects[i]
|
||||
if insetErr := SharedResourceManager.TableSpec().Insert(sharedResource); insetErr != nil {
|
||||
return nil, httperrors.NewInternalServerError("Insert shared resource failed %s", insetErr)
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(delProjects); i++ {
|
||||
delProjects[i].SetModelManager(SharedResourceManager, delProjects[i])
|
||||
if err := delProjects[i].Delete(ctx, userCred); err != nil {
|
||||
return nil, httperrors.NewInternalServerError("Unshare project failed %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if (len(addProjects) + len(srs) - len(delProjects)) > 0 {
|
||||
diff, err := Update(model, func() error {
|
||||
model.IsPublic = false
|
||||
model.PublicScope = string(targetScope)
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
OpsLog.LogEvent(model, ACT_UPDATE, diff, userCred)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, httperrors.NewMissingParameterError("shared_projects")
|
||||
}
|
||||
} else {
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
if targetScope.HigherThan(allowScope) {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
if targetScope != rbacutils.ScopeSystem && targetScope != rbacutils.ScopeDomain {
|
||||
return nil, httperrors.NewInputParameterError("invalid scope %s", targetScope)
|
||||
}
|
||||
diff, err := Update(model, func() error {
|
||||
model.IsPublic = true
|
||||
model.PublicScope = string(targetScope)
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
OpsLog.LogEvent(model, ACT_UPDATE, diff, userCred)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
func (model *SSharableVirtualResourceBase) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicInput) (jsonutils.JSONObject, error) {
|
||||
err := SharablePerformPublic(model, ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SharablePerformPublic")
|
||||
}
|
||||
model.GetIStandaloneModel().ClearSchedDescCache()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformProjectPrivateInput) bool {
|
||||
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "private")
|
||||
func (model *SSharableVirtualResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformProjectPrivateInput) (jsonutils.JSONObject, error) {
|
||||
if model.IsPublic {
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
|
||||
requireScope := rbacutils.String2ScopeDefault(model.PublicScope, rbacutils.ScopeSystem)
|
||||
if requireScope.HigherThan(allowScope) {
|
||||
return nil, httperrors.NewForbiddenError("not enough privileges: allow %s require %s", allowScope, requireScope)
|
||||
}
|
||||
diff, err := Update(model, func() error {
|
||||
model.PublicScope = string(rbacutils.ScopeNone)
|
||||
model.IsPublic = false
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
OpsLog.LogEvent(model, ACT_UPDATE, diff, userCred)
|
||||
} else {
|
||||
return nil, httperrors.NewInternalServerError("Update shared resource error: %s", err)
|
||||
}
|
||||
func (model *SSharableVirtualResourceBase) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
|
||||
err := SharablePerformPrivate(model, ctx, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SharablePerformPrivate")
|
||||
}
|
||||
|
||||
if err := SharedResourceManager.CleanModelSharedProjects(ctx, userCred, &model.SVirtualResourceBase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
model.GetIStandaloneModel().ClearSchedDescCache()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -249,34 +92,6 @@ func (model *SSharableVirtualResourceBase) GetISharableVirtualModel() ISharableV
|
||||
return model.GetVirtualObject().(ISharableVirtualModel)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) GetSharedProjects() []string {
|
||||
sharedResources := make([]SSharedResource, 0)
|
||||
res := make([]string, 0)
|
||||
SharedResourceManager.Query().Equals("resource_type", model.GetModelManager().Keyword()).Equals("resource_id", model.GetId()).All(&sharedResources)
|
||||
for i := 0; i < len(sharedResources); i++ {
|
||||
res = append(res, sharedResources[i].TargetProjectId)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/*func (model *SSharableVirtualResourceBase) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, out apis.SharableVirtualResourceDetails) apis.SharableVirtualResourceDetails {
|
||||
out.SharedProjects = []apis.SharedProject{}
|
||||
projects := model.GetSharedProjects()
|
||||
for i := 0; i < len(projects); i++ {
|
||||
tenant, err := TenantCacheManager.FetchTenantByIdOrName(ctx, projects[i])
|
||||
if err != nil {
|
||||
log.Errorf("failed fetch tenant by id %s", projects[i])
|
||||
continue
|
||||
}
|
||||
project := apis.SharedProject{
|
||||
Id: tenant.GetId(),
|
||||
Name: tenant.GetName(),
|
||||
}
|
||||
out.SharedProjects = append(out.SharedProjects, project)
|
||||
}
|
||||
return out
|
||||
}*/
|
||||
|
||||
func (manager *SSharableVirtualResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.SharableVirtualResourceCreateInput) (apis.SharableVirtualResourceCreateInput, error) {
|
||||
var err error
|
||||
input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
|
||||
@@ -296,15 +111,9 @@ func (manager *SSharableVirtualResourceBaseManager) ListItemFilter(
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if query.IsPublic != nil {
|
||||
if *query.IsPublic {
|
||||
q = q.IsTrue("is_public")
|
||||
} else {
|
||||
q = q.IsFalse("is_public")
|
||||
}
|
||||
}
|
||||
if len(query.PublicScope) > 0 {
|
||||
q = q.Equals("public_scope", query.PublicScope)
|
||||
q, err = manager.SSharableBaseResourceManager.ListItemFilter(ctx, q, userCred, query.SharableResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SSharableBaseResourceManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
@@ -337,33 +146,51 @@ func (manager *SSharableVirtualResourceBaseManager) FetchCustomizeColumns(
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []apis.SharableVirtualResourceDetails {
|
||||
|
||||
rows := make([]apis.SharableVirtualResourceDetails, len(objs))
|
||||
|
||||
virtRows := manager.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
resIds := make([]string, len(objs))
|
||||
shareRows := manager.SSharableBaseResourceManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
resIds[i] = objs[i].(ISharableVirtualModel).GetId()
|
||||
rows[i] = apis.SharableVirtualResourceDetails{
|
||||
VirtualResourceDetails: virtRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
tenants := TenantCacheManager.GetTenantQuery().SubQuery()
|
||||
resources := SharedResourceManager.Query().Equals("resource_type", manager.Keyword()).SubQuery()
|
||||
q := tenants.Query(tenants.Field("id"), tenants.Field("name"), resources.Field("resource_id"))
|
||||
q = q.Join(resources, sqlchemy.Equals(q.Field("id"), resources.Field("target_project_id")))
|
||||
projList := make(map[string][]apis.SharedProject)
|
||||
err := FetchQueryObjectsByIds(q, "resource_id", resIds, &projList)
|
||||
if err != nil {
|
||||
log.Errorf("FetchQueryObjectsByIds fail %s", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
for i := range rows {
|
||||
if projs, ok := projList[resIds[i]]; ok {
|
||||
rows[i].SharedProjects = projs
|
||||
VirtualResourceDetails: virtRows[i],
|
||||
SharableResourceBaseInfo: shareRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.SharableVirtualResourceBaseUpdateInput,
|
||||
) (apis.SharableVirtualResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.VirtualResourceBaseUpdateInput, err = model.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) GetSharedProjects() []string {
|
||||
return SharableGetSharedProjects(model, SharedTargetProject)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) GetSharedDomains() []string {
|
||||
return SharableGetSharedProjects(model, SharedTargetDomain)
|
||||
}
|
||||
|
||||
func (model *SSharableVirtualResourceBase) PerformChangeOwner(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.PerformChangeProjectOwnerInput,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
if model.IsShared() {
|
||||
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "cannot change owner when shared!")
|
||||
}
|
||||
return model.SVirtualResourceBase.PerformChangeOwner(ctx, userCred, query, input)
|
||||
}
|
||||
|
||||
@@ -16,14 +16,24 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/sqlchemy"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"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"
|
||||
)
|
||||
|
||||
// sharing resoure between project
|
||||
const (
|
||||
SharedTargetProject = "project"
|
||||
SharedTargetDomain = "domain"
|
||||
)
|
||||
|
||||
// sharing resource between projects/domains
|
||||
type SSharedResource struct {
|
||||
SResourceBase
|
||||
|
||||
@@ -33,6 +43,8 @@ type SSharedResource struct {
|
||||
ResourceId string `width:"128" charset:"ascii" nullable:"false" index:"true" list:"user" json:"resource_id"`
|
||||
OwnerProjectId string `width:"128" charset:"ascii" nullable:"false" index:"true" list:"user" json:"owner_project_id"`
|
||||
TargetProjectId string `width:"128" charset:"ascii" nullable:"false" index:"true" list:"user" json:"target_project_id"`
|
||||
|
||||
TargetType string `width:"8" charset:"ascii" default:"project" nullable:"false" list:"user" json:"target_type"`
|
||||
}
|
||||
|
||||
type SSharedResourceManager struct {
|
||||
@@ -52,22 +64,132 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SSharedResourceManager) CleanModelSharedProjects(ctx context.Context, userCred mcclient.TokenCredential, model *SVirtualResourceBase) error {
|
||||
srs := make([]SSharedResource, 0)
|
||||
q := manager.Query()
|
||||
err := q.Filter(sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("owner_project_id"), model.ProjectId),
|
||||
sqlchemy.Equals(q.Field("resource_id"), model.GetId()),
|
||||
sqlchemy.Equals(q.Field("resource_type"), model.GetModelManager().Keyword()),
|
||||
)).All(&srs)
|
||||
if err != nil {
|
||||
return httperrors.NewInternalServerError("Fetch project error %s", err)
|
||||
}
|
||||
for i := 0; i < len(srs); i++ {
|
||||
srs[i].SetModelManager(manager, &srs[i])
|
||||
if err := srs[i].Delete(ctx, userCred); err != nil {
|
||||
return httperrors.NewInternalServerError("Unshare project failed %s", err)
|
||||
func (manager *SSharedResourceManager) CleanModelShares(ctx context.Context, userCred mcclient.TokenCredential, model ISharableBaseModel) error {
|
||||
var err error
|
||||
resScope := model.GetModelManager().ResourceScope()
|
||||
switch resScope {
|
||||
case rbacutils.ScopeProject:
|
||||
_, err = manager.shareToTarget(ctx, userCred, model, SharedTargetProject, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "remove shared project")
|
||||
}
|
||||
_, err = manager.shareToTarget(ctx, userCred, model, SharedTargetDomain, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "remove shared domain")
|
||||
}
|
||||
case rbacutils.ScopeDomain:
|
||||
_, err = manager.shareToTarget(ctx, userCred, model, SharedTargetDomain, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "remove shared domain")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SSharedResourceManager) shareToTarget(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
model ISharableBaseModel,
|
||||
targetType string,
|
||||
targetIds []string,
|
||||
) ([]string, error) {
|
||||
var requireScope rbacutils.TRbacScope
|
||||
resScope := model.GetModelManager().ResourceScope()
|
||||
switch resScope {
|
||||
case rbacutils.ScopeProject:
|
||||
switch targetType {
|
||||
case SharedTargetProject:
|
||||
// should have domain-level privileges
|
||||
// cannot share to a project across domain
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
case SharedTargetDomain:
|
||||
// should have system-level privileges
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
}
|
||||
case rbacutils.ScopeDomain:
|
||||
switch targetType {
|
||||
case SharedTargetDomain:
|
||||
// should have system-level privileges
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
case SharedTargetProject:
|
||||
return nil, errors.Wrap(httperrors.ErrNotSupported, "cannot share a domain resource to specific project")
|
||||
}
|
||||
default:
|
||||
return nil, errors.Wrap(httperrors.ErrNotSupported, "cannot share a non-project/domain resource")
|
||||
}
|
||||
|
||||
srs := make([]SSharedResource, 0)
|
||||
q := SharedResourceManager.Query()
|
||||
q = q.Equals("resource_type", model.Keyword())
|
||||
q = q.Equals("resource_id", model.GetId())
|
||||
q = q.Equals("target_type", targetType)
|
||||
err := FetchModelObjects(SharedResourceManager, q, &srs)
|
||||
if err != nil && errors.Cause(err) != sql.ErrNoRows {
|
||||
return nil, errors.Wrap(err, "Fetch shared project")
|
||||
}
|
||||
srsMap := make(map[string]*SSharedResource)
|
||||
_existIds := make([]string, len(srs))
|
||||
for i := 0; i < len(srs); i++ {
|
||||
_existIds[i] = srs[i].TargetProjectId
|
||||
srsMap[srs[i].TargetProjectId] = &srs[i]
|
||||
}
|
||||
existIds := stringutils2.NewSortedStrings(_existIds)
|
||||
|
||||
newIds := stringutils2.NewSortedStrings([]string{})
|
||||
modelOwnerId := model.GetOwnerId()
|
||||
for i := 0; i < len(targetIds); i++ {
|
||||
switch targetType {
|
||||
case SharedTargetProject:
|
||||
tenant, err := TenantCacheManager.FetchTenantByIdOrName(ctx, targetIds[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fetch tenant %s error", targetIds[i])
|
||||
}
|
||||
if tenant.DomainId != modelOwnerId.GetProjectDomainId() {
|
||||
return nil, httperrors.NewBadRequestError("can't shared project to other domain")
|
||||
}
|
||||
if tenant.GetId() == modelOwnerId.GetProjectId() {
|
||||
return nil, httperrors.NewBadRequestError("can't share to self project")
|
||||
}
|
||||
newIds = stringutils2.Append(newIds, tenant.GetId())
|
||||
case SharedTargetDomain:
|
||||
domain, err := TenantCacheManager.FetchDomainByIdOrName(ctx, targetIds[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fetch domain %s error", targetIds[i])
|
||||
}
|
||||
if domain.GetId() == modelOwnerId.GetProjectDomainId() {
|
||||
return nil, httperrors.NewBadRequestError("can't share to self domain")
|
||||
}
|
||||
newIds = stringutils2.Append(newIds, domain.GetId())
|
||||
}
|
||||
}
|
||||
delIds, keepIds, addIds := stringutils2.Split(existIds, newIds)
|
||||
|
||||
if len(delIds) == 0 && len(addIds) == 0 {
|
||||
return keepIds, nil
|
||||
}
|
||||
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
if requireScope.HigherThan(allowScope) {
|
||||
return nil, errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", requireScope, allowScope)
|
||||
}
|
||||
|
||||
for _, targetId := range delIds {
|
||||
sr := srsMap[targetId]
|
||||
if err := sr.Delete(ctx, userCred); err != nil {
|
||||
return nil, errors.Wrap(err, "delete")
|
||||
}
|
||||
}
|
||||
for _, targetId := range addIds {
|
||||
sharedResource := new(SSharedResource)
|
||||
sharedResource.ResourceType = model.Keyword()
|
||||
sharedResource.ResourceId = model.GetId()
|
||||
sharedResource.TargetProjectId = targetId
|
||||
sharedResource.TargetType = targetType
|
||||
if insetErr := SharedResourceManager.TableSpec().Insert(sharedResource); insetErr != nil {
|
||||
return nil, httperrors.NewInternalServerError("Insert shared resource failed %s", insetErr)
|
||||
}
|
||||
}
|
||||
|
||||
keepIds = append(keepIds, addIds...)
|
||||
return keepIds, nil
|
||||
}
|
||||
|
||||
@@ -572,3 +572,23 @@ func (manager *SStandaloneResourceBaseManager) ListItemExportKeys(ctx context.Co
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.StandaloneResourceBaseUpdateInput) (apis.StandaloneResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.ResourceBaseUpdateInput, err = model.SResourceBase.ValidateUpdateData(ctx, userCred, query, input.ResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SModelBase.ValidateUpdateData")
|
||||
}
|
||||
|
||||
if len(input.Name) > 0 {
|
||||
err = alterNameValidator(model.GetIStandaloneModel(), input.Name)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "alterNameValidator")
|
||||
}
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) IsShared() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -39,22 +39,22 @@ type SStatusResourceBase struct {
|
||||
type IStatusBase interface {
|
||||
IModel
|
||||
SetStatusValue(status string)
|
||||
GetStatusValue() string
|
||||
GetStatus() string
|
||||
}
|
||||
|
||||
func (model *SStatusResourceBase) SetStatusValue(status string) {
|
||||
model.Status = status
|
||||
}
|
||||
|
||||
func (model SStatusResourceBase) GetStatusValue() string {
|
||||
func (model SStatusResourceBase) GetStatus() string {
|
||||
return model.Status
|
||||
}
|
||||
|
||||
func statusBaseSetStatus(model IStatusBase, userCred mcclient.TokenCredential, status string, reason string) error {
|
||||
if model.GetStatusValue() == status {
|
||||
if model.GetStatus() == status {
|
||||
return nil
|
||||
}
|
||||
oldStatus := model.GetStatusValue()
|
||||
oldStatus := model.GetStatus()
|
||||
_, err := Update(model, func() error {
|
||||
model.SetStatusValue(status)
|
||||
return nil
|
||||
|
||||
@@ -146,3 +146,17 @@ func (model *SStatusDomainLevelResourceBase) GetExtraDetails(
|
||||
) (apis.StatusDomainLevelResourceDetails, error) {
|
||||
return apis.StatusDomainLevelResourceDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SStatusDomainLevelResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.StatusDomainLevelResourceBaseUpdateInput,
|
||||
) (apis.StatusDomainLevelResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.DomainLevelResourceBaseUpdateInput, err = model.SDomainLevelResourceBase.ValidateUpdateData(ctx, userCred, query, input.DomainLevelResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SDomainLevelResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
// 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 db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SStatusInfrasResourceBase struct {
|
||||
SInfrasResourceBase
|
||||
SStatusResourceBase
|
||||
}
|
||||
|
||||
type SStatusInfrasResourceBaseManager struct {
|
||||
SInfrasResourceBaseManager
|
||||
SStatusResourceBaseManager
|
||||
}
|
||||
|
||||
func NewStatusInfrasResourceBaseManager(dt interface{}, tableName string, keyword string, keywordPlural string) SStatusInfrasResourceBaseManager {
|
||||
return SStatusInfrasResourceBaseManager{
|
||||
SInfrasResourceBaseManager: NewInfrasResourceBaseManager(dt, tableName, keyword, keywordPlural),
|
||||
}
|
||||
}
|
||||
|
||||
func (model *SStatusInfrasResourceBase) AllowGetDetailsStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return model.IsOwner(userCred) || IsDomainAllowGetSpec(userCred, model, "status")
|
||||
}
|
||||
|
||||
func (self *SStatusInfrasResourceBase) AllowPerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformStatusInput) bool {
|
||||
return IsDomainAllowPerform(userCred, self, "status")
|
||||
}
|
||||
|
||||
func (self *SStatusInfrasResourceBase) PerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformStatusInput) (jsonutils.JSONObject, error) {
|
||||
err := StatusBasePerformStatus(self, userCred, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "StatusBasePerformStatus")
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (model *SStatusInfrasResourceBase) SetStatus(userCred mcclient.TokenCredential, status string, reason string) error {
|
||||
return statusBaseSetStatus(model, userCred, status, reason)
|
||||
}
|
||||
|
||||
func (manager *SStatusInfrasResourceBaseManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.StatusInfrasResourceBaseCreateInput,
|
||||
) (apis.StatusInfrasResourceBaseCreateInput, error) {
|
||||
var err error
|
||||
input.InfrasResourceBaseCreateInput, err = manager.SInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.InfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SInfrasResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SStatusInfrasResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query apis.StatusInfrasResourceBaseListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.InfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SStatusResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SStatusInfrasResourceBaseManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query apis.StatusInfrasResourceBaseListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.InfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SInfrasResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SStatusResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStatusResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SStatusInfrasResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SStatusInfrasResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []apis.StatusInfrasResourceBaseDetails {
|
||||
rows := make([]apis.StatusInfrasResourceBaseDetails, len(objs))
|
||||
infRows := manager.SInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = apis.StatusInfrasResourceBaseDetails{
|
||||
InfrasResourceBaseDetails: infRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (model *SStatusInfrasResourceBase) GetExtraDetails(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
isList bool,
|
||||
) (apis.StatusInfrasResourceBaseDetails, error) {
|
||||
return apis.StatusInfrasResourceBaseDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SStatusInfrasResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.StatusInfrasResourceBaseUpdateInput,
|
||||
) (apis.StatusInfrasResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.InfrasResourceBaseUpdateInput, err = model.SInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.InfrasResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SInfrasResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -63,10 +63,6 @@ func (model *SStatusStandaloneResourceBase) SetStatus(userCred mcclient.TokenCre
|
||||
return statusBaseSetStatus(model, userCred, status, reason)
|
||||
}
|
||||
|
||||
func (model *SStatusStandaloneResourceBase) GetStatus() string {
|
||||
return model.Status
|
||||
}
|
||||
|
||||
func (manager *SStatusStandaloneResourceBaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input apis.StatusStandaloneResourceCreateInput) (apis.StatusStandaloneResourceCreateInput, error) {
|
||||
var err error
|
||||
input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput)
|
||||
@@ -139,3 +135,17 @@ func (model *SStatusStandaloneResourceBase) GetExtraDetails(
|
||||
) (apis.StatusStandaloneResourceDetails, error) {
|
||||
return apis.StatusStandaloneResourceDetails{}, nil
|
||||
}
|
||||
|
||||
func (model *SStatusStandaloneResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.StatusStandaloneResourceBaseUpdateInput,
|
||||
) (apis.StatusStandaloneResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.StandaloneResourceBaseUpdateInput, err = model.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import (
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -115,6 +117,13 @@ func (manager *STenantCacheManager) fetchTenant(ctx context.Context, idStr strin
|
||||
q = manager.GetTenantQuery()
|
||||
}
|
||||
q = filter(q)
|
||||
tcnt, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CountWithError")
|
||||
}
|
||||
if tcnt > 1 {
|
||||
return nil, httperrors.ErrDuplicateName
|
||||
}
|
||||
tobj, err := NewModelObject(manager)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "NewModelObject")
|
||||
|
||||
@@ -180,3 +180,17 @@ func (manager *SVirtualJointResourceBaseManager) OrderByExtraFields(
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SVirtualJointResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.VirtualJointResourceBaseUpdateInput,
|
||||
) (apis.VirtualJointResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.JointResourceBaseUpdateInput, err = self.SJointResourceBase.ValidateUpdateData(ctx, userCred, query, input.JointResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SJointResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ type SVirtualResourceBase struct {
|
||||
// 是否是系统资源
|
||||
IsSystem bool `nullable:"true" default:"false" list:"admin" create:"optional" json:"is_system"`
|
||||
|
||||
// 资源放入回收站时间
|
||||
PendingDeletedAt time.Time `json:"pending_deleted_at"`
|
||||
// 资源是否处于回收站中
|
||||
PendingDeleted bool `nullable:"false" default:"false" index:"true" get:"user" list:"user" json:"pending_deleted"`
|
||||
@@ -276,6 +277,25 @@ func (model *SVirtualResourceBase) PerformChangeOwner(ctx context.Context, userC
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var requireScope rbacutils.TRbacScope
|
||||
if ownerId.GetProjectDomainId() != model.DomainId {
|
||||
// change domain, do check
|
||||
if managed, ok := model.GetIVirtualModel().(IManagedResoucceBase); ok {
|
||||
if !managed.CanShareToDomain(ownerId.GetProjectDomainId()) {
|
||||
return nil, errors.Wrap(httperrors.ErrForbidden, "cann't share across domain")
|
||||
}
|
||||
}
|
||||
requireScope = rbacutils.ScopeSystem
|
||||
} else {
|
||||
requireScope = rbacutils.ScopeDomain
|
||||
}
|
||||
|
||||
allowScope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.KeywordPlural(), policy.PolicyActionPerform, "change-owner")
|
||||
if requireScope.HigherThan(allowScope) {
|
||||
return nil, errors.Wrapf(httperrors.ErrNotSufficientPrivilege, "require %s allow %s", requireScope, allowScope)
|
||||
}
|
||||
|
||||
q := manager.Query().Equals("name", model.GetName())
|
||||
q = manager.FilterByOwner(q, ownerId, manager.NamespaceScope())
|
||||
q = manager.FilterBySystemAttributes(q, nil, nil, manager.ResourceScope())
|
||||
@@ -295,8 +315,10 @@ func (model *SVirtualResourceBase) PerformChangeOwner(ctx context.Context, userC
|
||||
}
|
||||
|
||||
// clean shared projects before update project id
|
||||
if err := SharedResourceManager.CleanModelSharedProjects(ctx, userCred, model); err != nil {
|
||||
return nil, err
|
||||
if sharedModel, ok := model.GetIVirtualModel().(ISharableBaseModel); ok {
|
||||
if err := SharedResourceManager.CleanModelShares(ctx, userCred, sharedModel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = Update(model, func() error {
|
||||
@@ -495,3 +517,17 @@ func (manager *SVirtualResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (model *SVirtualResourceBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input apis.VirtualResourceBaseUpdateInput,
|
||||
) (apis.VirtualResourceBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.StatusStandaloneResourceBaseUpdateInput, err = model.SStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StatusStandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStatusStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package elect // import "yunion.io/x/onecloud/pkg/cloudcommon/elect"
|
||||
|
||||
@@ -34,6 +34,9 @@ func OnBaseOptionsChange(oOpts, nOpts interface{}) bool {
|
||||
if oldOpts.NonDefaultDomainProjects != newOpts.NonDefaultDomainProjects {
|
||||
consts.SetNonDefaultDomainProjects(newOpts.NonDefaultDomainProjects)
|
||||
}
|
||||
if oldOpts.DomainizedNamespace != newOpts.DomainizedNamespace {
|
||||
consts.SetDomainizedNamespace(newOpts.DomainizedNamespace)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ type BaseOptions struct {
|
||||
|
||||
TimeZone string `help:"time zone" default:"Asia/Shanghai"`
|
||||
|
||||
DomainizedNamespace bool `help:"turn on global name space, default is on" default:"false" json:"global_namespace,allowfalse"`
|
||||
|
||||
structarg.BaseOptions
|
||||
}
|
||||
|
||||
@@ -288,4 +290,6 @@ func ParseOptions(optStruct interface{}, args []string, configFileName string, s
|
||||
if len(optionsRef.Region) > 0 {
|
||||
consts.SetRegion(optionsRef.Region)
|
||||
}
|
||||
|
||||
consts.SetDomainizedNamespace(optionsRef.DomainizedNamespace)
|
||||
}
|
||||
|
||||
@@ -18,35 +18,35 @@ import "yunion.io/x/pkg/utils"
|
||||
|
||||
var (
|
||||
computeSystemResources = []string{
|
||||
"hosts",
|
||||
"zones",
|
||||
"storages",
|
||||
"wires",
|
||||
"globalvpcs",
|
||||
"route_tables",
|
||||
"cloudregions",
|
||||
"serverskus",
|
||||
"cachedimages",
|
||||
"dynamicschedtags",
|
||||
"baremetalagents",
|
||||
"schedpolicies",
|
||||
"isolated-devices",
|
||||
"reservedips",
|
||||
"dnsrecords",
|
||||
"metadatas",
|
||||
"loadbalancerclusters",
|
||||
"loadbalanceragents",
|
||||
"networkinterfaces",
|
||||
"natgateways",
|
||||
"natsentries",
|
||||
"natdentries",
|
||||
"isolated-devices",
|
||||
"reservedips",
|
||||
}
|
||||
computeDomainResources = []string{
|
||||
"cloudaccounts",
|
||||
"cloudproviders",
|
||||
"recyclebins",
|
||||
// migrate system resources to domain resources
|
||||
"hosts",
|
||||
"vpcs",
|
||||
"storages",
|
||||
"wires",
|
||||
"globalvpcs",
|
||||
"route_tables",
|
||||
"networkinterfaces",
|
||||
"natgateways",
|
||||
"natsentries",
|
||||
"natdentries",
|
||||
}
|
||||
computeUserResources = []string{
|
||||
"keypairs",
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudnet"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -113,10 +114,14 @@ func (man *SRouterManager) getById(id string) (*SRouter, error) {
|
||||
return router, err
|
||||
}
|
||||
|
||||
func (router *SRouter) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if _, err := router.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data); err != nil {
|
||||
return nil, err
|
||||
func (router *SRouter) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.RouterUpdateInput) (api.RouterUpdateInput, error) {
|
||||
var err error
|
||||
input.StandaloneResourceBaseUpdateInput, err = router.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
|
||||
data := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
vs := []validators.IValidator{
|
||||
validators.NewStringNonEmptyValidator("user"),
|
||||
validators.NewStringNonEmptyValidator("host"),
|
||||
@@ -129,11 +134,11 @@ func (router *SRouter) ValidateUpdateData(ctx context.Context, userCred mcclient
|
||||
for _, v := range vs {
|
||||
v.Optional(true)
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
return input, err
|
||||
}
|
||||
}
|
||||
data.Set("_old_endpoint", jsonutils.NewString(router.endpointIP()))
|
||||
return data, nil
|
||||
input.OldEndpoint = router.endpointIP()
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (router *SRouter) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudnet"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -136,10 +137,13 @@ func (man *SRouteManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (route *SRoute) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if _, err := route.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data); err != nil {
|
||||
return nil, err
|
||||
func (route *SRoute) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.RouteUpdateInput) (api.RouteUpdateInput, error) {
|
||||
var err error
|
||||
input.StandaloneResourceBaseUpdateInput, err = route.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
data := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
vs := []validators.IValidator{
|
||||
validators.NewIPv4PrefixValidator("network"),
|
||||
validators.NewIPv4AddrValidator("gateway"),
|
||||
@@ -147,10 +151,10 @@ func (route *SRoute) ValidateUpdateData(ctx context.Context, userCred mcclient.T
|
||||
for _, v := range vs {
|
||||
v.Optional(true)
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
return input, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (man *SRouteManager) removeByIface(ctx context.Context, userCred mcclient.TokenCredential, iface *SIface) error {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/cloudnet"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -233,14 +234,17 @@ func (man *SRuleManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery,
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (rule *SRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if _, err := rule.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data); err != nil {
|
||||
return nil, err
|
||||
func (rule *SRule) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.RuleUpdateInput) (api.RuleUpdateInput, error) {
|
||||
var err error
|
||||
input.StandaloneResourceBaseUpdateInput, err = rule.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
data := jsonutils.Marshal(input).(*jsonutils.JSONDict)
|
||||
if err := RuleManager.validateData(ctx, userCred, rule.GetOwnerId(), query, data, rule); err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "validateData")
|
||||
}
|
||||
return nil, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (man *SRuleManager) removeByRouter(ctx context.Context, userCred mcclient.TokenCredential, router *SRouter) error {
|
||||
|
||||
@@ -45,11 +45,11 @@ func (self *SAzureHostDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_AZURE
|
||||
}
|
||||
|
||||
func (self *SAzureHostDriver) ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if data.Contains("name") {
|
||||
return nil, httperrors.NewInputParameterError("cannot support change azure disk name")
|
||||
func (self *SAzureHostDriver) ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, input api.DiskUpdateInput) (api.DiskUpdateInput, error) {
|
||||
if len(input.Name) > 0 {
|
||||
return input, httperrors.NewInputParameterError("cannot support change azure disk name")
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAzureHostDriver) ValidateResetDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, guests []models.SGuest, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
|
||||
@@ -34,8 +34,8 @@ import (
|
||||
type SBaseHostDriver struct {
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return data, nil
|
||||
func (self *SBaseHostDriver) ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, input api.DiskUpdateInput) (api.DiskUpdateInput, error) {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) ValidateResetDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, guests []models.SGuest, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -80,41 +79,59 @@ func (self *SBaremetalagent) ValidateDeleteCondition(ctx context.Context) error
|
||||
return self.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SBaremetalagent) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
mangerUri, err := data.GetString("manager_uri")
|
||||
if err == nil {
|
||||
func (self *SBaremetalagent) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.BaremetalagentUpdateInput) (api.BaremetalagentUpdateInput, error) {
|
||||
var err error
|
||||
mangerUri := input.ManagerUri
|
||||
if len(mangerUri) > 0 {
|
||||
count, err := BaremetalagentManager.Query().Equals("manager_uri", mangerUri).
|
||||
NotEquals("id", self.Id).CountWithError()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("check agent uniqness fail %s", err)
|
||||
return input, httperrors.NewInternalServerError("check agent uniqness fail %s", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, httperrors.NewConflictError("Conflict manager_uri %s", mangerUri)
|
||||
return input, httperrors.NewConflictError("Conflict manager_uri %s", mangerUri)
|
||||
}
|
||||
}
|
||||
return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
if len(input.Zone) > 0 {
|
||||
zoneObj, err := ValidateZoneResourceInput(userCred, input.ZoneResourceInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "ValidateZoneResourceInput")
|
||||
}
|
||||
input.Zone = zoneObj.GetId()
|
||||
}
|
||||
input.StandaloneResourceBaseUpdateInput, err = self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SBaremetalagentManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
mangerUri, _ := data.GetString("manager_uri")
|
||||
func (manager *SBaremetalagentManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.BaremetalagentCreateInput) (api.BaremetalagentCreateInput, error) {
|
||||
var err error
|
||||
mangerUri := input.ManagerUri
|
||||
if len(mangerUri) == 0 {
|
||||
return input, errors.Wrap(httperrors.ErrMissingParameter, "manager_uri")
|
||||
}
|
||||
count, err := manager.Query().Equals("manager_uri", mangerUri).CountWithError()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("check agent uniqness fail %s", err)
|
||||
return input, httperrors.NewInternalServerError("check agent uniqness fail %s", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, httperrors.NewDuplicateResourceError("Duplicate manager_uri %s", mangerUri)
|
||||
return input, httperrors.NewDuplicateResourceError("Duplicate manager_uri %s", mangerUri)
|
||||
}
|
||||
input := apis.StandaloneResourceCreateInput{}
|
||||
err = data.Unmarshal(&input)
|
||||
if len(input.Zone) == 0 {
|
||||
return input, errors.Wrap(httperrors.ErrMissingParameter, "zone/zone_id")
|
||||
}
|
||||
zoneObj, err := ValidateZoneResourceInput(userCred, input.ZoneResourceInput)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err)
|
||||
return input, errors.Wrap(err, "ValidateZoneResourceInput")
|
||||
}
|
||||
input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
|
||||
input.Zone = zoneObj.GetId()
|
||||
input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "SStandaloneResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalagent) AllowPerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
|
||||
@@ -486,16 +486,20 @@ func (bucket *SBucket) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data *jsonutils.JSONDict,
|
||||
) (*jsonutils.JSONDict, error) {
|
||||
nameStr, _ := data.GetString("name")
|
||||
if len(nameStr) > 0 {
|
||||
err := isValidBucketName(nameStr)
|
||||
input api.BucketUpdateInput,
|
||||
) (api.BucketUpdateInput, error) {
|
||||
var err error
|
||||
if len(input.Name) > 0 {
|
||||
err := isValidBucketName(input.Name)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid bucket name: %s", err)
|
||||
return input, httperrors.NewInputParameterError("invalid bucket name(%s): %s", input.Name, err)
|
||||
}
|
||||
}
|
||||
return bucket.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input.VirtualResourceBaseUpdateInput, err = bucket.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (bucket *SBucket) RemoteCreate(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
|
||||
@@ -132,10 +132,13 @@ func getRegionZoneSubq(region *SCloudregion) *sqlchemy.SSubQuery {
|
||||
}
|
||||
|
||||
func domainManagerFieldFilter(domainId, field string) *sqlchemy.SSubQuery {
|
||||
providers := CloudproviderManager.Query().SubQuery()
|
||||
accounts := CloudaccountManager.Query().SubQuery()
|
||||
accounts := CloudaccountManager.Query("id")
|
||||
accounts = CloudaccountManager.filterByDomainId(accounts, domainId)
|
||||
accounts = accounts.Equals("status", api.CLOUD_PROVIDER_CONNECTED)
|
||||
accounts = accounts.IsTrue("enabled")
|
||||
|
||||
q := providers.Query(providers.Field(field))
|
||||
q := CloudproviderManager.Query(field).Equals("cloudaccount_id", accounts.SubQuery())
|
||||
/*q := providers.Query(providers.Field(field))
|
||||
q = q.Join(accounts, sqlchemy.Equals(accounts.Field("id"), providers.Field("cloudaccount_id")))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.AND(
|
||||
@@ -149,7 +152,7 @@ func domainManagerFieldFilter(domainId, field string) *sqlchemy.SSubQuery {
|
||||
),
|
||||
))
|
||||
q = q.Filter(sqlchemy.Equals(accounts.Field("status"), api.CLOUD_PROVIDER_CONNECTED))
|
||||
q = q.Filter(sqlchemy.IsTrue(accounts.Field("enabled")))
|
||||
q = q.Filter(sqlchemy.IsTrue(accounts.Field("enabled")))*/
|
||||
|
||||
return q.SubQuery()
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/proxy"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
@@ -56,7 +55,7 @@ import (
|
||||
)
|
||||
|
||||
type SCloudaccountManager struct {
|
||||
db.SEnabledStatusDomainLevelResourceBaseManager
|
||||
db.SEnabledStatusInfrasResourceBaseManager
|
||||
SSyncableBaseResourceManager
|
||||
}
|
||||
|
||||
@@ -64,7 +63,7 @@ var CloudaccountManager *SCloudaccountManager
|
||||
|
||||
func init() {
|
||||
CloudaccountManager = &SCloudaccountManager{
|
||||
SEnabledStatusDomainLevelResourceBaseManager: db.NewEnabledStatusDomainLevelResourceBaseManager(
|
||||
SEnabledStatusInfrasResourceBaseManager: db.NewEnabledStatusInfrasResourceBaseManager(
|
||||
SCloudaccount{},
|
||||
"cloudaccounts_tbl",
|
||||
"cloudaccount",
|
||||
@@ -77,7 +76,7 @@ func init() {
|
||||
}
|
||||
|
||||
type SCloudaccount struct {
|
||||
db.SEnabledStatusDomainLevelResourceBase
|
||||
db.SEnabledStatusInfrasResourceBase `"public_scope->default":""`
|
||||
|
||||
SSyncableBaseResource
|
||||
|
||||
@@ -151,7 +150,7 @@ type SCloudaccount struct {
|
||||
Options *jsonutils.JSONDict `get:"domain" create:"domain_optional" update:"domain"`
|
||||
|
||||
// for backward compatiblity, keep is_public field, but not usable
|
||||
IsPublic bool `default:"false" nullable:"false"`
|
||||
// IsPublic bool `default:"false" nullable:"false"`
|
||||
// add share_mode field to indicate the share range of this account
|
||||
ShareMode string `width:"32" charset:"ascii" nullable:"true" list:"domain"`
|
||||
|
||||
@@ -213,11 +212,11 @@ func (self *SCloudaccount) ValidateDeleteCondition(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
return self.SEnabledStatusDomainLevelResourceBase.ValidateDeleteCondition(ctx)
|
||||
return self.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) enableAccountOnly(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformEnableInput) (jsonutils.JSONObject, error) {
|
||||
return self.SEnabledStatusDomainLevelResourceBase.PerformEnable(ctx, userCred, query, input)
|
||||
return self.SEnabledStatusInfrasResourceBase.PerformEnable(ctx, userCred, query, input)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformEnableInput) (jsonutils.JSONObject, error) {
|
||||
@@ -241,7 +240,7 @@ func (self *SCloudaccount) PerformEnable(ctx context.Context, userCred mcclient.
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformDisableInput) (jsonutils.JSONObject, error) {
|
||||
_, err := self.SEnabledStatusDomainLevelResourceBase.PerformDisable(ctx, userCred, query, input)
|
||||
_, err := self.SEnabledStatusInfrasResourceBase.PerformDisable(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,36 +262,37 @@ func (self *SCloudaccount) PerformDisable(ctx context.Context, userCred mcclient
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if data.Contains("sync_interval_seconds") {
|
||||
syncIntervalSecs, _ := data.Int("sync_interval_seconds")
|
||||
func (self *SCloudaccount) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input api.CloudaccountUpdateInput,
|
||||
) (api.CloudaccountUpdateInput, error) {
|
||||
var err error
|
||||
if input.SyncIntervalSeconds != nil {
|
||||
syncIntervalSecs := *input.SyncIntervalSeconds
|
||||
if syncIntervalSecs == 0 {
|
||||
syncIntervalSecs = int64(options.Options.DefaultSyncIntervalSeconds)
|
||||
} else if syncIntervalSecs < int64(options.Options.MinimalSyncIntervalSeconds) {
|
||||
syncIntervalSecs = int64(options.Options.MinimalSyncIntervalSeconds)
|
||||
}
|
||||
data.Set("sync_interval_seconds", jsonutils.NewInt(syncIntervalSecs))
|
||||
input.SyncIntervalSeconds = &syncIntervalSecs
|
||||
}
|
||||
if data.Contains("options") || data.Contains("remove_options") {
|
||||
if (input.Options != nil && input.Options.Length() > 0) || len(input.RemoveOptions) > 0 {
|
||||
var optionsJson *jsonutils.JSONDict
|
||||
if self.Options != nil {
|
||||
toRemoveKeys, _ := data.GetArray("remove_options")
|
||||
removes := make([]string, 0)
|
||||
if len(toRemoveKeys) > 0 {
|
||||
for i := range toRemoveKeys {
|
||||
key, _ := toRemoveKeys[i].GetString()
|
||||
removes = append(removes, key)
|
||||
}
|
||||
if len(input.RemoveOptions) > 0 {
|
||||
removes = append(removes, input.RemoveOptions...)
|
||||
}
|
||||
optionsJson = self.Options.CopyExcludes(removes...)
|
||||
} else {
|
||||
optionsJson = jsonutils.NewDict()
|
||||
}
|
||||
toUpdate, _ := data.Get("options")
|
||||
if toUpdate != nil {
|
||||
optionsJson.Update(toUpdate)
|
||||
if input.Options != nil {
|
||||
optionsJson.Update(input.Options)
|
||||
}
|
||||
data.Set("options", optionsJson)
|
||||
input.Options = optionsJson
|
||||
}
|
||||
|
||||
v := validators.NewModelIdOrNameValidator(
|
||||
@@ -304,10 +304,21 @@ func (self *SCloudaccount) ValidateUpdateData(ctx context.Context, userCred mccl
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.SEnabledStatusDomainLevelResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input.EnabledStatusInfrasResourceBaseUpdateInput, err = self.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.ValidateUpdateData")
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.CloudaccountCreateInput) (api.CloudaccountCreateInput, error) {
|
||||
func (manager *SCloudaccountManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input api.CloudaccountCreateInput,
|
||||
) (api.CloudaccountCreateInput, error) {
|
||||
// check domainId
|
||||
err := db.ValidateCreateDomainId(ownerId.GetProjectDomainId())
|
||||
if err != nil {
|
||||
@@ -422,7 +433,7 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use
|
||||
}
|
||||
}
|
||||
|
||||
input.EnabledStatusDomainLevelResourceCreateInput, err = manager.SEnabledStatusDomainLevelResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusDomainLevelResourceCreateInput)
|
||||
input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
@@ -438,11 +449,11 @@ func (self *SCloudaccount) CustomizeCreate(ctx context.Context, userCred mcclien
|
||||
self.DomainId = ownerId.GetProjectDomainId()
|
||||
// self.EnableAutoSync = false
|
||||
self.ShareMode = api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN
|
||||
return self.SEnabledStatusDomainLevelResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
return self.SEnabledStatusInfrasResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SEnabledStatusDomainLevelResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
self.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
self.savePassword(self.Secret)
|
||||
|
||||
// if !self.EnableAutoSync {
|
||||
@@ -1038,10 +1049,10 @@ func (manager *SCloudaccountManager) FetchCustomizeColumns(
|
||||
isList bool,
|
||||
) []api.CloudaccountDetail {
|
||||
rows := make([]api.CloudaccountDetail, len(objs))
|
||||
stdRows := manager.SEnabledStatusDomainLevelResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
stdRows := manager.SEnabledStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.CloudaccountDetail{
|
||||
EnabledStatusDomainLevelResourceDetails: stdRows[i],
|
||||
EnabledStatusInfrasResourceBaseDetails: stdRows[i],
|
||||
}
|
||||
rows[i] = objs[i].(*SCloudaccount).getMoreDetails(rows[i])
|
||||
}
|
||||
@@ -1163,34 +1174,42 @@ func (manager *SCloudaccountManager) initializeShareMode() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) InitializeData() error {
|
||||
cloudproviders := []SCloudprovider{}
|
||||
q := CloudproviderManager.Query()
|
||||
q = q.IsNullOrEmpty("cloudaccount_id")
|
||||
err := db.FetchModelObjects(CloudproviderManager, q, &cloudproviders)
|
||||
func (manager *SCloudaccountManager) initializePublicScope() error {
|
||||
accounts := []SCloudaccount{}
|
||||
q := manager.Query().IsNullOrEmpty("public_scope")
|
||||
err := db.FetchModelObjects(manager, q, &accounts)
|
||||
if err != nil {
|
||||
log.Errorf("fetch all clound provider fail %s", err)
|
||||
log.Errorf("fetch all clound account fail %v", err)
|
||||
return err
|
||||
}
|
||||
for i := 0; i < len(cloudproviders); i++ {
|
||||
err = migrateCloudprovider(&cloudproviders[i])
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
account := &accounts[i]
|
||||
_, err = db.Update(account, func() error {
|
||||
switch account.ShareMode {
|
||||
case api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN:
|
||||
account.PublicScope = string(rbacutils.ScopeNone)
|
||||
account.IsPublic = false
|
||||
case api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN:
|
||||
account.PublicScope = string(rbacutils.ScopeSystem)
|
||||
account.IsPublic = true
|
||||
case api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM:
|
||||
account.PublicScope = string(rbacutils.ScopeSystem)
|
||||
account.IsPublic = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = manager.initializeBrand()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = manager.initializeShareMode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) initializeVMWareAccountId() error {
|
||||
// init accountid
|
||||
q = manager.Query().Equals("provider", api.CLOUD_PROVIDER_VMWARE)
|
||||
q := manager.Query().Equals("provider", api.CLOUD_PROVIDER_VMWARE)
|
||||
cloudaccounts := make([]SCloudaccount, 0)
|
||||
err = db.FetchModelObjects(manager, q, &cloudaccounts)
|
||||
err := db.FetchModelObjects(manager, q, &cloudaccounts)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch vmware cloudaccount fail")
|
||||
}
|
||||
@@ -1218,6 +1237,41 @@ func (manager *SCloudaccountManager) InitializeData() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) InitializeData() error {
|
||||
cloudproviders := []SCloudprovider{}
|
||||
q := CloudproviderManager.Query()
|
||||
q = q.IsNullOrEmpty("cloudaccount_id")
|
||||
err := db.FetchModelObjects(CloudproviderManager, q, &cloudproviders)
|
||||
if err != nil {
|
||||
log.Errorf("fetch all clound provider fail %s", err)
|
||||
return err
|
||||
}
|
||||
for i := 0; i < len(cloudproviders); i++ {
|
||||
err = migrateCloudprovider(&cloudproviders[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = manager.initializeBrand()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "initializeBrand")
|
||||
}
|
||||
err = manager.initializeShareMode()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "initializeShareMode")
|
||||
}
|
||||
err = manager.initializeVMWareAccountId()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "initializeVMWareAccountId")
|
||||
}
|
||||
err = manager.initializePublicScope()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "initializePublicScope")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) GetBalance() (float64, error) {
|
||||
/*driver, err := self.GetProvider()
|
||||
if err != nil {
|
||||
@@ -1292,19 +1346,72 @@ func (self *SCloudaccount) GetVCenterAccessInfo(privateId string) (SVCenterAcces
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) AllowPerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
// +onecloud:swagger-gen-ignore
|
||||
func (account *SCloudaccount) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
|
||||
return nil, errors.Wrap(httperrors.ErrForbidden, "can't change domain owner of cloudaccount, use PerformChangeProject instead")
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) AllowPerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "change-project")
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) PerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SCloudaccount) PerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) (jsonutils.JSONObject, error) {
|
||||
if self.IsShared() {
|
||||
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "cannot change owner when shared!")
|
||||
}
|
||||
|
||||
project := input.Project
|
||||
|
||||
tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(ctx, project)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewNotFoundError("project %s not found", project)
|
||||
}
|
||||
|
||||
if tenant.Id == self.ProjectId {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
providers := self.GetCloudproviders()
|
||||
if len(providers) > 1 {
|
||||
return nil, httperrors.NewInvalidStatusError("multiple subaccounts")
|
||||
if len(providers) > 0 {
|
||||
for i := range providers {
|
||||
if providers[i].ProjectId != self.ProjectId {
|
||||
return nil, errors.Wrap(httperrors.ErrConflict, "cloudproviders' project is different from cloudaccount's")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(providers) == 0 {
|
||||
return nil, httperrors.NewInvalidStatusError("no subaccount")
|
||||
|
||||
if tenant.DomainId != self.DomainId {
|
||||
// do change domainId
|
||||
input2 := apis.PerformChangeDomainOwnerInput{}
|
||||
input2.ProjectDomain = tenant.DomainId
|
||||
_, err := self.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input2)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformChangeOwner")
|
||||
}
|
||||
}
|
||||
return providers[0].PerformChangeProject(ctx, userCred, query, data)
|
||||
|
||||
// save project_id change
|
||||
diff, err := db.Update(self, func() error {
|
||||
self.ProjectId = tenant.Id
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "db.Update ProjectId")
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(self, db.ACT_UPDATE, diff, userCred)
|
||||
|
||||
if len(providers) > 0 {
|
||||
for i := range providers {
|
||||
_, err := providers[i].PerformChangeProject(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "providers[i].PerformChangeProject %s(%s)", providers[i].Name, providers[i].Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 云账号列表
|
||||
@@ -1327,9 +1434,9 @@ func (manager *SCloudaccountManager) ListItemFilter(
|
||||
q = q.Equals("id", accountObj.GetId())
|
||||
}
|
||||
|
||||
q, err := manager.SEnabledStatusDomainLevelResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusDomainLevelResourceListInput)
|
||||
q, err := manager.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusDomainLevelResourceBaseManager")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager")
|
||||
}
|
||||
q, err = manager.SSyncableBaseResourceManager.ListItemFilter(ctx, q, userCred, query.SyncableBaseResourceListInput)
|
||||
if err != nil {
|
||||
@@ -1395,7 +1502,7 @@ func (manager *SCloudaccountManager) QueryDistinctExtraField(q *sqlchemy.SQuery,
|
||||
q = q.AppendField(q.Field("name").Label("account")).Distinct()
|
||||
return q, nil
|
||||
}
|
||||
q, err := manager.SEnabledStatusDomainLevelResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
q, err := manager.SEnabledStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
@@ -1408,9 +1515,9 @@ func (manager *SCloudaccountManager) OrderByExtraFields(
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.CloudaccountListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SEnabledStatusDomainLevelResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusDomainLevelResourceListInput)
|
||||
q, err := manager.SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusDomainLevelResourceBaseManager.OrderByExtraFields")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
@@ -1738,7 +1845,7 @@ func (self *SCloudaccount) Delete(ctx context.Context, userCred mcclient.TokenCr
|
||||
|
||||
func (self *SCloudaccount) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
self.SetStatus(userCred, api.CLOUD_PROVIDER_DELETED, "real delete")
|
||||
return self.SEnabledStatusDomainLevelResourceBase.Delete(ctx, userCred)
|
||||
return self.SEnabledStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
@@ -1792,76 +1899,96 @@ func (account *SCloudaccount) setShareMode(userCred mcclient.TokenCredential, mo
|
||||
return nil
|
||||
}
|
||||
|
||||
func (account *SCloudaccount) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
func (account *SCloudaccount) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudaccountPerformPublicInput) bool {
|
||||
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, account, "public")
|
||||
}
|
||||
|
||||
func (account *SCloudaccount) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), account.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
func (account *SCloudaccount) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudaccountPerformPublicInput) (jsonutils.JSONObject, error) {
|
||||
if input.ShareMode != api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN && input.ShareMode != api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM {
|
||||
return nil, errors.Wrap(httperrors.ErrInputParameter, "share_mode cannot be account_domain")
|
||||
}
|
||||
|
||||
err := account.setShareMode(userCred, api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM)
|
||||
if input.ShareMode == api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN {
|
||||
providers := account.GetCloudproviders()
|
||||
for i := range providers {
|
||||
if !utils.IsInStringArray(providers[i].DomainId, input.SharedDomains) {
|
||||
log.Warningf("provider's domainId %s is outside of list of shared domains", providers[i].DomainId)
|
||||
input.SharedDomains = append(input.SharedDomains, providers[i].DomainId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err := account.SInfrasResourceBase.PerformPublic(ctx, userCred, query, input.PerformPublicInput)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
return nil, errors.Wrap(err, "SInfrasResourceBase.PerformPublic")
|
||||
}
|
||||
// scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), account.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "public")
|
||||
// if scope != rbacutils.ScopeSystem {
|
||||
// return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
// }
|
||||
|
||||
err = account.setShareMode(userCred, input.ShareMode)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "account.setShareMode")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (account *SCloudaccount) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
func (account *SCloudaccount) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) bool {
|
||||
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, account, "private")
|
||||
}
|
||||
|
||||
func (account *SCloudaccount) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (account *SCloudaccount) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
|
||||
providers := account.GetCloudproviders()
|
||||
for i := range providers {
|
||||
if providers[i].DomainId != account.DomainId {
|
||||
return nil, httperrors.NewConflictError("provider is shared outside of domain")
|
||||
}
|
||||
}
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), account.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
|
||||
err := account.setShareMode(userCred, api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN)
|
||||
_, err := account.SInfrasResourceBase.PerformPrivate(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
return nil, errors.Wrap(err, "SInfrasResourceBase.PerformPrivate")
|
||||
}
|
||||
// scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), account.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
|
||||
// if scope != rbacutils.ScopeSystem {
|
||||
// return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
// }
|
||||
|
||||
err = account.setShareMode(userCred, api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "account.setShareMode")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (account *SCloudaccount) AllowPerformShareMode(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
func (account *SCloudaccount) AllowPerformShareMode(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudaccountShareModeInput) bool {
|
||||
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, account, "share-mode")
|
||||
}
|
||||
|
||||
func (account *SCloudaccount) PerformShareMode(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
input := api.CloudaccountShareModeInput{}
|
||||
err := data.Unmarshal(&input)
|
||||
func (account *SCloudaccount) PerformShareMode(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudaccountShareModeInput) (jsonutils.JSONObject, error) {
|
||||
err := input.Validate()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("fail to unmarshal input: %s", err)
|
||||
}
|
||||
err = input.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "CloudaccountShareModeInput.Validate")
|
||||
}
|
||||
if account.ShareMode == input.ShareMode {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if input.ShareMode == api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN {
|
||||
providers := account.GetCloudproviders()
|
||||
for i := range providers {
|
||||
if providers[i].DomainId != account.DomainId {
|
||||
return nil, httperrors.NewConflictError("provider is shared outside of domain")
|
||||
}
|
||||
return account.PerformPrivate(ctx, userCred, query, apis.PerformPrivateInput{})
|
||||
} else {
|
||||
input2 := api.CloudaccountPerformPublicInput{
|
||||
ShareMode: input.ShareMode,
|
||||
PerformPublicInput: apis.PerformPublicInput{
|
||||
Scope: string(rbacutils.ScopeSystem),
|
||||
},
|
||||
}
|
||||
return account.PerformPublic(ctx, userCred, query, input2)
|
||||
}
|
||||
|
||||
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), account.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "share-mode")
|
||||
/*scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), account.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "share-mode")
|
||||
if scope != rbacutils.ScopeSystem {
|
||||
return nil, httperrors.NewForbiddenError("not enough privilege")
|
||||
}
|
||||
@@ -1871,7 +1998,48 @@ func (account *SCloudaccount) PerformShareMode(ctx context.Context, userCred mcc
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
return nil, nil*/
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) filterByDomainId(q *sqlchemy.SQuery, domainId string) *sqlchemy.SQuery {
|
||||
subq := db.SharedResourceManager.Query("resource_id")
|
||||
subq = subq.Equals("resource_type", manager.Keyword())
|
||||
subq = subq.Equals("target_project_id", domainId)
|
||||
subq = subq.Equals("target_type", db.SharedTargetDomain)
|
||||
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
q = q.LeftJoin(cloudproviders, sqlchemy.Equals(
|
||||
q.Field("id"),
|
||||
cloudproviders.Field("cloudaccount_id"),
|
||||
))
|
||||
|
||||
q = q.Distinct()
|
||||
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
// share_mode=account_domain/private
|
||||
sqlchemy.Equals(q.Field("domain_id"), domainId),
|
||||
// share_mode=provider_domain/public_scope=domain
|
||||
// share_mode=provider_domain/public_scope=system
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN),
|
||||
sqlchemy.Equals(cloudproviders.Field("domain_id"), domainId),
|
||||
),
|
||||
// share_mode=system/public_scope=domain
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM),
|
||||
sqlchemy.In(q.Field("id"), subq.SubQuery()),
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeDomain),
|
||||
),
|
||||
// share_mode=system/public_scope=system
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM),
|
||||
sqlchemy.IsTrue(q.Field("is_public")),
|
||||
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
|
||||
),
|
||||
))
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SCloudaccountManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
|
||||
@@ -1879,7 +2047,8 @@ func (manager *SCloudaccountManager) FilterByOwner(q *sqlchemy.SQuery, owner mcc
|
||||
switch scope {
|
||||
case rbacutils.ScopeProject, rbacutils.ScopeDomain:
|
||||
if len(owner.GetProjectDomainId()) > 0 {
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
q = manager.filterByDomainId(q, owner.GetProjectDomainId())
|
||||
/*cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
q = q.LeftJoin(cloudproviders, sqlchemy.Equals(
|
||||
q.Field("id"),
|
||||
cloudproviders.Field("cloudaccount_id"),
|
||||
@@ -1895,7 +2064,7 @@ func (manager *SCloudaccountManager) FilterByOwner(q *sqlchemy.SQuery, owner mcc
|
||||
sqlchemy.Equals(q.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN),
|
||||
sqlchemy.Equals(cloudproviders.Field("domain_id"), owner.GetProjectDomainId()),
|
||||
),
|
||||
))
|
||||
))*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2002,7 +2171,8 @@ func (manager *SCloudaccountManager) queryCloudAccountByCapability(region *SClou
|
||||
q = q.Filter(sqlchemy.Equals(providerregions.Field("cloudregion_id"), region.Id))
|
||||
}
|
||||
if len(domainId) > 0 {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
q = manager.filterByDomainId(q, domainId)
|
||||
/*q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN),
|
||||
sqlchemy.Equals(q.Field("domain_id"), domainId),
|
||||
@@ -2012,7 +2182,7 @@ func (manager *SCloudaccountManager) queryCloudAccountByCapability(region *SClou
|
||||
sqlchemy.Equals(q.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN),
|
||||
sqlchemy.Equals(providers.Field("domain_id"), domainId),
|
||||
),
|
||||
))
|
||||
))*/
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -292,12 +292,18 @@ func (self *SCloudprovider) getSyncRegionCount() (int, error) {
|
||||
return CloudproviderRegionManager.Query().Equals("cloudprovider_id", self.Id).CountWithError()
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
func (self *SCloudprovider) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudproviderUpdateInput) (api.CloudproviderUpdateInput, error) {
|
||||
var err error
|
||||
input.EnabledStatusStandaloneResourceBaseUpdateInput, err = self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusStandaloneResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SEnabledStatusStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SCloudproviderManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewUnsupportOperationError("Directly creating cloudprovider is not supported, create cloudaccount instead")
|
||||
// +onecloud:swagger-gen-ignore
|
||||
func (self *SCloudproviderManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.CloudproviderCreateInput) (api.CloudproviderCreateInput, error) {
|
||||
return input, httperrors.NewUnsupportOperationError("Directly creating cloudprovider is not supported, create cloudaccount instead")
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) getAccessUrl() string {
|
||||
@@ -559,15 +565,12 @@ func (self *SCloudprovider) StartSyncCloudProviderInfoTask(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) AllowPerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
func (self *SCloudprovider) AllowPerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "change-project")
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) PerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
project, err := data.GetString("project")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("project")
|
||||
}
|
||||
func (self *SCloudprovider) PerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeProjectOwnerInput) (jsonutils.JSONObject, error) {
|
||||
project := input.Project
|
||||
|
||||
tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(ctx, project)
|
||||
if err != nil {
|
||||
@@ -583,9 +586,16 @@ func (self *SCloudprovider) PerformChangeProject(ctx context.Context, userCred m
|
||||
if !db.IsAdminAllowPerform(userCred, self, "change-project") {
|
||||
return nil, httperrors.NewForbiddenError("not allow to change project across domain")
|
||||
}
|
||||
if account.ShareMode == api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN {
|
||||
if account.ShareMode == api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN && account.DomainId != tenant.DomainId {
|
||||
return nil, httperrors.NewInvalidStatusError("not a public cloud account")
|
||||
}
|
||||
// if account's public_scope=domain and share_mode=provider_domain, only allow to share to specific domains
|
||||
if account.PublicScope == string(rbacutils.ScopeDomain) {
|
||||
sharedDomains := account.GetSharedDomains()
|
||||
if !utils.IsInStringArray(tenant.DomainId, sharedDomains) && account.DomainId != tenant.DomainId {
|
||||
return nil, errors.Wrap(httperrors.ErrForbidden, "cannot set to domain outside of the shared domains")
|
||||
}
|
||||
}
|
||||
// otherwise, allow change project across domain
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ func syncVpcRouteTables(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
log.Errorf(msg)
|
||||
return
|
||||
}
|
||||
_, _, result := RouteTableManager.SyncRouteTables(ctx, userCred, localVpc, routeTables)
|
||||
_, _, result := RouteTableManager.SyncRouteTables(ctx, userCred, localVpc, routeTables, provider)
|
||||
|
||||
syncResults.Add(RouteTableManager, result)
|
||||
|
||||
@@ -345,7 +345,7 @@ func syncNatDTable(ctx context.Context, userCred mcclient.TokenCredential, provi
|
||||
log.Errorf(msg)
|
||||
return
|
||||
}
|
||||
result := NatDEntryManager.SyncNatDTable(ctx, userCred, provider.GetOwnerId(), provider, localNatGateway, dtable)
|
||||
result := NatDEntryManager.SyncNatDTable(ctx, userCred, provider, localNatGateway, dtable)
|
||||
msg := result.Result()
|
||||
log.Infof("SyncNatDTable for NatGateway %s result: %s", localNatGateway.Name, msg)
|
||||
if result.IsError() {
|
||||
@@ -361,7 +361,7 @@ func syncNatSTable(ctx context.Context, userCred mcclient.TokenCredential, provi
|
||||
log.Errorf(msg)
|
||||
return
|
||||
}
|
||||
result := NatSEntryManager.SyncNatSTable(ctx, userCred, provider.GetOwnerId(), provider, localNatGateway, stable)
|
||||
result := NatSEntryManager.SyncNatSTable(ctx, userCred, provider, localNatGateway, stable)
|
||||
msg := result.Result()
|
||||
log.Infof("SyncNatSTable for NatGateway %s result: %s", localNatGateway.Name, msg)
|
||||
if result.IsError() {
|
||||
@@ -377,7 +377,7 @@ func syncVpcWires(ctx context.Context, userCred mcclient.TokenCredential, syncRe
|
||||
log.Errorf(msg)
|
||||
return
|
||||
}
|
||||
localWires, remoteWires, result := WireManager.SyncWires(ctx, userCred, localVpc, wires)
|
||||
localWires, remoteWires, result := WireManager.SyncWires(ctx, userCred, localVpc, wires, provider)
|
||||
|
||||
if syncResults != nil {
|
||||
syncResults.Add(WireManager, result)
|
||||
@@ -1212,3 +1212,14 @@ func SyncCloudProject(userCred mcclient.TokenCredential, model db.IVirtualModel,
|
||||
}
|
||||
model.SyncCloudProjectId(userCred, newOwnerId)
|
||||
}
|
||||
|
||||
func SyncCloudDomain(userCred mcclient.TokenCredential, model db.IDomainLevelModel, syncOwnerId mcclient.IIdentityProvider) {
|
||||
var newOwnerId mcclient.IIdentityProvider
|
||||
if syncOwnerId != nil && len(syncOwnerId.GetProjectDomainId()) > 0 {
|
||||
newOwnerId = syncOwnerId
|
||||
}
|
||||
if newOwnerId == nil {
|
||||
newOwnerId = userCred
|
||||
}
|
||||
model.SyncCloudDomainId(userCred, newOwnerId)
|
||||
}
|
||||
|
||||
+19
-12
@@ -376,29 +376,36 @@ func (self *SDisk) CustomizeCreate(ctx context.Context, userCred mcclient.TokenC
|
||||
return self.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (self *SDisk) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (self *SDisk) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DiskUpdateInput) (api.DiskUpdateInput, error) {
|
||||
var err error
|
||||
|
||||
if input.DiskType != "" {
|
||||
if !utils.IsInStringArray(input.DiskType, []string{api.DISK_TYPE_DATA, api.DISK_TYPE_VOLUME}) {
|
||||
return input, httperrors.NewInputParameterError("not support update disk_type %s", input.DiskType)
|
||||
}
|
||||
}
|
||||
|
||||
storage := self.GetStorage()
|
||||
if storage == nil {
|
||||
return nil, httperrors.NewNotFoundError("failed to find storage for disk %s", self.Name)
|
||||
return input, httperrors.NewNotFoundError("failed to find storage for disk %s", self.Name)
|
||||
}
|
||||
|
||||
host := storage.GetMasterHost()
|
||||
if host == nil {
|
||||
return nil, httperrors.NewNotFoundError("failed to find host for storage %s with disk %s", storage.Name, self.Name)
|
||||
return input, httperrors.NewNotFoundError("failed to find host for storage %s with disk %s", storage.Name, self.Name)
|
||||
}
|
||||
|
||||
if diskType, _ := data.GetString("disk_type"); diskType != "" {
|
||||
if !utils.IsInStringArray(diskType, []string{api.DISK_TYPE_DATA, api.DISK_TYPE_VOLUME}) {
|
||||
return nil, httperrors.NewInputParameterError("not support update disk_type %s", diskType)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := host.GetHostDriver().ValidateUpdateDisk(ctx, userCred, data)
|
||||
input, err = host.GetHostDriver().ValidateUpdateDisk(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "GetHostDriver().ValidateUpdateDisk")
|
||||
}
|
||||
|
||||
return self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input.VirtualResourceBaseUpdateInput, err = self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func diskCreateInput2ComputeQuotaKeys(input api.DiskCreateInput, ownerId mcclient.IIdentityProvider) SComputeResourceKeys {
|
||||
|
||||
@@ -419,7 +419,17 @@ func (rec *SDnsRecord) ValidateUpdateData(ctx context.Context, userCred mcclient
|
||||
}
|
||||
data.Set("records", jsonutils.NewString(strings.Join(records, DNS_RECORDS_SEPARATOR)))
|
||||
}
|
||||
return rec.SAdminSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input := apis.AdminSharableVirtualResourceBaseUpdateInput{}
|
||||
err = data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "data.Unmarshal AdminSharableVirtualResourceBaseUpdateInput")
|
||||
}
|
||||
input, err = rec.SAdminSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SAdminSharableVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (rec *SDnsRecord) AddInfo(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
|
||||
|
||||
@@ -167,7 +167,18 @@ func (self *SDynamicschedtag) ValidateUpdateData(ctx context.Context, userCred m
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input := apis.StandaloneResourceBaseUpdateInput{}
|
||||
err = data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
input, err = self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SStandaloneResourceBase.ValidateUpdateData")
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SDynamicschedtag) GetExtraDetails(
|
||||
|
||||
@@ -30,14 +30,14 @@ import (
|
||||
)
|
||||
|
||||
type SGlobalVpcManager struct {
|
||||
db.SEnabledStatusStandaloneResourceBaseManager
|
||||
db.SEnabledStatusInfrasResourceBaseManager
|
||||
}
|
||||
|
||||
var GlobalVpcManager *SGlobalVpcManager
|
||||
|
||||
func init() {
|
||||
GlobalVpcManager = &SGlobalVpcManager{
|
||||
SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(
|
||||
SEnabledStatusInfrasResourceBaseManager: db.NewEnabledStatusInfrasResourceBaseManager(
|
||||
SGlobalVpc{},
|
||||
"globalvpcs_tbl",
|
||||
"globalvpc",
|
||||
@@ -48,7 +48,7 @@ func init() {
|
||||
}
|
||||
|
||||
type SGlobalVpc struct {
|
||||
db.SEnabledStatusStandaloneResourceBase
|
||||
db.SEnabledStatusInfrasResourceBase
|
||||
}
|
||||
|
||||
func (manager *SGlobalVpcManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
@@ -63,7 +63,7 @@ func (self *SGlobalVpc) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if len(vpcs) > 0 {
|
||||
return fmt.Errorf("not an empty globalvpc")
|
||||
}
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
return self.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SGlobalVpc) GetVpcs() ([]SVpc, error) {
|
||||
@@ -89,27 +89,43 @@ func (manager *SGlobalVpcManager) FetchCustomizeColumns(
|
||||
isList bool,
|
||||
) []api.GlobalVpcDetails {
|
||||
rows := make([]api.GlobalVpcDetails, len(objs))
|
||||
stdRows := manager.SEnabledStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
stdRows := manager.SEnabledStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.GlobalVpcDetails{
|
||||
EnabledStatusStandaloneResourceDetails: stdRows[i],
|
||||
EnabledStatusInfrasResourceBaseDetails: stdRows[i],
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SGlobalVpcManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.GlobalVpcCreateInput) (api.GlobalVpcCreateInput, error) {
|
||||
func (manager *SGlobalVpcManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input api.GlobalVpcCreateInput,
|
||||
) (api.GlobalVpcCreateInput, error) {
|
||||
input.Status = api.GLOBAL_VPC_STATUS_AVAILABLE
|
||||
var err error
|
||||
input.EnabledStatusStandaloneResourceCreateInput, err = manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusStandaloneResourceCreateInput)
|
||||
input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData")
|
||||
return input, errors.Wrap(err, "manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SGlobalVpc) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
func (self *SGlobalVpc) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input api.GlobalvpcUpdateInput,
|
||||
) (api.GlobalvpcUpdateInput, error) {
|
||||
var err error
|
||||
input.EnabledStatusInfrasResourceBaseUpdateInput, err = self.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// 全局VPC列表
|
||||
@@ -119,9 +135,9 @@ func (manager *SGlobalVpcManager) ListItemFilter(
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GlobalVpcListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SEnabledStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
q, err := manager.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
@@ -132,9 +148,9 @@ func (manager *SGlobalVpcManager) OrderByExtraFields(
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GlobalVpcListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
q, err := manager.SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
@@ -142,7 +158,7 @@ func (manager *SGlobalVpcManager) OrderByExtraFields(
|
||||
func (manager *SGlobalVpcManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
q, err = manager.SEnabledStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
@@ -151,5 +167,5 @@ func (manager *SGlobalVpcManager) QueryDistinctExtraField(q *sqlchemy.SQuery, fi
|
||||
}
|
||||
|
||||
func (self *SGlobalVpc) ValidateUpdateCondition(ctx context.Context) error {
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateCondition(ctx)
|
||||
return self.SEnabledStatusInfrasResourceBase.ValidateUpdateCondition(ctx)
|
||||
}
|
||||
|
||||
@@ -94,12 +94,13 @@ func (gtm *SGuestTemplateManager) ValidateCreateData(
|
||||
query jsonutils.JSONObject,
|
||||
input computeapis.GuesttemplateCreateInput,
|
||||
) (computeapis.GuesttemplateCreateInput, error) {
|
||||
var err error
|
||||
|
||||
if input.Content == nil {
|
||||
return input, httperrors.NewMissingParameterError("content")
|
||||
}
|
||||
|
||||
input, err := gtm.validateData(ctx, userCred, ownerId, query, input)
|
||||
input.GuesttemplateInput, err = gtm.validateData(ctx, userCred, ownerId, query, input.GuesttemplateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "gtm.validateData")
|
||||
}
|
||||
@@ -128,8 +129,8 @@ func (gtm *SGuestTemplateManager) validateData(
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
cinput computeapis.GuesttemplateCreateInput,
|
||||
) (computeapis.GuesttemplateCreateInput, error) {
|
||||
cinput computeapis.GuesttemplateInput,
|
||||
) (computeapis.GuesttemplateInput, error) {
|
||||
if cinput.Content == nil {
|
||||
return cinput, nil
|
||||
}
|
||||
@@ -181,15 +182,22 @@ func (gtm *SGuestTemplateManager) validateData(
|
||||
return cinput, nil
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, cinput *computeapis.GuesttemplateCreateInput) (*jsonutils.JSONDict, error) {
|
||||
|
||||
input, err := GuestTemplateManager.validateData(ctx, userCred, gt.GetOwnerId(), query, *cinput)
|
||||
func (gt *SGuestTemplate) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input computeapis.GuesttemplateUpdateInput,
|
||||
) (computeapis.GuesttemplateUpdateInput, error) {
|
||||
var err error
|
||||
input.GuesttemplateInput, err = GuestTemplateManager.validateData(ctx, userCred, gt.GetOwnerId(), query, input.GuesttemplateInput)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
return input, errors.Wrap(err, "GuestTemplateManager.validateData")
|
||||
}
|
||||
data := input.JSON(input)
|
||||
return gt.SSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input.SharableVirtualResourceBaseUpdateInput, err = gt.SSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.SharableVirtualResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SSharableVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SGuestTemplateManager) FetchCustomizeColumns(
|
||||
@@ -364,8 +372,12 @@ func (gt *SGuestTemplate) getMoreDetails(ctx context.Context, userCred mcclient.
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (gt *SGuestTemplate) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data apis.PerformProjectPublicInput) (jsonutils.JSONObject, error) {
|
||||
func (gt *SGuestTemplate) PerformPublic(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data apis.PerformPublicInput,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
|
||||
// image, network, secgroup, instancegroup
|
||||
input, err := cmdline.FetchServerCreateInputByJSON(gt.Content)
|
||||
|
||||
@@ -85,24 +85,26 @@ func (self *SGuestdisk) AllowDeleteItem(ctx context.Context, userCred mcclient.T
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SGuestdisk) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if data.Contains("index") {
|
||||
if index, err := data.Int("index"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
guestdisk := GuestdiskManager.Query().SubQuery()
|
||||
count, err := guestdisk.Query().Filter(sqlchemy.Equals(guestdisk.Field("guest_id"), self.GuestId)).
|
||||
Filter(sqlchemy.NotEquals(guestdisk.Field("disk_id"), self.DiskId)).
|
||||
Filter(sqlchemy.Equals(guestdisk.Field("index"), index)).CountWithError()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("check disk index uniqueness fail %s", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, httperrors.NewInputParameterError("DISK Index %d has been occupied", index)
|
||||
}
|
||||
func (self *SGuestdisk) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.GuestdiskUpdateInput) (api.GuestdiskUpdateInput, error) {
|
||||
if input.Index != nil {
|
||||
index := *input.Index
|
||||
guestdisk := GuestdiskManager.Query().SubQuery()
|
||||
count, err := guestdisk.Query().Filter(sqlchemy.Equals(guestdisk.Field("guest_id"), self.GuestId)).
|
||||
Filter(sqlchemy.NotEquals(guestdisk.Field("disk_id"), self.DiskId)).
|
||||
Filter(sqlchemy.Equals(guestdisk.Field("index"), index)).CountWithError()
|
||||
if err != nil {
|
||||
return input, httperrors.NewInternalServerError("check disk index uniqueness fail %s", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return input, httperrors.NewInputParameterError("DISK Index %d has been occupied", index)
|
||||
}
|
||||
}
|
||||
return self.SGuestJointsBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
var err error
|
||||
input.GuestJointBaseUpdateInput, err = self.SGuestJointsBase.ValidateUpdateData(ctx, userCred, query, input.GuestJointBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SGuestJointsBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (joint *SGuestdisk) Master() db.IStandaloneModel {
|
||||
|
||||
@@ -150,3 +150,17 @@ func (manager *SGuestJointsManager) OrderByExtraFields(
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (self *SGuestJointsBase) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input api.GuestJointBaseUpdateInput,
|
||||
) (api.GuestJointBaseUpdateInput, error) {
|
||||
var err error
|
||||
input.VirtualJointResourceBaseUpdateInput, err = self.SVirtualJointResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualJointResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SVirtualJointResourceBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -511,24 +511,31 @@ func (self *SGuestnetwork) GetDetailedString() string {
|
||||
self.MacAddr, network.VlanId, network.Name, self.Driver, self.getBandwidth())
|
||||
}
|
||||
|
||||
func (self *SGuestnetwork) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
if data.Contains("index") {
|
||||
index, err := data.Int("index")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("fail to fetch index %s", err)
|
||||
}
|
||||
func (self *SGuestnetwork) ValidateUpdateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
input api.GuestnetworkUpdateInput,
|
||||
) (api.GuestnetworkUpdateInput, error) {
|
||||
if input.Index != nil {
|
||||
index := *input.Index
|
||||
q := GuestnetworkManager.Query().SubQuery()
|
||||
count, err := q.Query().Filter(sqlchemy.Equals(q.Field("guest_id"), self.GuestId)).
|
||||
Filter(sqlchemy.NotEquals(q.Field("network_id"), self.NetworkId)).
|
||||
Filter(sqlchemy.Equals(q.Field("index"), index)).CountWithError()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("checkout nic index uniqueness fail %s", err)
|
||||
return input, httperrors.NewInternalServerError("checkout nic index uniqueness fail %s", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, httperrors.NewDuplicateResourceError("NIC Index %d has been occupied", index)
|
||||
return input, httperrors.NewDuplicateResourceError("NIC Index %d has been occupied", index)
|
||||
}
|
||||
}
|
||||
return self.SJointResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
var err error
|
||||
input.GuestJointBaseUpdateInput, err = self.SGuestJointsBase.ValidateUpdateData(ctx, userCred, query, input.GuestJointBaseUpdateInput)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "SGuestJointsBase.ValidateUpdateData")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SGuestnetworkManager) DeleteGuestNics(ctx context.Context, userCred mcclient.TokenCredential, gns []SGuestnetwork, reserve bool) error {
|
||||
|
||||
@@ -23,6 +23,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -863,7 +865,17 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
|
||||
return nil, httperrors.NewInputParameterError("name is too short")
|
||||
}
|
||||
}
|
||||
return self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input := apis.VirtualResourceBaseUpdateInput{}
|
||||
err = data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "data.Unmarshal")
|
||||
}
|
||||
input, err = self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func serverCreateInput2ComputeQuotaKeys(input api.ServerCreateInput, ownerId mcclient.IIdentityProvider) SComputeResourceKeys {
|
||||
|
||||
@@ -32,7 +32,7 @@ type IHostDriver interface {
|
||||
CheckAndSetCacheImage(ctx context.Context, host *SHost, storagecache *SStoragecache, task taskman.ITask) error
|
||||
RequestUncacheImage(ctx context.Context, host *SHost, storageCache *SStoragecache, task taskman.ITask) error
|
||||
|
||||
ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
ValidateUpdateDisk(ctx context.Context, userCred mcclient.TokenCredential, input api.DiskUpdateInput) (api.DiskUpdateInput, error)
|
||||
ValidateResetDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, snapshot *SSnapshot, guests []SGuest, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
ValidateDiskSize(storage *SStorage, sizeGb int) error
|
||||
RequestPrepareSaveDiskOnHost(ctx context.Context, host *SHost, disk *SDisk, imageId string, task taskman.ITask) error
|
||||
|
||||
+260
-185
@@ -25,6 +25,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -58,7 +60,7 @@ import (
|
||||
)
|
||||
|
||||
type SHostManager struct {
|
||||
db.SEnabledStatusStandaloneResourceBaseManager
|
||||
db.SEnabledStatusInfrasResourceBaseManager
|
||||
db.SExternalizedResourceBaseManager
|
||||
SZoneResourceBaseManager
|
||||
SManagedResourceBaseManager
|
||||
@@ -68,7 +70,7 @@ var HostManager *SHostManager
|
||||
|
||||
func init() {
|
||||
HostManager = &SHostManager{
|
||||
SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(
|
||||
SEnabledStatusInfrasResourceBaseManager: db.NewEnabledStatusInfrasResourceBaseManager(
|
||||
SHost{},
|
||||
"hosts_tbl",
|
||||
"host",
|
||||
@@ -80,7 +82,7 @@ func init() {
|
||||
}
|
||||
|
||||
type SHost struct {
|
||||
db.SEnabledStatusStandaloneResourceBase
|
||||
db.SEnabledStatusInfrasResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
SZoneResourceBase
|
||||
SManagedResourceBase
|
||||
@@ -227,9 +229,9 @@ func (manager *SHostManager) ListItemFilter(
|
||||
}
|
||||
}
|
||||
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
q, err = manager.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemFilter")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
anyMac := query.AnyMac
|
||||
@@ -436,9 +438,9 @@ func (manager *SHostManager) OrderByExtraFields(
|
||||
query api.HostListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusStandaloneResourceListInput)
|
||||
q, err = manager.SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.OrderByExtraFields")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
|
||||
if err != nil {
|
||||
@@ -453,7 +455,7 @@ func (manager *SHostManager) OrderByExtraFields(
|
||||
|
||||
func (manager *SHostManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SEnabledStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
q, err = manager.SEnabledStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
@@ -610,7 +612,7 @@ func (self *SHost) validateDeleteCondition(ctx context.Context, purge bool) erro
|
||||
}
|
||||
|
||||
}
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
||||
return self.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SHost) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
@@ -677,7 +679,7 @@ func (self *SHost) RealDelete(ctx context.Context, userCred mcclient.TokenCreden
|
||||
store.Delete(ctx, userCred)
|
||||
}
|
||||
}
|
||||
return self.SEnabledStatusStandaloneResourceBase.Delete(ctx, userCred)
|
||||
return self.SEnabledStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SHost) GetHoststoragesQuery() *sqlchemy.SQuery {
|
||||
@@ -1183,6 +1185,18 @@ func (self *SHost) GetAttachedLocalStorageCapacity() SStorageCapacity {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SHost) GetAttachedLocalStorages() []SStorage {
|
||||
ret := make([]SStorage, 0)
|
||||
storages := self.GetAttachedStorages("")
|
||||
for _, s := range storages {
|
||||
if !utils.IsInStringArray(s.StorageType, api.HOST_STORAGE_LOCAL_TYPES) {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, s)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func _getLeastUsedStorage(storages []SStorage, backends []string) *SStorage {
|
||||
var best *SStorage
|
||||
var bestCap int64
|
||||
@@ -1505,7 +1519,7 @@ func (manager *SHostManager) SyncHosts(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].syncWithCloudHost(ctx, userCred, commonext[i])
|
||||
err = commondb[i].syncWithCloudHost(ctx, userCred, commonext[i], provider.GetOwnerId())
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
} else {
|
||||
@@ -1551,7 +1565,7 @@ func (self *SHost) syncRemoveCloudHost(ctx context.Context, userCred mcclient.To
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SHost) syncWithCloudHost(ctx context.Context, userCred mcclient.TokenCredential, extHost cloudprovider.ICloudHost) error {
|
||||
func (self *SHost) syncWithCloudHost(ctx context.Context, userCred mcclient.TokenCredential, extHost cloudprovider.ICloudHost, syncOwnerId mcclient.IIdentityProvider) error {
|
||||
diff, err := db.UpdateWithLock(ctx, self, func() error {
|
||||
// self.Name = extHost.GetName()
|
||||
|
||||
@@ -1597,6 +1611,8 @@ func (self *SHost) syncWithCloudHost(ctx context.Context, userCred mcclient.Toke
|
||||
|
||||
db.OpsLog.LogSyncUpdate(self, diff, userCred)
|
||||
|
||||
SyncCloudDomain(userCred, self, syncOwnerId)
|
||||
|
||||
if err := HostManager.ClearSchedDescCache(self.Id); err != nil {
|
||||
log.Errorf("ClearSchedDescCache for host %s error %v", self.Name, err)
|
||||
}
|
||||
@@ -1693,6 +1709,9 @@ func (manager *SHostManager) newFromCloudHost(ctx context.Context, userCred mccl
|
||||
host.IsMaintenance = extHost.GetIsMaintenance()
|
||||
host.Version = extHost.GetVersion()
|
||||
|
||||
host.IsPublic = false
|
||||
host.PublicScope = string(rbacutils.ScopeNone)
|
||||
|
||||
err = manager.TableSpec().Insert(&host)
|
||||
if err != nil {
|
||||
log.Errorf("newFromCloudHost fail %s", err)
|
||||
@@ -1701,6 +1720,8 @@ func (manager *SHostManager) newFromCloudHost(ctx context.Context, userCred mccl
|
||||
|
||||
db.OpsLog.LogEvent(&host, db.ACT_CREATE, host.GetShortDesc(ctx), userCred)
|
||||
|
||||
SyncCloudDomain(userCred, &host, provider.GetOwnerId())
|
||||
|
||||
if err := manager.ClearSchedDescCache(host.Id); err != nil {
|
||||
log.Errorf("ClearSchedDescCache for host %s error %v", host.Name, err)
|
||||
}
|
||||
@@ -1802,7 +1823,7 @@ func (self *SHost) syncWithCloudHostStorage(ctx context.Context, userCred mcclie
|
||||
return err
|
||||
}
|
||||
s := hs.GetStorage()
|
||||
err = s.syncWithCloudStorage(ctx, userCred, extStorage)
|
||||
err = s.syncWithCloudStorage(ctx, userCred, extStorage, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2550,12 +2571,12 @@ func (manager *SHostManager) FetchCustomizeColumns(
|
||||
isList bool,
|
||||
) []api.HostDetails {
|
||||
rows := make([]api.HostDetails, len(objs))
|
||||
stdRows := manager.SEnabledStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
stdRows := manager.SEnabledStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
zoneRows := manager.SZoneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i] = api.HostDetails{
|
||||
EnabledStatusStandaloneResourceDetails: stdRows[i],
|
||||
EnabledStatusInfrasResourceBaseDetails: stdRows[i],
|
||||
ManagedResourceInfo: managerRows[i],
|
||||
ZoneResourceInfo: zoneRows[i],
|
||||
}
|
||||
@@ -2642,37 +2663,50 @@ func (self *SHost) GetStoragecache() *SStoragecache {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
kwargs := data.(*jsonutils.JSONDict)
|
||||
ipmiInfo, err := fetchIpmiInfo(kwargs, self.Id)
|
||||
func (self *SHost) PostCreate(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject,
|
||||
) {
|
||||
self.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
input := api.HostCreateInput{}
|
||||
err := data.Unmarshal(&input)
|
||||
if err != nil {
|
||||
log.Errorln(err.Error())
|
||||
} else if ipmiInfo.Length() > 0 {
|
||||
log.Errorf("data.Unmarshal fail %s", err)
|
||||
return
|
||||
}
|
||||
kwargs := data.(*jsonutils.JSONDict)
|
||||
ipmiInfo, err := fetchIpmiInfo(input.HostIpmiAttributes, self.Id)
|
||||
if err != nil {
|
||||
log.Errorf("fetchIpmiInfo fail %s", err)
|
||||
return
|
||||
}
|
||||
ipmiInfoJson := jsonutils.Marshal(ipmiInfo).(*jsonutils.JSONDict)
|
||||
if ipmiInfoJson.Length() > 0 {
|
||||
_, err := self.SaveUpdates(func() error {
|
||||
self.IpmiInfo = ipmiInfo
|
||||
self.IpmiInfo = ipmiInfoJson
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(err.Error())
|
||||
} else {
|
||||
ipmiIp, _ := ipmiInfo.GetString("ip_addr")
|
||||
if len(ipmiIp) > 0 {
|
||||
self.setIpmiIp(userCred, ipmiIp)
|
||||
}
|
||||
} else if len(ipmiInfo.IpAddr) > 0 {
|
||||
self.setIpmiIp(userCred, ipmiInfo.IpAddr)
|
||||
}
|
||||
}
|
||||
accessIp, _ := data.GetString("access_ip")
|
||||
if len(accessIp) > 0 {
|
||||
self.setAccessIp(userCred, accessIp)
|
||||
if len(input.AccessIp) > 0 {
|
||||
self.setAccessIp(userCred, input.AccessIp)
|
||||
}
|
||||
accessMac, _ := data.GetString("access_mac")
|
||||
if len(accessMac) > 0 {
|
||||
self.setAccessMac(userCred, accessMac)
|
||||
if len(input.AccessMac) > 0 {
|
||||
self.setAccessMac(userCred, input.AccessMac)
|
||||
}
|
||||
noProbe := false
|
||||
if input.NoProbe != nil {
|
||||
noProbe = *input.NoProbe
|
||||
}
|
||||
noProbe := jsonutils.QueryBoolean(data, "no_probe", false)
|
||||
if len(self.ZoneId) > 0 && self.HostType == api.HOST_TYPE_BAREMETAL && !noProbe {
|
||||
ipmiInfo, _ := self.GetIpmiInfo()
|
||||
// ipmiInfo, _ := self.GetIpmiInfo()
|
||||
if len(ipmiInfo.IpAddr) > 0 {
|
||||
self.StartBaremetalCreateTask(ctx, userCred, kwargs, "")
|
||||
}
|
||||
@@ -2689,49 +2723,51 @@ func (self *SHost) StartBaremetalCreateTask(ctx context.Context, userCred mcclie
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SHostManager) ValidateSizeParams(data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
memStr, _ := data.GetString("mem_size")
|
||||
func (manager *SHostManager) ValidateSizeParams(input api.HostSizeAttributes) (api.HostSizeAttributes, error) {
|
||||
memStr := input.MemSize
|
||||
if len(memStr) > 0 {
|
||||
if !regutils.MatchSize(memStr) {
|
||||
return nil, fmt.Errorf("Memory size must be number[+unit], like 256M, 1G or 256")
|
||||
return input, errors.Wrap(httperrors.ErrInputParameter, "Memory size must be number[+unit], like 256M, 1G or 256")
|
||||
}
|
||||
memSize, err := fileutils.GetSizeMb(memStr, 'M', 1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "fileutils.GetSizeMb")
|
||||
}
|
||||
data.Set("mem_size", jsonutils.NewInt(int64(memSize)))
|
||||
input.MemSize = strconv.FormatInt(int64(memSize), 10)
|
||||
// data.Set("mem_size", jsonutils.NewInt(int64(memSize)))
|
||||
}
|
||||
memReservedStr, _ := data.GetString("mem_reserved")
|
||||
memReservedStr := input.MemReserved
|
||||
if len(memReservedStr) > 0 {
|
||||
if !regutils.MatchSize(memReservedStr) {
|
||||
return nil, fmt.Errorf("Memory size must be number[+unit], like 256M, 1G or 256")
|
||||
return input, errors.Wrap(httperrors.ErrInputParameter, "Memory size must be number[+unit], like 256M, 1G or 256")
|
||||
}
|
||||
memSize, err := fileutils.GetSizeMb(memReservedStr, 'M', 1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "fileutils.GetSizeMb")
|
||||
}
|
||||
data.Set("mem_reserved", jsonutils.NewInt(int64(memSize)))
|
||||
input.MemReserved = strconv.FormatInt(int64(memSize), 10)
|
||||
// data.Set("mem_reserved", jsonutils.NewInt(int64(memSize)))
|
||||
}
|
||||
cpuCacheStr, _ := data.GetString("cpu_cache")
|
||||
cpuCacheStr := input.CpuCache
|
||||
if len(cpuCacheStr) > 0 {
|
||||
if !regutils.MatchSize(cpuCacheStr) {
|
||||
return nil, fmt.Errorf("Illegal cpu cache size %s", cpuCacheStr)
|
||||
return input, errors.Wrapf(httperrors.ErrInputParameter, "Illegal cpu cache size %s", cpuCacheStr)
|
||||
}
|
||||
cpuCache, err := fileutils.GetSizeKb(cpuCacheStr, 'K', 1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "fileutils.GetSizeKb")
|
||||
}
|
||||
data.Set("cpu_cache", jsonutils.NewInt(int64(cpuCache)))
|
||||
input.CpuCache = strconv.FormatInt(int64(cpuCache), 10)
|
||||
// data.Set("cpu_cache", jsonutils.NewInt(int64(cpuCache)))
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SHostManager) inputUniquenessCheck(data *jsonutils.JSONDict, zoneId string, hostId string) (*jsonutils.JSONDict, error) {
|
||||
for _, key := range []string{
|
||||
"manager_uri",
|
||||
"access_ip",
|
||||
func (manager *SHostManager) inputUniquenessCheck(input api.HostAccessAttributes, zoneId string, hostId string) (api.HostAccessAttributes, error) {
|
||||
for key, val := range map[string]string{
|
||||
"manager_uri": input.ManagerUri,
|
||||
"access_ip": input.AccessIp,
|
||||
} {
|
||||
val, _ := data.GetString(key)
|
||||
if len(val) > 0 {
|
||||
q := manager.Query().Equals(key, val)
|
||||
if len(zoneId) > 0 {
|
||||
@@ -2744,19 +2780,19 @@ func (manager *SHostManager) inputUniquenessCheck(data *jsonutils.JSONDict, zone
|
||||
}
|
||||
cnt, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("check %s duplication fail %s", key, err)
|
||||
return input, httperrors.NewInternalServerError("check %s duplication fail %s", key, err)
|
||||
}
|
||||
if cnt > 0 {
|
||||
return nil, httperrors.NewConflictError("duplicate %s %s", key, val)
|
||||
return input, httperrors.NewConflictError("duplicate %s %s", key, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
accessMac, _ := data.GetString("access_mac")
|
||||
accessMac := input.AccessMac
|
||||
if len(accessMac) > 0 {
|
||||
accessMac2 := netutils.FormatMacAddr(accessMac)
|
||||
if len(accessMac2) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("invalid macAddr %s", accessMac)
|
||||
return input, httperrors.NewInputParameterError("invalid macAddr %s", accessMac)
|
||||
}
|
||||
if accessMac2 != api.ACCESS_MAC_ANY {
|
||||
q := manager.Query().Equals("access_mac", accessMac2)
|
||||
@@ -2765,71 +2801,76 @@ func (manager *SHostManager) inputUniquenessCheck(data *jsonutils.JSONDict, zone
|
||||
}
|
||||
cnt, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("check access_mac duplication fail %s", err)
|
||||
return input, httperrors.NewInternalServerError("check access_mac duplication fail %s", err)
|
||||
}
|
||||
if cnt > 0 {
|
||||
return nil, httperrors.NewConflictError("duplicate access_mac %s", accessMac)
|
||||
return input, httperrors.NewConflictError("duplicate access_mac %s", accessMac)
|
||||
}
|
||||
data.Set("access_mac", jsonutils.NewString(accessMac2))
|
||||
input.AccessMac = accessMac2
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
zoneId, zoneKey := jsonutils.GetAnyString2(data, []string{"zone_id", "zone"})
|
||||
if len(zoneId) > 0 {
|
||||
data.Remove(zoneKey)
|
||||
zoneObj, err := ZoneManager.FetchByIdOrName(userCred, zoneId)
|
||||
func (manager *SHostManager) ValidateCreateData(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider,
|
||||
query jsonutils.JSONObject,
|
||||
input api.HostCreateInput,
|
||||
) (api.HostCreateInput, error) {
|
||||
var err error
|
||||
|
||||
if len(input.Zone) > 0 {
|
||||
zoneObj, err := ValidateZoneResourceInput(userCred, input.ZoneResourceInput)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(ZoneManager.Keyword(), zoneId)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
return input, errors.Wrap(err, "ValidateZoneResourceInput")
|
||||
}
|
||||
zoneId = zoneObj.GetId()
|
||||
data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
|
||||
input.Zone = zoneObj.GetId()
|
||||
}
|
||||
|
||||
noProbe := jsonutils.QueryBoolean(data, "no_probe", false)
|
||||
|
||||
data, err := manager.inputUniquenessCheck(data, zoneId, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
noProbe := false
|
||||
if input.NoProbe != nil {
|
||||
noProbe = *input.NoProbe
|
||||
}
|
||||
|
||||
data, err = manager.ValidateSizeParams(data)
|
||||
input.HostAccessAttributes, err = manager.inputUniquenessCheck(input.HostAccessAttributes, input.Zone, "")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
return input, errors.Wrap(err, "manager.inputUniquenessCheck")
|
||||
}
|
||||
memReserved, err := data.Int("mem_reserved")
|
||||
|
||||
input.HostSizeAttributes, err = manager.ValidateSizeParams(input.HostSizeAttributes)
|
||||
if err != nil {
|
||||
hostType, _ := data.GetString("host_type")
|
||||
if hostType != api.HOST_TYPE_BAREMETAL {
|
||||
memSize, _ := data.Int("mem_size")
|
||||
memReserved = memSize / 8
|
||||
return input, errors.Wrap(err, "manager.ValidateSizeParams")
|
||||
}
|
||||
|
||||
if len(input.MemReserved) == 0 {
|
||||
if input.HostType != api.HOST_TYPE_BAREMETAL {
|
||||
memSize, _ := strconv.ParseInt(input.MemSize, 10, 64)
|
||||
memReserved := memSize / 8
|
||||
if memReserved > 4096 {
|
||||
memReserved = 4096
|
||||
}
|
||||
data.Set("mem_reserved", jsonutils.NewInt(memReserved))
|
||||
input.MemReserved = strconv.FormatInt(memReserved, 10)
|
||||
// data.Set("mem_reserved", jsonutils.NewInt(memReserved))
|
||||
} else {
|
||||
data.Set("mem_reserved", jsonutils.NewInt(0))
|
||||
input.MemReserved = "0"
|
||||
// data.Set("mem_reserved", jsonutils.NewInt(0))
|
||||
}
|
||||
}
|
||||
ipmiInfo, err := fetchIpmiInfo(data, "")
|
||||
|
||||
ipmiInfo, err := fetchIpmiInfo(input.HostIpmiAttributes, "")
|
||||
if err != nil {
|
||||
log.Errorln(err.Error())
|
||||
return nil, httperrors.NewInputParameterError("%s", err)
|
||||
return input, errors.Wrap(err, "fetchIpmiInfo")
|
||||
}
|
||||
ipmiIpAddr, _ := ipmiInfo.GetString("ip_addr")
|
||||
ipmiIpAddr := ipmiInfo.IpAddr
|
||||
if len(ipmiIpAddr) == 0 {
|
||||
noProbe = true
|
||||
}
|
||||
if len(ipmiIpAddr) > 0 && !noProbe {
|
||||
net, _ := NetworkManager.GetOnPremiseNetworkOfIP(ipmiIpAddr, "", tristate.None)
|
||||
if net == nil {
|
||||
return nil, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
|
||||
return input, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
|
||||
}
|
||||
// check ip has been reserved
|
||||
rip := ReservedipManager.GetReservedIP(net, ipmiIpAddr)
|
||||
@@ -2837,49 +2878,50 @@ func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
// if not, reserve this IP temporarily
|
||||
err := net.reserveIpWithDuration(ctx, userCred, ipmiIpAddr, "reserve for baremetal ipmi IP", 30*time.Minute)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "net.reserveIpWithDuration")
|
||||
return input, errors.Wrap(err, "net.reserveIpWithDuration")
|
||||
}
|
||||
}
|
||||
zoneObj := net.GetZone()
|
||||
if zoneObj == nil {
|
||||
return nil, httperrors.NewInputParameterError("IPMI network has no zone???")
|
||||
return input, httperrors.NewInputParameterError("IPMI network has no zone???")
|
||||
}
|
||||
originZoneId, _ := data.GetString("zone_id")
|
||||
originZoneId := input.Zone
|
||||
if len(originZoneId) > 0 && originZoneId != zoneObj.GetId() {
|
||||
return nil, httperrors.NewInputParameterError("IPMI address located in different zone than specified")
|
||||
return input, httperrors.NewInputParameterError("IPMI address located in different zone than specified")
|
||||
}
|
||||
data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
|
||||
input.Zone = zoneObj.GetId()
|
||||
// data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
|
||||
}
|
||||
if !noProbe {
|
||||
var accessNet *SNetwork
|
||||
accessIpAddr, _ := data.GetString("access_ip")
|
||||
accessIpAddr := input.AccessIp // tString("access_ip")
|
||||
if len(accessIpAddr) > 0 {
|
||||
net, _ := NetworkManager.GetOnPremiseNetworkOfIP(accessIpAddr, "", tristate.None)
|
||||
if net == nil {
|
||||
return nil, httperrors.NewInputParameterError("%s is out of network IP ranges", accessIpAddr)
|
||||
return input, httperrors.NewInputParameterError("%s is out of network IP ranges", accessIpAddr)
|
||||
}
|
||||
accessNet = net
|
||||
} else {
|
||||
accessNetStr, _ := data.GetString("access_net")
|
||||
accessNetStr := input.AccessNet // data.GetString("access_net")
|
||||
if len(accessNetStr) > 0 {
|
||||
netObj, err := NetworkManager.FetchByIdOrName(userCred, accessNetStr)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2("network", accessNetStr)
|
||||
return input, httperrors.NewResourceNotFoundError2("network", accessNetStr)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
return input, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
accessNet = netObj.(*SNetwork)
|
||||
} else {
|
||||
accessWireStr, _ := data.GetString("access_wire")
|
||||
accessWireStr := input.AccessWire // data.GetString("access_wire")
|
||||
if len(accessWireStr) > 0 {
|
||||
wireObj, err := WireManager.FetchByIdOrName(userCred, accessWireStr)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2("wire", accessWireStr)
|
||||
return input, httperrors.NewResourceNotFoundError2("wire", accessWireStr)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
return input, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
wire := wireObj.(*SWire)
|
||||
@@ -2887,7 +2929,7 @@ func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
defer lockman.ReleaseObject(ctx, wire)
|
||||
net, err := wire.GetCandidatePrivateNetwork(userCred, false, []string{api.NETWORK_TYPE_PXE, api.NETWORK_TYPE_BAREMETAL, api.NETWORK_TYPE_GUEST})
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
return input, httperrors.NewGeneralError(err)
|
||||
}
|
||||
accessNet = net
|
||||
}
|
||||
@@ -2899,20 +2941,20 @@ func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
|
||||
accessIp, err := accessNet.GetFreeIP(ctx, userCred, nil, nil, accessIpAddr, api.IPAllocationNone, true)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
return input, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
if len(accessIpAddr) > 0 && accessIpAddr != accessIp {
|
||||
return nil, httperrors.NewConflictError("Access ip %s has been used", accessIpAddr)
|
||||
return input, httperrors.NewConflictError("Access ip %s has been used", accessIpAddr)
|
||||
}
|
||||
|
||||
zoneObj := accessNet.GetZone()
|
||||
if zoneObj == nil {
|
||||
return nil, httperrors.NewInputParameterError("Access network has no zone???")
|
||||
return input, httperrors.NewInputParameterError("Access network has no zone???")
|
||||
}
|
||||
originZoneId, _ := data.GetString("zone_id")
|
||||
originZoneId := input.Zone // data.GetString("zone_id")
|
||||
if len(originZoneId) > 0 && originZoneId != zoneObj.GetId() {
|
||||
return nil, httperrors.NewInputParameterError("Access address located in different zone than specified")
|
||||
return input, httperrors.NewInputParameterError("Access address located in different zone than specified")
|
||||
}
|
||||
|
||||
// check ip has been reserved
|
||||
@@ -2921,90 +2963,93 @@ func (manager *SHostManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
// if not reserved, reserve this IP temporarily
|
||||
err = accessNet.reserveIpWithDuration(ctx, userCred, accessIp, "reserve for baremetal access IP", 30*time.Minute)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, err
|
||||
}
|
||||
}
|
||||
data.Set("access_ip", jsonutils.NewString(accessIp))
|
||||
data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
|
||||
|
||||
input.AccessIp = accessIp
|
||||
input.Zone = zoneObj.GetId()
|
||||
// data.Set("access_ip", jsonutils.NewString(accessIp))
|
||||
// data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
|
||||
}
|
||||
}
|
||||
// only baremetal can be created
|
||||
hostType, _ := data.GetString("host_type")
|
||||
hostType := input.HostType // .GetString("host_type")
|
||||
if len(hostType) == 0 {
|
||||
hostType = api.HOST_TYPE_BAREMETAL
|
||||
data.Set("host_type", jsonutils.NewString(hostType))
|
||||
input.HostType = hostType
|
||||
// data.Set("host_type", jsonutils.NewString(hostType))
|
||||
}
|
||||
if hostType == api.HOST_TYPE_BAREMETAL {
|
||||
data.Set("is_baremetal", jsonutils.JSONTrue)
|
||||
isBaremetal := true
|
||||
input.IsBaremetal = &isBaremetal
|
||||
// data.Set("is_baremetal", jsonutils.JSONTrue)
|
||||
}
|
||||
|
||||
if noProbe {
|
||||
accessMac, _ := data.GetString("access_mac")
|
||||
uuid, _ := data.GetString("uuid")
|
||||
if len(accessMac) == 0 && len(uuid) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("missing access_mac and uuid in no_probe mode")
|
||||
// accessMac := input.AccessMac // data.GetString("access_mac")
|
||||
// uuid := input.Uuid // data.GetString("uuid")
|
||||
if len(input.AccessMac) == 0 && len(input.Uuid) == 0 {
|
||||
return input, httperrors.NewInputParameterError("missing access_mac and uuid in no_probe mode")
|
||||
}
|
||||
}
|
||||
|
||||
input := apis.EnabledStatusStandaloneResourceCreateInput{}
|
||||
err = data.Unmarshal(&input)
|
||||
input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("unmarshal EnabledStatusStandaloneCreateInput fail %s", err)
|
||||
return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ValidateCreateData")
|
||||
}
|
||||
input, err = manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SHost) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := HostManager.inputUniquenessCheck(data, self.ZoneId, self.Id)
|
||||
func (self *SHost) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.HostUpdateInput) (api.HostUpdateInput, error) {
|
||||
var err error
|
||||
input.HostAccessAttributes, err = HostManager.inputUniquenessCheck(input.HostAccessAttributes, self.ZoneId, self.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "inputUniquenessCheck")
|
||||
}
|
||||
|
||||
data, err = HostManager.ValidateSizeParams(data)
|
||||
input.HostSizeAttributes, err = HostManager.ValidateSizeParams(input.HostSizeAttributes)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
return input, errors.Wrap(err, "ValidateSizeParams")
|
||||
}
|
||||
ipmiInfo, err := fetchIpmiInfo(data, self.Id)
|
||||
|
||||
ipmiInfo, err := fetchIpmiInfo(input.HostIpmiAttributes, self.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "fetchIpmiInfo")
|
||||
}
|
||||
if ipmiInfo.Length() > 0 {
|
||||
ipmiIpAddr, _ := ipmiInfo.GetString("ip_addr")
|
||||
ipmiInfoJson := jsonutils.Marshal(ipmiInfo).(*jsonutils.JSONDict)
|
||||
if ipmiInfoJson.Length() > 0 {
|
||||
ipmiIpAddr := ipmiInfo.IpAddr
|
||||
if len(ipmiIpAddr) > 0 {
|
||||
net, _ := NetworkManager.GetOnPremiseNetworkOfIP(ipmiIpAddr, "", tristate.None)
|
||||
if net == nil {
|
||||
return nil, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
|
||||
return input, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
|
||||
}
|
||||
zoneObj := net.GetZone()
|
||||
if zoneObj == nil {
|
||||
return nil, httperrors.NewInputParameterError("IPMI network has not zone???")
|
||||
return input, httperrors.NewInputParameterError("IPMI network has not zone???")
|
||||
}
|
||||
if zoneObj.GetId() != self.ZoneId {
|
||||
return nil, httperrors.NewInputParameterError("New IPMI address located in another zone!")
|
||||
return input, httperrors.NewInputParameterError("New IPMI address located in another zone!")
|
||||
}
|
||||
}
|
||||
val := jsonutils.NewDict()
|
||||
val.Update(self.IpmiInfo)
|
||||
val.Update(ipmiInfo)
|
||||
data.Set("ipmi_info", val)
|
||||
val.Update(ipmiInfoJson)
|
||||
input.IpmiInfo = val
|
||||
}
|
||||
data, err = self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
input.EnabledStatusInfrasResourceBaseUpdateInput, err = self.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.ValidateUpdateData")
|
||||
}
|
||||
if data.Contains("name") {
|
||||
if len(input.Name) > 0 {
|
||||
self.UpdateDnsRecords(false)
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SHost) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.SEnabledStatusStandaloneResourceBase.PostUpdate(ctx, userCred, query, data)
|
||||
self.SEnabledStatusInfrasResourceBase.PostUpdate(ctx, userCred, query, data)
|
||||
|
||||
if data.Contains("cpu_cmtbound") || data.Contains("mem_cmtbound") {
|
||||
self.ClearSchedDescCache()
|
||||
@@ -3043,33 +3088,44 @@ func (self *SHost) GetNetifName(netif *SNetInterface) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func fetchIpmiInfo(data *jsonutils.JSONDict, hostId string) (*jsonutils.JSONDict, error) {
|
||||
IPMI_KEY_PERFIX := "ipmi_"
|
||||
ipmiInfo := jsonutils.NewDict()
|
||||
kv, _ := data.GetMap()
|
||||
var err error
|
||||
for key := range kv {
|
||||
if strings.HasPrefix(key, IPMI_KEY_PERFIX) {
|
||||
value, _ := data.GetString(key)
|
||||
subkey := key[len(IPMI_KEY_PERFIX):]
|
||||
if subkey == "password" && len(hostId) > 0 {
|
||||
value, err = utils.EncryptAESBase64(hostId, value)
|
||||
if err != nil {
|
||||
log.Errorf("encrypt password failed %s", err)
|
||||
return nil, err
|
||||
}
|
||||
} else if subkey == "ip_addr" {
|
||||
if !regutils.MatchIP4Addr(value) {
|
||||
msg := fmt.Sprintf("%s: %s not valid ipv4 address", key, value)
|
||||
log.Errorf(msg)
|
||||
err = fmt.Errorf(msg)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ipmiInfo.Set(subkey, jsonutils.NewString(value))
|
||||
func fetchIpmiInfo(data api.HostIpmiAttributes, hostId string) (types.SIPMIInfo, error) {
|
||||
info := types.SIPMIInfo{}
|
||||
info.Username = data.IpmiUsername
|
||||
if len(hostId) > 0 {
|
||||
value, err := utils.EncryptAESBase64(hostId, data.IpmiPassword)
|
||||
if err != nil {
|
||||
log.Errorf("encrypt password failed %s", err)
|
||||
return info, errors.Wrap(err, "utils.EncryptAESBase64")
|
||||
}
|
||||
info.Password = value
|
||||
} else {
|
||||
info.Password = data.IpmiPassword
|
||||
}
|
||||
return ipmiInfo, nil
|
||||
if len(data.IpmiIpAddr) > 0 && !regutils.MatchIP4Addr(data.IpmiIpAddr) {
|
||||
msg := fmt.Sprintf("ipmi_ip_addr: %s not valid ipv4 address", data.IpmiIpAddr)
|
||||
log.Errorf(msg)
|
||||
return info, errors.Wrap(httperrors.ErrInvalidFormat, msg)
|
||||
}
|
||||
info.IpAddr = data.IpmiIpAddr
|
||||
if data.IpmiPresent != nil {
|
||||
info.Present = *data.IpmiPresent
|
||||
}
|
||||
if data.IpmiLanChannel != nil {
|
||||
info.LanChannel = *data.IpmiLanChannel
|
||||
}
|
||||
if data.IpmiVerified != nil {
|
||||
info.Verified = *data.IpmiVerified
|
||||
}
|
||||
if data.IpmiRedfishApi != nil {
|
||||
info.RedfishApi = *data.IpmiRedfishApi
|
||||
}
|
||||
if data.IpmiCdromBoot != nil {
|
||||
info.CdromBoot = *data.IpmiCdromBoot
|
||||
}
|
||||
if data.IpmiPxeBoot != nil {
|
||||
info.PxeBoot = *data.IpmiPxeBoot
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (self *SHost) AllowPerformStart(ctx context.Context,
|
||||
@@ -3986,7 +4042,7 @@ func (self *SHost) AllowPerformEnable(
|
||||
query jsonutils.JSONObject,
|
||||
input apis.PerformEnableInput,
|
||||
) bool {
|
||||
return self.SEnabledStatusStandaloneResourceBase.AllowPerformEnable(ctx, userCred, query, input)
|
||||
return self.SEnabledStatusInfrasResourceBase.AllowPerformEnable(ctx, userCred, query, input)
|
||||
}
|
||||
|
||||
func (self *SHost) PerformEnable(
|
||||
@@ -3996,9 +4052,9 @@ func (self *SHost) PerformEnable(
|
||||
input apis.PerformEnableInput,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
if !self.GetEnabled() {
|
||||
_, err := self.SEnabledStatusStandaloneResourceBase.PerformEnable(ctx, userCred, query, input)
|
||||
_, err := self.SEnabledStatusInfrasResourceBase.PerformEnable(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBase.PerformEnable")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformEnable")
|
||||
}
|
||||
self.SyncAttachedStorageStatus()
|
||||
}
|
||||
@@ -4011,14 +4067,14 @@ func (self *SHost) AllowPerformDisable(
|
||||
query jsonutils.JSONObject,
|
||||
input apis.PerformDisableInput,
|
||||
) bool {
|
||||
return self.SEnabledStatusStandaloneResourceBase.AllowPerformDisable(ctx, userCred, query, input)
|
||||
return self.SEnabledStatusInfrasResourceBase.AllowPerformDisable(ctx, userCred, query, input)
|
||||
}
|
||||
|
||||
func (self *SHost) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformDisableInput) (jsonutils.JSONObject, error) {
|
||||
if self.GetEnabled() {
|
||||
_, err := self.SEnabledStatusStandaloneResourceBase.PerformDisable(ctx, userCred, query, input)
|
||||
_, err := self.SEnabledStatusInfrasResourceBase.PerformDisable(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBase.PerformDisable")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformDisable")
|
||||
}
|
||||
self.SyncAttachedStorageStatus()
|
||||
}
|
||||
@@ -4449,7 +4505,7 @@ func (self *SHost) getCloudProviderInfo() SCloudProviderInfo {
|
||||
}
|
||||
|
||||
func (self *SHost) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
|
||||
desc := self.SEnabledStatusStandaloneResourceBase.GetShortDesc(ctx)
|
||||
desc := self.SEnabledStatusInfrasResourceBase.GetShortDesc(ctx)
|
||||
info := self.getCloudProviderInfo()
|
||||
desc.Update(jsonutils.Marshal(&info))
|
||||
return desc
|
||||
@@ -4505,9 +4561,9 @@ func (host *SHost) GetDynamicConditionInput() *jsonutils.JSONDict {
|
||||
}
|
||||
|
||||
func (host *SHost) PerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformStatusInput) (jsonutils.JSONObject, error) {
|
||||
ret, err := host.SEnabledStatusStandaloneResourceBase.PerformStatus(ctx, userCred, query, input)
|
||||
ret, err := host.SEnabledStatusInfrasResourceBase.PerformStatus(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBase.PerformStatus")
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformStatus")
|
||||
}
|
||||
host.ClearSchedDescCache()
|
||||
return ret, nil
|
||||
@@ -4598,7 +4654,7 @@ func (host *SHost) PerformHostMaintenance(ctx context.Context, userCred mcclient
|
||||
}
|
||||
|
||||
func (host *SHost) SetStatus(userCred mcclient.TokenCredential, status string, reason string) error {
|
||||
err := host.SEnabledStatusStandaloneResourceBase.SetStatus(userCred, status, reason)
|
||||
err := host.SEnabledStatusInfrasResourceBase.SetStatus(userCred, status, reason)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -4850,3 +4906,22 @@ func (self *SHost) StartSyncConfig(ctx context.Context, userCred mcclient.TokenC
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (model *SHost) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
// make host default public
|
||||
model.IsPublic = true
|
||||
model.PublicScope = string(rbacutils.ScopeSystem)
|
||||
return model.SEnabledStatusInfrasResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (host *SHost) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
|
||||
localStorages := host.GetAttachedLocalStorages()
|
||||
for i := range localStorages {
|
||||
_, err := localStorages[i].PerformChangeOwner(ctx, userCred, query, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "local storage change owner")
|
||||
}
|
||||
}
|
||||
|
||||
return host.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user