blob: aefacfb5f6f0047c0042aede5aff6ae6d722e876 [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"
David Bainbridge7052fe82020-03-25 10:37:00 -070021 "os"
22 "strconv"
23 "strings"
24
Zack Williamse940c7a2019-08-21 14:25:39 -070025 "github.com/fullstorydev/grpcurl"
26 flags "github.com/jessevdk/go-flags"
27 "github.com/jhump/protoreflect/dynamic"
Scott Baker2b0ad652019-08-21 14:57:07 -070028 "github.com/opencord/voltctl/pkg/format"
29 "github.com/opencord/voltctl/pkg/model"
Zack Williamse940c7a2019-08-21 14:25:39 -070030)
31
32const (
David K. Bainbridge89003c42020-02-27 17:22:49 -080033 DEFAULT_DEVICE_FORMAT = "table{{ .Id }}\t{{.Type}}\t{{.Root}}\t{{.ParentId}}\t{{.SerialNumber}}\t{{.AdminState}}\t{{.OperStatus}}\t{{.ConnectStatus}}\t{{.Reason}}"
Zack Williamse940c7a2019-08-21 14:25:39 -070034 DEFAULT_DEVICE_PORTS_FORMAT = "table{{.PortNo}}\t{{.Label}}\t{{.Type}}\t{{.AdminState}}\t{{.OperStatus}}\t{{.DeviceId}}\t{{.Peers}}"
35 DEFAULT_DEVICE_INSPECT_FORMAT = `ID: {{.Id}}
36 TYPE: {{.Type}}
37 ROOT: {{.Root}}
38 PARENTID: {{.ParentId}}
39 SERIALNUMBER: {{.SerialNumber}}
40 VLAN: {{.Vlan}}
41 ADMINSTATE: {{.AdminState}}
42 OPERSTATUS: {{.OperStatus}}
43 CONNECTSTATUS: {{.ConnectStatus}}`
44)
45
46type DeviceList struct {
47 ListOutputOptions
48}
49
50type DeviceCreate struct {
David Bainbridge835dd0e2020-04-01 10:30:09 -070051 DeviceType string `short:"t" long:"devicetype" default:"" description:"Device type"`
52 MACAddress string `short:"m" long:"macaddress" default:"" description:"MAC Address"`
Zack Williamse940c7a2019-08-21 14:25:39 -070053 IPAddress string `short:"i" long:"ipaddress" default:"" description:"IP Address"`
54 HostAndPort string `short:"H" long:"hostandport" default:"" description:"Host and port"`
55}
56
57type DeviceId string
58
kesavand12cd8eb2020-01-20 22:25:22 -050059type PortNum uint32
60
Zack Williamse940c7a2019-08-21 14:25:39 -070061type DeviceDelete struct {
62 Args struct {
63 Ids []DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
64 } `positional-args:"yes"`
65}
66
67type DeviceEnable struct {
68 Args struct {
69 Ids []DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
70 } `positional-args:"yes"`
71}
72
73type DeviceDisable struct {
74 Args struct {
75 Ids []DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
76 } `positional-args:"yes"`
77}
78
79type DeviceReboot struct {
80 Args struct {
81 Ids []DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
82 } `positional-args:"yes"`
83}
84
85type DeviceFlowList struct {
86 ListOutputOptions
87 Args struct {
88 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
89 } `positional-args:"yes"`
90}
91
92type DevicePortList struct {
93 ListOutputOptions
94 Args struct {
95 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
96 } `positional-args:"yes"`
97}
98
99type DeviceInspect struct {
100 OutputOptionsJson
101 Args struct {
102 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
103 } `positional-args:"yes"`
104}
105
kesavand12cd8eb2020-01-20 22:25:22 -0500106type DevicePortEnable struct {
107 Args struct {
108 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
109 PortId PortNum `positional-arg-name:"PORT_NUMBER" required:"yes"`
110 } `positional-args:"yes"`
111}
112
113type DevicePortDisable struct {
114 Args struct {
115 Id DeviceId `positional-arg-name:"DEVICE_ID" required:"yes"`
116 PortId PortNum `positional-arg-name:"PORT_NUMBER" required:"yes"`
117 } `positional-args:"yes"`
118}
119
Zack Williamse940c7a2019-08-21 14:25:39 -0700120type DeviceOpts struct {
121 List DeviceList `command:"list"`
122 Create DeviceCreate `command:"create"`
123 Delete DeviceDelete `command:"delete"`
124 Enable DeviceEnable `command:"enable"`
125 Disable DeviceDisable `command:"disable"`
126 Flows DeviceFlowList `command:"flows"`
kesavand12cd8eb2020-01-20 22:25:22 -0500127 Port struct {
128 List DevicePortList `command:"list"`
129 Enable DevicePortEnable `command:"enable"`
130 Disable DevicePortDisable `command:"disable"`
131 } `command:"port"`
132 Inspect DeviceInspect `command:"inspect"`
133 Reboot DeviceReboot `command:"reboot"`
Zack Williamse940c7a2019-08-21 14:25:39 -0700134}
135
136var deviceOpts = DeviceOpts{}
137
138func RegisterDeviceCommands(parser *flags.Parser) {
David Bainbridge12f036f2019-10-15 22:09:04 +0000139 if _, err := parser.AddCommand("device", "device commands", "Commands to query and manipulate VOLTHA devices", &deviceOpts); err != nil {
David Bainbridgea6722342019-10-24 23:55:53 +0000140 Error.Fatalf("Unexpected error while attempting to register device commands : %s", err)
David Bainbridge12f036f2019-10-15 22:09:04 +0000141 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700142}
143
kesavand12cd8eb2020-01-20 22:25:22 -0500144func (i *PortNum) Complete(match string) []flags.Completion {
145 conn, err := NewConnection()
146 if err != nil {
147 return nil
148 }
149 defer conn.Close()
150
151 descriptor, method, err := GetMethod("device-ports")
152 if err != nil {
153 return nil
154 }
155
156 /*
157 * The command line args when completing for PortNum will be a DeviceId
158 * followed by one or more PortNums. So walk the argument list from the
159 * end and find the first argument that is enable/disable as those are
160 * the subcommands that come before the positional arguments. It would
161 * be nice if this package gave us the list of optional arguments
162 * already parsed.
163 */
164 var deviceId string
165found:
166 for i := len(os.Args) - 1; i >= 0; i -= 1 {
167 switch os.Args[i] {
168 case "enable":
169 fallthrough
170 case "disable":
171 if len(os.Args) > i+1 {
172 deviceId = os.Args[i+1]
173 } else {
174 return nil
175 }
176 break found
177 default:
178 }
179 }
180
181 if len(deviceId) == 0 {
182 return nil
183 }
184
185 h := &RpcEventHandler{
186 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": deviceId}},
187 }
188 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
189 defer cancel()
190 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
191 if err != nil {
192 return nil
193 }
194
195 if h.Status != nil && h.Status.Err() != nil {
196 return nil
197 }
198
199 d, err := dynamic.AsDynamicMessage(h.Response)
200 if err != nil {
201 return nil
202 }
203
204 items, err := d.TryGetFieldByName("items")
205 if err != nil {
206 return nil
207 }
208
209 list := make([]flags.Completion, 0)
210 for _, item := range items.([]interface{}) {
211 val := item.(*dynamic.Message)
212 pn := strconv.FormatUint(uint64(val.GetFieldByName("port_no").(uint32)), 10)
213 if strings.HasPrefix(pn, match) {
214 list = append(list, flags.Completion{Item: pn})
215 }
216 }
217
218 return list
219}
220
Zack Williamse940c7a2019-08-21 14:25:39 -0700221func (i *DeviceId) Complete(match string) []flags.Completion {
222 conn, err := NewConnection()
223 if err != nil {
224 return nil
225 }
226 defer conn.Close()
227
228 descriptor, method, err := GetMethod("device-list")
229 if err != nil {
230 return nil
231 }
232
233 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
234 defer cancel()
235
236 h := &RpcEventHandler{}
237 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
238 if err != nil {
239 return nil
240 }
241
242 if h.Status != nil && h.Status.Err() != nil {
243 return nil
244 }
245
246 d, err := dynamic.AsDynamicMessage(h.Response)
247 if err != nil {
248 return nil
249 }
250
251 items, err := d.TryGetFieldByName("items")
252 if err != nil {
253 return nil
254 }
255
256 list := make([]flags.Completion, 0)
257 for _, item := range items.([]interface{}) {
258 val := item.(*dynamic.Message)
259 id := val.GetFieldByName("id").(string)
260 if strings.HasPrefix(id, match) {
261 list = append(list, flags.Completion{Item: id})
262 }
263 }
264
265 return list
266}
267
268func (options *DeviceList) Execute(args []string) error {
269
270 conn, err := NewConnection()
271 if err != nil {
272 return err
273 }
274 defer conn.Close()
275
276 descriptor, method, err := GetMethod("device-list")
277 if err != nil {
278 return err
279 }
280
281 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
282 defer cancel()
283
284 h := &RpcEventHandler{}
285 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
286 if err != nil {
287 return err
288 }
289
290 if h.Status != nil && h.Status.Err() != nil {
291 return h.Status.Err()
292 }
293
294 d, err := dynamic.AsDynamicMessage(h.Response)
295 if err != nil {
296 return err
297 }
298
299 items, err := d.TryGetFieldByName("items")
300 if err != nil {
301 return err
302 }
303
304 outputFormat := CharReplacer.Replace(options.Format)
305 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000306 outputFormat = GetCommandOptionWithDefault("device-list", "format", DEFAULT_DEVICE_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700307 }
308 if options.Quiet {
309 outputFormat = "{{.Id}}"
310 }
311
David Bainbridgea6722342019-10-24 23:55:53 +0000312 orderBy := options.OrderBy
313 if orderBy == "" {
314 orderBy = GetCommandOptionWithDefault("device-list", "order", "")
315 }
316
Zack Williamse940c7a2019-08-21 14:25:39 -0700317 data := make([]model.Device, len(items.([]interface{})))
318 for i, item := range items.([]interface{}) {
319 val := item.(*dynamic.Message)
320 data[i].PopulateFrom(val)
321 }
322
323 result := CommandResult{
324 Format: format.Format(outputFormat),
325 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000326 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700327 OutputAs: toOutputType(options.OutputAs),
328 NameLimit: options.NameLimit,
329 Data: data,
330 }
331
332 GenerateOutput(&result)
333 return nil
334}
335
336func (options *DeviceCreate) Execute(args []string) error {
337
338 dm := make(map[string]interface{})
339 if options.HostAndPort != "" {
340 dm["host_and_port"] = options.HostAndPort
341 } else if options.IPAddress != "" {
342 dm["ipv4_address"] = options.IPAddress
Hardik Windlassce1de342020-02-04 21:58:07 +0000343 }
344 if options.MACAddress != "" {
Zack Williamse940c7a2019-08-21 14:25:39 -0700345 dm["mac_address"] = strings.ToLower(options.MACAddress)
346 }
347 if options.DeviceType != "" {
348 dm["type"] = options.DeviceType
349 }
350
351 conn, err := NewConnection()
352 if err != nil {
353 return err
354 }
355 defer conn.Close()
356
357 descriptor, method, err := GetMethod("device-create")
358 if err != nil {
359 return err
360 }
361
362 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
363 defer cancel()
364
365 h := &RpcEventHandler{
366 Fields: map[string]map[string]interface{}{"voltha.Device": dm},
367 }
368 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
369 if err != nil {
370 return err
371 } else if h.Status != nil && h.Status.Err() != nil {
372 return h.Status.Err()
373 }
374
375 resp, err := dynamic.AsDynamicMessage(h.Response)
376 if err != nil {
377 return err
378 }
379 fmt.Printf("%s\n", resp.GetFieldByName("id").(string))
380
381 return nil
382}
383
384func (options *DeviceDelete) Execute(args []string) error {
385
386 conn, err := NewConnection()
387 if err != nil {
388 return err
389 }
390 defer conn.Close()
391
392 descriptor, method, err := GetMethod("device-delete")
393 if err != nil {
394 return err
395 }
396
David Bainbridge7052fe82020-03-25 10:37:00 -0700397 var lastErr error
Zack Williamse940c7a2019-08-21 14:25:39 -0700398 for _, i := range options.Args.Ids {
399
400 h := &RpcEventHandler{
401 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": i}},
402 }
403 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
404 defer cancel()
405
406 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
407 if err != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000408 Error.Printf("Error while deleting '%s': %s\n", i, err)
David Bainbridge7052fe82020-03-25 10:37:00 -0700409 lastErr = err
Zack Williamse940c7a2019-08-21 14:25:39 -0700410 continue
411 } else if h.Status != nil && h.Status.Err() != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000412 Error.Printf("Error while deleting '%s': %s\n", i, ErrorToString(h.Status.Err()))
David Bainbridge7052fe82020-03-25 10:37:00 -0700413 lastErr = h.Status.Err()
Zack Williamse940c7a2019-08-21 14:25:39 -0700414 continue
415 }
416 fmt.Printf("%s\n", i)
417 }
418
David Bainbridge7052fe82020-03-25 10:37:00 -0700419 if lastErr != nil {
420 return NoReportErr
421 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700422 return nil
423}
424
425func (options *DeviceEnable) Execute(args []string) error {
426 conn, err := NewConnection()
427 if err != nil {
428 return err
429 }
430 defer conn.Close()
431
432 descriptor, method, err := GetMethod("device-enable")
433 if err != nil {
434 return err
435 }
436
David Bainbridge7052fe82020-03-25 10:37:00 -0700437 var lastErr error
Zack Williamse940c7a2019-08-21 14:25:39 -0700438 for _, i := range options.Args.Ids {
439 h := &RpcEventHandler{
440 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": i}},
441 }
442 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
443 defer cancel()
444
445 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
446 if err != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000447 Error.Printf("Error while enabling '%s': %s\n", i, err)
David Bainbridge7052fe82020-03-25 10:37:00 -0700448 lastErr = err
Zack Williamse940c7a2019-08-21 14:25:39 -0700449 continue
450 } else if h.Status != nil && h.Status.Err() != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000451 Error.Printf("Error while enabling '%s': %s\n", i, ErrorToString(h.Status.Err()))
David Bainbridge7052fe82020-03-25 10:37:00 -0700452 lastErr = h.Status.Err()
Zack Williamse940c7a2019-08-21 14:25:39 -0700453 continue
454 }
455 fmt.Printf("%s\n", i)
456 }
457
David Bainbridge7052fe82020-03-25 10:37:00 -0700458 if lastErr != nil {
459 return NoReportErr
460 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700461 return nil
462}
463
464func (options *DeviceDisable) Execute(args []string) error {
465 conn, err := NewConnection()
466 if err != nil {
467 return err
468 }
469 defer conn.Close()
470
471 descriptor, method, err := GetMethod("device-disable")
472 if err != nil {
473 return err
474 }
475
David Bainbridge7052fe82020-03-25 10:37:00 -0700476 var lastErr error
Zack Williamse940c7a2019-08-21 14:25:39 -0700477 for _, i := range options.Args.Ids {
478 h := &RpcEventHandler{
479 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": i}},
480 }
481 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
482 defer cancel()
483
484 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
485 if err != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000486 Error.Printf("Error while disabling '%s': %s\n", i, err)
David Bainbridge7052fe82020-03-25 10:37:00 -0700487 lastErr = err
Zack Williamse940c7a2019-08-21 14:25:39 -0700488 continue
489 } else if h.Status != nil && h.Status.Err() != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000490 Error.Printf("Error while disabling '%s': %s\n", i, ErrorToString(h.Status.Err()))
David Bainbridge7052fe82020-03-25 10:37:00 -0700491 lastErr = h.Status.Err()
Zack Williamse940c7a2019-08-21 14:25:39 -0700492 continue
493 }
494 fmt.Printf("%s\n", i)
495 }
496
David Bainbridge7052fe82020-03-25 10:37:00 -0700497 if lastErr != nil {
498 return NoReportErr
499 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700500 return nil
501}
502
503func (options *DeviceReboot) Execute(args []string) error {
504 conn, err := NewConnection()
505 if err != nil {
506 return err
507 }
508 defer conn.Close()
509
510 descriptor, method, err := GetMethod("device-reboot")
511 if err != nil {
512 return err
513 }
514
David Bainbridge7052fe82020-03-25 10:37:00 -0700515 var lastErr error
Zack Williamse940c7a2019-08-21 14:25:39 -0700516 for _, i := range options.Args.Ids {
517 h := &RpcEventHandler{
518 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": i}},
519 }
520 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
521 defer cancel()
522
523 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
524 if err != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000525 Error.Printf("Error while rebooting '%s': %s\n", i, err)
David Bainbridge7052fe82020-03-25 10:37:00 -0700526 lastErr = err
Zack Williamse940c7a2019-08-21 14:25:39 -0700527 continue
528 } else if h.Status != nil && h.Status.Err() != nil {
David Bainbridge0f758d42019-10-26 05:17:48 +0000529 Error.Printf("Error while rebooting '%s': %s\n", i, ErrorToString(h.Status.Err()))
David Bainbridge7052fe82020-03-25 10:37:00 -0700530 lastErr = h.Status.Err()
Zack Williamse940c7a2019-08-21 14:25:39 -0700531 continue
532 }
533 fmt.Printf("%s\n", i)
534 }
535
David Bainbridge7052fe82020-03-25 10:37:00 -0700536 if lastErr != nil {
537 return NoReportErr
538 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700539 return nil
540}
541
542func (options *DevicePortList) Execute(args []string) error {
543
544 conn, err := NewConnection()
545 if err != nil {
546 return err
547 }
548 defer conn.Close()
549
550 descriptor, method, err := GetMethod("device-ports")
551 if err != nil {
552 return err
553 }
554
555 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
556 defer cancel()
557
558 h := &RpcEventHandler{
559 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": options.Args.Id}},
560 }
561 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
562 if err != nil {
563 return err
564 }
565
566 if h.Status != nil && h.Status.Err() != nil {
567 return h.Status.Err()
568 }
569
570 d, err := dynamic.AsDynamicMessage(h.Response)
571 if err != nil {
572 return err
573 }
574
575 items, err := d.TryGetFieldByName("items")
576 if err != nil {
577 return err
578 }
579
580 outputFormat := CharReplacer.Replace(options.Format)
581 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000582 outputFormat = GetCommandOptionWithDefault("device-ports", "format", DEFAULT_DEVICE_PORTS_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700583 }
584 if options.Quiet {
585 outputFormat = "{{.Id}}"
586 }
587
David Bainbridgea6722342019-10-24 23:55:53 +0000588 orderBy := options.OrderBy
589 if orderBy == "" {
590 orderBy = GetCommandOptionWithDefault("device-ports", "order", "")
591 }
592
Zack Williamse940c7a2019-08-21 14:25:39 -0700593 data := make([]model.DevicePort, len(items.([]interface{})))
594 for i, item := range items.([]interface{}) {
595 data[i].PopulateFrom(item.(*dynamic.Message))
596 }
597
598 result := CommandResult{
599 Format: format.Format(outputFormat),
600 Filter: options.Filter,
David Bainbridgea6722342019-10-24 23:55:53 +0000601 OrderBy: orderBy,
Zack Williamse940c7a2019-08-21 14:25:39 -0700602 OutputAs: toOutputType(options.OutputAs),
603 NameLimit: options.NameLimit,
604 Data: data,
605 }
606
607 GenerateOutput(&result)
608 return nil
609}
610
611func (options *DeviceFlowList) Execute(args []string) error {
612 fl := &FlowList{}
613 fl.ListOutputOptions = options.ListOutputOptions
614 fl.Args.Id = string(options.Args.Id)
David Bainbridgea6722342019-10-24 23:55:53 +0000615 fl.Method = "device-flows"
Zack Williamse940c7a2019-08-21 14:25:39 -0700616 return fl.Execute(args)
617}
618
619func (options *DeviceInspect) Execute(args []string) error {
620 if len(args) > 0 {
621 return fmt.Errorf("only a single argument 'DEVICE_ID' can be provided")
622 }
623
624 conn, err := NewConnection()
625 if err != nil {
626 return err
627 }
628 defer conn.Close()
629
630 descriptor, method, err := GetMethod("device-inspect")
631 if err != nil {
632 return err
633 }
634
635 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
636 defer cancel()
637
638 h := &RpcEventHandler{
639 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["ID"]: {"id": options.Args.Id}},
640 }
641 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{"Get-Depth: 2"}, h, h.GetParams)
642 if err != nil {
643 return err
644 } else if h.Status != nil && h.Status.Err() != nil {
645 return h.Status.Err()
646 }
647
648 d, err := dynamic.AsDynamicMessage(h.Response)
649 if err != nil {
650 return err
651 }
652
653 device := &model.Device{}
654 device.PopulateFrom(d)
655
656 outputFormat := CharReplacer.Replace(options.Format)
657 if outputFormat == "" {
David Bainbridgea6722342019-10-24 23:55:53 +0000658 outputFormat = GetCommandOptionWithDefault("device-inspect", "format", DEFAULT_DEVICE_INSPECT_FORMAT)
Zack Williamse940c7a2019-08-21 14:25:39 -0700659 }
660 if options.Quiet {
661 outputFormat = "{{.Id}}"
662 }
663
664 result := CommandResult{
665 Format: format.Format(outputFormat),
666 OutputAs: toOutputType(options.OutputAs),
667 NameLimit: options.NameLimit,
668 Data: device,
669 }
670 GenerateOutput(&result)
671 return nil
672}
kesavand12cd8eb2020-01-20 22:25:22 -0500673
674/*Device Port Enable */
675func (options *DevicePortEnable) Execute(args []string) error {
676 conn, err := NewConnection()
677 if err != nil {
678 return err
679 }
680 defer conn.Close()
681
682 descriptor, method, err := GetMethod("device-port-enable")
683 if err != nil {
684 return err
685 }
686
687 h := &RpcEventHandler{
688 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["port"]: {"device_id": options.Args.Id, "port_no": options.Args.PortId}},
689 }
690 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
691 defer cancel()
692
693 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
694 if err != nil {
695 Error.Printf("Error enabling port number %v on device Id %s,err=%s\n", options.Args.PortId, options.Args.Id, ErrorToString(err))
696 return err
697 } else if h.Status != nil && h.Status.Err() != nil {
698 Error.Printf("Error enabling port number %v on device Id %s,err=%s\n", options.Args.PortId, options.Args.Id, ErrorToString(h.Status.Err()))
699 return h.Status.Err()
700 }
701
702 return nil
703}
704
705/*Device Port Disable */
706func (options *DevicePortDisable) Execute(args []string) error {
707 conn, err := NewConnection()
708 if err != nil {
709 return err
710 }
711 defer conn.Close()
712
713 descriptor, method, err := GetMethod("device-port-disable")
714 if err != nil {
715 return err
716 }
717 h := &RpcEventHandler{
718 Fields: map[string]map[string]interface{}{ParamNames[GlobalConfig.ApiVersion]["port"]: {"device_id": options.Args.Id, "port_no": options.Args.PortId}},
719 }
720 ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
721 defer cancel()
722
723 err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
724 if err != nil {
725 Error.Printf("Error disabling port number %v on device Id %s,err=%s\n", options.Args.PortId, options.Args.Id, ErrorToString(err))
726 return err
727 } else if h.Status != nil && h.Status.Err() != nil {
728 Error.Printf("Error disabling port number %v on device Id %s,err=%s\n", options.Args.PortId, options.Args.Id, ErrorToString(h.Status.Err()))
729 return h.Status.Err()
730 }
731 return nil
732}