Esempio n. 1
0
 def __init__(self):
     self.args = parse_args()
     self.paragraphs = None
     self.parsed = ParsedJson()
     self.version = VersionHeading()
     self.version.name = 'csv-generator'
     self.version.create_time = time.time()
     self.version.itu_document = self.args.ITU
Esempio n. 2
0
    def __init__(self):
        self.args = parse_args()
        self.paragraphs = None
        self.body = None

        self.preparsed = PreParsedJson()
        self.parsed = ParsedJson()
        self.attribute_hints = dict()       # Class ID -> attribute hints list
        version = VersionHeading()
        version.name = 'parser'
        version.create_time = time.time()
        version.itu_document = self.args.ITU
        version.version = self.get_version()
        version.sha256 = self.get_file_hash(version.itu_document)
        self.parsed.add(version)
Esempio n. 3
0
    def __init__(self):
        self.args = parse_args()
        self.paragraphs = None
        loader = jinja2.FileSystemLoader(searchpath=self.args.templates)
        self.templateEnv = jinja2.Environment(
            loader=loader, extensions=['jinja2.ext.loopcontrols'])
        self.templateEnv.filters['zero_b64_string'] = zero_b64_string
        self.templateEnv.filters['attribute_bitmask'] = attribute_bitmask

        self.parsed = ParsedJson()
        self.version = VersionHeading()
        self.version.name = 'code-generator'
        self.version.create_time = time.time()
        self.version.itu_document = self.args.ITU
        self.version.version = self.get_version()
        self.version.sha256 = self.get_file_hash(self.version.itu_document)
Esempio n. 4
0
class Main(object):
    """ Main program """
    def __init__(self):
        self.args = parse_args()
        self.paragraphs = None
        loader = jinja2.FileSystemLoader(searchpath=self.args.templates)
        self.templateEnv = jinja2.Environment(
            loader=loader, extensions=['jinja2.ext.loopcontrols'])
        self.templateEnv.filters['zero_b64_string'] = zero_b64_string
        self.templateEnv.filters['attribute_bitmask'] = attribute_bitmask

        self.parsed = ParsedJson()
        self.version = VersionHeading()
        self.version.name = 'code-generator'
        self.version.create_time = time.time()
        self.version.itu_document = self.args.ITU
        self.version.version = self.get_version()
        self.version.sha256 = self.get_file_hash(self.version.itu_document)

    @staticmethod
    def get_version():
        with open('VERSION', 'r') as f:
            for line in f:
                line = line.strip().lower()
                if len(line) > 0:
                    return line

    @staticmethod
    def get_file_hash(filename):
        import hashlib
        with open(filename, 'rb') as f:
            data = f.read()
            return hashlib.sha256(data).hexdigest()

    def load_itu_document(self):
        return Document(self.args.ITU)

    def start(self):
        print("Loading ITU Document '{}' and parsed data file '{}'".format(
            self.args.ITU, self.args.input))
        try:
            document = self.load_itu_document()
            self.paragraphs = document.paragraphs

            # Directory exists
            if os.path.isdir(self.args.dir):
                if not self.args.force:
                    print("Directory '{}' exists, use --force to overwrite",
                          self.args.dir)
                    return
                shutil.rmtree(self.args.dir)

            # Load JSON class ID list and sort by ID
            self.parsed.load(self.args.input)
            self.parsed.add(self.version)

            class_ids = [c for c in self.parsed.class_ids.values()]
            class_ids.sort(key=lambda x: x.cid)

            # Create output directory
            os.mkdir(self.args.dir)

            # Generate some somewhat fixed templates
            create_base_templates(self.args.dir, self.templateEnv)

            # Create Version File
            create_version_file(self.parsed.versions, self.args.dir,
                                self.templateEnv)

            # Create Class ID Map
            create_class_id_map(class_ids, self.args.dir, self.templateEnv)

            # Create Managed Entity files
            for class_id in class_ids:
                create_managed_entity_file(class_id, self.args.dir,
                                           self.templateEnv, self.paragraphs)
                # if class_id.cid == 2:
                #    print('TODO: remove later')  # Good place for breakpoint

        except Exception as _e:
            raise
        # Done
        print('Code generation completed successfully')
Esempio n. 5
0
 def __init__(self):
     self.args = parse_args()
     self.parsed = ParsedJson()
     self.filepath = self.args.output + os.path.sep + "attrNames_test.json"
