blob: fc7c4ec9b6ac2b1d16833458b5518869e09df03f [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),
Sergio Slobodriana95f99b2017-03-21 10:22:47 -040079 self.get_device(depth=-1))
Zsolt Haraszti85f12852016-12-24 08:30:58 -080080
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'''
Sergio Slobodrian57979ec2017-03-21 22:32:17 -040092perf_config [show | set | commit | reset] [-f <default frequency>] [{-e <metric/group
93 name>}] [{-d <metric/group name>}] [{-o <metric/group name> <override
94 frequency>}]
Sergio Slobodrian038bd3c2017-03-22 15:53:25 -040095
Sergio Slobodrian3fb99b32017-03-22 22:18:21 -040096show: displays the performance configuration of the device
Sergio Slobodrian57979ec2017-03-21 22:32:17 -040097set: changes the parameters specified with -e, -d, and -o
98reset: reverts any changes made since the last commit
99commit: commits any changes made which applies them to the device.
100
101-e: enable collection of the specified metric, more than one -e may be
102 specified.
Sergio Slobodrian3fb99b32017-03-22 22:18:21 -0400103-d: disable collection of the specified metric, more than on -d may be
Sergio Slobodrian57979ec2017-03-21 22:32:17 -0400104 specified.
105-o override the collection frequency of the specified metric, more than one -o
106 may be specified. Note that -o isn't valid unless
Sergio Slobodrian3fb99b32017-03-22 22:18:21 -0400107 frequency_override is set to True for the device.
Sergio Slobodrian57979ec2017-03-21 22:32:17 -0400108
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400109Changes made by set are held locally until a commit or reset command is issued.
110A commit command will write the configuration to the device and it takes effect
111immediately. The reset command will undo any changes sinc the start of the
112device session.
113
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400114If grouped is true then the -d, -e and -o commands refer to groups and not
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400115individual metrics.
116'''
117 )
118
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400119 @options([
120 make_option('-f', '--default_freq', action="store", dest='default_freq',
121 type='long', default=None),
122 make_option('-e', '--enable', action='append', dest='enable',
123 default=None),
124 make_option('-d', '--disable', action='append', dest='disable',
125 default=None),
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400126 make_option('-o', '--overried', action='append', dest='override',
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400127 nargs=2, default=None, type='string'),
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400128 ])
129 def do_perf_config(self, line, opts):
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400130 #print(line)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400131 """Show and set the performance monitoring configuration of the device"""
132
133 device = self.get_device(depth=-1)
134 if not self.pm_config_last:
135 self.pm_config_last = device.pm_configs
136
137 # Ensure that a valid sub-command was provided
138 if line.strip() not in {"set", "show", "commit", "reset", ""}:
139 self.poutput(self.colorize('Error: ', 'red') + \
140 self.colorize(self.colorize(line.strip(), 'blue'),
141 'bold') + ' is not recognized')
142 return
143
144 # Ensure no options are provided when requesting to view the config
145 if line.strip() == "show" or line.strip() == "":
146 if opts.default_freq or opts.enable or opts.disable:
147 self.poutput(opts.disable)
148 self.poutput(self.colorize('Error: ', 'red') + 'use ' + \
149 self.colorize(self.colorize('"set"', 'blue'),
150 'bold') + ' to change settings')
151 return
152
153 if line.strip() == "set": # Set the supplied values
154 # The defualt frequency
155 if opts.default_freq:
156 self.pm_config_last.default_freq = opts.default_freq
157 self.pm_config_dirty = True
158
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400159 # Field or group visibility
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400160 if self.pm_config_last.grouped:
161 for g in self.pm_config_last.groups:
162 if opts.enable:
163 if g.group_name in opts.enable:
164 g.enabled = True
165 self.pm_config_dirty = True
166 for g in self.pm_config_last.groups:
167 if opts.disable:
168 if g.group_name in opts.disable:
169 g.enabled = False
170 self.pm_config_dirty = True
171 else:
172 for m in self.pm_config_last.metrics:
173 if opts.enable:
174 if m.name in opts.enable:
175 m.enabled = True
176 self.pm_config_dirty = True
177 for m in self.pm_config_last.metrics:
178 if opts.disable:
179 if m.name in opts.disable:
180 m.enabled = False
181 self.pm_config_dirty = True
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400182
183 #Frequency overrides.
184 if opts.override:
185 if self.pm_config_last.freq_override:
186 oo = dict()
187 for o in opts.override:
188 oo[o[0]] = o[1]
189 if self.pm_config_last.grouped:
190 for g in self.pm_config_last.groups:
191 if g.group_name in oo:
192 try:
193 g.group_freq = int(oo[g.group_name])
194 except ValueError:
195 self.poutput(self.colorize('Warning: ',
196 'yellow') + \
197 self.colorize(oo[m.name],
198 'blue') +\
199 " is not an integer... ignored")
200 del oo[g.group_name]
201 self.pm_config_dirty = True
202 else:
203 for m in self.pm_config_last.metrics:
204 if m.name in oo:
205 try:
206 m.sample_freq = int(oo[m.name])
207 except ValueError:
208 self.poutput(self.colorize('Warning: ',
209 'yellow') + \
210 self.colorize(oo[m.name],
211 'blue') +\
212 " is not an integer... ignored")
213 del oo[m.name]
214 self.pm_config_dirty = True
215
216 # If there's anything left the input was typoed
217 if self.pm_config_last.grouped:
218 field = 'group'
219 else:
220 field = 'metric'
221 for o in oo:
222 self.poutput(self.colorize('Warning: ', 'yellow') + \
223 'the parameter' + ' ' + \
224 self.colorize(o, 'blue') + ' is not ' + \
225 'a ' + field + ' name... ignored')
226 if oo:
227 return
228
229 else: # Frequency overrides not enabled
230 self.poutput(self.colorize('Error: ', 'red') + \
231 'Individual overrides are only ' + \
232 'supported if ' + \
233 self.colorize('freq_override', 'blue') + \
234 ' is set to ' + self.colorize('True', 'blue'))
235 return
236 self.poutput("Success")
237 return
238
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400239 elif line.strip() == "commit" and self.pm_config_dirty:
240 stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
241 stub.UpdateDevicePmConfigs(self.pm_config_last)
242 self.pm_config_last = self.get_device(depth=-1).pm_configs
243 self.pm_config_dirty = False
244 elif line.strip() == "reset" and self.pm_config_dirty:
245 self.pm_config_last = self.get_device(depth=-1).pm_configs
246 self.pm_config_dirty = False
247
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400248
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400249 omit_fields = {'groups', 'metrics', 'id'}
250 print_pb_as_table('PM Config:', self.pm_config_last, omit_fields,
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400251 self.poutput,show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400252 if self.pm_config_last.grouped:
253 #self.poutput("Supported metric groups:")
254 for g in self.pm_config_last.groups:
255 if self.pm_config_last.freq_override:
256 omit_fields = {'metrics'}
257 else:
258 omit_fields = {'group_freq','metrics'}
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400259 print_pb_as_table('', g, omit_fields, self.poutput,
260 show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400261 if g.enabled:
262 state = 'enabled'
263 else:
264 state = 'disabled'
265 print_pb_list_as_table(
266 'Metric group {} is {}'.format(g.name,state),
267 g.metrics, {'enabled', 'sample_freq'}, self.poutput,
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400268 dividers=100, show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400269 else:
270 if self.pm_config_last.freq_override:
271 omit_fields = {}
272 else:
273 omit_fields = {'sample_freq'}
274 print_pb_list_as_table('Supported metrics:', self.pm_config_last.metrics,
Sergio Slobodrian038bd3c2017-03-22 15:53:25 -0400275 omit_fields, self.poutput, dividers=100,
276 show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400277
278
Zsolt Haraszti80175202016-12-24 00:17:51 -0800279 def do_flows(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800280 """Show flow table for device"""
281 device = pb2dict(self.get_device(-1))
282 print_flows(
283 'Device',
284 self.device_id,
285 type=device['type'],
286 flows=device['flows']['items'],
287 groups=device['flow_groups']['items']
288 )
289