blob: 37513df75b2643932ff39e81c8c107b5cf38c429 [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'''
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
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400100If grouped is true then the -d, -e and -o commands refer to groups and not
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400101individual 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 Slobodrian4236ade2017-03-17 22:01:20 -0400112 make_option('-o', '--overried', action='append', dest='override',
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400113 nargs=2, default=None, type='string'),
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400114 ])
115 def do_perf_config(self, line, opts):
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400116 #print(line)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400117 """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
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400145 # Field or group visibility
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400146 if self.pm_config_last.grouped:
147 for g in self.pm_config_last.groups:
148 if opts.enable:
149 if g.group_name in opts.enable:
150 g.enabled = True
151 self.pm_config_dirty = True
152 for g in self.pm_config_last.groups:
153 if opts.disable:
154 if g.group_name in opts.disable:
155 g.enabled = False
156 self.pm_config_dirty = True
157 else:
158 for m in self.pm_config_last.metrics:
159 if opts.enable:
160 if m.name in opts.enable:
161 m.enabled = True
162 self.pm_config_dirty = True
163 for m in self.pm_config_last.metrics:
164 if opts.disable:
165 if m.name in opts.disable:
166 m.enabled = False
167 self.pm_config_dirty = True
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400168
169 #Frequency overrides.
170 if opts.override:
171 if self.pm_config_last.freq_override:
172 oo = dict()
173 for o in opts.override:
174 oo[o[0]] = o[1]
175 if self.pm_config_last.grouped:
176 for g in self.pm_config_last.groups:
177 if g.group_name in oo:
178 try:
179 g.group_freq = int(oo[g.group_name])
180 except ValueError:
181 self.poutput(self.colorize('Warning: ',
182 'yellow') + \
183 self.colorize(oo[m.name],
184 'blue') +\
185 " is not an integer... ignored")
186 del oo[g.group_name]
187 self.pm_config_dirty = True
188 else:
189 for m in self.pm_config_last.metrics:
190 if m.name in oo:
191 try:
192 m.sample_freq = int(oo[m.name])
193 except ValueError:
194 self.poutput(self.colorize('Warning: ',
195 'yellow') + \
196 self.colorize(oo[m.name],
197 'blue') +\
198 " is not an integer... ignored")
199 del oo[m.name]
200 self.pm_config_dirty = True
201
202 # If there's anything left the input was typoed
203 if self.pm_config_last.grouped:
204 field = 'group'
205 else:
206 field = 'metric'
207 for o in oo:
208 self.poutput(self.colorize('Warning: ', 'yellow') + \
209 'the parameter' + ' ' + \
210 self.colorize(o, 'blue') + ' is not ' + \
211 'a ' + field + ' name... ignored')
212 if oo:
213 return
214
215 else: # Frequency overrides not enabled
216 self.poutput(self.colorize('Error: ', 'red') + \
217 'Individual overrides are only ' + \
218 'supported if ' + \
219 self.colorize('freq_override', 'blue') + \
220 ' is set to ' + self.colorize('True', 'blue'))
221 return
222 self.poutput("Success")
223 return
224
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400225 elif line.strip() == "commit" and self.pm_config_dirty:
226 stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
227 stub.UpdateDevicePmConfigs(self.pm_config_last)
228 self.pm_config_last = self.get_device(depth=-1).pm_configs
229 self.pm_config_dirty = False
230 elif line.strip() == "reset" and self.pm_config_dirty:
231 self.pm_config_last = self.get_device(depth=-1).pm_configs
232 self.pm_config_dirty = False
233
Sergio Slobodrian4236ade2017-03-17 22:01:20 -0400234
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400235 omit_fields = {'groups', 'metrics', 'id'}
236 print_pb_as_table('PM Config:', self.pm_config_last, omit_fields,
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400237 self.poutput,show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400238 if self.pm_config_last.grouped:
239 #self.poutput("Supported metric groups:")
240 for g in self.pm_config_last.groups:
241 if self.pm_config_last.freq_override:
242 omit_fields = {'metrics'}
243 else:
244 omit_fields = {'group_freq','metrics'}
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400245 print_pb_as_table('', g, omit_fields, self.poutput,
246 show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400247 if g.enabled:
248 state = 'enabled'
249 else:
250 state = 'disabled'
251 print_pb_list_as_table(
252 'Metric group {} is {}'.format(g.name,state),
253 g.metrics, {'enabled', 'sample_freq'}, self.poutput,
Sergio Slobodriana95f99b2017-03-21 10:22:47 -0400254 dividers=100, show_nulls=True)
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400255 else:
256 if self.pm_config_last.freq_override:
257 omit_fields = {}
258 else:
259 omit_fields = {'sample_freq'}
260 print_pb_list_as_table('Supported metrics:', self.pm_config_last.metrics,
261 omit_fields, self.poutput, dividers=100)
262
263
Zsolt Haraszti80175202016-12-24 00:17:51 -0800264 def do_flows(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800265 """Show flow table for device"""
266 device = pb2dict(self.get_device(-1))
267 print_flows(
268 'Device',
269 self.device_id,
270 type=device['type'],
271 flows=device['flows']['items'],
272 groups=device['flow_groups']['items']
273 )
274