Esempio n. 6
0
class Main(object):
    """ Main program """
    def __init__(self):
        self.args = parse_args()
        self.parsed = ParsedJson()
        self.filepath = self.args.output + os.path.sep + "attrNames_test.json"

    @staticmethod
    def camelCase(input: str) -> str:
        s = sub(r"(_|-|\.|/)+", " ", input).title().replace(" ", "")
        output = ''.join([s[0].upper(), s[1:]])
        return output

    @staticmethod
    def golangfile(input: str) -> str:
        s = sub(r"(|/)+", " ", input).title().replace(" ", "")
        output = ''.join([s[0].lower(), s[1:].lower()]) + ".go"
        return output

    def start(self):
        try:
            # Directory exists
            if not os.path.isdir(self.args.output):
                print("Directory '{}' does not exist", self.args.output)
                return

            # Load JSON class ID list and sort by ID
            self.parsed.load(self.args.input)

            class_ids = [c for c in self.parsed.class_ids.values()]
            class_ids.sort(key=lambda x: x.cid)

            results = {}
            for entry in class_ids:
                entry_camelCase = self.camelCase(entry.name)
                entry_filename = self.golangfile(entry.name)
                results[entry.cid] = {
                    "Name": f"{entry.name}",
                    "Filename": entry_filename,
                    "CamelCase": entry_camelCase,
                    "ClassID": entry.cid,
                    "Attributes": {},
                }
                for attribute in entry.attributes:
                    camelCase = self.camelCase(attribute.name)
                    results[entry.cid]["Attributes"][attribute.index] = {
                        "Name":
                        f"{attribute.name}",
                        "CamelCase":
                        camelCase,
                        "Final":
                        f"{entry_camelCase}_{camelCase}"
                        if attribute.index != 0 else f"{camelCase}",
                        "Index":
                        attribute.index,
                    }
            # Output results
            json_data = json.dumps(results, indent=2, separators=(',', ': '))

        except Exception as _e:
            raise

        # Done output results
        with open(self.filepath, 'w') as json_file:
            json_file.write(json_data)
        print('Done')
