blob: adef6ff1e8b03fa3f911c2e618a72ce6492d4216 [file] [log] [blame]
Zsolt Harasztid036b7e2016-12-23 15:36:01 -08001#!/usr/bin/env python
2#
3# Copyright 2016 the original author or authors.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18"""
19Device level CLI commands
20"""
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -040021from optparse import make_option
22from cmd2 import Cmd, options
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080023from simplejson import dumps
24
Zsolt Haraszti85f12852016-12-24 08:30:58 -080025from cli.table import print_pb_as_table, print_pb_list_as_table
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080026from cli.utils import print_flows, pb2dict
27from voltha.protos import third_party
28
29_ = third_party
30from voltha.protos import voltha_pb2
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -040031from voltha.protos.device_pb2 import PmConfigs, PmConfig, PmGroupConfig
32from google.protobuf.json_format import MessageToDict
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080033
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -040034# Since proto3 won't send fields that are set to 0/false/"" any object that
35# might have those values set in them needs to be replicated here such that the
36# fields can be adequately
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080037
38class DeviceCli(Cmd):
39
40 def __init__(self, get_channel, device_id):
41 Cmd.__init__(self)
42 self.get_channel = get_channel
43 self.device_id = device_id
44 self.prompt = '(' + self.colorize(
45 self.colorize('device {}'.format(device_id), 'red'), 'bold') + ') '
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -040046 self.pm_config_last = None
47 self.pm_config_dirty = False
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080048
Zsolt Haraszti9b485fb2016-12-26 23:11:15 -080049 def cmdloop(self):
50 self._cmdloop()
51
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080052 def get_device(self, depth=0):
53 stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
54 res = stub.GetDevice(voltha_pb2.ID(id=self.device_id),
55 metadata=(('get-depth', str(depth)), ))
56 return res
57
Zsolt Haraszti80175202016-12-24 00:17:51 -080058 do_exit = Cmd.do_quit
Zsolt Harasztid036b7e2016-12-23 15:36:01 -080059
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -040060 def do_quit(self, line):
61 if self.pm_config_dirty:
62 self.poutput("Uncommited changes for " + \
63 self.colorize(
64 self.colorize("perf_config,", "blue"),
65 "bold") + " please either " + self.colorize(
66 self.colorize("commit", "blue"), "bold") + \
67 " or " + self.colorize(
68 self.colorize("reset", "blue"), "bold") + \
69 " your changes using " + \
70 self.colorize(
71 self.colorize("perf_config", "blue"), "bold"))
72 return False
73 else:
74 return self._STOP_AND_EXIT
75
Zsolt Haraszti80175202016-12-24 00:17:51 -080076 def do_show(self, line):
77 """Show detailed device information"""
Zsolt Haraszti85f12852016-12-24 08:30:58 -080078 print_pb_as_table('Device {}'.format(self.device_id),
79 self.get_device(depth=-1))
80
81 def do_ports(self, line):
82 """Show ports of device"""
83 device = self.get_device(depth=-1)
84 omit_fields = {
85 }
86 print_pb_list_as_table('Device ports:', device.ports,
87 omit_fields, self.poutput)
Zsolt Haraszti80175202016-12-24 00:17:51 -080088
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -040089 def help_perf_config(self):
90 self.poutput(
91'''
92perfo_config [show | set | commit | reset] [-f <default frequency>] [-e <metric/group
93 name>] [-d <metric/group name>] [-o <metric/group name> <override
94 frequency>]
95Changes made by set are held locally until a commit or reset command is issued.
96A commit command will write the configuration to the device and it takes effect
97immediately. The reset command will undo any changes sinc the start of the
98device session.
99
100If grouped is tre then the -d, -e and -o commands refer to groups and not
101individual metrics.
102'''
103 )
104
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400105 @options([
106 make_option('-f', '--default_freq', action="store", dest='default_freq',
107 type='long', default=None),
108 make_option('-e', '--enable', action='append', dest='enable',
109 default=None),
110 make_option('-d', '--disable', action='append', dest='disable',
111 default=None),
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400112 make_option('-o', '--overried', action='store', dest='override',
113 nargs=2, default=None, type='string'),
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400114 ])
115 def do_perf_config(self, line, opts):
116 print(line)
117 """Show and set the performance monitoring configuration of the device"""
118
119 device = self.get_device(depth=-1)
120 if not self.pm_config_last:
121 self.pm_config_last = device.pm_configs
122
123 # Ensure that a valid sub-command was provided
124 if line.strip() not in {"set", "show", "commit", "reset", ""}:
125 self.poutput(self.colorize('Error: ', 'red') + \
126 self.colorize(self.colorize(line.strip(), 'blue'),
127 'bold') + ' is not recognized')
128 return
129
130 # Ensure no options are provided when requesting to view the config
131 if line.strip() == "show" or line.strip() == "":
132 if opts.default_freq or opts.enable or opts.disable:
133 self.poutput(opts.disable)
134 self.poutput(self.colorize('Error: ', 'red') + 'use ' + \
135 self.colorize(self.colorize('"set"', 'blue'),
136 'bold') + ' to change settings')
137 return
138
139 if line.strip() == "set": # Set the supplied values
140 # The defualt frequency
141 if opts.default_freq:
142 self.pm_config_last.default_freq = opts.default_freq
143 self.pm_config_dirty = True
144
145 if self.pm_config_last.grouped:
146 for g in self.pm_config_last.groups:
147 if opts.enable:
148 if g.group_name in opts.enable:
149 g.enabled = True
150 self.pm_config_dirty = True
151 for g in self.pm_config_last.groups:
152 if opts.disable:
153 if g.group_name in opts.disable:
154 g.enabled = False
155 self.pm_config_dirty = True
156 else:
157 for m in self.pm_config_last.metrics:
158 if opts.enable:
159 if m.name in opts.enable:
160 m.enabled = True
161 self.pm_config_dirty = True
162 for m in self.pm_config_last.metrics:
163 if opts.disable:
164 if m.name in opts.disable:
165 m.enabled = False
166 self.pm_config_dirty = True
167 #TODO: Add frequency overrides.
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400168 if opts.override:
169 pass
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400170 elif line.strip() == "commit" and self.pm_config_dirty:
171 stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
172 stub.UpdateDevicePmConfigs(self.pm_config_last)
173 self.pm_config_last = self.get_device(depth=-1).pm_configs
174 self.pm_config_dirty = False
175 elif line.strip() == "reset" and self.pm_config_dirty:
176 self.pm_config_last = self.get_device(depth=-1).pm_configs
177 self.pm_config_dirty = False
178
179 omit_fields = {'groups', 'metrics', 'id'}
180 print_pb_as_table('PM Config:', self.pm_config_last, omit_fields,
181 self.poutput)
182 if self.pm_config_last.grouped:
183 #self.poutput("Supported metric groups:")
184 for g in self.pm_config_last.groups:
185 if self.pm_config_last.freq_override:
186 omit_fields = {'metrics'}
187 else:
188 omit_fields = {'group_freq','metrics'}
189 print_pb_as_table('', g, omit_fields, self.poutput)
190 if g.enabled:
191 state = 'enabled'
192 else:
193 state = 'disabled'
194 print_pb_list_as_table(
195 'Metric group {} is {}'.format(g.name,state),
196 g.metrics, {'enabled', 'sample_freq'}, self.poutput,
197 dividers=100)
198 else:
199 if self.pm_config_last.freq_override:
200 omit_fields = {}
201 else:
202 omit_fields = {'sample_freq'}
203 print_pb_list_as_table('Supported metrics:', self.pm_config_last.metrics,
204 omit_fields, self.poutput, dividers=100)
205
206
Zsolt Haraszti80175202016-12-24 00:17:51 -0800207 def do_flows(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800208 """Show flow table for device"""
209 device = pb2dict(self.get_device(-1))
210 print_flows(
211 'Device',
212 self.device_id,
213 type=device['type'],
214 flows=device['flows']['items'],
215 groups=device['flow_groups']['items']
216 )
217