From 1c78817aba5c950264c514e7bb6da99d371eca71 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Tue, 21 Apr 2020 00:29:16 +0800 Subject: [PATCH] fix: adjust scope of isolated_device and reservedips --- cmd/climc/shell/networks.go | 17 ++++++ pkg/apis/compute/isolated_device.go | 21 +++++++ pkg/compute/models/isolated_devices.go | 85 ++++++++++++++++++++------ pkg/compute/models/reservedips.go | 54 ++++++++++++++++ pkg/compute/policy/resources.go | 4 +- 5 files changed, 161 insertions(+), 20 deletions(-) diff --git a/cmd/climc/shell/networks.go b/cmd/climc/shell/networks.go index 03a243581d..c71cb6729d 100644 --- a/cmd/climc/shell/networks.go +++ b/cmd/climc/shell/networks.go @@ -405,4 +405,21 @@ func init() { printObject(result) return nil }) + + type NetworkChangeOwnerOptions struct { + ID string `help:"Network to change owner" json:"-"` + PROJECT string `help:"Project ID or change" json:"tenant"` + } + R(&NetworkChangeOwnerOptions{}, "network-change-owner", "Change owner project of a network", func(s *mcclient.ClientSession, args *NetworkChangeOwnerOptions) error { + params, err := options.StructToParams(args) + if err != nil { + return err + } + net, err := modules.Networks.PerformAction(s, args.ID, "change-owner", params) + if err != nil { + return err + } + printObject(net) + return nil + }) } diff --git a/pkg/apis/compute/isolated_device.go b/pkg/apis/compute/isolated_device.go index 41590bff97..eacb1f413a 100644 --- a/pkg/apis/compute/isolated_device.go +++ b/pkg/apis/compute/isolated_device.go @@ -54,3 +54,24 @@ type IsolatedDeviceListInput struct { // 设备VENDOE编号 VendorDeviceId []string `json:"vendor_device_id"` } + +type IsolatedDeviceCreateInput struct { + apis.StandaloneResourceCreateInput + + HostResourceInput + + // 设备类型USB/GPU + // example: GPU + DevType string `json:"dev_type"` + + // 设备型号 + // # Specific device name read from lspci command, e.g. `Tesla K40m` ... + Model string `json:"model"` + + // PCI地址 + // # pci address of `Bus:Device.Function` format, or usb bus address of `bus.addr` + Addr string `json:"addr"` + + // 设备VendorId + VendorDeviceId string `json:"vendor_device_id"` +} diff --git a/pkg/compute/models/isolated_devices.go b/pkg/compute/models/isolated_devices.go index 3e2e344aab..526d0dbe62 100644 --- a/pkg/compute/models/isolated_devices.go +++ b/pkg/compute/models/isolated_devices.go @@ -26,11 +26,12 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/cloudcommon/db" "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" ) @@ -112,28 +113,28 @@ func (manager *SIsolatedDeviceManager) AllowCreateItem(ctx context.Context, user return db.IsAdminAllowCreate(userCred, manager) } -func (manager *SIsolatedDeviceManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - hostId, _ := data.GetString("host_id") - host := HostManager.FetchHostById(hostId) - if host == nil { - return nil, httperrors.NewNotFoundError("Host %s not found", hostId) +func (manager *SIsolatedDeviceManager) ValidateCreateData(ctx context.Context, + userCred mcclient.TokenCredential, + ownerId mcclient.IIdentityProvider, + query jsonutils.JSONObject, + input api.IsolatedDeviceCreateInput, +) (api.IsolatedDeviceCreateInput, error) { + var err error + var host *SHost + host, input.HostResourceInput, err = ValidateHostResourceInput(userCred, input.HostResourceInput) + if err != nil { + return input, errors.Wrap(err, "ValidateHostResourceInput") } - if name, _ := data.GetString("name"); len(name) == 0 { - name = fmt.Sprintf("dev_%s_%d", host.GetName(), time.Now().UnixNano()) - data.Set("name", jsonutils.NewString(name)) + if len(input.Name) == 0 { + input.Name = fmt.Sprintf("dev_%s_%d", host.GetName(), time.Now().UnixNano()) } - input := apis.StandaloneResourceCreateInput{} - err := data.Unmarshal(&input) + input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput) if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StandaloneRes ourceCreateInput fail %s", err) + return input, errors.Wrap(err, "SStandaloneResourceBaseManager.ValidateCreateData") } - input, err = manager.SStandaloneResourceBaseManager.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 *SIsolatedDevice) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool { @@ -729,3 +730,51 @@ func (manager *SIsolatedDeviceManager) GetDevsOnHost(hostId string, model string } return devs, nil } + +func (manager *SIsolatedDeviceManager) FetchParentId(ctx context.Context, data jsonutils.JSONObject) string { + parentId, _ := data.GetString("host_id") + return parentId +} + +func (manager *SIsolatedDeviceManager) FilterByParentId(q *sqlchemy.SQuery, parentId string) *sqlchemy.SQuery { + if len(parentId) > 0 { + q = q.Equals("host_id", parentId) + } + return q +} + +func (manager *SIsolatedDeviceManager) NamespaceScope() rbacutils.TRbacScope { + if consts.IsDomainizedNamespace() { + return rbacutils.ScopeDomain + } else { + return rbacutils.ScopeSystem + } +} + +func (manager *SIsolatedDeviceManager) ResourceScope() rbacutils.TRbacScope { + return rbacutils.ScopeDomain +} + +func (manager *SIsolatedDeviceManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery { + if owner != nil { + switch scope { + case rbacutils.ScopeProject, rbacutils.ScopeDomain: + hosts := HostManager.Query("id", "domain_id").SubQuery() + q = q.Join(hosts, sqlchemy.Equals(q.Field("host_id"), hosts.Field("id"))) + q = q.Filter(sqlchemy.Equals(hosts.Field("domain_id"), owner.GetProjectDomainId())) + } + } + return q +} + +func (manager *SIsolatedDeviceManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { + return db.FetchDomainInfo(ctx, data) +} + +func (model *SIsolatedDevice) GetOwnerId() mcclient.IIdentityProvider { + host := model.getHost() + if host != nil { + return host.GetOwnerId() + } + return nil +} diff --git a/pkg/compute/models/reservedips.go b/pkg/compute/models/reservedips.go index 22bd7a2813..d03dd10f7e 100644 --- a/pkg/compute/models/reservedips.go +++ b/pkg/compute/models/reservedips.go @@ -26,9 +26,11 @@ import ( "yunion.io/x/sqlchemy" api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/cloudcommon/db" "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" ) @@ -316,3 +318,55 @@ func (rip *SReservedip) IsExpired() bool { } return false } + +func (manager *SReservedipManager) FetchParentId(ctx context.Context, data jsonutils.JSONObject) string { + parentId, _ := data.GetString("network_id") + return parentId +} + +func (manager *SReservedipManager) FilterByParentId(q *sqlchemy.SQuery, parentId string) *sqlchemy.SQuery { + if len(parentId) > 0 { + q = q.Equals("network_id", parentId) + } + return q +} + +func (manager *SReservedipManager) NamespaceScope() rbacutils.TRbacScope { + if consts.IsDomainizedNamespace() { + return rbacutils.ScopeDomain + } else { + return rbacutils.ScopeSystem + } +} + +func (manager *SReservedipManager) ResourceScope() rbacutils.TRbacScope { + return rbacutils.ScopeProject +} + +func (manager *SReservedipManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery { + if owner != nil { + switch scope { + case rbacutils.ScopeProject, rbacutils.ScopeDomain: + nets := NetworkManager.Query("id", "domain_id", "tenant_id").SubQuery() + q = q.Join(nets, sqlchemy.Equals(q.Field("network_id"), nets.Field("id"))) + if scope == rbacutils.ScopeProject { + q = q.Filter(sqlchemy.Equals(nets.Field("tenant_id"), owner.GetProjectId())) + } else { + q = q.Filter(sqlchemy.Equals(nets.Field("domain_id"), owner.GetProjectDomainId())) + } + } + } + return q +} + +func (manager *SReservedipManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { + return db.FetchProjectInfo(ctx, data) +} + +func (rip *SReservedip) GetOwnerId() mcclient.IIdentityProvider { + network := rip.GetNetwork() + if network != nil { + return network.GetOwnerId() + } + return nil +} diff --git a/pkg/compute/policy/resources.go b/pkg/compute/policy/resources.go index f689958a65..6809141d91 100644 --- a/pkg/compute/policy/resources.go +++ b/pkg/compute/policy/resources.go @@ -32,8 +32,7 @@ var ( "metadatas", "loadbalancerclusters", "loadbalanceragents", - "isolated-devices", - "reservedips", + // "reservedips", "policy_definitions", } computeDomainResources = []string{ @@ -42,6 +41,7 @@ var ( "recyclebins", // migrate system resources to domain resources "hosts", + "isolated-devices", "vpcs", "storages", "wires",