blob: cb66ac8625c8574487c1991f8d5bb50568bfdf06 [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001/*
2 * Copyright 2019-present Ciena Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package commands
17
18import (
19 "context"
20 "fmt"
Scott Baker9173ed82020-05-19 08:30:12 -070021 "github.com/golang/protobuf/ptypes/empty"
Zack Williamse940c7a2019-08-21 14:25:39 -070022 flags "github.com/jessevdk/go-flags"
Scott Baker2b0ad652019-08-21 14:57:07 -070023 "github.com/opencord/voltctl/pkg/format"
David K. Bainbridgebd6b2882021-08-26 13:31:02 +000024 "github.com/opencord/voltha-protos/v5/go/openflow_13"
25 "github.com/opencord/voltha-protos/v5/go/voltha"
Zack Williamse940c7a2019-08-21 14:25:39 -070026 "strings"
27)
28
29const (
Scott Baker9173ed82020-05-19 08:30:12 -070030 DEFAULT_LOGICAL_DEVICE_FORMAT = "table{{ .Id }}\t{{printf \"%016x\" .DatapathId}}\t{{.RootDeviceId}}\t{{.Desc.SerialNum}}\t{{.SwitchFeatures.NBuffers}}\t{{.SwitchFeatures.NTables}}\t{{printf \"0x%08x\" .SwitchFeatures.Capabilities}}"
Hardik Windlass9361bb82022-03-23 05:58:48 +000031 DEFAULT_LOGICAL_DEVICE_ORDER = "Id"
Scott Bakerb6f07692020-06-10 12:52:15 -070032 DEFAULT_LOGICAL_DEVICE_PORT_FORMAT = "table{{.Id}}\t{{.DeviceId}}\t{{.DevicePortNo}}\t{{.RootPort}}\t{{.OfpPortStats.PortNo}}\t{{.OfpPort.HwAddr}}\t{{.OfpPort.Name}}\t{{printf \"0x%08x\" .OfpPort.State}}\t{{printf \"0x%08x\" .OfpPort.Curr}}\t{{.OfpPort.CurrSpeed}}"
Zack Williamse940c7a2019-08-21 14:25:39 -070033 DEFAULT_LOGICAL_DEVICE_INSPECT_FORMAT = `ID: {{.Id}}
34 DATAPATHID: {{.DatapathId}}
35 ROOTDEVICEID: {{.RootDeviceId}}
Scott Baker9173ed82020-05-19 08:30:12 -070036 SERIALNUMNER: {{.Desc.SerialNum}}`
Zack Williamse940c7a2019-08-21 14:25:39 -070037)
38
39type LogicalDeviceId string
40
41type LogicalDeviceList struct {
42 ListOutputOptions
43}
44
45type LogicalDeviceFlowList struct {
46 ListOutputOptions
Maninder045921e2020-09-29 16:46:02 +053047 FlowIdOptions
Zack Williamse940c7a2019-08-21 14:25:39 -070048 Args struct {
49 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
50 } `positional-args:"yes"`
51}
52
Himani Chawla3c161c62021-05-13 16:36:51 +053053type LogicalDeviceFlowGroupList struct {
54 ListOutputOptions
55 GroupListOptions
56 Args struct {
57 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
58 } `positional-args:"yes"`
59}
60
Zack Williamse940c7a2019-08-21 14:25:39 -070061type LogicalDevicePortList struct {
62 ListOutputOptions
63 Args struct {
64 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
65 } `positional-args:"yes"`
66}
67
68type LogicalDeviceInspect struct {
69 OutputOptionsJson
70 Args struct {
71 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
72 } `positional-args:"yes"`
73}
74
75type LogicalDeviceOpts struct {
Himani Chawla3c161c62021-05-13 16:36:51 +053076 List LogicalDeviceList `command:"list"`
77 Flows LogicalDeviceFlowList `command:"flows"`
78 Groups LogicalDeviceFlowGroupList `command:"groups"`
79 Port struct {
kesavand12cd8eb2020-01-20 22:25:22 -050080 List LogicalDevicePortList `command:"list"`
81 } `command:"port"`
82 Inspect LogicalDeviceInspect `command:"inspect"`
Zack Williamse940c7a2019-08-21 14:25:39 -070083}
84
85var logicalDeviceOpts = LogicalDeviceOpts{}
86
87func RegisterLogicalDeviceCommands(parser *flags.Parser) {
David Bainbridge12f036f2019-10-15 22:09:04 +000088 if _, err := parser.AddCommand("logicaldevice", "logical device commands", "Commands to query and manipulate VOLTHA logical devices", &logicalDeviceOpts); err != nil {
David Bainbridgea6722342019-10-24 23:55:53 +000089 Error.Fatalf("Unexpected error while attempting to register logical device commands : %s", err)
David Bainbridge12f036f2019-10-15 22:09:04 +000090 }
Zack Williamse940c7a2019-08-21 14:25:39 -070091}
92
93func (i *LogicalDeviceId) Complete(match string) []flags.Completion {
94 conn, err := NewConnection()
95 if err != nil {
96 return nil
97 }
98 defer conn.Close()
99
Scott Baker9173ed82020-05-19 08:30:12 -0700100 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700101
David K. Bainbridge9189c632021-03-26 21:52:21 +0000102 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700103 defer cancel()
104
Scott Baker9173ed82020-05-19 08:30:12 -0700105 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -0700106 if err != nil {
107 return nil
108 }
109
110 list := make([]flags.Completion, 0)
Scott Baker9173ed82020-05-19 08:30:12 -0700111 for _, item := range logicalDevices.Items {
112 if strings.HasPrefix(item.Id, match) {
113 list = append(list, flags.Completion{Item: item.Id})
Zack Williamse940c7a2019-08-21 14:25:39 -0700114 }
115 }
116
117 return list
118}
119
120func (options *LogicalDeviceList) Execute(args []string) error {
121
122 conn, err := NewConnection()
123 if err != nil {
124 return err
125 }
126 defer conn.Close()
127
Scott Baker9173ed82020-05-19 08:30:12 -0700128 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700129
David K. Bainbridge9189c632021-03-26 21:52:21 +0000130 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700131 defer cancel()
132
Scott Baker9173ed82020-05-19 08:30:12 -0700133 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -0700134 if err != nil {
135 return err
136 }
137
Scott Baker9173ed82020-05-19 08:30:12 -0700138 // Make sure json output prints an empty list, not "null"
139 if logicalDevices.Items == nil {
140 logicalDevices.Items = make([]*voltha.LogicalDevice, 0)
Zack Williamse940c7a2019-08-21 14:25:39 -0700141 }
142
143 outputFormat := CharReplacer.Replace(options.Format)
144 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000145 outputFormat = GetCommandOptionWithDefault("logical-device-list", "format", DEFAULT_LOGICAL_DEVICE_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700146 }
147 if options.Quiet {
148 outputFormat = "{{.Id}}"
149 }
David Bainbridgea6722342019-10-24 23:55:53 +0000150 orderBy := options.OrderBy
151 if orderBy == "" {
Hardik Windlass9361bb82022-03-23 05:58:48 +0000152 orderBy = GetCommandOptionWithDefault("local-device-list", "order", DEFAULT_LOGICAL_DEVICE_ORDER)
David Bainbridgea6722342019-10-24 23:55:53 +0000153 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700154
Zack Williamse940c7a2019-08-21 14:25:39 -0700155 result := CommandResult{
156 Format: format.Format(outputFormat),
157 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000158 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700159 OutputAs: toOutputType(options.OutputAs),
160 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700161 Data: logicalDevices.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700162 }
163
164 GenerateOutput(&result)
165 return nil
166}
167
168func (options *LogicalDevicePortList) Execute(args []string) error {
169
170 conn, err := NewConnection()
171 if err != nil {
172 return err
173 }
174 defer conn.Close()
175
Scott Baker9173ed82020-05-19 08:30:12 -0700176 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700177
David K. Bainbridge9189c632021-03-26 21:52:21 +0000178 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700179 defer cancel()
180
Scott Baker9173ed82020-05-19 08:30:12 -0700181 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700182
Scott Baker9173ed82020-05-19 08:30:12 -0700183 ports, err := client.ListLogicalDevicePorts(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700184 if err != nil {
185 return err
186 }
187
Scott Bakerb6f07692020-06-10 12:52:15 -0700188 // ensure no nil pointers
189 for _, v := range ports.Items {
190 if v.OfpPortStats == nil {
191 v.OfpPortStats = &openflow_13.OfpPortStats{}
192 }
193 if v.OfpPort == nil {
194 v.OfpPort = &openflow_13.OfpPort{}
195 }
196 }
197
Zack Williamse940c7a2019-08-21 14:25:39 -0700198 outputFormat := CharReplacer.Replace(options.Format)
199 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000200 outputFormat = GetCommandOptionWithDefault("logical-device-ports", "format", DEFAULT_LOGICAL_DEVICE_PORT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700201 }
202 if options.Quiet {
203 outputFormat = "{{.Id}}"
204 }
David Bainbridgea6722342019-10-24 23:55:53 +0000205 orderBy := options.OrderBy
206 if orderBy == "" {
207 orderBy = GetCommandOptionWithDefault("logical-device-ports", "order", "")
208 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700209
Zack Williamse940c7a2019-08-21 14:25:39 -0700210 result := CommandResult{
211 Format: format.Format(outputFormat),
212 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000213 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700214 OutputAs: toOutputType(options.OutputAs),
215 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700216 Data: ports.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700217 }
218
219 GenerateOutput(&result)
220 return nil
221}
222
223func (options *LogicalDeviceFlowList) Execute(args []string) error {
224 fl := &FlowList{}
225 fl.ListOutputOptions = options.ListOutputOptions
Maninder045921e2020-09-29 16:46:02 +0530226 fl.FlowIdOptions = options.FlowIdOptions
Zack Williamse940c7a2019-08-21 14:25:39 -0700227 fl.Args.Id = string(options.Args.Id)
David Bainbridgea6722342019-10-24 23:55:53 +0000228 fl.Method = "logical-device-flows"
Zack Williamse940c7a2019-08-21 14:25:39 -0700229 return fl.Execute(args)
230}
231
Himani Chawla3c161c62021-05-13 16:36:51 +0530232func (options *LogicalDeviceFlowGroupList) Execute(args []string) error {
233 grp := &GroupList{}
234 grp.ListOutputOptions = options.ListOutputOptions
235 grp.GroupListOptions = options.GroupListOptions
236 grp.Args.Id = string(options.Args.Id)
237 grp.Method = "logical-device-groups"
238 return grp.Execute(args)
239
240}
241
Zack Williamse940c7a2019-08-21 14:25:39 -0700242func (options *LogicalDeviceInspect) Execute(args []string) error {
243 if len(args) > 0 {
244 return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")
245 }
246
247 conn, err := NewConnection()
248 if err != nil {
249 return err
250 }
251 defer conn.Close()
252
Scott Baker9173ed82020-05-19 08:30:12 -0700253 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700254
David K. Bainbridge9189c632021-03-26 21:52:21 +0000255 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700256 defer cancel()
257
Scott Baker9173ed82020-05-19 08:30:12 -0700258 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700259
Scott Baker9173ed82020-05-19 08:30:12 -0700260 logicalDevice, err := client.GetLogicalDevice(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700261 if err != nil {
262 return err
263 }
264
Zack Williamse940c7a2019-08-21 14:25:39 -0700265 outputFormat := CharReplacer.Replace(options.Format)
266 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000267 outputFormat = GetCommandOptionWithDefault("logical-device-inspect", "format", DEFAULT_LOGICAL_DEVICE_INSPECT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700268 }
269 if options.Quiet {
270 outputFormat = "{{.Id}}"
271 }
272
273 result := CommandResult{
274 Format: format.Format(outputFormat),
275 OutputAs: toOutputType(options.OutputAs),
276 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700277 Data: logicalDevice,
Zack Williamse940c7a2019-08-21 14:25:39 -0700278 }
279 GenerateOutput(&result)
280 return nil
281}