Esempio n. 1
0
    def _add_new_instance(self,  device_id, class_id, instance_id, attributes):
        """
        Create an entry for a instance of an existing class in the external database

        :param device_id: (str) ONU Device ID
        :param class_id: (int) ME Class ID
        :param instance_id: (int) ME Entity ID
        :param attributes: (dict) Attribute dictionary

        :returns: (bool) True if the value was saved to the database. False if the
                         value was identical to the current instance
        """
        self.log.debug('add', device_id=device_id, class_id=class_id,
                       instance_id=instance_id, attributes=attributes)

        now = self._time_to_string(datetime.utcnow())
        attrs = [MibAttributeData(name=k,
                                  value=self._attribute_to_string(device_id,
                                                                  class_id,
                                                                  k,
                                                                  v)) for k, v in attributes.items()]
        instance_data = MibInstanceData(instance_id=instance_id,
                                        created=now,
                                        modified=now,
                                        attributes=attrs)

        self._root_proxy.add(MibDbExternal.INSTANCES_PATH.format(device_id, class_id),
                             instance_data)

        self.log.debug('set-complete', device_id=device_id, class_id=class_id,
                       entity_id=instance_id, attributes=attributes)
        return True
Esempio n. 2
0
    def _instance_proxy(self, device_id, class_id, instance_id, create=False):
        """
        Get a config proxy to a specific managed entity instance
        :param device_id: (str) ONU Device ID
        :param class_id: (int) Class ID
        :param instance_id: (int) Instance ID
        :param create: (bool) If true, create default instance (and class)
        :return: (ConfigProxy) Instance configuration proxy

        :raises DatabaseStateError: If database is not started
        :raises KeyError: If Instance does not exist and 'create' is False
        """
        if not self._started:
            raise DatabaseStateError('The Database is not currently active')

        if not isinstance(device_id, basestring):
            raise TypeError('Device ID is a string')

        if not 0 <= class_id <= 0xFFFF:
            raise ValueError('class-id is 0..0xFFFF')

        if not 0 <= instance_id <= 0xFFFF:
            raise ValueError('instance-id is 0..0xFFFF')

        fmt = MibDbExternal.DEVICE_PATH + MibDbExternal.INSTANCE_PATH
        path = fmt.format(device_id, class_id, instance_id)

        try:
            return self._core.get_proxy(path)

        except KeyError:
            if not create:
                # This can occur right after a MIB Reset if the ONU publishes AVCs right away
                # and during the MIB audit resync for ONU created MEs in response to an OLT
                # created ME.  Fail since for these test cases they occur during a verification
                # 'query' and not the ME creation during resync. Calling code should handle
                # they exception if it is expected to occur on occasion.
                self.log.info('instance-proxy-does-not-exist',
                              device_id=device_id,
                              class_id=class_id,
                              instance_id=instance_id)
                raise

        # Create instance, first make sure class exists
        self._class_proxy(device_id, class_id, create=True)

        now = self._time_to_string(datetime.utcnow())
        data = MibInstanceData(instance_id=instance_id,
                               created=now,
                               modified=now)
        root_path = MibDbExternal.INSTANCES_PATH.format(device_id, class_id)
        self._root_proxy.add(root_path, data)

        return self._core.get_proxy(path)
Esempio n. 3
0
    def _add_new_class(self, device_id, class_id, instance_id, attributes):
        """
        Create an entry for a new class in the external database

        :param device_id: (str) ONU Device ID
        :param class_id: (int) ME Class ID
        :param instance_id: (int) ME Entity ID
        :param attributes: (dict) Attribute dictionary

        :returns: (bool) True if the value was saved to the database. False if the
                         value was identical to the current instance
        """
        self.log.debug('add',
                       device_id=device_id,
                       class_id=class_id,
                       instance_id=instance_id,
                       attributes=attributes)

        now = self._time_to_string(datetime.utcnow())
        #        attrs = [MibAttributeData(name=k,
        #                                  value=self._attribute_to_string(device_id,
        #                                                                  class_id,
        #                                                                  k,
        #                                                                  v)) for k, v in attributes.items()]
        attrs = []
        for k, v in attributes.items():
            if k == 'serial_number':
                vendor_id = str(v[0:4])
                vendor_specific = v[4:]
                vendor_specific = str(vendor_specific.encode('hex'))
                str_value = vendor_id + vendor_specific
                attrs.append(MibAttributeData(name=k, value=str_value))
            else:
                str_value = self._attribute_to_string(device_id, class_id, k,
                                                      v)
                attrs.append(MibAttributeData(name=k, value=str_value))

        class_data = MibClassData(class_id=class_id,
                                  instances=[
                                      MibInstanceData(instance_id=instance_id,
                                                      created=now,
                                                      modified=now,
                                                      attributes=attrs)
                                  ])

        self._root_proxy.add(MibDbExternal.CLASSES_PATH.format(device_id),
                             class_data)
        self.log.debug('set-complete',
                       device_id=device_id,
                       class_id=class_id,
                       entity_id=instance_id,
                       attributes=attributes)
        return True
