blob: 69ead3b232c2c7dc40c54310655d1d1aa72c6ad5 [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}}"
Scott Bakerb6f07692020-06-10 12:52:15 -070031 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 -070032 DEFAULT_LOGICAL_DEVICE_INSPECT_FORMAT = `ID: {{.Id}}
33 DATAPATHID: {{.DatapathId}}
34 ROOTDEVICEID: {{.RootDeviceId}}
Scott Baker9173ed82020-05-19 08:30:12 -070035 SERIALNUMNER: {{.Desc.SerialNum}}`
Zack Williamse940c7a2019-08-21 14:25:39 -070036)
37
38type LogicalDeviceId string
39
40type LogicalDeviceList struct {
41 ListOutputOptions
42}
43
44type LogicalDeviceFlowList struct {
45 ListOutputOptions
Maninder045921e2020-09-29 16:46:02 +053046 FlowIdOptions
Zack Williamse940c7a2019-08-21 14:25:39 -070047 Args struct {
48 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
49 } `positional-args:"yes"`
50}
51
Himani Chawla3c161c62021-05-13 16:36:51 +053052type LogicalDeviceFlowGroupList struct {
53 ListOutputOptions
54 GroupListOptions
55 Args struct {
56 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
57 } `positional-args:"yes"`
58}
59
Zack Williamse940c7a2019-08-21 14:25:39 -070060type LogicalDevicePortList struct {
61 ListOutputOptions
62 Args struct {
63 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
64 } `positional-args:"yes"`
65}
66
67type LogicalDeviceInspect struct {
68 OutputOptionsJson
69 Args struct {
70 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
71 } `positional-args:"yes"`
72}
73
74type LogicalDeviceOpts struct {
Himani Chawla3c161c62021-05-13 16:36:51 +053075 List LogicalDeviceList `command:"list"`
76 Flows LogicalDeviceFlowList `command:"flows"`
77 Groups LogicalDeviceFlowGroupList `command:"groups"`
78 Port struct {
kesavand12cd8eb2020-01-20 22:25:22 -050079 List LogicalDevicePortList `command:"list"`
80 } `command:"port"`
81 Inspect LogicalDeviceInspect `command:"inspect"`
Zack Williamse940c7a2019-08-21 14:25:39 -070082}
83
84var logicalDeviceOpts = LogicalDeviceOpts{}
85
86func RegisterLogicalDeviceCommands(parser *flags.Parser) {
David Bainbridge12f036f2019-10-15 22:09:04 +000087 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 +000088 Error.Fatalf("Unexpected error while attempting to register logical device commands : %s", err)
David Bainbridge12f036f2019-10-15 22:09:04 +000089 }
Zack Williamse940c7a2019-08-21 14:25:39 -070090}
91
92func (i *LogicalDeviceId) Complete(match string) []flags.Completion {
93 conn, err := NewConnection()
94 if err != nil {
95 return nil
96 }
97 defer conn.Close()
98
Scott Baker9173ed82020-05-19 08:30:12 -070099 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700100
David K. Bainbridge9189c632021-03-26 21:52:21 +0000101 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700102 defer cancel()
103
Scott Baker9173ed82020-05-19 08:30:12 -0700104 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -0700105 if err != nil {
106 return nil
107 }
108
109 list := make([]flags.Completion, 0)
Scott Baker9173ed82020-05-19 08:30:12 -0700110 for _, item := range logicalDevices.Items {
111 if strings.HasPrefix(item.Id, match) {
112 list = append(list, flags.Completion{Item: item.Id})
Zack Williamse940c7a2019-08-21 14:25:39 -0700113 }
114 }
115
116 return list
117}
118
119func (options *LogicalDeviceList) Execute(args []string) error {
120
121 conn, err := NewConnection()
122 if err != nil {
123 return err
124 }
125 defer conn.Close()
126
Scott Baker9173ed82020-05-19 08:30:12 -0700127 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700128
David K. Bainbridge9189c632021-03-26 21:52:21 +0000129 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700130 defer cancel()
131
Scott Baker9173ed82020-05-19 08:30:12 -0700132 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -0700133 if err != nil {
134 return err
135 }
136
Scott Baker9173ed82020-05-19 08:30:12 -0700137 // Make sure json output prints an empty list, not "null"
138 if logicalDevices.Items == nil {
139 logicalDevices.Items = make([]*voltha.LogicalDevice, 0)
Zack Williamse940c7a2019-08-21 14:25:39 -0700140 }
141
142 outputFormat := CharReplacer.Replace(options.Format)
143 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000144 outputFormat = GetCommandOptionWithDefault("logical-device-list", "format", DEFAULT_LOGICAL_DEVICE_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700145 }
146 if options.Quiet {
147 outputFormat = "{{.Id}}"
148 }
David Bainbridgea6722342019-10-24 23:55:53 +0000149 orderBy := options.OrderBy
150 if orderBy == "" {
151 orderBy = GetCommandOptionWithDefault("local-device-list", "order", "")
152 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700153
Zack Williamse940c7a2019-08-21 14:25:39 -0700154 result := CommandResult{
155 Format: format.Format(outputFormat),
156 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000157 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700158 OutputAs: toOutputType(options.OutputAs),
159 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700160 Data: logicalDevices.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700161 }
162
163 GenerateOutput(&result)
164 return nil
165}
166
167func (options *LogicalDevicePortList) Execute(args []string) error {
168
169 conn, err := NewConnection()
170 if err != nil {
171 return err
172 }
173 defer conn.Close()
174
Scott Baker9173ed82020-05-19 08:30:12 -0700175 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700176
David K. Bainbridge9189c632021-03-26 21:52:21 +0000177 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700178 defer cancel()
179
Scott Baker9173ed82020-05-19 08:30:12 -0700180 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700181
Scott Baker9173ed82020-05-19 08:30:12 -0700182 ports, err := client.ListLogicalDevicePorts(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700183 if err != nil {
184 return err
185 }
186
Scott Bakerb6f07692020-06-10 12:52:15 -0700187 // ensure no nil pointers
188 for _, v := range ports.Items {
189 if v.OfpPortStats == nil {
190 v.OfpPortStats = &openflow_13.OfpPortStats{}
191 }
192 if v.OfpPort == nil {
193 v.OfpPort = &openflow_13.OfpPort{}
194 }
195 }
196
Zack Williamse940c7a2019-08-21 14:25:39 -0700197 outputFormat := CharReplacer.Replace(options.Format)
198 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000199 outputFormat = GetCommandOptionWithDefault("logical-device-ports", "format", DEFAULT_LOGICAL_DEVICE_PORT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700200 }
201 if options.Quiet {
202 outputFormat = "{{.Id}}"
203 }
David Bainbridgea6722342019-10-24 23:55:53 +0000204 orderBy := options.OrderBy
205 if orderBy == "" {
206 orderBy = GetCommandOptionWithDefault("logical-device-ports", "order", "")
207 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700208
Zack Williamse940c7a2019-08-21 14:25:39 -0700209 result := CommandResult{
210 Format: format.Format(outputFormat),
211 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000212 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700213 OutputAs: toOutputType(options.OutputAs),
214 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700215 Data: ports.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700216 }
217
218 GenerateOutput(&result)
219 return nil
220}
221
222func (options *LogicalDeviceFlowList) Execute(args []string) error {
223 fl := &FlowList{}
224 fl.ListOutputOptions = options.ListOutputOptions
Maninder045921e2020-09-29 16:46:02 +0530225 fl.FlowIdOptions = options.FlowIdOptions
Zack Williamse940c7a2019-08-21 14:25:39 -0700226 fl.Args.Id = string(options.Args.Id)
David Bainbridgea6722342019-10-24 23:55:53 +0000227 fl.Method = "logical-device-flows"
Zack Williamse940c7a2019-08-21 14:25:39 -0700228 return fl.Execute(args)
229}
230
Himani Chawla3c161c62021-05-13 16:36:51 +0530231func (options *LogicalDeviceFlowGroupList) Execute(args []string) error {
232 grp := &GroupList{}
233 grp.ListOutputOptions = options.ListOutputOptions
234 grp.GroupListOptions = options.GroupListOptions
235 grp.Args.Id = string(options.Args.Id)
236 grp.Method = "logical-device-groups"
237 return grp.Execute(args)
238
239}
240
Zack Williamse940c7a2019-08-21 14:25:39 -0700241func (options *LogicalDeviceInspect) Execute(args []string) error {
242 if len(args) > 0 {
243 return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")
244 }
245
246 conn, err := NewConnection()
247 if err != nil {
248 return err
249 }
250 defer conn.Close()
251
Scott Baker9173ed82020-05-19 08:30:12 -0700252 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700253
David K. Bainbridge9189c632021-03-26 21:52:21 +0000254 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700255 defer cancel()
256
Scott Baker9173ed82020-05-19 08:30:12 -0700257 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700258
Scott Baker9173ed82020-05-19 08:30:12 -0700259 logicalDevice, err := client.GetLogicalDevice(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700260 if err != nil {
261 return err
262 }
263
Zack Williamse940c7a2019-08-21 14:25:39 -0700264 outputFormat := CharReplacer.Replace(options.Format)
265 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000266 outputFormat = GetCommandOptionWithDefault("logical-device-inspect", "format", DEFAULT_LOGICAL_DEVICE_INSPECT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700267 }
268 if options.Quiet {
269 outputFormat = "{{.Id}}"
270 }
271
272 result := CommandResult{
273 Format: format.Format(outputFormat),
274 OutputAs: toOutputType(options.OutputAs),
275 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700276 Data: logicalDevice,
Zack Williamse940c7a2019-08-21 14:25:39 -0700277 }
278 GenerateOutput(&result)
279 return nil
280}