Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright 2018 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 | """ |
| 19 | OpenOMCI level CLI commands |
| 20 | """ |
| 21 | from optparse import make_option |
| 22 | from cmd2 import Cmd, options |
| 23 | from datetime import datetime |
| 24 | from google.protobuf.empty_pb2 import Empty |
| 25 | from cli.table import print_pb_list_as_table |
| 26 | from voltha.protos import third_party |
| 27 | from voltha.protos import voltha_pb2 |
| 28 | from voltha.protos.omci_mib_db_pb2 import MibDeviceData, MibClassData, \ |
| 29 | MibInstanceData |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 30 | from voltha.protos.omci_alarm_db_pb2 import AlarmDeviceData, AlarmClassData, \ |
| 31 | AlarmInstanceData |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 32 | from os import linesep |
| 33 | |
| 34 | _ = third_party |
| 35 | |
| 36 | |
| 37 | class OmciCli(Cmd): |
| 38 | CREATED_KEY = 'created' |
| 39 | MODIFIED_KEY = 'modified' |
| 40 | MDS_KEY = 'mib_data_sync' |
| 41 | LAST_SYNC_KEY = 'last_mib_sync' |
| 42 | VERSION_KEY = 'version' |
| 43 | DEVICE_ID_KEY = 'device_id' |
| 44 | CLASS_ID_KEY = 'class_id' |
| 45 | INSTANCE_ID_KEY = 'instance_id' |
| 46 | ATTRIBUTES_KEY = 'attributes' |
| 47 | TIME_FORMAT = '%Y%m%d-%H%M%S.%f' |
| 48 | ME_KEY = 'managed_entities' |
| 49 | MSG_TYPE_KEY = 'message_types' |
| 50 | |
| 51 | MSG_TYPE_TO_NAME = { |
| 52 | 4: 'Create', |
| 53 | 5: 'Create Complete', |
| 54 | 6: 'Delete', |
| 55 | 8: 'Set', |
| 56 | 9: 'Get', |
| 57 | 10: 'Get Complete', |
| 58 | 11: 'Get All Alarms', |
| 59 | 12: 'Get All Alarms Next', |
| 60 | 13: 'Mib Upload', |
| 61 | 14: 'Mib Upload Next', |
| 62 | 15: 'Mib Reset', |
| 63 | 16: 'Alarm Notification', |
| 64 | 17: 'Attribute Value Change', |
| 65 | 18: 'Test', |
| 66 | 19: 'Start Software Download', |
| 67 | 20: 'Download Section', |
| 68 | 21: 'End Software Download', |
| 69 | 22: 'Activate Software', |
| 70 | 23: 'Commit Software', |
| 71 | 24: 'Synchronize Time', |
| 72 | 25: 'Reboot', |
| 73 | 26: 'Get Next', |
| 74 | 27: 'Test Result', |
| 75 | 28: 'Get Current Data', |
| 76 | 29: 'Set Table' |
| 77 | } |
| 78 | |
| 79 | def __init__(self, device_id, get_stub): |
| 80 | Cmd.__init__(self) |
| 81 | self.get_stub = get_stub |
| 82 | self.device_id = device_id |
| 83 | self.prompt = '(' + self.colorize( |
| 84 | self.colorize('omci {}'.format(device_id), 'green'), |
| 85 | 'bold') + ') ' |
| 86 | |
| 87 | def cmdloop(self, intro=None): |
| 88 | self._cmdloop() |
| 89 | |
| 90 | do_exit = Cmd.do_quit |
| 91 | |
| 92 | def do_quit(self, line): |
| 93 | return self._STOP_AND_EXIT |
| 94 | |
| 95 | def get_device_mib(self, device_id, depth=-1): |
| 96 | stub = self.get_stub() |
| 97 | |
| 98 | try: |
| 99 | res = stub.GetMibDeviceData(voltha_pb2.ID(id=device_id), |
| 100 | metadata=(('get-depth', str(depth)), )) |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 101 | except Exception as _e: |
| 102 | res = None |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 103 | |
| 104 | return res |
| 105 | |
| 106 | def help_show_mib(self): |
| 107 | self.poutput('show_mib [-d <device-id>] [-c <class-id> [-i <instance-id>]]' + |
| 108 | linesep + '-d: <device-id> ONU Device ID' + |
| 109 | linesep + '-c: <class-id> Managed Entity Class ID' + |
| 110 | linesep + '-i: <instance-id> ME Instance ID') |
| 111 | |
| 112 | @options([ |
| 113 | make_option('-d', '--device-id', action="store", dest='device_id', type='string', |
| 114 | help='ONU Device ID', default=None), |
| 115 | make_option('-c', '--class-id', action="store", dest='class_id', |
| 116 | type='int', help='Managed Entity Class ID', default=None), |
| 117 | make_option('-i', '--instance-id', action="store", dest='instance_id', |
| 118 | type='int', help='ME Instance ID', default=None) |
| 119 | ]) |
| 120 | def do_show_mib(self, _line, opts): |
| 121 | """ |
| 122 | Show OMCI MIB Database Information |
| 123 | """ |
| 124 | device_id = opts.device_id or self.device_id |
| 125 | |
| 126 | if opts.class_id is not None and not 1 <= opts.class_id <= 0xFFFF: |
| 127 | self.poutput(self.colorize('Error: ', 'red') + |
| 128 | self.colorize('Class ID must be 1..65535', 'blue')) |
| 129 | return |
| 130 | |
| 131 | if opts.instance_id is not None and opts.class_id is None: |
| 132 | self.poutput(self.colorize('Error: ', 'red') + |
| 133 | self.colorize('Class ID required if specifying an Instance ID', |
| 134 | 'blue')) |
| 135 | return |
| 136 | |
| 137 | if opts.instance_id is not None and not 0 <= opts.instance_id <= 0xFFFF: |
| 138 | self.poutput(self.colorize('Error: ', 'red') + |
| 139 | self.colorize('Instance ID must be 0..65535', 'blue')) |
| 140 | return |
| 141 | |
| 142 | try: |
| 143 | mib_db = self.get_device_mib(device_id, depth=-1) |
| 144 | |
| 145 | except Exception: # UnboundLocalError if Device ID not found in DB |
| 146 | self.poutput(self.colorize('Failed to get MIB database for ONU {}' |
| 147 | .format(device_id), 'red')) |
| 148 | return |
| 149 | |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 150 | if mib_db is None: |
| 151 | self.poutput(self.colorize('MIB database for ONU {} is not currently available' |
| 152 | .format(device_id), 'red')) |
| 153 | return |
| 154 | |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 155 | mib = self._device_to_dict(mib_db) |
| 156 | |
| 157 | self.poutput('OpenOMCI MIB Database for ONU {}'.format(device_id)) |
| 158 | |
| 159 | if opts.class_id is None and opts.instance_id is None: |
| 160 | self.poutput('Version : {}'.format(mib[OmciCli.VERSION_KEY])) |
| 161 | self.poutput('Created : {}'.format(mib[OmciCli.CREATED_KEY])) |
| 162 | self.poutput('Last In-Sync Time : {}'.format(mib[OmciCli.LAST_SYNC_KEY])) |
| 163 | self.poutput('MIB Data Sync Value: {}'.format(mib[OmciCli.MDS_KEY])) |
| 164 | |
| 165 | class_ids = [k for k in mib.iterkeys() |
| 166 | if isinstance(k, int) and |
| 167 | (opts.class_id is None or opts.class_id == k)] |
| 168 | class_ids.sort() |
| 169 | |
| 170 | if len(class_ids) == 0 and opts.class_id is not None: |
| 171 | self.poutput(self.colorize('Class ID {} not found in MIB Database' |
| 172 | .format(opts.class_id), 'red')) |
| 173 | return |
| 174 | |
| 175 | for cls_id in class_ids: |
| 176 | class_data = mib[cls_id] |
| 177 | self.poutput(' ----------------------------------------------') |
Chip Boling | 07912c3 | 2018-09-28 14:13:31 -0500 | [diff] [blame] | 178 | self.poutput(' Class ID : {0} - ({0:#x}): {1}'. |
| 179 | format(cls_id, mib[OmciCli.ME_KEY].get(cls_id, 'Unknown'))) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 180 | inst_ids = [k for k in class_data.iterkeys() |
| 181 | if isinstance(k, int) and |
| 182 | (opts.instance_id is None or opts.instance_id == k)] |
| 183 | inst_ids.sort() |
| 184 | |
| 185 | if len(inst_ids) == 0 and opts.instance_id is not None: |
| 186 | self.poutput(self.colorize('Instance ID {} of Class ID {} not ' + |
| 187 | 'found in MIB Database'. |
| 188 | format(opts.instance_id, opts.class_id), |
| 189 | 'red')) |
| 190 | return |
| 191 | |
| 192 | for inst_id in inst_ids: |
| 193 | inst_data = class_data[inst_id] |
| 194 | self.poutput(' Instance ID: {0} - ({0:#x})'.format(inst_id)) |
| 195 | self.poutput(' Created : {}'.format(inst_data[OmciCli.CREATED_KEY])) |
| 196 | self.poutput(' Modified : {}'.format(inst_data[OmciCli.MODIFIED_KEY])) |
| 197 | |
| 198 | attributes = inst_data[OmciCli.ATTRIBUTES_KEY] |
| 199 | attr_names = attributes.keys() |
Chip Boling | 07912c3 | 2018-09-28 14:13:31 -0500 | [diff] [blame] | 200 | if len(attr_names): |
| 201 | attr_names.sort() |
| 202 | max_len = max([len(attr) for attr in attr_names]) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 203 | |
Chip Boling | 07912c3 | 2018-09-28 14:13:31 -0500 | [diff] [blame] | 204 | for attr in attr_names: |
| 205 | name = self._cleanup_attribute_name(attr).ljust(max_len) |
| 206 | value = attributes[attr] |
| 207 | try: |
| 208 | ivalue = int(value) |
| 209 | self.poutput(' {0}: {1} - ({1:#x})'.format(name, ivalue)) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 210 | |
Chip Boling | 07912c3 | 2018-09-28 14:13:31 -0500 | [diff] [blame] | 211 | except ValueError: |
| 212 | self.poutput(' {}: {}'.format(name, value)) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 213 | |
Chip Boling | 07912c3 | 2018-09-28 14:13:31 -0500 | [diff] [blame] | 214 | if inst_id is not inst_ids[-1]: |
| 215 | self.poutput(linesep) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 216 | |
| 217 | def _cleanup_attribute_name(self, attr): |
| 218 | """Change underscore to space and capitalize first character""" |
| 219 | return ' '.join([v[0].upper() + v[1:] for v in attr.split('_')]) |
| 220 | |
| 221 | def _instance_to_dict(self, instance): |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 222 | if not isinstance(instance, (MibInstanceData, AlarmInstanceData)): |
| 223 | raise TypeError('{} is not of type MIB/Alarm Instance Data'.format(type(instance))) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 224 | |
| 225 | data = { |
| 226 | OmciCli.INSTANCE_ID_KEY: instance.instance_id, |
| 227 | OmciCli.CREATED_KEY: self._string_to_time(instance.created), |
| 228 | OmciCli.MODIFIED_KEY: self._string_to_time(instance.modified), |
| 229 | OmciCli.ATTRIBUTES_KEY: dict() |
| 230 | } |
| 231 | for attribute in instance.attributes: |
| 232 | data[OmciCli.ATTRIBUTES_KEY][attribute.name] = str(attribute.value) |
| 233 | |
| 234 | return data |
| 235 | |
| 236 | def _class_to_dict(self, val): |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 237 | if not isinstance(val, (MibClassData, AlarmClassData)): |
| 238 | raise TypeError('{} is not of type MIB/Alarm Class Data'.format(type(val))) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 239 | |
| 240 | data = { |
| 241 | OmciCli.CLASS_ID_KEY: val.class_id, |
| 242 | } |
| 243 | for instance in val.instances: |
| 244 | data[instance.instance_id] = self._instance_to_dict(instance) |
| 245 | return data |
| 246 | |
| 247 | def _device_to_dict(self, val): |
| 248 | if not isinstance(val, MibDeviceData): |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 249 | raise TypeError('{} is not of type MIB Device Data'.format(type(val))) |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 250 | |
| 251 | data = { |
| 252 | OmciCli.DEVICE_ID_KEY: val.device_id, |
| 253 | OmciCli.CREATED_KEY: self._string_to_time(val.created), |
| 254 | OmciCli.LAST_SYNC_KEY: self._string_to_time(val.last_sync_time), |
| 255 | OmciCli.MDS_KEY: val.mib_data_sync, |
| 256 | OmciCli.VERSION_KEY: val.version, |
| 257 | OmciCli.ME_KEY: dict(), |
| 258 | OmciCli.MSG_TYPE_KEY: set() |
| 259 | } |
| 260 | for class_data in val.classes: |
| 261 | data[class_data.class_id] = self._class_to_dict(class_data) |
| 262 | |
| 263 | for managed_entity in val.managed_entities: |
| 264 | data[OmciCli.ME_KEY][managed_entity.class_id] = managed_entity.name |
| 265 | |
| 266 | for msg_type in val.message_types: |
| 267 | data[OmciCli.MSG_TYPE_KEY].add(msg_type.message_type) |
| 268 | |
| 269 | return data |
| 270 | |
| 271 | def _string_to_time(self, time): |
| 272 | return datetime.strptime(time, OmciCli.TIME_FORMAT) if len(time) else None |
| 273 | |
| 274 | def help_show_me(self): |
| 275 | self.poutput('show_me [-d <device-id>]' + |
| 276 | linesep + '-d: <device-id> ONU Device ID') |
| 277 | |
| 278 | @options([ |
| 279 | make_option('-d', '--device-id', action="store", dest='device_id', type='string', |
| 280 | help='ONU Device ID', default=None), |
| 281 | ]) |
| 282 | def do_show_me(self, _line, opts): |
| 283 | """ Show supported OMCI Managed Entities""" |
| 284 | |
| 285 | device_id = opts.device_id or self.device_id |
| 286 | |
| 287 | try: |
| 288 | mib_db = self.get_device_mib(device_id, depth=1) |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 289 | if mib_db is None: |
| 290 | self.poutput(self.colorize('Supported ME information for ONU {} is not currently available' |
| 291 | .format(device_id), 'red')) |
| 292 | return |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 293 | mib = self._device_to_dict(mib_db) |
| 294 | |
| 295 | except Exception: # UnboundLocalError if Device ID not found in DB |
| 296 | self.poutput(self.colorize('Failed to get supported ME information for ONU {}' |
| 297 | .format(device_id), 'red')) |
| 298 | return |
| 299 | |
| 300 | class_ids = [class_id for class_id in mib[OmciCli.ME_KEY].keys()] |
| 301 | class_ids.sort() |
| 302 | |
| 303 | self.poutput('Supported Managed Entities for ONU {}'.format(device_id)) |
| 304 | for class_id in class_ids: |
| 305 | self.poutput(' {0} - ({0:#x}): {1}'.format(class_id, |
| 306 | mib[OmciCli.ME_KEY][class_id])) |
| 307 | |
| 308 | def help_show_msg_types(self): |
| 309 | self.poutput('show_msg_types [-d <device-id>]' + |
| 310 | linesep + '-d: <device-id> ONU Device ID') |
| 311 | |
| 312 | @options([ |
| 313 | make_option('-d', '--device-id', action="store", dest='device_id', type='string', |
| 314 | help='ONU Device ID', default=None), |
| 315 | ]) |
| 316 | def do_show_msg_types(self, _line, opts): |
| 317 | """ Show supported OMCI Message Types""" |
| 318 | device_id = opts.device_id or self.device_id |
| 319 | |
| 320 | try: |
| 321 | mib_db = self.get_device_mib(device_id, depth=1) |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 322 | if mib_db is None: |
| 323 | self.poutput(self.colorize('Message Types for ONU {} are not currently available' |
| 324 | .format(device_id), 'red')) |
| 325 | return |
| 326 | |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 327 | mib = self._device_to_dict(mib_db) |
| 328 | |
| 329 | except Exception: # UnboundLocalError if Device ID not found in DB |
| 330 | self.poutput(self.colorize('Failed to get supported Message Types for ONU {}' |
| 331 | .format(device_id), 'red')) |
| 332 | return |
| 333 | |
| 334 | msg_types = [msg_type for msg_type in mib[OmciCli.MSG_TYPE_KEY]] |
| 335 | msg_types.sort() |
| 336 | |
| 337 | self.poutput('Supported Message Types for ONU {}'.format(device_id)) |
| 338 | for msg_type in msg_types: |
| 339 | self.poutput(' {0} - ({0:#x}): {1}'. |
| 340 | format(msg_type, |
| 341 | OmciCli.MSG_TYPE_TO_NAME.get(msg_type, 'Unknown'))) |
| 342 | |
| 343 | def get_devices(self): |
| 344 | stub = self.get_stub() |
| 345 | res = stub.ListDevices(Empty()) |
| 346 | return res.items |
| 347 | |
| 348 | def do_devices(self, line): |
| 349 | """List devices registered in Voltha reduced for OMCI menu""" |
| 350 | devices = self.get_devices() |
| 351 | omit_fields = { |
| 352 | 'adapter', |
| 353 | 'model', |
| 354 | 'hardware_version', |
| 355 | 'images', |
| 356 | 'firmware_version', |
| 357 | 'serial_number', |
| 358 | 'vlan', |
| 359 | 'root', |
| 360 | 'extra_args', |
| 361 | 'proxy_address', |
| 362 | } |
| 363 | print_pb_list_as_table('Devices:', devices, omit_fields, self.poutput) |
| 364 | |
| 365 | def help_devices(self): |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 366 | self.poutput('List devices registered in Voltha') |
Chip Boling | 69abce8 | 2018-06-18 09:56:23 -0500 | [diff] [blame] | 367 | |
| 368 | def poutput(self, msg): |
| 369 | """Convenient shortcut for self.stdout.write(); adds newline if necessary.""" |
| 370 | if msg: |
| 371 | self.stdout.write(msg) |
| 372 | if msg[-1] != '\n': |
| 373 | self.stdout.write('\n') |
Chip Boling | 0846330 | 2018-11-06 13:54:47 -0600 | [diff] [blame] | 374 | |
| 375 | def do_show(self, _): |
| 376 | """Show detailed omci information""" |
| 377 | self.poutput('Use show_mib, show_alarms, show_me, show_msg_types for detailed OMCI information') |
Chip Boling | 5584d20 | 2018-11-09 15:17:40 -0600 | [diff] [blame] | 378 | |
| 379 | def get_alarm_table(self, device_id, depth=-1): |
| 380 | stub = self.get_stub() |
| 381 | |
| 382 | try: |
| 383 | res = stub.GetAlarmDeviceData(voltha_pb2.ID(id=device_id), |
| 384 | metadata=(('get-depth', str(depth)), )) |
| 385 | except Exception as _e: |
| 386 | res = None |
| 387 | |
| 388 | return res |
| 389 | |
| 390 | def _alarms_to_dict(self, val): |
| 391 | if not isinstance(val, AlarmDeviceData): |
| 392 | raise TypeError('{} is not of type Alarm Device Data'.format(type(val))) |
| 393 | |
| 394 | data = { |
| 395 | OmciCli.DEVICE_ID_KEY: val.device_id, |
| 396 | OmciCli.CREATED_KEY: self._string_to_time(val.created), |
| 397 | OmciCli.VERSION_KEY: val.version |
| 398 | } |
| 399 | for class_data in val.classes: |
| 400 | data[class_data.class_id] = self._class_to_dict(class_data) |
| 401 | |
| 402 | return data |
| 403 | |
| 404 | def help_show_alarms(self): |
| 405 | self.poutput('show_alarms [-d <device-id>]' + |
| 406 | linesep + '-d: <device-id> ONU Device ID') |
| 407 | |
| 408 | @options([ |
| 409 | make_option('-d', '--device-id', action="store", dest='device_id', type='string', |
| 410 | help='ONU Device ID', default=None), |
| 411 | ]) |
| 412 | def do_show_alarms(self, _line, opts): |
| 413 | """ Show contents of the alarm table""" |
| 414 | device_id = opts.device_id or self.device_id |
| 415 | |
| 416 | try: |
| 417 | alarm_db = self.get_alarm_table(device_id, depth=-1) |
| 418 | if alarm_db is None: |
| 419 | self.poutput(self.colorize('Alarm Table for ONU {} is not currently available' |
| 420 | .format(device_id), 'red')) |
| 421 | return |
| 422 | |
| 423 | except Exception: # UnboundLocalError if Device ID not found in DB |
| 424 | self.poutput(self.colorize('Failed to get Alarm Table for ONU {}' |
| 425 | .format(device_id), 'red')) |
| 426 | return |
| 427 | |
| 428 | alarms = self._alarms_to_dict(alarm_db) |
| 429 | self.poutput('OpenOMCI Alarm Table for ONU {}'.format(device_id)) |
| 430 | self.poutput('Version : {}'.format(alarms[OmciCli.VERSION_KEY])) |
| 431 | self.poutput('Created : {}'.format(alarms[OmciCli.CREATED_KEY])) |
| 432 | |
| 433 | class_ids = [k for k in alarms.iterkeys() if isinstance(k, int)] |
| 434 | class_ids.sort() |
| 435 | |
| 436 | if len(class_ids) == 0: |
| 437 | self.poutput('No active alarms') |
| 438 | return |
| 439 | |
| 440 | for cls_id in class_ids: |
| 441 | from omci_alarm_info import _alarm_info |
| 442 | class_data = alarms[cls_id] |
| 443 | info = _alarm_info.get(cls_id) |
| 444 | |
| 445 | self.poutput(' ----------------------------------------------') |
| 446 | self.poutput(' Class ID: {0} - ({0:#x}): {1}'. |
| 447 | format(cls_id, |
| 448 | info.get('name') if info is not None else 'Unknown Class ID')) |
| 449 | |
| 450 | inst_ids = [k for k in class_data.iterkeys() if isinstance(k, int)] |
| 451 | inst_ids.sort() |
| 452 | |
| 453 | for inst_id in inst_ids: |
| 454 | inst_data = class_data[inst_id] |
| 455 | self.poutput(' Instance ID : {0} - ({0:#x})'.format(inst_id)) |
| 456 | self.poutput(' Created : {}'.format(inst_data[OmciCli.CREATED_KEY])) |
| 457 | self.poutput(' Modified : {}'.format(inst_data[OmciCli.MODIFIED_KEY])) |
| 458 | |
| 459 | try: |
| 460 | alarm_value = int(inst_data[OmciCli.ATTRIBUTES_KEY]['alarm_bit_map']) |
| 461 | except ValueError: |
| 462 | alarm_value = 0 |
| 463 | |
| 464 | if alarm_value == 0: |
| 465 | self.poutput(' Active Alarms: No Active Alarms') |
| 466 | |
| 467 | else: |
| 468 | padding = ' Active Alarms:' |
| 469 | for alarm_no in xrange(0, 224): |
| 470 | if (1 << (223 - alarm_no)) & alarm_value: |
| 471 | if info is None: |
| 472 | txt = 'Unknown alarm number' |
| 473 | else: |
| 474 | txt = info.get(alarm_no, 'Unknown alarm number') |
| 475 | |
| 476 | self.poutput('{} {}: {}'.format(padding, alarm_no, txt)) |
| 477 | padding = ' ' |
| 478 | |
| 479 | if inst_id is not inst_ids[-1]: |
| 480 | self.poutput(linesep) |