Esempio n. 7
0
class Main(object):
    """ Main program """
    def __init__(self):
        self.args = parse_args()
        self.paragraphs = None
        self.body = None

        self.preparsed = PreParsedJson()
        self.parsed = ParsedJson()
        self.attribute_hints = dict()       # Class ID -> attribute hints list
        version = VersionHeading()
        version.name = 'parser'
        version.create_time = time.time()
        version.itu_document = self.args.ITU
        version.version = self.get_version()
        version.sha256 = self.get_file_hash(version.itu_document)
        self.parsed.add(version)

    @staticmethod
    def get_version():
        with open('VERSION', 'r') as f:
            for line in f:
                line = line.strip().lower()
                if len(line) > 0:
                    return line

    @staticmethod
    def get_file_hash(filename):
        import hashlib
        with open(filename, 'rb') as f:
            data = f.read()
            return hashlib.sha256(data).hexdigest()

    @property
    def sections(self):
        return self.preparsed.sections

    @property
    def section_list(self):
        return self.preparsed.section_list

    @property
    def class_ids(self):
        return self.parsed.class_ids

    def load_itu_document(self):
        return Document(self.args.ITU)

    def start(self):
        print("Loading ITU Document '{}' and parsed data file '{}'".format(self.args.ITU,
                                                                           self.args.input))
        self.preparsed.load(self.args.input)
        for version in self.preparsed.versions:
            self.parsed.add(version)

        self.attribute_hints = MetadataYAML().load(self.args.hints)

        document = self.load_itu_document()
        self.paragraphs = document.paragraphs
        # doc_sections = document.sections
        # styles = document.styles
        # self.body = document.element.body

        print('Extracting ME Class ID values')
        class_ids = ClassIdList.parse_sections(self.section_list,
                                               self.args.classes)
        for _cid, me_class in class_ids.items():
            self.parsed.add(me_class)

        print('Found {} ME Class ID entries. {} have sections associated to them'.
              format(len(self.class_ids),
                     len([c for c in self.class_ids.values()
                          if c.section is not None])))

        crazy_formatted_mes = {}  # Try all
        todo_class_ids = {k: v for k, v in self.class_ids.items()
                          if k not in crazy_formatted_mes}

        print('Managed Entities without Sections')
        for c in [c for c in todo_class_ids.values() if c.section is None]:
            print('    {:>4}: {}'.format(c.cid, c.name))

        # Work with what we have
        todo_class_ids = {cid: c for cid, c in todo_class_ids.items()
                          if c.section is not None}
        print('')
        print('Parsing deeper for managed Entities with Sections')

        final_class_ids = todo_class_ids

        # c = final_class_ids[441]              # Uncomment for fast debug of a single Class ID
        # c.deep_parse(self.paragraphs)

        for c in final_class_ids.values():
            if c.section is None:
                c.failure(None, None)
                continue

            print('    {:>9}:  {:>4}: {} -> {}'.format(c.section.section_number,
                                                       c.cid,
                                                       c.name,
                                                       camelcase(c.name)))
            c.deep_parse(self.paragraphs)
            pass

        # Some just need some manual intervention
        final_class_ids = self.fix_difficult_class_ids(final_class_ids)

        # Who creates them
        final_class_ids = self.find_class_access(final_class_ids)

        completed = len([c for c in final_class_ids.values() if c.state == 'complete'])
        failed = len([c for c in final_class_ids.values() if c.state == 'failure'])

        print('Of {} MEs, {} were parsed successfully and {} failed'.format(len(final_class_ids),
                                                                            completed,
                                                                            failed))
        # Run some sanity checks
        print('\n\n\nValidating ME Class Information, total of {}:\n'.
              format(len(final_class_ids)))

        class_with_issues = dict()
        class_with_no_actions = dict()
        class_with_no_attributes = dict()
        attributes_with_no_access = dict()
        attributes_with_no_size = dict()
        attributes_with_zero_size = dict()
        class_with_too_many_attributes = dict()
        num_attributes = 0

        for c in final_class_ids.values():
            print('  ID: {}: {} -\t{}'.format(c.cid, c.section.section_number, c.name),
                  end='')

            if c.state != 'complete':
                print('\t\tParsing ended in state {}', c.state)
                class_with_issues[c.cid] = c

            if len(c.actions) == 0:
                print('\t\tActions: No actions decoded for ME')
                class_with_issues[c.cid] = c
                class_with_no_actions[c.cid] = c
                c.failure(None, None)       # Mark invalid
            else:
                print('\t\tActions: {}'.format({a.name for a in c.actions}))

            if len(c.attributes) == 0:
                print('\t\tNO ATTRIBUTES')      # TODO Look for 'set' without 'get'
                class_with_issues[c.cid] = c
                class_with_no_attributes[c.cid] = c
                c.failure(None, None)       # Mark invalid

            elif len(c.attributes) > 17:        # Entity ID counts as well in this list
                print('\t\tTOO MANY ATTRIBUTES')
                class_with_issues[c.cid] = c
                class_with_too_many_attributes[c.cid] = c
                c.failure(None, None)       # Mark invalid

            else:
                for attr in c.attributes:
                    num_attributes += 1
                    print('\t\t\t\t{}'.format(attr.name), end='')
                    if attr.access is None or len(attr.access) == 0:
                        print('\t\t\t\tNO ACCESS INFORMATION')
                        attributes_with_no_access[c.cid] = c
                        c.failure(None, None)       # Mark invalid
                    else:
                        print('\t\t\t\tAccess: {}'.format({a.name for a in attr.access}))

                    if attr.size is None:
                        attributes_with_no_size[c.cid] = c
                        print('\t\t\t\tNO SIZE INFORMATION')
                        c.failure(None, None)       # Mark invalid

                    elif attr.size.octets == 0:
                        attributes_with_zero_size[c.cid] = c
                        print('\t\t\t\tSIZE zero')
                        c.failure(None, None)       # Mark invalid

        print('Section parsing is complete, saving JSON output...')
        print('=======================================================')

        # Output the results to a JSON file so it can be used by a code-generation
        # tool
        self.parsed.save(self.args.output)

        # Restore and verify
        self.parsed.load(self.args.output)
        self.parsed.dump()

        # Results
        print("Of the {} class IDs, {} had issues: {} had no actions and {} had no attributes and {} with too many".
              format(len(final_class_ids), len(class_with_issues), len(class_with_no_actions),
                     len(class_with_no_attributes), len(class_with_too_many_attributes)))

        print("Of the {} attributes, {} had no access info and {} had no size info and {} had zero size".
              format(num_attributes, len(attributes_with_no_access), len(attributes_with_no_size),
                     len(attributes_with_zero_size)))

        bad_cids = {key for key in class_with_no_actions.keys()} | \
                   {key for key in class_with_no_attributes.keys()} | \
                   {key for key in class_with_too_many_attributes.keys()} | \
                   {key for key in attributes_with_no_access.keys()} | \
                   {key for key in attributes_with_no_size.keys()} | \
                   {key for key in attributes_with_zero_size.keys()}

        if bad_cids:
            print('=======================================================')
            print("Bad Classes: {}".format(len(bad_cids)))
            for cid in bad_cids:
                c = final_class_ids[cid]
                bad = []
                if cid in class_with_no_actions:
                    bad.append("No Action")
                if cid in class_with_no_attributes:
                    bad.append("No Attributes")
                if cid in class_with_too_many_attributes:
                    bad.append("Too Nany Attributes")
                if cid in attributes_with_no_access:
                    bad.append("No Access")
                if cid in attributes_with_no_size:
                    bad.append("No Size")
                if cid in attributes_with_zero_size:
                    bad.append("Zero Size")

                print("  {:3d}: {:<60s}: {}".format(cid, c.name, ', '.join(what for what in bad)))

    def fix_difficult_class_ids(self, class_list):
        # Special exception. Ethernet frame performance monitoring history data downstream
        # is in identical upstream and only a note of that exists. Fix it now
        from parser_lib.actions import Actions
        from parser_lib.size import AttributeSize
        from parser_lib.attributes import AttributeAccess, AttributeList, AttributeType

        # Circuit Pack is now created only by ONU (OLT creation kept only for backwards
        # compatibility
        if 6 in class_list.keys():
            item = class_list[6]
            item.access = ClassAccess.CreatedByOnu

        if 58 in class_list.keys():
            item = class_list[58]
            item.actions.add(Actions.GetNext)

        if 113 in class_list.keys():
            item = class_list[113]
            item.alarms._alarms[7] = ('leftr defect seconds', item.alarms._alarms[7][1])

        if 134 in class_list.keys():
            item = class_list[134]
            item.actions.add(Actions.Test)

        if 408 in class_list.keys():
            item = class_list[408]
            item.alarms._alarms[0] = ('leftr defect seconds', item.alarms._alarms[0][1])

        if 149 in class_list.keys():
            sip = class_list[149]       # SIP config portal (zero size for config text table)

            sz = AttributeSize()
            sz._octets = 25             # Assume it is 25 at most since it is vendor specific
            sip.attributes[1].size = sz

        if 150 in class_list.keys():
            item = class_list[150]
            item.actions.add(Actions.GetNext)

        if 154 in class_list.keys():
            mgc = class_list[154]       # MGC config portal (zero size for config text table)

            sz = AttributeSize()
            sz._octets = 25             # Assume it is 25 at most since it is vendor specific
            mgc.attributes[1].size = sz

        # For SIP user data, the Username&Password attribute is a pointer
        # to a security methods ME and is 2 bytes but is in the document as
        # just (2)
        if 153 in class_list.keys():
            sip = class_list[153]

            sz = AttributeSize()
            sz._octets = 25
            sip.attributes[3].size = sz
            sip.attributes[3].access.add(AttributeAccess.Read)
            sip.attributes[3].access.add(AttributeAccess.Write)

            sz2 = AttributeSize()
            sz2._octets = 2
            sip.attributes[4].size = sz2

        # Large string
        if 157 in class_list.keys():
            item = class_list[157]
            part1 = item.attributes[2]
            part1.name = 'Part 1'
            part1.optional = False
            part1.size._repeat_max = 1

            for part in range(2, 16):
                newPart = copy.deepcopy(part1)
                newPart.name = 'Part {}'.format(part)
                item.attributes.add(newPart)

        # ONU remote debug - reply table size not bounded
        if 158 in class_list.keys():
            item = class_list[158]
            reply_table = item.attributes[3]
            sz = copy.deepcopy(reply_table.size)
            sz._octets = -1
            reply_table.size = sz

        # MCAST GEM Interworking - IPv4
        if 281 in class_list.keys():
            item = class_list[281]
            sz = AttributeSize()
            sz._octets = 12
            sz.getnext_required = True
            item.attributes[9].size = sz
            item.attributes[9].access.add(AttributeAccess.Read)
            item.attributes[9].access.add(AttributeAccess.Write)

        # OMCI.  IPv6 Table is 24N octets
        if 287 in class_list.keys():
            item = class_list[287]
            item.attributes[1].getnext_required = True

            sz = AttributeSize()
            sz._octets = 1
            sz.getnext_required = True
            item.attributes[2].size = sz

        # Managed entity tables.  4 tables need fixing
        if 288 in class_list.keys():
            me = class_list[288]
            class_list[288].name += ' ME'       # To avoid conflicts with Go file/struct names
            sz = AttributeSize()
            sz._octets = 1
            me.attributes[4].size = sz
            me.attributes[5].size = sz

        # Managed entity code points table.  Table is 2*n octets
        if 289 in class_list.keys():
            class_list[289].name += ' ME'       # To avoid conflicts with Go file/struct names

        # Dot1ag maintenance domain. Has multiple attributes defined on one line that need
        # to be split up
        if 299 in class_list.keys():
            item = class_list[299]
            for index in range(6, 3, -1):
                item.attributes[index] = item.attributes[index-1]

            item.attributes[3].name = "MD Name 1"
            item.attributes[4].name = "MD Name 2"

        # Dot1ag maintenance association. Has multiple attributes defined on one line that need
        # to be split up
        if 300 in class_list.keys():
            item = class_list[300]
            for index in range(7, 3, -1):
                item.attributes[index] = item.attributes[index-1]

            item.attributes[3].name = "Short MA Name 1"
            item.attributes[4].name = "Short MA Name 2"

        # Dot1ag chassis-managment info. Has multiple attributes defined on one line that need
        # to be split up.  Three times...
        if 306 in class_list.keys():
            item = class_list[306]
            for index in range(8, 3, -1):
                item.attributes[index] = item.attributes[index-1]

            item.attributes[3].name = "Chassis ID Part 1"
            item.attributes[4].name = "Chassis ID Part 2"

            for index in range(9, 6, -1):
                item.attributes[index] = item.attributes[index-1]

            item.attributes[6].name = "Management Address Domain 1"
            item.attributes[7].name = "Management Address Domain 2"

            for index in range(10, 9, -1):
                item.attributes[index] = item.attributes[index-1]

            item.attributes[9].name = "Management Address 1"
            item.attributes[10].name = "Management Address 2"

        # Octet String - 1..15 row entries
        if 307 in class_list.keys():
            item = class_list[307]
            part1 = item.attributes[2]
            part1.name = 'Part 1'
            part1.optional = False
            part1.size._repeat_max = 1

            for part in range(2, 16):
                newPart = copy.deepcopy(part1)
                newPart.name = 'Part {}'.format(part)
                newPart.optional = True
                item.attributes.add(newPart)

        # General Purpose Buffer - Buffer table is one big unbounded string
        if 308 in class_list.keys():
            item = class_list[308]
            buffer_table = item.attributes[2]
            sz = copy.deepcopy(buffer_table.size)
            sz._octets = -1
            buffer_table.size = sz

        # For multicast operations profile - Attributes getting polluted with table info/descriptions
        if 309 in class_list.keys():
            item = class_list[309]
            if len(item.attributes) == 20:
                first_bad = 8   # Table Control is description of attribute 7
                next_good = 11  # Pick back up to good attributes at the Static Access Control List Table
                # Also attribute 7 lost its information on access...
                old_attributes = item.attributes
                item.attributes = AttributeList()
                for index, attribute in enumerate(old_attributes):
                    if index < first_bad or index >= next_good:
                        item.attributes.add(attribute)

                # And a quick attribute name fixup here
                item.attributes[16].name = "Downstream IGMP and multicast TCI"
                # Some enumerated items
                item.attributes[1].attribute_type = AttributeType.Enumeration
                item.attributes[2].attribute_type = AttributeType.Enumeration
                item.attributes[3].attribute_type = AttributeType.Enumeration

                item.attributes[16].name = "Downstream IGMP and multicast TCI"
                # The pain in the rear table in the document
                sz = AttributeSize()
                sz._octets = 24
                sz.getnext_required = True
                item.attributes[7].size = sz
                item.attributes[7].access.add(AttributeAccess.Read)
                item.attributes[7].access.add(AttributeAccess.Write)

        # For multicast subscriber config info. very hard to decode automatically
        if 310 in class_list.keys():
            msci = class_list[310]
            msci.attributes.remove(8)
            item = msci.attributes[7]
            sz = AttributeSize()
            sz._octets = 22
            sz.getnext_required = True
            item.size = sz
            item.access.add(AttributeAccess.Read)
            item.access.add(AttributeAccess.Write)

        if 321 in class_list.keys() and 322 in class_list.keys():
            down = class_list[321]
            up = class_list[322]
            down.attributes = up.attributes
            down.actions = up.actions
            down.optional_actions = up.optional_actions
            down.alarms = up.alarms
            down.avcs = up.avcs
            down.test_results = up.test_results
            down.hidden = up.hidden

        # xDSL line inventory and status data part 5
        if 325 in class_list.keys():
            item = class_list[325]
            try:
                # Type in document, not table attributes present
                item.actions.remove(Actions.GetNext)
            except KeyError:
                pass

        # Enhanced security control
        if 332 in class_list.keys():
            item = class_list[332]
            try:
                # Type in document, not table attributes present
                item.attributes[7].access.add(AttributeAccess.Read)
            except KeyError:
                pass

        # ONU dynamic power management control
        if 336 in class_list.keys():
            item = class_list[336]
            try:
                old_attributes = item.attributes
                item.attributes = AttributeList()
                for index, attribute in enumerate(old_attributes):
                    if index < 11:
                        item.attributes.add(attribute)

                item.attributes.add(old_attributes[12])
                item.attributes.add(old_attributes[14])
                sz = AttributeSize()
                sz._octets = 1
                item.attributes[10].size = sz
                item.attributes[10].optional = True
                item.attributes[10].access.add(AttributeAccess.Read)

                item.attributes[11].size = sz
                item.attributes[11].optional = True
                item.attributes[11].access.add(AttributeAccess.Read)
                item.attributes[11].access.add(AttributeAccess.Write)
            except KeyError:
                pass

        # xDSL line inventory and status data part 8
        if 414 in class_list.keys():
            item = class_list[414]
            try:
                # Type in document, not table attributes present
                item.actions.remove(Actions.GetNext)
            except KeyError:
                pass

        # Fast Channel COnfigureation Profile ME is missing Managed Entity
        if 432 in class_list.keys():
            item = class_list[432]
            for index in range(11, 0, -1):
                item.attributes[index] = item.attributes[index - 1]

            item.attributes[0] = Attribute().load(
                {
                    "name":          "Managed Entity Id",
                    "description":   [
                        5374
                    ],
                    "access":        [
                        "Read",
                        "SetByCreate"
                    ],
                    "optional":      False,
                    "deprecated":    False,
                    "size":          {
                        "octets":           2,
                        "bits":             None,
                        "repeat_count":     1,
                        "repeat_max":       1,
                        "getnext_required": False
                    },
                    "avc":           False,
                    "tca":           False,
                    "table-support": False,
                    "type":          "Pointer",
                    "constraint":    None,
                    "default":       None
                }, 0)
            item.attributes[1].attribute_type = AttributeType.UnsignedInteger

        # ONU-3G
        if 441 in class_list.keys():
            item = class_list[441]

            old_attributes = item.attributes
            item.attributes = AttributeList()
            for index, attribute in enumerate(old_attributes):
                if index != 3:
                    item.attributes.add(attribute)

            sz = AttributeSize()
            sz._octets = 1
            item.attributes[2].size = sz
            item.attributes[2].optional = False
            item.attributes[2].access.add(AttributeAccess.Read)

            sz = copy.deepcopy(item.attributes[8].size)
            sz._octets = 25     # N bytes. Vendor specific. 25 bytes is max get attribute size
            item.attributes[8].size = sz
            item.attributes[6].size = sz        # Same issue M rows of 'n' size....

        # ONU Manufacturing data has two attributes on the same line
        if 456 in class_list.keys():
            item = class_list[456]
            for index in range(7, 2, -1):
                item.attributes[index] = item.attributes[index-1]

            item.attributes[2].name = "Serial Number 1"
            item.attributes[3].name = "Serial Number 2"


        # Now even some other crazy things
        class_list = self.fix_other_difficulties(class_list)

        # Find counter and other types of attributes
        self.find_attribute_types(class_list)

        return class_list

    @staticmethod
    def fix_other_difficulties(class_list):
        # Some uncommon cleanups
        # for cid, cls in class_list.items():
        #     pass
        return class_list

    @staticmethod
    def find_class_access(class_list):
        from parser_lib.class_id import ClassAccess, Actions
        for _, item in class_list.items():
            if item.access == ClassAccess.UnknownAccess and len(item.actions):
                if Actions.Create in item.actions:
                    item.access = ClassAccess.CreatedByOlt
                else:
                    item.access = ClassAccess.CreatedByOnu

        return class_list

    def find_attribute_types(self, class_list):
        # A bit more in depth look at the attributes
        from parser_lib.attributes import AttributeType

        for cid, item in class_list.items():
            # Any hints to apply before seeding default settings?
            if cid in self.attribute_hints:
                hints = self.attribute_hints[cid]
                for index, attr_hint in hints['attributes'].items():
                    item_attribute = next((attr for attr in item.attributes if attr.index == index), None)
                    if item_attribute is not None:
                        if 'type' in attr_hint:
                            item_attribute.attribute_type = attr_hint['type']
                        if 'default' in attr_hint:
                            item_attribute.default = attr_hint['default']
                        if 'constraint' in attr_hint:
                            item_attribute.constraint = attr_hint['constraint']

            for attr in item.attributes:
                # Only set unknown types (or integer since it may be a counter)
                if attr.attribute_type == AttributeType.Unknown:
                    attr.find_type(item)

        return class_list
