From 4593c1fb999b8bfa0bb84bde3ef32867ca3f849f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Tue, 25 Aug 2020 18:31:32 +0800 Subject: [PATCH] fix: avoid network-list --zone not work (#7619) Co-authored-by: Qu Xuan --- cmd/climc/shell/compute/networks.go | 215 ++-------------------------- cmd/climc/shell/helper.go | 42 +++--- pkg/apis/compute/geo_input.go | 2 +- pkg/compute/models/wireresource.go | 8 +- pkg/mcclient/options/base.go | 14 ++ pkg/mcclient/options/network.go | 140 ++++++++++++++++++ 6 files changed, 197 insertions(+), 224 deletions(-) create mode 100644 pkg/mcclient/options/network.go diff --git a/cmd/climc/shell/compute/networks.go b/cmd/climc/shell/compute/networks.go index 4b8c32de2a..36f8ce086a 100644 --- a/cmd/climc/shell/compute/networks.go +++ b/cmd/climc/shell/compute/networks.go @@ -19,6 +19,7 @@ import ( "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/cmd/climc/shell" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/modulebase" "yunion.io/x/onecloud/pkg/mcclient/modules" @@ -26,172 +27,21 @@ import ( ) func init() { - type NetworkListOptions struct { - options.BaseListOptions - Ip string `help:"search networks that contain this IP"` - Zone []string `help:"search networks in zones"` - Wire string `help:"search networks belongs to a wire" json:"-"` - Host string `help:"search networks attached to a host"` - Vpc string `help:"search networks belongs to a VPC"` - Region string `help:"search networks belongs to a CloudRegion" json:"cloudregion"` - City string `help:"search networks belongs to a city"` - Usable *bool `help:"search usable networks"` - ServerType string `help:"search networks belongs to a ServerType" choices:"baremetal|container|eip|guest|ipmi|pxe"` - Schedtag string `help:"filter networks by schedtag"` - - IsAutoAlloc *bool `help:"search network with is_auto_alloc"` - IsClassic *bool `help:"search classic on-premise network"` - - Status string `help:"filter by network status"` - } - R(&NetworkListOptions{}, "network-list", "List networks", func(s *mcclient.ClientSession, opts *NetworkListOptions) error { - params, err := options.ListStructToParams(opts) - if err != nil { - return err - } - var result *modulebase.ListResult - if len(opts.Wire) > 0 { - result, err = modules.Networks.ListInContext(s, params, &modules.Wires, opts.Wire) - } else { - result, err = modules.Networks.List(s, params) - } - if err != nil { - return err - } - if len(opts.ExportFile) > 0 { - exportList(result, opts.ExportFile, opts.ExportKeys, opts.ExportTexts, modules.Networks.GetColumns(s)) - } else { - printList(result, modules.Networks.GetColumns(s)) - } - return nil - }) - - type NetworkUpdateOptions struct { - ID string `help:"ID or Name of zone to update"` - Name string `help:"Name of zone"` - Desc string `metavar:"" help:"Description"` - ServerType string `help:"server type," choices:"baremetal|container|eip|guest|ipmi|pxe"` - StartIp string `help:"Start ip"` - EndIp string `help:"end ip"` - NetMask int64 `help:"Netmask"` - Gateway string `help:"IP of gateway"` - Dns string `help:"IP of DNS server"` - Domain string `help:"Domain"` - Dhcp string `help:"DHCP server IP"` - VlanId int64 `help:"Vlan ID" default:"1"` - ExternalId string `help:"External ID"` - AllocPolicy string `help:"Address allocation policy" choices:"none|stepdown|stepup|random"` - IsAutoAlloc *bool `help:"Add network into auto-allocation pool" negative:"no_auto_alloc"` - } - R(&NetworkUpdateOptions{}, "network-update", "Update network", func(s *mcclient.ClientSession, args *NetworkUpdateOptions) error { - params := jsonutils.NewDict() - if len(args.Name) > 0 { - params.Add(jsonutils.NewString(args.Name), "name") - } - if len(args.Desc) > 0 { - params.Add(jsonutils.NewString(args.Desc), "description") - } - if len(args.ServerType) > 0 { - params.Add(jsonutils.NewString(args.ServerType), "server_type") - } - if len(args.StartIp) > 0 { - params.Add(jsonutils.NewString(args.StartIp), "guest_ip_start") - } - if len(args.EndIp) > 0 { - params.Add(jsonutils.NewString(args.EndIp), "guest_ip_end") - } - if args.NetMask > 0 { - params.Add(jsonutils.NewInt(args.NetMask), "guest_ip_mask") - } - if len(args.Gateway) > 0 { - params.Add(jsonutils.NewString(args.Gateway), "guest_gateway") - } - if len(args.Dns) > 0 { - if args.Dns == "none" { - params.Add(jsonutils.NewString(""), "guest_dns") - } else { - params.Add(jsonutils.NewString(args.Dns), "guest_dns") - } - } - if len(args.Domain) > 0 { - if args.Domain == "none" { - params.Add(jsonutils.NewString(""), "guest_domain") - } else { - params.Add(jsonutils.NewString(args.Domain), "guest_domain") - } - } - if len(args.Dhcp) > 0 { - if args.Dhcp == "none" { - params.Add(jsonutils.NewString(""), "guest_dhcp") - } else { - params.Add(jsonutils.NewString(args.Dhcp), "guest_dhcp") - } - } - if args.VlanId > 0 { - params.Add(jsonutils.NewInt(args.VlanId), "vlan_id") - } - if len(args.ExternalId) > 0 { - params.Add(jsonutils.NewString(args.ExternalId), "external_id") - } - if len(args.AllocPolicy) > 0 { - params.Add(jsonutils.NewString(args.AllocPolicy), "alloc_policy") - } - if args.IsAutoAlloc != nil { - params.Add(jsonutils.NewBool(*args.IsAutoAlloc), "is_auto_alloc") - } - if params.Size() == 0 { - return InvalidUpdateError() - } - result, err := modules.Networks.Update(s, args.ID, params) - if err != nil { - return err - } - printObject(result) - return nil - }) - - type NetworkIdOptions struct { - ID string `help:"ID or Name of the zone to show"` - } - R(&NetworkIdOptions{}, "network-show", "Show network details", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.Get(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&NetworkIdOptions{}, "network-metadata", "Show metadata of a network", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.GetMetadata(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&NetworkIdOptions{}, "network-private", "Make a network private", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.PerformAction(s, args.ID, "private", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&NetworkIdOptions{}, "network-syncstatus", "Sync network status", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.PerformAction(s, args.ID, "syncstatus", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) + cmd := shell.NewResourceCmd(&modules.Networks).WithContextManager(&modules.Wires) + cmd.List(&options.NetworkListOptions{}) + cmd.Update(&options.NetworkUpdateOptions{}) + cmd.Show(&options.NetworkIdOptions{}) + cmd.Delete(&options.NetworkIdOptions{}) + cmd.GetMetadata(&options.NetworkIdOptions{}) + cmd.Perform("private", &options.NetworkIdOptions{}) + cmd.Perform("syncstatus", &options.NetworkIdOptions{}) + cmd.Perform("sync", &options.NetworkIdOptions{}) + cmd.Perform("purge", &options.NetworkIdOptions{}) + cmd.Get("change-owner-candidate-domains", &options.NetworkIdOptions{}) type NetworkShareOptions struct { - NetworkIdOptions + ID string `help:"ID or Name of the zone to show"` Scope string `help:"sharing scope" choices:"system|domain|project"` SharedProjects []string `help:"Share to prjects"` SharedDomains []string `help:"share to domains"` @@ -206,24 +56,6 @@ func init() { return nil }) - R(&NetworkIdOptions{}, "network-delete", "Delete a network", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.Delete(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&NetworkIdOptions{}, "network-purge", "Purge a managed network, not delete the remote entity", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.PerformAction(s, args.ID, "purge", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - type NetworkCreateOptions struct { WIRE string `help:"ID or Name of wire in which the network is created"` NETWORK string `help:"Name of new network"` @@ -386,18 +218,6 @@ func init() { return nil }) - type NetworkSyncOptions struct { - NETWORK string `help:"id or name of network to sync"` - } - R(&NetworkSyncOptions{}, "network-sync", "Sync network status", func(s *mcclient.ClientSession, args *NetworkSyncOptions) error { - result, err := modules.Networks.PerformAction(s, args.NETWORK, "sync", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - type NetworkStatusOptions struct { NETWORK string `help:"id or name of network to sync" json:"-"` STATUS string `help:"status of network" choices:"available|unavailable" json:"status"` @@ -413,15 +233,6 @@ func init() { return nil }) - R(&NetworkIdOptions{}, "network-change-owner-candidate-domains", "Show candiate domains of a network for changing owner", func(s *mcclient.ClientSession, args *NetworkIdOptions) error { - result, err := modules.Networks.GetSpecific(s, args.ID, "change-owner-candidate-domains", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - type NetworkChangeOwnerOptions struct { ID string `help:"Network to change owner" json:"-"` PROJECT string `help:"Project ID or change" json:"tenant"` diff --git a/cmd/climc/shell/helper.go b/cmd/climc/shell/helper.go index ad1741253d..a30cc87b17 100644 --- a/cmd/climc/shell/helper.go +++ b/cmd/climc/shell/helper.go @@ -27,7 +27,9 @@ import ( ) type ResourceCmd struct { - manager modulebase.IBaseManager + manager modulebase.IBaseManager + contextManager modulebase.IBaseManager + keyword string prefix string } @@ -44,6 +46,11 @@ func (cmd *ResourceCmd) SetPrefix(prefix string) *ResourceCmd { return cmd } +func (cmd *ResourceCmd) WithContextManager(manager modulebase.IBaseManager) *ResourceCmd { + cmd.contextManager = manager + return cmd +} + func (cmd *ResourceCmd) WithKeyword(keyword string) *ResourceCmd { return cmd.SetKeyword(keyword) } @@ -61,10 +68,7 @@ type IOpt interface { type IListOpt interface { IOpt -} - -type IListExportFileOpt interface { - IListOpt + GetContextId() string GetExportFile() string GetExportKeys() string GetExportTexts() string @@ -105,19 +109,23 @@ func (cmd ResourceCmd) List(args IListOpt) { if err != nil { return err } - result, err := man.List(s, params) - if err != nil { - return err - } - exportArgs, isExportArgs := args.(IListExportFileOpt) - if isExportArgs { - if len(exportArgs.GetExportFile()) > 0 { - ExportList(result, exportArgs.GetExportFile(), exportArgs.GetExportKeys(), exportArgs.GetExportTexts(), man.GetColumns(s)) - return nil - } else { - printList(result, man.GetColumns(s)) - return nil + var result *modulebase.ListResult + contextId := args.GetContextId() + if cmd.contextManager != nil && len(contextId) > 0 { + result, err = man.(modulebase.Manager).ListInContext(s, params, cmd.contextManager.(modulebase.Manager), contextId) + if err != nil { + return err } + } else { + result, err = man.List(s, params) + if err != nil { + return err + } + } + exportFile := args.GetExportFile() + if len(exportFile) > 0 { + ExportList(result, exportFile, args.GetExportKeys(), args.GetExportTexts(), man.GetColumns(s)) + return nil } printList(result, man.GetColumns(s)) return nil diff --git a/pkg/apis/compute/geo_input.go b/pkg/apis/compute/geo_input.go index 3b02f7a3e5..d2ee5dadf2 100644 --- a/pkg/apis/compute/geo_input.go +++ b/pkg/apis/compute/geo_input.go @@ -75,7 +75,7 @@ func (input ZonalFilterListBase) ZoneList() []string { if len(input.ZoneId) > 0 { zones = append(zones, input.ZoneId) } - return input.ZoneIds + return zones } func (input ZonalFilterListBase) FirstZone() string { diff --git a/pkg/compute/models/wireresource.go b/pkg/compute/models/wireresource.go index 1c6560a493..7714758cde 100644 --- a/pkg/compute/models/wireresource.go +++ b/pkg/compute/models/wireresource.go @@ -178,19 +178,19 @@ func (manager *SWireResourceBaseManager) ListItemFilter( region := &SCloudregion{} firstZone := query.FirstZone() sq := ZoneManager.Query().SubQuery() - q := CloudregionManager.Query() - q = q.Join(sq, sqlchemy.Equals(sq.Field("cloudregion_id"), q.Field("id"))).Filter(sqlchemy.OR( + regionQ := CloudregionManager.Query() + regionQ = regionQ.Join(sq, sqlchemy.Equals(sq.Field("cloudregion_id"), regionQ.Field("id"))).Filter(sqlchemy.OR( sqlchemy.Equals(sq.Field("id"), firstZone), sqlchemy.Equals(sq.Field("name"), firstZone), )) - count, err := q.CountWithError() + count, err := regionQ.CountWithError() if err != nil { return nil, errors.Wrap(err, "CountWithError") } if count < 1 { return nil, httperrors.NewResourceNotFoundError2("zone", firstZone) } - err = q.First(region) + err = regionQ.First(region) if err != nil { return nil, errors.Wrap(err, "q.First") } diff --git a/pkg/mcclient/options/base.go b/pkg/mcclient/options/base.go index 10e3a9a67f..09abe2b24a 100644 --- a/pkg/mcclient/options/base.go +++ b/pkg/mcclient/options/base.go @@ -238,6 +238,10 @@ type BaseListOptions struct { OrderByTag string `help:"Order results by tag values, composed by a tag key and order, e.g user:部门:ASC"` } +func (opts *BaseListOptions) GetContextId() string { + return "" +} + func (opts *BaseListOptions) addTag(prefix, tag string, idx int, params *jsonutils.JSONDict) error { tagInfo := strings.Split(tag, "=") if len(tagInfo) > 2 { @@ -322,3 +326,13 @@ type ScopedResourceListOptions struct { func (o *ScopedResourceListOptions) Params() (*jsonutils.JSONDict, error) { return optionsStructToParams(o) } + +type BaseUpdateOptions struct { + ID string `help:"ID or Name of resource to update"` + Name string `help:"Name of resource to update"` + Desc string `metavar:"" help:"Description"` +} + +func (opts *BaseUpdateOptions) GetId() string { + return opts.ID +} diff --git a/pkg/mcclient/options/network.go b/pkg/mcclient/options/network.go new file mode 100644 index 0000000000..ddab37c1a9 --- /dev/null +++ b/pkg/mcclient/options/network.go @@ -0,0 +1,140 @@ +// 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 options + +import ( + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/cmd/climc/shell" +) + +type NetworkListOptions struct { + BaseListOptions + + Ip string `help:"search networks that contain this IP"` + ZoneIds []string `help:"search networks in zones"` + Wire string `help:"search networks belongs to a wire" json:"-"` + Host string `help:"search networks attached to a host"` + Vpc string `help:"search networks belongs to a VPC"` + Region string `help:"search networks belongs to a CloudRegion" json:"cloudregion"` + City string `help:"search networks belongs to a city"` + Usable *bool `help:"search usable networks"` + ServerType string `help:"search networks belongs to a ServerType" choices:"baremetal|container|eip|guest|ipmi|pxe"` + Schedtag string `help:"filter networks by schedtag"` + + IsAutoAlloc *bool `help:"search network with is_auto_alloc"` + IsClassic *bool `help:"search classic on-premise network"` + + Status string `help:"filter by network status"` +} + +func (opts *NetworkListOptions) GetContextId() string { + return opts.Wire +} + +func (opts *NetworkListOptions) Params() (jsonutils.JSONObject, error) { + return ListStructToParams(opts) +} + +type NetworkUpdateOptions struct { + BaseUpdateOptions + + ServerType string `help:"server type," choices:"baremetal|container|eip|guest|ipmi|pxe"` + StartIp string `help:"Start ip"` + EndIp string `help:"end ip"` + NetMask int64 `help:"Netmask"` + Gateway string `help:"IP of gateway"` + Dns string `help:"IP of DNS server"` + Domain string `help:"Domain"` + Dhcp string `help:"DHCP server IP"` + VlanId int64 `help:"Vlan ID" default:"1"` + ExternalId string `help:"External ID"` + AllocPolicy string `help:"Address allocation policy" choices:"none|stepdown|stepup|random"` + IsAutoAlloc *bool `help:"Add network into auto-allocation pool" negative:"no_auto_alloc"` +} + +func (opts *NetworkUpdateOptions) Params() (jsonutils.JSONObject, error) { + params := jsonutils.NewDict() + if len(opts.Name) > 0 { + params.Add(jsonutils.NewString(opts.Name), "name") + } + if len(opts.Desc) > 0 { + params.Add(jsonutils.NewString(opts.Desc), "description") + } + if len(opts.ServerType) > 0 { + params.Add(jsonutils.NewString(opts.ServerType), "server_type") + } + if len(opts.StartIp) > 0 { + params.Add(jsonutils.NewString(opts.StartIp), "guest_ip_start") + } + if len(opts.EndIp) > 0 { + params.Add(jsonutils.NewString(opts.EndIp), "guest_ip_end") + } + if opts.NetMask > 0 { + params.Add(jsonutils.NewInt(opts.NetMask), "guest_ip_mask") + } + if len(opts.Gateway) > 0 { + params.Add(jsonutils.NewString(opts.Gateway), "guest_gateway") + } + if len(opts.Dns) > 0 { + if opts.Dns == "none" { + params.Add(jsonutils.NewString(""), "guest_dns") + } else { + params.Add(jsonutils.NewString(opts.Dns), "guest_dns") + } + } + if len(opts.Domain) > 0 { + if opts.Domain == "none" { + params.Add(jsonutils.NewString(""), "guest_domain") + } else { + params.Add(jsonutils.NewString(opts.Domain), "guest_domain") + } + } + if len(opts.Dhcp) > 0 { + if opts.Dhcp == "none" { + params.Add(jsonutils.NewString(""), "guest_dhcp") + } else { + params.Add(jsonutils.NewString(opts.Dhcp), "guest_dhcp") + } + } + if opts.VlanId > 0 { + params.Add(jsonutils.NewInt(opts.VlanId), "vlan_id") + } + if len(opts.ExternalId) > 0 { + params.Add(jsonutils.NewString(opts.ExternalId), "external_id") + } + if len(opts.AllocPolicy) > 0 { + params.Add(jsonutils.NewString(opts.AllocPolicy), "alloc_policy") + } + if opts.IsAutoAlloc != nil { + params.Add(jsonutils.NewBool(*opts.IsAutoAlloc), "is_auto_alloc") + } + if params.Size() == 0 { + return nil, shell.InvalidUpdateError() + } + return params, nil +} + +type NetworkIdOptions struct { + ID string `help:"ID or Name of the network to show"` +} + +func (opts *NetworkIdOptions) GetId() string { + return opts.ID +} + +func (opts *NetworkIdOptions) Params() (jsonutils.JSONObject, error) { + return nil, nil +}