blob: d503c48cee3a1da539598aba10dbaa0acaac2560 [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"""
Sergio Slobodrianb5ef3482017-03-17 16:56:16 -040078 omit_fields = {
79 'pm_configs',
80 'flows',
81 'flow_groups',
82 'ports',
83 'parent_port_no',
84 'reason',
85 'vlan',
86 'parent_id',
87 'root',
88 'type',
89 'vendor',
90 'id'
91 }
Zsolt Haraszti85f12852016-12-24 08:30:58 -080092 print_pb_as_table('Device {}'.format(self.device_id),
Sergio Slobodrianb5ef3482017-03-17 16:56:16 -040093 self.get_device(depth=-1), omit_fields)
Zsolt Haraszti85f12852016-12-24 08:30:58 -080094
95 def do_ports(self, line):
96 """Show ports of device"""
97 device = self.get_device(depth=-1)
98 omit_fields = {
Sergio Slobodrianb5ef3482017-03-17 16:56:16 -040099 'peers'
Zsolt Haraszti85f12852016-12-24 08:30:58 -0800100 }
101 print_pb_list_as_table('Device ports:', device.ports,
102 omit_fields, self.poutput)
Zsolt Haraszti80175202016-12-24 00:17:51 -0800103
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400104 def help_perf_config(self):
105 self.poutput(
106'''
107perfo_config [show | set | commit | reset] [-f <default frequency>] [-e <metric/group
108 name>] [-d <metric/group name>] [-o <metric/group name> <override
109 frequency>]
110Changes made by set are held locally until a commit or reset command is issued.
111A commit command will write the configuration to the device and it takes effect
112immediately. The reset command will undo any changes sinc the start of the
113device session.
114
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400115If grouped is true then the -d, -e and -o commands refer to groups and not
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400116individual metrics.
117'''
118 )
119
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400120 @options([
121 make_option('-f', '--default_freq', action="store", dest='default_freq',
122 type='long', default=None),
123 make_option('-e', '--enable', action='append', dest='enable',
124 default=None),
125 make_option('-d', '--disable', action='append', dest='disable',
126 default=None),
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400127 make_option('-o', '--overried', action='append', dest='override',
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400128 nargs=2, default=None, type='string'),
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400129 ])
130 def do_perf_config(self, line, opts):
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400131 #print(line)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400132 """Show and set the performance monitoring configuration of the device"""
133
134 device = self.get_device(depth=-1)
135 if not self.pm_config_last:
136 self.pm_config_last = device.pm_configs
137
138 # Ensure that a valid sub-command was provided
139 if line.strip() not in {"set", "show", "commit", "reset", ""}:
140 self.poutput(self.colorize('Error: ', 'red') + \
141 self.colorize(self.colorize(line.strip(), 'blue'),
142 'bold') + ' is not recognized')
143 return
144
145 # Ensure no options are provided when requesting to view the config
146 if line.strip() == "show" or line.strip() == "":
147 if opts.default_freq or opts.enable or opts.disable:
148 self.poutput(opts.disable)
149 self.poutput(self.colorize('Error: ', 'red') + 'use ' + \
150 self.colorize(self.colorize('"set"', 'blue'),
151 'bold') + ' to change settings')
152 return
153
154 if line.strip() == "set": # Set the supplied values
155 # The defualt frequency
156 if opts.default_freq:
157 self.pm_config_last.default_freq = opts.default_freq
158 self.pm_config_dirty = True
159
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400160 # Field or group visibility
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400161 if self.pm_config_last.grouped:
162 for g in self.pm_config_last.groups:
163 if opts.enable:
164 if g.group_name in opts.enable:
165 g.enabled = True
166 self.pm_config_dirty = True
167 for g in self.pm_config_last.groups:
168 if opts.disable:
169 if g.group_name in opts.disable:
170 g.enabled = False
171 self.pm_config_dirty = True
172 else:
173 for m in self.pm_config_last.metrics:
174 if opts.enable:
175 if m.name in opts.enable:
176 m.enabled = True
177 self.pm_config_dirty = True
178 for m in self.pm_config_last.metrics:
179 if opts.disable:
180 if m.name in opts.disable:
181 m.enabled = False
182 self.pm_config_dirty = True
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400183
184 #Frequency overrides.
185 if opts.override:
186 if self.pm_config_last.freq_override:
187 oo = dict()
188 for o in opts.override:
189 oo[o[0]] = o[1]
190 if self.pm_config_last.grouped:
191 for g in self.pm_config_last.groups:
192 if g.group_name in oo:
193 try:
194 g.group_freq = int(oo[g.group_name])
195 except ValueError:
196 self.poutput(self.colorize('Warning: ',
197 'yellow') + \
198 self.colorize(oo[m.name],
199 'blue') +\
200 " is not an integer... ignored")
201 del oo[g.group_name]
202 self.pm_config_dirty = True
203 else:
204 for m in self.pm_config_last.metrics:
205 if m.name in oo:
206 try:
207 m.sample_freq = int(oo[m.name])
208 except ValueError:
209 self.poutput(self.colorize('Warning: ',
210 'yellow') + \
211 self.colorize(oo[m.name],
212 'blue') +\
213 " is not an integer... ignored")
214 del oo[m.name]
215 self.pm_config_dirty = True
216
217 # If there's anything left the input was typoed
218 if self.pm_config_last.grouped:
219 field = 'group'
220 else:
221 field = 'metric'
222 for o in oo:
223 self.poutput(self.colorize('Warning: ', 'yellow') + \
224 'the parameter' + ' ' + \
225 self.colorize(o, 'blue') + ' is not ' + \
226 'a ' + field + ' name... ignored')
227 if oo:
228 return
229
230 else: # Frequency overrides not enabled
231 self.poutput(self.colorize('Error: ', 'red') + \
232 'Individual overrides are only ' + \
233 'supported if ' + \
234 self.colorize('freq_override', 'blue') + \
235 ' is set to ' + self.colorize('True', 'blue'))
236 return
237 self.poutput("Success")
238 return
239
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400240 elif line.strip() == "commit" and self.pm_config_dirty:
241 stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
242 stub.UpdateDevicePmConfigs(self.pm_config_last)
243 self.pm_config_last = self.get_device(depth=-1).pm_configs
244 self.pm_config_dirty = False
245 elif line.strip() == "reset" and self.pm_config_dirty:
246 self.pm_config_last = self.get_device(depth=-1).pm_configs
247 self.pm_config_dirty = False
248
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400249
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400250 omit_fields = {'groups', 'metrics', 'id'}
251 print_pb_as_table('PM Config:', self.pm_config_last, omit_fields,
252 self.poutput)
253 if self.pm_config_last.grouped:
254 #self.poutput("Supported metric groups:")
255 for g in self.pm_config_last.groups:
256 if self.pm_config_last.freq_override:
257 omit_fields = {'metrics'}
258 else:
259 omit_fields = {'group_freq','metrics'}
260 print_pb_as_table('', g, omit_fields, self.poutput)
261 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,
268 dividers=100)
269 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,
275 omit_fields, self.poutput, dividers=100)
276
277
Zsolt Haraszti80175202016-12-24 00:17:51 -0800278 def do_flows(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800279 """Show flow table for device"""
280 device = pb2dict(self.get_device(-1))
281 print_flows(
282 'Device',
283 self.device_id,
284 type=device['type'],
285 flows=device['flows']['items'],
286 groups=device['flow_groups']['items']
287 )
288