blob: 919138567e240880d18a923b93a7f704ec18fb13 [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"
kesavand8ec4fc02021-01-27 09:10:22 -050024 "github.com/opencord/voltha-protos/v4/go/openflow_13"
25 "github.com/opencord/voltha-protos/v4/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
52type LogicalDevicePortList struct {
53 ListOutputOptions
54 Args struct {
55 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
56 } `positional-args:"yes"`
57}
58
59type LogicalDeviceInspect struct {
60 OutputOptionsJson
61 Args struct {
62 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
63 } `positional-args:"yes"`
64}
65
66type LogicalDeviceOpts struct {
kesavand12cd8eb2020-01-20 22:25:22 -050067 List LogicalDeviceList `command:"list"`
68 Flows LogicalDeviceFlowList `command:"flows"`
69 Port struct {
70 List LogicalDevicePortList `command:"list"`
71 } `command:"port"`
72 Inspect LogicalDeviceInspect `command:"inspect"`
Zack Williamse940c7a2019-08-21 14:25:39 -070073}
74
75var logicalDeviceOpts = LogicalDeviceOpts{}
76
77func RegisterLogicalDeviceCommands(parser *flags.Parser) {
David Bainbridge12f036f2019-10-15 22:09:04 +000078 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 +000079 Error.Fatalf("Unexpected error while attempting to register logical device commands : %s", err)
David Bainbridge12f036f2019-10-15 22:09:04 +000080 }
Zack Williamse940c7a2019-08-21 14:25:39 -070081}
82
83func (i *LogicalDeviceId) Complete(match string) []flags.Completion {
84 conn, err := NewConnection()
85 if err != nil {
86 return nil
87 }
88 defer conn.Close()
89
Scott Baker9173ed82020-05-19 08:30:12 -070090 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -070091
David K. Bainbridge9189c632021-03-26 21:52:21 +000092 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -070093 defer cancel()
94
Scott Baker9173ed82020-05-19 08:30:12 -070095 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -070096 if err != nil {
97 return nil
98 }
99
100 list := make([]flags.Completion, 0)
Scott Baker9173ed82020-05-19 08:30:12 -0700101 for _, item := range logicalDevices.Items {
102 if strings.HasPrefix(item.Id, match) {
103 list = append(list, flags.Completion{Item: item.Id})
Zack Williamse940c7a2019-08-21 14:25:39 -0700104 }
105 }
106
107 return list
108}
109
110func (options *LogicalDeviceList) Execute(args []string) error {
111
112 conn, err := NewConnection()
113 if err != nil {
114 return err
115 }
116 defer conn.Close()
117
Scott Baker9173ed82020-05-19 08:30:12 -0700118 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700119
David K. Bainbridge9189c632021-03-26 21:52:21 +0000120 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700121 defer cancel()
122
Scott Baker9173ed82020-05-19 08:30:12 -0700123 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -0700124 if err != nil {
125 return err
126 }
127
Scott Baker9173ed82020-05-19 08:30:12 -0700128 // Make sure json output prints an empty list, not "null"
129 if logicalDevices.Items == nil {
130 logicalDevices.Items = make([]*voltha.LogicalDevice, 0)
Zack Williamse940c7a2019-08-21 14:25:39 -0700131 }
132
133 outputFormat := CharReplacer.Replace(options.Format)
134 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000135 outputFormat = GetCommandOptionWithDefault("logical-device-list", "format", DEFAULT_LOGICAL_DEVICE_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700136 }
137 if options.Quiet {
138 outputFormat = "{{.Id}}"
139 }
David Bainbridgea6722342019-10-24 23:55:53 +0000140 orderBy := options.OrderBy
141 if orderBy == "" {
142 orderBy = GetCommandOptionWithDefault("local-device-list", "order", "")
143 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700144
Zack Williamse940c7a2019-08-21 14:25:39 -0700145 result := CommandResult{
146 Format: format.Format(outputFormat),
147 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000148 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700149 OutputAs: toOutputType(options.OutputAs),
150 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700151 Data: logicalDevices.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700152 }
153
154 GenerateOutput(&result)
155 return nil
156}
157
158func (options *LogicalDevicePortList) Execute(args []string) error {
159
160 conn, err := NewConnection()
161 if err != nil {
162 return err
163 }
164 defer conn.Close()
165
Scott Baker9173ed82020-05-19 08:30:12 -0700166 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700167
David K. Bainbridge9189c632021-03-26 21:52:21 +0000168 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700169 defer cancel()
170
Scott Baker9173ed82020-05-19 08:30:12 -0700171 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700172
Scott Baker9173ed82020-05-19 08:30:12 -0700173 ports, err := client.ListLogicalDevicePorts(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700174 if err != nil {
175 return err
176 }
177
Scott Bakerb6f07692020-06-10 12:52:15 -0700178 // ensure no nil pointers
179 for _, v := range ports.Items {
180 if v.OfpPortStats == nil {
181 v.OfpPortStats = &openflow_13.OfpPortStats{}
182 }
183 if v.OfpPort == nil {
184 v.OfpPort = &openflow_13.OfpPort{}
185 }
186 }
187
Zack Williamse940c7a2019-08-21 14:25:39 -0700188 outputFormat := CharReplacer.Replace(options.Format)
189 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000190 outputFormat = GetCommandOptionWithDefault("logical-device-ports", "format", DEFAULT_LOGICAL_DEVICE_PORT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700191 }
192 if options.Quiet {
193 outputFormat = "{{.Id}}"
194 }
David Bainbridgea6722342019-10-24 23:55:53 +0000195 orderBy := options.OrderBy
196 if orderBy == "" {
197 orderBy = GetCommandOptionWithDefault("logical-device-ports", "order", "")
198 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700199
Zack Williamse940c7a2019-08-21 14:25:39 -0700200 result := CommandResult{
201 Format: format.Format(outputFormat),
202 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000203 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700204 OutputAs: toOutputType(options.OutputAs),
205 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700206 Data: ports.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700207 }
208
209 GenerateOutput(&result)
210 return nil
211}
212
213func (options *LogicalDeviceFlowList) Execute(args []string) error {
214 fl := &FlowList{}
215 fl.ListOutputOptions = options.ListOutputOptions
Maninder045921e2020-09-29 16:46:02 +0530216 fl.FlowIdOptions = options.FlowIdOptions
Zack Williamse940c7a2019-08-21 14:25:39 -0700217 fl.Args.Id = string(options.Args.Id)
David Bainbridgea6722342019-10-24 23:55:53 +0000218 fl.Method = "logical-device-flows"
Zack Williamse940c7a2019-08-21 14:25:39 -0700219 return fl.Execute(args)
220}
221
222func (options *LogicalDeviceInspect) Execute(args []string) error {
223 if len(args) > 0 {
224 return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")
225 }
226
227 conn, err := NewConnection()
228 if err != nil {
229 return err
230 }
231 defer conn.Close()
232
Scott Baker9173ed82020-05-19 08:30:12 -0700233 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700234
David K. Bainbridge9189c632021-03-26 21:52:21 +0000235 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Current().Grpc.Timeout)
Zack Williamse940c7a2019-08-21 14:25:39 -0700236 defer cancel()
237
Scott Baker9173ed82020-05-19 08:30:12 -0700238 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700239
Scott Baker9173ed82020-05-19 08:30:12 -0700240 logicalDevice, err := client.GetLogicalDevice(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700241 if err != nil {
242 return err
243 }
244
Zack Williamse940c7a2019-08-21 14:25:39 -0700245 outputFormat := CharReplacer.Replace(options.Format)
246 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000247 outputFormat = GetCommandOptionWithDefault("logical-device-inspect", "format", DEFAULT_LOGICAL_DEVICE_INSPECT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700248 }
249 if options.Quiet {
250 outputFormat = "{{.Id}}"
251 }
252
253 result := CommandResult{
254 Format: format.Format(outputFormat),
255 OutputAs: toOutputType(options.OutputAs),
256 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700257 Data: logicalDevice,
Zack Williamse940c7a2019-08-21 14:25:39 -0700258 }
259 GenerateOutput(&result)
260 return nil
261}