Esempio n. 4
0
    def _instance_proxy(self, device_id, class_id, instance_id, create=False):
        """
        Get a config proxy to a specific managed entity instance
        :param device_id: (str) ONU Device ID
        :param class_id: (int) Class ID
        :param instance_id: (int) Instance ID
        :param create: (bool) If true, create default instance (and class)
        :return: (ConfigProxy) Instance configuration proxy

        :raises DatabaseStateError: If database is not started
        :raises KeyError: If Instance does not exist and 'create' is False
        """
        if not self._started:
            raise DatabaseStateError('The Database is not currently active')

        if not isinstance(device_id, basestring):
            raise TypeError('Device ID is a string')

        if not 0 <= class_id <= 0xFFFF:
            raise ValueError('class-id is 0..0xFFFF')

        if not 0 <= instance_id <= 0xFFFF:
            raise ValueError('instance-id is 0..0xFFFF')

        fmt = MibDbExternal.DEVICE_PATH + MibDbExternal.INSTANCE_PATH
        path = fmt.format(device_id, class_id, instance_id)

        try:
            return self._core.get_proxy(path)

        except KeyError:
            if not create:
                self.log.error('instance-proxy-does-not-exist',
                               device_id=device_id,
                               class_id=class_id,
                               instance_id=instance_id)
                raise

        # Create instance, first make sure class exists
        self._class_proxy(device_id, class_id, create=True)

        now = self._time_to_string(datetime.utcnow())
        data = MibInstanceData(instance_id=instance_id,
                               created=now,
                               modified=now)
        root_path = MibDbExternal.INSTANCES_PATH.format(device_id, class_id)
        self._root_proxy.add(root_path, data)

        return self._core.get_proxy(path)
Esempio n. 5
0
    def set(self, device_id, class_id, instance_id, attributes):
        """
        Set a database value.  This should only be called by the MIB synchronizer
        and its related tasks

        :param device_id: (str) ONU Device ID
        :param class_id: (int) ME Class ID
        :param instance_id: (int) ME Entity ID
        :param attributes: (dict) Attribute dictionary

        :returns: (bool) True if the value was saved to the database. False if the
                         value was identical to the current instance

        :raises KeyError: If device does not exist
        :raises DatabaseStateError: If the database is not enabled
        """
        self.log.debug('set', device_id=device_id, class_id=class_id,
                       instance_id=instance_id, attributes=attributes)
        try:
            if not isinstance(device_id, basestring):
                raise TypeError('Device ID should be a string')

            if not 0 <= class_id <= 0xFFFF:
                raise ValueError("Invalid Class ID: {}, should be 0..65535".format(class_id))

            if not 0 <= instance_id <= 0xFFFF:
                raise ValueError("Invalid Instance ID: {}, should be 0..65535".format(instance_id))

            if not isinstance(attributes, dict):
                raise TypeError("Attributes should be a dictionary")

            if not self._started:
                raise DatabaseStateError('The Database is not currently active')

            # Determine the best strategy to add the information
            dev_proxy = self._device_proxy(device_id)

            operation = 'set'
            start_time = None
            try:
                class_data = dev_proxy.get(MibDbExternal.CLASS_PATH.format(class_id), deep=True)

                inst_data = next((inst for inst in class_data.instances
                                 if inst.instance_id == instance_id), None)

                if inst_data is None:
                    operation = 'create'
                    start_time = datetime.utcnow()
                    return self._add_new_instance(device_id, class_id, instance_id, attributes)

                # Possibly adding to or updating an existing instance
                # Get instance proxy, creating it if needed

                modified = False
                new_attributes = []
                exist_attr_indexes = dict()
                attr_len = len(inst_data.attributes)

                for index in xrange(0, attr_len):
                    name = inst_data.attributes[index].name
                    value = inst_data.attributes[index].value
                    exist_attr_indexes[name] = index
                    new_attributes.append(MibAttributeData(name=name, value=value))

                for k, v in attributes.items():
                    try:
                        old_value = None if k not in exist_attr_indexes \
                            else new_attributes[exist_attr_indexes[k]].value

                        str_value = self._attribute_to_string(device_id, class_id, k, v, old_value)

                        if k not in exist_attr_indexes:
                            new_attributes.append(MibAttributeData(name=k, value=str_value))
                            modified = True

                        elif new_attributes[exist_attr_indexes[k]].value != str_value:
                            new_attributes[exist_attr_indexes[k]].value = str_value
                            modified = True

                    except Exception as e:
                        self.log.exception('save-error', e=e, class_id=class_id,
                                           attr=k, value_type=type(v))

                if modified:
                    now = datetime.utcnow()
                    start_time = now
                    new_data = MibInstanceData(instance_id=instance_id,
                                               created=inst_data.created,
                                               modified=self._time_to_string(now),
                                               attributes=new_attributes)
                    dev_proxy.remove(MibDbExternal.INSTANCE_PATH.format(class_id, instance_id))
                    self._root_proxy.add(MibDbExternal.INSTANCES_PATH.format(device_id,
                                                                             class_id), new_data)
                return modified

            except KeyError:
                # Here if the class-id does not yet exist in the database
                self.log.debug("adding-key-not-found", class_id=class_id)
                return self._add_new_class(device_id, class_id, instance_id,
                                           attributes)
            finally:
                if start_time is not None:
                    diff = datetime.utcnow() - start_time
                    # NOTE: Change to 'debug' when checked in, manually change to 'info'
                    #       for development testing.
                    self.log.debug('db-{}-time'.format(operation), milliseconds=diff.microseconds/1000)
                    self._statistics[operation].increment(diff.microseconds/1000)

        except Exception as e:
            self.log.exception('set-exception', device_id=device_id, class_id=class_id,
                               instance_id=instance_id, attributes=attributes, e=e)
            raise
