blob: 3a5dd66b38c100338b0b0b7833aedba695779f5c [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"
Scott Bakerb6f07692020-06-10 12:52:15 -070024 "github.com/opencord/voltha-protos/v3/go/openflow_13"
Scott Baker9173ed82020-05-19 08:30:12 -070025 "github.com/opencord/voltha-protos/v3/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
46 Args struct {
47 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
48 } `positional-args:"yes"`
49}
50
51type LogicalDevicePortList struct {
52 ListOutputOptions
53 Args struct {
54 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
55 } `positional-args:"yes"`
56}
57
58type LogicalDeviceInspect struct {
59 OutputOptionsJson
60 Args struct {
61 Id LogicalDeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
62 } `positional-args:"yes"`
63}
64
65type LogicalDeviceOpts struct {
kesavand12cd8eb2020-01-20 22:25:22 -050066 List LogicalDeviceList `command:"list"`
67 Flows LogicalDeviceFlowList `command:"flows"`
68 Port struct {
69 List LogicalDevicePortList `command:"list"`
70 } `command:"port"`
71 Inspect LogicalDeviceInspect `command:"inspect"`
Zack Williamse940c7a2019-08-21 14:25:39 -070072}
73
74var logicalDeviceOpts = LogicalDeviceOpts{}
75
76func RegisterLogicalDeviceCommands(parser *flags.Parser) {
David Bainbridge12f036f2019-10-15 22:09:04 +000077 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 +000078 Error.Fatalf("Unexpected error while attempting to register logical device commands : %s", err)
David Bainbridge12f036f2019-10-15 22:09:04 +000079 }
Zack Williamse940c7a2019-08-21 14:25:39 -070080}
81
82func (i *LogicalDeviceId) Complete(match string) []flags.Completion {
83 conn, err := NewConnection()
84 if err != nil {
85 return nil
86 }
87 defer conn.Close()
88
Scott Baker9173ed82020-05-19 08:30:12 -070089 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -070090
91 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
92 defer cancel()
93
Scott Baker9173ed82020-05-19 08:30:12 -070094 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -070095 if err != nil {
96 return nil
97 }
98
99 list := make([]flags.Completion, 0)
Scott Baker9173ed82020-05-19 08:30:12 -0700100 for _, item := range logicalDevices.Items {
101 if strings.HasPrefix(item.Id, match) {
102 list = append(list, flags.Completion{Item: item.Id})
Zack Williamse940c7a2019-08-21 14:25:39 -0700103 }
104 }
105
106 return list
107}
108
109func (options *LogicalDeviceList) Execute(args []string) error {
110
111 conn, err := NewConnection()
112 if err != nil {
113 return err
114 }
115 defer conn.Close()
116
Scott Baker9173ed82020-05-19 08:30:12 -0700117 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700118
119 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
120 defer cancel()
121
Scott Baker9173ed82020-05-19 08:30:12 -0700122 logicalDevices, err := client.ListLogicalDevices(ctx, &empty.Empty{})
Zack Williamse940c7a2019-08-21 14:25:39 -0700123 if err != nil {
124 return err
125 }
126
Scott Baker9173ed82020-05-19 08:30:12 -0700127 // Make sure json output prints an empty list, not "null"
128 if logicalDevices.Items == nil {
129 logicalDevices.Items = make([]*voltha.LogicalDevice, 0)
Zack Williamse940c7a2019-08-21 14:25:39 -0700130 }
131
132 outputFormat := CharReplacer.Replace(options.Format)
133 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000134 outputFormat = GetCommandOptionWithDefault("logical-device-list", "format", DEFAULT_LOGICAL_DEVICE_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700135 }
136 if options.Quiet {
137 outputFormat = "{{.Id}}"
138 }
David Bainbridgea6722342019-10-24 23:55:53 +0000139 orderBy := options.OrderBy
140 if orderBy == "" {
141 orderBy = GetCommandOptionWithDefault("local-device-list", "order", "")
142 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700143
Zack Williamse940c7a2019-08-21 14:25:39 -0700144 result := CommandResult{
145 Format: format.Format(outputFormat),
146 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000147 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700148 OutputAs: toOutputType(options.OutputAs),
149 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700150 Data: logicalDevices.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700151 }
152
153 GenerateOutput(&result)
154 return nil
155}
156
157func (options *LogicalDevicePortList) Execute(args []string) error {
158
159 conn, err := NewConnection()
160 if err != nil {
161 return err
162 }
163 defer conn.Close()
164
Scott Baker9173ed82020-05-19 08:30:12 -0700165 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700166
167 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
168 defer cancel()
169
Scott Baker9173ed82020-05-19 08:30:12 -0700170 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700171
Scott Baker9173ed82020-05-19 08:30:12 -0700172 ports, err := client.ListLogicalDevicePorts(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700173 if err != nil {
174 return err
175 }
176
Scott Bakerb6f07692020-06-10 12:52:15 -0700177 // ensure no nil pointers
178 for _, v := range ports.Items {
179 if v.OfpPortStats == nil {
180 v.OfpPortStats = &openflow_13.OfpPortStats{}
181 }
182 if v.OfpPort == nil {
183 v.OfpPort = &openflow_13.OfpPort{}
184 }
185 }
186
Zack Williamse940c7a2019-08-21 14:25:39 -0700187 outputFormat := CharReplacer.Replace(options.Format)
188 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000189 outputFormat = GetCommandOptionWithDefault("logical-device-ports", "format", DEFAULT_LOGICAL_DEVICE_PORT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700190 }
191 if options.Quiet {
192 outputFormat = "{{.Id}}"
193 }
David Bainbridgea6722342019-10-24 23:55:53 +0000194 orderBy := options.OrderBy
195 if orderBy == "" {
196 orderBy = GetCommandOptionWithDefault("logical-device-ports", "order", "")
197 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700198
Zack Williamse940c7a2019-08-21 14:25:39 -0700199 result := CommandResult{
200 Format: format.Format(outputFormat),
201 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000202 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700203 OutputAs: toOutputType(options.OutputAs),
204 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700205 Data: ports.Items,
Zack Williamse940c7a2019-08-21 14:25:39 -0700206 }
207
208 GenerateOutput(&result)
209 return nil
210}
211
212func (options *LogicalDeviceFlowList) Execute(args []string) error {
213 fl := &FlowList{}
214 fl.ListOutputOptions = options.ListOutputOptions
215 fl.Args.Id = string(options.Args.Id)
David Bainbridgea6722342019-10-24 23:55:53 +0000216 fl.Method = "logical-device-flows"
Zack Williamse940c7a2019-08-21 14:25:39 -0700217 return fl.Execute(args)
218}
219
220func (options *LogicalDeviceInspect) Execute(args []string) error {
221 if len(args) > 0 {
222 return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")
223 }
224
225 conn, err := NewConnection()
226 if err != nil {
227 return err
228 }
229 defer conn.Close()
230
Scott Baker9173ed82020-05-19 08:30:12 -0700231 client := voltha.NewVolthaServiceClient(conn)
Zack Williamse940c7a2019-08-21 14:25:39 -0700232
233 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
234 defer cancel()
235
Scott Baker9173ed82020-05-19 08:30:12 -0700236 id := voltha.ID{Id: string(options.Args.Id)}
Zack Williamse940c7a2019-08-21 14:25:39 -0700237
Scott Baker9173ed82020-05-19 08:30:12 -0700238 logicalDevice, err := client.GetLogicalDevice(ctx, &id)
Zack Williamse940c7a2019-08-21 14:25:39 -0700239 if err != nil {
240 return err
241 }
242
Zack Williamse940c7a2019-08-21 14:25:39 -0700243 outputFormat := CharReplacer.Replace(options.Format)
244 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000245 outputFormat = GetCommandOptionWithDefault("logical-device-inspect", "format", DEFAULT_LOGICAL_DEVICE_INSPECT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700246 }
247 if options.Quiet {
248 outputFormat = "{{.Id}}"
249 }
250
251 result := CommandResult{
252 Format: format.Format(outputFormat),
253 OutputAs: toOutputType(options.OutputAs),
254 NameLimit: options.NameLimit,
Scott Baker9173ed82020-05-19 08:30:12 -0700255 Data: logicalDevice,
Zack Williamse940c7a2019-08-21 14:25:39 -0700256 }
257 GenerateOutput(&result)
258 return nil
259}