Code changes for VOL-3928 Voltctl support to list flow groups
Change-Id: I4e374a0c837511f41bed25937f70c5781133debf
diff --git a/VERSION b/VERSION
index 9f05f9f..ec70f75 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.5
+1.6.6
diff --git a/internal/pkg/commands/command.go b/internal/pkg/commands/command.go
index ec9318c..8cefc14 100644
--- a/internal/pkg/commands/command.go
+++ b/internal/pkg/commands/command.go
@@ -114,6 +114,9 @@
HexId bool `short:"x" long:"hex-id" description:"Output Ids in hex format"`
}
+type GroupListOptions struct {
+ Bucket bool `short:"b" long:"buckets" description:"Display Buckets"`
+}
type ListOutputOptions struct {
OutputOptions
Filter string `short:"f" long:"filter" default:"" value-name:"FILTER" description:"Only display results that match filter"`
diff --git a/internal/pkg/commands/devices.go b/internal/pkg/commands/devices.go
index 10ebad8..073cd66 100644
--- a/internal/pkg/commands/devices.go
+++ b/internal/pkg/commands/devices.go
@@ -132,6 +132,13 @@
} `positional-args:"yes"`
}
+type DeviceFlowGroupList struct {
+ ListOutputOptions
+ GroupListOptions
+ Args struct {
+ Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
+ } `positional-args:"yes"`
+}
type DevicePortList struct {
ListOutputOptions
Args struct {
@@ -367,12 +374,13 @@
}
type DeviceOpts struct {
- List DeviceList `command:"list"`
- Create DeviceCreate `command:"create"`
- Delete DeviceDelete `command:"delete"`
- Enable DeviceEnable `command:"enable"`
- Disable DeviceDisable `command:"disable"`
- Flows DeviceFlowList `command:"flows"`
+ List DeviceList `command:"list"`
+ Create DeviceCreate `command:"create"`
+ Delete DeviceDelete `command:"delete"`
+ Enable DeviceEnable `command:"enable"`
+ Disable DeviceDisable `command:"disable"`
+ Flows DeviceFlowList `command:"flows"`
+ Groups DeviceFlowGroupList `command:"groups"`
Port struct {
List DevicePortList `command:"list"`
Enable DevicePortEnable `command:"enable"`
@@ -890,6 +898,15 @@
return fl.Execute(args)
}
+func (options *DeviceFlowGroupList) Execute(args []string) error {
+ grp := &GroupList{}
+ grp.ListOutputOptions = options.ListOutputOptions
+ grp.GroupListOptions = options.GroupListOptions
+ grp.Args.Id = string(options.Args.Id)
+ grp.Method = "device-groups"
+ return grp.Execute(args)
+}
+
func (options *DeviceInspect) Execute(args []string) error {
if len(args) > 0 {
return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")
diff --git a/internal/pkg/commands/groups.go b/internal/pkg/commands/groups.go
new file mode 100644
index 0000000..5e71e8f
--- /dev/null
+++ b/internal/pkg/commands/groups.go
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2021-present Ciena Corporation
+ *
+ * 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 commands
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/opencord/voltctl/pkg/format"
+ "github.com/opencord/voltha-protos/v4/go/openflow_13"
+ "github.com/opencord/voltha-protos/v4/go/voltha"
+)
+
+const (
+ DEFAULT_DEVICE_GROUPS_FORMAT = "table{{.GroupId}}\t{{.Type}}"
+ DEFAULT_DEVICE_GROUPS_BUCKET_FORMAT = "table{{.GroupId}}\t{{.Buckets}}\t{{.Type}}"
+)
+
+type GroupList struct {
+ ListOutputOptions
+ GroupListOptions
+ Args struct {
+ Id string `positional-arg-name:"DEVICE_ID" required:"yes"`
+ } `positional-args:"yes"`
+
+ Method string
+}
+
+func (options *GroupList) Execute(args []string) error {
+
+ conn, err := NewConnection()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := voltha.NewVolthaServiceClient(conn)
+
+ ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
+ defer cancel()
+
+ id := voltha.ID{Id: string(options.Args.Id)}
+
+ var groups *openflow_13.FlowGroups
+ switch options.Method {
+ case "device-groups":
+ groups, err = client.ListDeviceFlowGroups(ctx, &id)
+ case "logical-device-groups":
+ groups, err = client.ListLogicalDeviceFlowGroups(ctx, &id)
+ default:
+ Error.Fatalf("Unknown method name: '%s'", options.Method)
+ }
+
+ var groupList []*openflow_13.OfpGroupDesc
+ if err != nil {
+ return err
+ }
+ if toOutputType(options.OutputAs) == OUTPUT_TABLE && (groups == nil || len(groups.Items) == 0) {
+ fmt.Println("*** NO GROUPS ***")
+ return nil
+ }
+ for _, item := range groups.Items {
+ if item.Desc.Type != openflow_13.OfpGroupType_OFPGT_FF {
+ // Since onos is setting watch port and watch group as max uint32,
+ // for group type other than FF, we need to remove watch port and group for them.
+ for _, bucket := range item.Desc.Buckets {
+ bucket.WatchPort = 0
+ bucket.WatchGroup = 0
+ }
+ }
+ groupList = append(groupList, item.Desc)
+ }
+
+ outputFormat := CharReplacer.Replace(options.Format)
+ if options.Quiet {
+ outputFormat = "{{.GroupId}}"
+ } else if outputFormat == "" {
+ if options.Bucket {
+ outputFormat = GetCommandOptionWithDefault(options.Method, "format", DEFAULT_DEVICE_GROUPS_BUCKET_FORMAT)
+ } else {
+ outputFormat = GetCommandOptionWithDefault(options.Method, "format", DEFAULT_DEVICE_GROUPS_FORMAT)
+ }
+ }
+
+ orderBy := options.OrderBy
+ if orderBy == "" {
+ orderBy = GetCommandOptionWithDefault(options.Method, "order", "")
+ }
+
+ result := CommandResult{
+ Format: format.Format(outputFormat),
+ Filter: options.Filter,
+ OrderBy: orderBy,
+ OutputAs: toOutputType(options.OutputAs),
+ NameLimit: options.NameLimit,
+ Data: groupList,
+ }
+ GenerateOutput(&result)
+
+ return nil
+}
diff --git a/internal/pkg/commands/logicaldevices.go b/internal/pkg/commands/logicaldevices.go
index 9191385..2f2a1bc 100644
--- a/internal/pkg/commands/logicaldevices.go
+++ b/internal/pkg/commands/logicaldevices.go
@@ -49,6 +49,14 @@
} `positional-args:"yes"`
}
+type LogicalDeviceFlowGroupList struct {
+ ListOutputOptions
+ GroupListOptions
+ Args struct {
+ Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
+ } `positional-args:"yes"`
+}
+
type LogicalDevicePortList struct {
ListOutputOptions
Args struct {
@@ -64,9 +72,10 @@
}
type LogicalDeviceOpts struct {
- List LogicalDeviceList `command:"list"`
- Flows LogicalDeviceFlowList `command:"flows"`
- Port struct {
+ List LogicalDeviceList `command:"list"`
+ Flows LogicalDeviceFlowList `command:"flows"`
+ Groups LogicalDeviceFlowGroupList `command:"groups"`
+ Port struct {
List LogicalDevicePortList `command:"list"`
} `command:"port"`
Inspect LogicalDeviceInspect `command:"inspect"`
@@ -219,6 +228,16 @@
return fl.Execute(args)
}
+func (options *LogicalDeviceFlowGroupList) Execute(args []string) error {
+ grp := &GroupList{}
+ grp.ListOutputOptions = options.ListOutputOptions
+ grp.GroupListOptions = options.GroupListOptions
+ grp.Args.Id = string(options.Args.Id)
+ grp.Method = "logical-device-groups"
+ return grp.Execute(args)
+
+}
+
func (options *LogicalDeviceInspect) Execute(args []string) error {
if len(args) > 0 {
return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")