Initial changes to the CLI to support performance management
configuration. There are still some todos left in the code which will
be addressed in later commits.
Change-Id: I329a54f4ad9fca1599e53949a621c316e9b2d4fc
diff --git a/cli/device.py b/cli/device.py
index cd3e3ce..5dba144 100644
--- a/cli/device.py
+++ b/cli/device.py
@@ -18,7 +18,8 @@
"""
Device level CLI commands
"""
-from cmd2 import Cmd
+from optparse import make_option
+from cmd2 import Cmd, options
from simplejson import dumps
from cli.table import print_pb_as_table, print_pb_list_as_table
@@ -27,7 +28,12 @@
_ = third_party
from voltha.protos import voltha_pb2
+from voltha.protos.device_pb2 import PmConfigs, PmConfig, PmGroupConfig
+from google.protobuf.json_format import MessageToDict
+# Since proto3 won't send fields that are set to 0/false/"" any object that
+# might have those values set in them needs to be replicated here such that the
+# fields can be adequately
class DeviceCli(Cmd):
@@ -37,6 +43,8 @@
self.device_id = device_id
self.prompt = '(' + self.colorize(
self.colorize('device {}'.format(device_id), 'red'), 'bold') + ') '
+ self.pm_config_last = None
+ self.pm_config_dirty = False
def cmdloop(self):
self._cmdloop()
@@ -62,6 +70,105 @@
print_pb_list_as_table('Device ports:', device.ports,
omit_fields, self.poutput)
+ @options([
+ make_option('-f', '--default_freq', action="store", dest='default_freq',
+ type='long', default=None),
+ make_option('-e', '--enable', action='append', dest='enable',
+ default=None),
+ make_option('-d', '--disable', action='append', dest='disable',
+ default=None),
+ ])
+ def do_perf_config(self, line, opts):
+ print(line)
+ """Show and set the performance monitoring configuration of the device"""
+
+ device = self.get_device(depth=-1)
+ if not self.pm_config_last:
+ self.pm_config_last = device.pm_configs
+
+ # Ensure that a valid sub-command was provided
+ if line.strip() not in {"set", "show", "commit", "reset", ""}:
+ self.poutput(self.colorize('Error: ', 'red') + \
+ self.colorize(self.colorize(line.strip(), 'blue'),
+ 'bold') + ' is not recognized')
+ return
+
+ # Ensure no options are provided when requesting to view the config
+ if line.strip() == "show" or line.strip() == "":
+ if opts.default_freq or opts.enable or opts.disable:
+ self.poutput(opts.disable)
+ self.poutput(self.colorize('Error: ', 'red') + 'use ' + \
+ self.colorize(self.colorize('"set"', 'blue'),
+ 'bold') + ' to change settings')
+ return
+
+ if line.strip() == "set": # Set the supplied values
+ # The defualt frequency
+ if opts.default_freq:
+ self.pm_config_last.default_freq = opts.default_freq
+ self.pm_config_dirty = True
+
+ if self.pm_config_last.grouped:
+ for g in self.pm_config_last.groups:
+ if opts.enable:
+ if g.group_name in opts.enable:
+ g.enabled = True
+ self.pm_config_dirty = True
+ for g in self.pm_config_last.groups:
+ if opts.disable:
+ if g.group_name in opts.disable:
+ g.enabled = False
+ self.pm_config_dirty = True
+ else:
+ for m in self.pm_config_last.metrics:
+ if opts.enable:
+ if m.name in opts.enable:
+ m.enabled = True
+ self.pm_config_dirty = True
+ for m in self.pm_config_last.metrics:
+ if opts.disable:
+ if m.name in opts.disable:
+ m.enabled = False
+ self.pm_config_dirty = True
+ #TODO: Add frequency overrides.
+
+ elif line.strip() == "commit" and self.pm_config_dirty:
+ stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+ stub.UpdateDevicePmConfigs(self.pm_config_last)
+ self.pm_config_last = self.get_device(depth=-1).pm_configs
+ self.pm_config_dirty = False
+ elif line.strip() == "reset" and self.pm_config_dirty:
+ self.pm_config_last = self.get_device(depth=-1).pm_configs
+ self.pm_config_dirty = False
+
+ omit_fields = {'groups', 'metrics', 'id'}
+ print_pb_as_table('PM Config:', self.pm_config_last, omit_fields,
+ self.poutput)
+ if self.pm_config_last.grouped:
+ #self.poutput("Supported metric groups:")
+ for g in self.pm_config_last.groups:
+ if self.pm_config_last.freq_override:
+ omit_fields = {'metrics'}
+ else:
+ omit_fields = {'group_freq','metrics'}
+ print_pb_as_table('', g, omit_fields, self.poutput)
+ if g.enabled:
+ state = 'enabled'
+ else:
+ state = 'disabled'
+ print_pb_list_as_table(
+ 'Metric group {} is {}'.format(g.name,state),
+ g.metrics, {'enabled', 'sample_freq'}, self.poutput,
+ dividers=100)
+ else:
+ if self.pm_config_last.freq_override:
+ omit_fields = {}
+ else:
+ omit_fields = {'sample_freq'}
+ print_pb_list_as_table('Supported metrics:', self.pm_config_last.metrics,
+ omit_fields, self.poutput, dividers=100)
+
+
def do_flows(self, line):
"""Show flow table for device"""
device = pb2dict(self.get_device(-1))
diff --git a/cli/table.py b/cli/table.py
index 6485787..1a1f576 100644
--- a/cli/table.py
+++ b/cli/table.py
@@ -89,7 +89,8 @@
assert self.field_names[field_key] == field_name
-def print_pb_list_as_table(header, items, fields_to_omit=None, printfn=_printfn):
+def print_pb_list_as_table(header, items, fields_to_omit=None,
+ printfn=_printfn, dividers=10):
from cli.utils import pb2dict
t = TablePrinter()
@@ -98,21 +99,36 @@
def add(_row, pb, prefix='', number=0):
d = pb2dict(pb)
- for field in pb._fields:
- fname = prefix + field.name
+ l=[]
+ for field in sorted(pb._fields, key=lambda f: f.number):
+ l.append(field.name)
+ for field in d:
+ if field not in l:
+ l.append(field)
+
+ field_number = 0
+ #for field in pb._fields:
+ for field in sorted(d, key=lambda f: l.index(f)):
+ #fname = prefix + field.name
+ fname = prefix + field
if fname in fields_to_omit:
continue
- value = getattr(pb, field.name)
+ #value = getattr(pb, field.name)
+ value = getattr(pb, field)
if isinstance(value, Message):
add(_row, value, fname + '.',
- 100 * (number + field.number))
+ 100 * (number + field_number))
+ #100 * (number + field.number))
else:
- t.add_cell(_row, number + field.number, fname,
- d.get(field.name))
+ t.add_cell(_row, number + field_number, fname,
+ d.get(field))
+ #t.add_cell(_row, number + field.number, fname,
+ #d.get(field.name))
+ field_number += 1
add(row, obj)
- t.print_table(header, printfn)
+ t.print_table(header, printfn, dividers)
def print_pb_as_table(header, pb, fields_to_omit={}, printfn=_printfn):
@@ -122,11 +138,14 @@
def pr(_pb, prefix=''):
d = pb2dict(_pb)
- for field in sorted(_pb._fields, key=lambda f: f.number):
- fname = prefix + field.name
+ #for field in sorted(_pb._fields, key=lambda f: f.number):
+ for field in sorted(d):
+ #fname = prefix + field.name
+ fname = prefix + field
if fname in fields_to_omit:
continue
- value = getattr(_pb, field.name)
+ #value = getattr(_pb, field.name)
+ value = getattr(_pb, field)
if isinstance(value, Message):
pr(value, fname + '.')
elif isinstance(value, RepeatedCompositeFieldContainer):
@@ -137,7 +156,8 @@
else:
row = t.number_of_rows()
t.add_cell(row, 0, 'field', fname)
- t.add_cell(row, 1, 'value', d.get(field.name))
+ #t.add_cell(row, 1, 'value', d.get(field.name))
+ t.add_cell(row, 1, 'value', d.get(field))
pr(pb)