Esempio n. 8
0
 def __init__(self):
     self.args = parse_args()
     self.paragraphs = None
     self.parsed = ParsedJson()
     self.metadata = MetadataYAML()
Esempio n. 9
0
class Main(object):
    """ Main program """
    def __init__(self):
        self.args = parse_args()
        self.paragraphs = None
        self.parsed = ParsedJson()
        self.metadata = MetadataYAML()

    def start(self):
        try:
            # Load any existing Metadata YAML file
            self.metadata.load(self.args.existing)

            # Load JSON class ID
            self.parsed.load(self.args.input)

            for cid, item in self.parsed.class_ids.items():
                if cid not in _class_ids_of_interest:
                    continue

                # Add class if not already present
                self.metadata.add_class(cid, item.name)

                # Walk attributes. Attribute features only added if not already present
                for attribute in item.attributes:
                    default_value = self.type_default(attribute.attribute_type, attribute.size)
                    constraint = self.type_constraint(attribute.attribute_type, attribute.size)
                    self.metadata.add_attribute(cid, attribute.index, attribute.name, attribute.attribute_type,
                                                default_value, constraint)

            # Create output directory
            try:
                os.mkdir(self.args.dir)

            except Exception as _e:
                pass

            # Create the output file
            filepath = os.path.join(self.args.dir, "augmented.yaml")
            self.metadata.save(filepath)

        except Exception as _e:
            raise

        # Done
        print('YAML generation completed successfully')

    @staticmethod
    def type_default(attr_type, size):
        if attr_type == AttributeType.Unknown:
            return None

        if attr_type == AttributeType.Octets:
            octets = bytearray(size.octets)            # Zeros
            return base64.b64encode(octets)

        if attr_type == AttributeType.String:
            octets = bytearray(b' ') * size.octets     # Spaces
            return base64.b64encode(octets)

        if attr_type == AttributeType.UnsignedInteger:
            return 0

        if attr_type == AttributeType.Table:
            octets = bytearray(size.octets)            # Zeros
            return base64.b64encode(octets)

        if attr_type == AttributeType.SignedInteger:
            return 0

        if attr_type == AttributeType.Pointer:
            return 0

        if attr_type == AttributeType.BitField:
            return 0

        if attr_type == AttributeType.Enumeration:
            return 0

        if attr_type == AttributeType.Counter:
            return 0

        assert False, 'Not expected'

    @staticmethod
    def type_constraint(attr_type, size):
        if attr_type == AttributeType.Unknown:
            return None

        if attr_type == AttributeType.Octets:
            return 'len({})'.format(size.octets)

        if attr_type == AttributeType.String:
            return 'len({})'.format(size.octets)

        if attr_type == AttributeType.UnsignedInteger:
            return '0..0x{:X}'.format(0xFF if size.octets == 1 else
                                      0xFFFF if size.octets == 2 else
                                      0xFFFFFFFF if size.octets == 4 else
                                      0xFFFFFFFFFFFFFFFF)

        if attr_type == AttributeType.Table:
            octets = bytearray(size.octets)          # Zeros
            return base64.b64encode(octets)

        if attr_type == AttributeType.SignedInteger:
            return 0

        if attr_type == AttributeType.Pointer:
            return '0..0xFFFF'

        if attr_type == AttributeType.BitField:
            return '0x{:X}'.format(0xFF if size.octets == 1 else
                                   0xFFFF if size.octets == 2 else
                                   0xFFFFFFFF if size.octets == 4 else
                                   0xFFFFFFFFFFFFFFFF)

        if attr_type == AttributeType.Enumeration:
            return '0..0x{:X}'.format(0xFF if size.octets == 1 else
                                      0xFFFF if size.octets == 2 else
                                      0xFFFFFFFF if size.octets == 4 else
                                      0xFFFFFFFFFFFFFFFF)

        if attr_type == AttributeType.Counter:
            return None

        assert False, 'Not expected'
