blob: 05f97c9a36a8c7febb433a9e5666a5cfcf131cca [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
115If grouped is tre then the -d, -e and -o commands refer to groups and not
116individual 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 Slobodrian6e9fb692017-03-17 14:46:33 -0400127 make_option('-o', '--overried', action='store', dest='override',
128 nargs=2, default=None, type='string'),
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400129 ])
130 def do_perf_config(self, line, opts):
131 print(line)
132 """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
160 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
182 #TODO: Add frequency overrides.
Sergio Slobodrian6e9fb692017-03-17 14:46:33 -0400183 if opts.override:
184 pass
Sergio Slobodrian901bf4e2017-03-17 12:54:39 -0400185 elif line.strip() == "commit" and self.pm_config_dirty:
186 stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
187 stub.UpdateDevicePmConfigs(self.pm_config_last)
188 self.pm_config_last = self.get_device(depth=-1).pm_configs
189 self.pm_config_dirty = False
190 elif line.strip() == "reset" and self.pm_config_dirty:
191 self.pm_config_last = self.get_device(depth=-1).pm_configs
192 self.pm_config_dirty = False
193
194 omit_fields = {'groups', 'metrics', 'id'}
195 print_pb_as_table('PM Config:', self.pm_config_last, omit_fields,
196 self.poutput)
197 if self.pm_config_last.grouped:
198 #self.poutput("Supported metric groups:")
199 for g in self.pm_config_last.groups:
200 if self.pm_config_last.freq_override:
201 omit_fields = {'metrics'}
202 else:
203 omit_fields = {'group_freq','metrics'}
204 print_pb_as_table('', g, omit_fields, self.poutput)
205 if g.enabled:
206 state = 'enabled'
207 else:
208 state = 'disabled'
209 print_pb_list_as_table(
210 'Metric group {} is {}'.format(g.name,state),
211 g.metrics, {'enabled', 'sample_freq'}, self.poutput,
212 dividers=100)
213 else:
214 if self.pm_config_last.freq_override:
215 omit_fields = {}
216 else:
217 omit_fields = {'sample_freq'}
218 print_pb_list_as_table('Supported metrics:', self.pm_config_last.metrics,
219 omit_fields, self.poutput, dividers=100)
220
221
Zsolt Haraszti80175202016-12-24 00:17:51 -0800222 def do_flows(self, line):
Zsolt Harasztid036b7e2016-12-23 15:36:01 -0800223 """Show flow table for device"""
224 device = pb2dict(self.get_device(-1))
225 print_flows(
226 'Device',
227 self.device_id,
228 type=device['type'],
229 flows=device['flows']['items'],
230 groups=device['flow_groups']['items']
231 )
232