Esempio n. 6
0
    def set(self, device_id, class_id, instance_id, attributes):
        """
        Set a database value.  This should only be called by the MIB synchronizer
        and its related tasks

        :param device_id: (str) ONU Device ID
        :param class_id: (int) ME Class ID
        :param instance_id: (int) ME Entity ID
        :param attributes: (dict) Attribute dictionary

        :returns: (bool) True if the value was saved to the database. False if the
                         value was identical to the current instance

        :raises KeyError: If device does not exist
        :raises DatabaseStateError: If the database is not enabled
        """
        self.log.debug('set',
                       device_id=device_id,
                       class_id=class_id,
                       instance_id=instance_id,
                       attributes=attributes)
        try:
            if not isinstance(device_id, basestring):
                raise TypeError('Device ID should be a string')

            if not 0 <= class_id <= 0xFFFF:
                raise ValueError(
                    "Invalid Class ID: {}, should be 0..65535".format(
                        class_id))

            if not 0 <= instance_id <= 0xFFFF:
                raise ValueError(
                    "Invalid Instance ID: {}, should be 0..65535".format(
                        instance_id))

            if not isinstance(attributes, dict):
                raise TypeError("Attributes should be a dictionary")

            if not self._started:
                raise DatabaseStateError(
                    'The Database is not currently active')

            # Determine the best strategy to add the information
            dev_proxy = self._device_proxy(device_id)

            try:
                class_data = dev_proxy.get(
                    MibDbExternal.CLASS_PATH.format(class_id), deep=True)

                inst_data = next((inst for inst in class_data.instances
                                  if inst.instance_id == instance_id), None)

                if inst_data is None:
                    return self._add_new_instance(device_id, class_id,
                                                  instance_id, attributes)

                # Possibly adding to or updating an existing instance
                # Get instance proxy, creating it if needed

                exist_attr_indexes = dict()
                attr_len = len(inst_data.attributes)

                for index in xrange(0, attr_len):
                    exist_attr_indexes[
                        inst_data.attributes[index].name] = index

                modified = False
                new_attributes = []

                for k, v in attributes.items():
                    str_value = self._attribute_to_string(
                        device_id, class_id, k, v)
                    new_attributes.append(
                        MibAttributeData(name=k, value=str_value))

                    if k not in exist_attr_indexes or \
                            inst_data.attributes[exist_attr_indexes[k]].value != str_value:
                        modified = True

                if modified:
                    now = datetime.utcnow()
                    new_data = MibInstanceData(
                        instance_id=instance_id,
                        created=inst_data.created,
                        modified=self._time_to_string(now),
                        attributes=new_attributes)
                    dev_proxy.remove(
                        MibDbExternal.INSTANCE_PATH.format(
                            class_id, instance_id))
                    self._root_proxy.add(
                        MibDbExternal.INSTANCES_PATH.format(
                            device_id, class_id), new_data)

                self.log.debug('set-complete',
                               device_id=device_id,
                               class_id=class_id,
                               entity_id=instance_id,
                               attributes=attributes,
                               modified=modified)

                return modified

            except KeyError:
                # Here if the class-id does not yet exist in the database
                return self._add_new_class(device_id, class_id, instance_id,
                                           attributes)
        except Exception as e:
            self.log.exception('set-exception',
                               device_id=device_id,
                               class_id=class_id,
                               instance_id=instance_id,
                               attributes=attributes,
                               e=e)
            raise