Esempio n. 10
0
class Main(object):
    """ Main program """
    def __init__(self):
        self.args = parse_args()
        self.paragraphs = None
        self.parsed = ParsedJson()
        self.version = VersionHeading()
        self.version.name = 'csv-generator'
        self.version.create_time = time.time()
        self.version.itu_document = self.args.ITU

    @staticmethod
    def get_file_hash(filename):
        import hashlib
        with open(filename, 'rb') as f:
            data = f.read()
            return hashlib.sha256(data).hexdigest()

    def load_itu_document(self):
        return Document(self.args.ITU)

    def start(self):
        print("Loading ITU Document '{}' and parsed data file '{}'".format(self.args.ITU,
                                                                           self.args.input))
        try:
            document = self.load_itu_document()
            self.paragraphs = document.paragraphs

            # Directory exists
            if os.path.isdir(self.args.dir):
                if not self.args.force:
                    print("Directory '{}' exists, use --force to overwrite", self.args.dir)
                    return
                shutil.rmtree(self.args.dir)

            # Load JSON class ID list and sort by ID
            self.parsed.load(self.args.input)
            self.parsed.add(self.version)

            class_ids = [c for c in self.parsed.class_ids.values()]
            class_ids.sort(key=lambda x: x.cid)

            # Create output directory
            os.mkdir(self.args.dir)

            # Create the file
            filename = os.path.join(self.args.dir, "omci.csv")
            with open(filename, 'w') as f:
                header = 'Class ID, Class Name, CID Supported, Created By, Actions, MIB Reset, '\
                         'Attribute Number, Attribute Name, Access, Optional, Attr Supported, Type, '\
                         'AVC, Default Value, Constraints, Notes\n'
                f.write(header)

                for class_id in class_ids:
                    name = class_id.name
                    cid = class_id.cid
                    cid_supported = 'n/a'
                    created_by = 'OLT' if Actions.Create in class_id.actions else 'ONU'
                    # actions = '","'.join(action.name for action in class_id.actions)
                    actions = ' '.join(action.name for action in class_id.actions)
                    reset = 'yes' if created_by == 'ONU' else 'no'
                    cid_info = '{}, {}, {}, {}, {}, {}'.format(name, cid, cid_supported,
                                                               created_by, actions, reset)
                    f.write('{}, , , , , , , , , ,\n'.format(cid_info))
                    for attribute in class_id.attributes:
                        pass
                        attr_number = attribute.index
                        attr_name = attribute.name
                        # attr_access = '","'.join(access.name for access in attribute.access)
                        attr_access = ' '.join(access.name for access in attribute.access)
                        attr_optional = 'yes' if attribute.optional else 'no'
                        attr_supported = 'n/a'
                        attr_type = self.attr_type(attribute)
                        attr_default = 'None'
                        attr_constraint = 'None'
                        attr_avc = 'yes' if attribute.avc else 'no'
                        #
                        f.write('{}, {}, {}, {}, {}, {}, {}, {}, {}, {}\n'.format(cid_info, attr_number, attr_name,
                                                                                  attr_access, attr_optional,
                                                                                  attr_supported, attr_type,
                                                                                  attr_avc,
                                                                                  attr_default, attr_constraint))
        except Exception as _e:
            raise
        # Done
        print('CSV generation completed successfully')

    def attr_type(self, attribute):
        results = ''
        pass
        if attribute.table_support:
            results = 'table({})'.format(attribute.size.octets)
            pass
            pass
            pass

        elif attribute.counter:
            results = 'uint'
            pass
        else:
            size = '{}'.format(attribute.size.octets)
            if attribute.size.repeat_count > 1:
                if attribute.size.repeat_max:
                    size += '*{}..{}'.format(attribute.size.repeat_count,
                                             attribute.size.repeat_count)
                else:
                    size += '*{}'.format(attribute.size.repeat_count)

            results = 'uint({})'.format(size)

        return results