Ejemplo n.º 1
0
def initialize(notification_callback=None):
    """ Initialize the NTF library

    Args:
        notification_callback (SaNtfNotificationCallbackT): Callback to be
            invoked by NTF server to deliver a notification to the subscriber

    Raises:
        SafException: If any NTF API call did not return SA_AIS_OK
    """
    # Set the NTF API version to initialize
    version = SaVersionT('A', 1, 1)

    global _ntf_producer
    _ntf_producer = NtfProducer(version)

    global _ntf_subscriber
    _ntf_subscriber = NtfSubscriber(version)

    rc = _ntf_producer.init()
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    rc = _ntf_subscriber.init(notification_callback)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 2
0
def track_stop():
    """ Stop cluster membership tracking

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    if _clm_agent is None:
        # Return SA_AIS_ERR_INIT if user calls this function without first
        # calling initialize()
        raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)

    rc = _clm_agent.track_stop()
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 3
0
def admin_op_invoke(dn, op_id, params=None):
    ''' invokes admin op for dn '''
    owner_handle = saImmOm.SaImmAdminOwnerHandleT()
    owner_name = saImmOm.SaImmAdminOwnerNameT(os.getlogin())
    err = saImmOmAdminOwnerInitialize(HANDLE, owner_name,
                                      saAis.eSaBoolT.SA_TRUE, owner_handle)

    idx = dn.rfind(",")
    parent_name = SaNameT(dn[idx + 1:])
    object_names = [parent_name]
    err = saImmOmAdminOwnerSet(owner_handle, object_names,
                               eSaImmScopeT.SA_IMM_SUBTREE)

    if params is None:
        params = []

    object_dn = SaNameT(dn)
    retval = saAis.SaAisErrorT()

    err = saImmOmAdminOperationInvoke_2(owner_handle, object_dn, 0, op_id,
                                        params, retval,
                                        saAis.saAis.SA_TIME_ONE_SECOND * 10)

    if retval.value != eSaAisErrorT.SA_AIS_OK:
        print "saImmOmAdminOperationInvoke_2: %s" % \
            eSaAisErrorT.whatis(retval.value)
        raise SafException(retval.value)

    error = saImmOmAdminOwnerFinalize(owner_handle)
Ejemplo n.º 4
0
def send_attribute_change_notification(
        vendor_id,
        major_id,
        minor_id,
        additional_text="",
        notification_object="",
        notifying_object="",
        event_type=saNtf.eSaNtfEventTypeT.SA_NTF_ATTRIBUTE_ADDED,
        event_time=saAis.SA_TIME_UNKNOWN,
        additional_info=None,
        changed_attributes=None):
    """ Send notification about an attribute change event

    Args:
        vendor_id (SaUint32T): Vendor id
        major_id (SaUint16T): Major id
        minor_id (SaUint16T): Minor id
        additional_text (str): Additional text
        notification_object (str): Notification object's dn
        notifying_object (str): Notifying object's dn
        event_type (SaNtfEventTypeT): Event type
        event_time (SaTimeT): Event time
        additional_info (list(AdditionalInfo)): List of AdditionalInfo
            structures
        changed_attributes (list(AttributeChange)): List of AttributeChange
            structures

    Returns:
        SaAisErrorT: Return code of the corresponding NTF API call(s)

    Raises:
        SafException: If any NTF API call did not return SA_AIS_OK
    """
    ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
    if _ntf_producer is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        return eSaAisErrorT.SA_AIS_ERR_INIT

    _ntf_producer.set_event_type(event_type)
    _ntf_producer.set_class_id(ntf_class_id)
    _ntf_producer.set_additional_text(additional_text)
    _ntf_producer.set_notification_object(notification_object)
    _ntf_producer.set_notifying_object(notifying_object)
    _ntf_producer.set_event_time(event_time)
    if additional_info:
        _ntf_producer.set_additional_info(additional_info)
    if changed_attributes:
        _ntf_producer.set_changed_attributes(changed_attributes)

    rc = _ntf_producer.send_attribute_change_notification()
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    # Clear the internally saved notification information
    _ntf_producer.clear_info()

    return rc
Ejemplo n.º 5
0
def send_alarm_notification(
        vendor_id,
        major_id,
        minor_id,
        perceived_severity,
        additional_text="",
        notification_object="",
        notifying_object="",
        event_type=saNtf.eSaNtfEventTypeT.SA_NTF_ALARM_PROCESSING,
        event_time=saAis.SA_TIME_UNKNOWN,
        additional_info=None):
    """ Send an alarm notification

    Args:
        vendor_id (SaUint32T): Vendor id
        major_id (SaUint16T): Major id
        minor_id (SaUint16T): Minor id
        perceived_severity (SaNtfSeverityT): Perceived severity
        additional_text (str): Additional text
        notification_object (str): Notification object's dn
        notifying_object (str): Notifying object's dn
        event_type (SaNtfEventTypeT): Event type
        event_time (SaTimeT): Event time
        additional_info (list(AdditionalInfo)): List of AdditionalInfo
            structures

    Returns:
        SaAisErrorT: Return code of the corresponding NTF API call(s)

    Raises:
        SafException: If any NTF API call did not return SA_AIS_OK
    """
    ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
    if _ntf_producer is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        return eSaAisErrorT.SA_AIS_ERR_INIT

    _ntf_producer.set_event_type(event_type)
    _ntf_producer.set_class_id(ntf_class_id)
    _ntf_producer.set_additional_text(additional_text)
    _ntf_producer.set_notification_object(notification_object)
    _ntf_producer.set_notifying_object(notifying_object)
    _ntf_producer.set_event_time(event_time)
    _ntf_producer.set_perceived_severity(perceived_severity)
    if additional_info:
        _ntf_producer.set_additional_info(additional_info)

    rc = _ntf_producer.send_alarm_notification()
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    # Clear the internally saved notification information
    _ntf_producer.clear_info()

    return rc
Ejemplo n.º 6
0
    def __init__(self, dn=None, attributes=None, class_name=None):
        """ Constructor for IMM object
        Attributes is a map where attribute name is key, value is a tuple of
        (valueType, values), values is a list.
        class_name and attributes are mutually exclusive.

        Raises:
            SafException: If the return code of the corresponding API call(s)
                is not SA_AIS_OK
        """
        self.__dict__["dn"] = dn
        _imm_om = ImmOmAgent()
        rc = _imm_om.init()
        if rc != eSaAisErrorT.SA_AIS_OK:
            raise SafException(rc)
        # mutually exclusive for read vs create
        if class_name is not None:
            assert attributes is None
            self.__dict__["attrs"] = {}
            self.__dict__["class_name"] = class_name
            rc, class_desc = _imm_om.get_class_description(class_name)
            if rc != eSaAisErrorT.SA_AIS_OK:
                raise SafException(rc)
            self.class_desc[str(class_name)] = class_desc
        elif attributes is not None:
            assert class_name is None
            self.__dict__["attrs"] = attributes
            class_name = attributes["SaImmAttrClassName"][1][0]
            self.__dict__["class_name"] = class_name
            if class_name not in self.class_desc:
                rc, class_desc = _imm_om.get_class_description(class_name)
                if rc != eSaAisErrorT.SA_AIS_OK:
                    raise SafException(rc)
                self.class_desc[str(class_name)] = class_desc
        else:
            raise ValueError("Class and attributes are None")

        self.__dict__["rdn_attribute"] = \
            _imm_om.get_rdn_attribute_for_class(class_name)
Ejemplo n.º 7
0
def initialize():
    """ Initialize the IMM OM library

    Raises:
        SafException: If any IMM OM API call did not return SA_AIS_OK
    """
    global _om_agent
    _om_agent = agent.ImmOmAgent()

    # Initialize IMM OM handle and return the API return code
    rc = _om_agent.init()
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 8
0
    def delete(self, _object_name):
        ''' Adds a delete operation of the object with the given DN to the
            CCB'''

        if _object_name is None:
            raise SafException(eSaAisErrorT.SA_AIS_ERR_NOT_EXIST)

        object_name = SaNameT(_object_name)
        object_names = [object_name]

        immom.saImmOmAdminOwnerSet(self.owner_handle, object_names,
                                   eSaImmScopeT.SA_IMM_SUBTREE)

        immom.saImmOmCcbObjectDelete(self.ccb_handle, object_name)
Ejemplo n.º 9
0
def get_selection_object():
    """ Get an selection object for event polling

    Returns:
        SaSelectionObjectT: Return code of selection object get

    Raises:
        SafException: If the OI agent is not initialized
    """
    if _oi_agent is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)

    return _oi_agent.get_selection_object()
Ejemplo n.º 10
0
    def modify_value_add(self, object_name, attr_name, values):
        ''' add to the CCB an ADD modification of an existing object '''

        assert object_name

        # Make sure the values field is a list
        if not isinstance(values, list):
            values = [values]

        # first get class name to read class description to get value type...
        try:
            obj = immom.get(object_name)
        except SafException as err:
            print "failed: %s" % err
            return

        object_names = [SaNameT(object_name)]
        class_name = obj.SaImmAttrClassName
        value_type = None
        attr_def_list = immom.class_description_get(class_name)
        for attr_def in attr_def_list:
            if attr_def.attrName == attr_name:
                value_type = attr_def.attrValueType
                break

        if value_type is None:
            # means attribute name is invalid
            raise SafException(eSaAisErrorT.SA_AIS_ERR_NOT_EXIST,
                               "attribute '%s' does not exist" % attr_name)

        err = immom.saImmOmAdminOwnerSet(self.owner_handle, object_names,
                                         eSaImmScopeT.SA_IMM_ONE)

        attr_mods = []

        attr_mod = saImmOm.SaImmAttrModificationT_2()
        attr_mod.modType = \
            saImm.eSaImmAttrModificationTypeT.SA_IMM_ATTR_VALUES_ADD
        attr_mod.modAttr = SaImmAttrValuesT_2()
        attr_mod.modAttr.attrName = attr_name
        attr_mod.modAttr.attrValueType = value_type
        attr_mod.modAttr.attrValuesNumber = len(values)
        attr_mod.modAttr.attrValues = marshal_c_array(value_type, values)

        attr_mods.append(attr_mod)

        err = immom.saImmOmCcbObjectModify_2(self.ccb_handle, object_names[0],
                                             attr_mods)
Ejemplo n.º 11
0
def initialize(callbacks=None):
    """ Initialize the IMM OI library

    Args:
        callbacks (SaImmOiCallbacksT_2): OI callbacks to register with IMM

    Raises:
        SafException: If the return code of the corresponding OI API call(s)
            is not SA_AIS_OK
    """
    global _oi_agent
    _oi_agent = OiAgent()

    rc = _oi_agent.initialize(callbacks=callbacks)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 12
0
def get_selection_object():
    """ Get the selection object associated with this CLM agent

    Returns:
        SaSelectionObjectT: Selection object associated with the CLM handle

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    if _clm_agent is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        raise SafException(eSaAisErrorT.SA_AIS_ERR_INIT)

    return _clm_agent.get_selection_object()
Ejemplo n.º 13
0
def delete_rt_object(dn):
    """ Delete a runtime object

    Args:
        dn (str): Runtime object dn

    Raises:
        SafException: If the return code of the corresponding OI API call(s)
            is not SA_AIS_OK
    """
    if _oi_agent is None:
        initialize()

    rc = _oi_agent.delete_runtime_object(dn)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 14
0
def track(flags=saAis.SA_TRACK_CHANGES_ONLY):
    """ Start cluster membership tracking with specified flags

    Args:
        flags (SaUint8T): Type of cluster membership tracking

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    if _clm_agent is None:
        # Return SA_AIS_ERR_INIT if user calls this function without first
        # calling initialize()
        return eSaAisErrorT.SA_AIS_ERR_INIT

    rc = _clm_agent.track_start(flags)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 15
0
def initialize(track_func=None, node_get_func=None, version=None):
    """ Initialize the CLM agent library

    Args:
        track_func (callback): Cluster track callback function
        node_get_func (callback): Cluster node get callback function
        version (SaVersionT): Clm version being initialized

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    global _clm_agent
    _clm_agent = ClmAgent(version)

    rc = _clm_agent.initialize(track_func, node_get_func)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 16
0
def report_admin_operation_result(invocation_id, result):
    """ Report the result of an administrative operation

    Args:
        invocation_id (SaInvocationT): Invocation id
        result (SaAisErrorT): Result of admin operation

    Raises:
        SafException: If the return code of the corresponding OI API call(s)
            is not SA_AIS_OK
    """
    if _oi_agent is None:
        initialize()

    rc = _oi_agent.report_admin_operation_result(invocation_id, result)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 17
0
def admin_op_invoke(dn, op_id, params=None):
    """ Invoke admin op for dn

    Args:
        dn (str): Object dn
        op_id (str): Operation id
        params (list): List of parameters

    Raises:
        SafException: If any IMM OM API call did not return SA_AIS_OK
    """
    if _om_agent is None:
        initialize()

    rc = _om_agent.invoke_admin_operation(dn, op_id, params)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 18
0
def dispatch(flags=eSaDispatchFlagsT.SA_DISPATCH_ALL):
    """ Invoke NTF callbacks for queued events. The default is to dispatch all
    available events.

    Args:
        flags (eSaDispatchFlagsT): Flags specifying dispatch mode

    Returns:
        SaAisErrorT: Return code of the corresponding NTF API call(s)

    Raises:
        SafException: If any NTF API call did not return SA_AIS_OK
    """
    rc = _ntf_subscriber.dispatch(flags)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    return rc
Ejemplo n.º 19
0
def response(invocation, result):
    """ Respond to CLM the result of execution of the requested callback

    Args:
        invocation (SaInvocationT): Invocation id associated with the callback
        result (SaAisErrorT): Result of callback execution

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    if _clm_agent is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        rc = eSaAisErrorT.SA_AIS_ERR_INIT
    else:
        rc = _clm_agent.response(invocation, result)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 20
0
def create_rt_object(class_name, parent_name, runtime_obj):
    """ Create a runtime object

    Args:
        class_name (str): Class name
        parent_name (str): Parent name
        runtime_obj (ImmObject): Runtime object to create

    Raises:
        SafException: If the return code of the corresponding OI API call(s)
            is not SA_AIS_OK
    """
    if _oi_agent is None:
        initialize()

    rc = _oi_agent.create_runtime_object(class_name, parent_name, runtime_obj)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 21
0
def update_rt_object(dn, attributes):
    """ Update the specified object with the requested attribute
    modifications

    Args:
        dn (str): Object dn
        attributes (dict): Dictionary of attribute modifications

    Raises:
        SafException: If the return code of the corresponding OI API call(s)
            is not SA_AIS_OK
    """
    if _oi_agent is None:
        initialize()

    rc = _oi_agent.update_runtime_object(dn, attributes)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 22
0
def set_error_string(ccb_id, error_string):
    """ Set the error string
    This can only be called from within OI callbacks of a real implementer.

    Args:
        ccb_id (SaImmOiCcbIdT): CCB id
        error_string (str): Error string

    Raises:
        SafException: If the return code of the corresponding OI API call(s)
            is not SA_AIS_OK
    """
    if _oi_agent is None:
        initialize()

    rc = _oi_agent.set_error_string(ccb_id, error_string)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 23
0
def dispatch(flags=eSaDispatchFlagsT.SA_DISPATCH_ALL):
    """ Invoke CLM callbacks for queued events with the given dispatch flag.
    If no dispatch flag is specified, the default is to dispatch all available
    events.

    Args:
        flags (eSaDispatchFlagsT): Flags specifying dispatch mode

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    if _clm_agent is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        rc = eSaAisErrorT.SA_AIS_ERR_INIT
    else:
        rc = _clm_agent.dispatch(flags)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)
Ejemplo n.º 24
0
def class_description_get(class_name):
    """ Get class description as a Python list

    Args:
        class_name (str): Class name

    Returns:
        list: List of class attributes

    Raises:
        SafException: If any IMM OM API call did not return SA_AIS_OK
    """
    if _om_agent is None:
        initialize()

    rc, class_attrs = _om_agent.get_class_description(class_name)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    return class_attrs
Ejemplo n.º 25
0
def get_members():
    """ Get member notifications from notification buffer

    Returns:
        ClusterNode: The node information

    Raises:
        SafException: If the return code of the corresponding CLM API call(s)
            is not SA_AIS_OK
    """
    if _clm_agent is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        rc = eSaAisErrorT.SA_AIS_ERR_INIT
    else:
        rc, cluster_nodes = _clm_agent.get_members()

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    return cluster_nodes
Ejemplo n.º 26
0
def subscribe_for_notifications(notification_types=None):
    """ Subscribe for notifications from NTF with the types specified in the
    notification_types list
    If the list is not provided, all types of notification are subscribed to
    by default.

    Args:
        notification_types (list(SaNtfNotificationTypeT)): List of
            notification types

    Returns:
        SaAisErrorT: Return code of the corresponding NTF API call(s)

    Raises:
        SafException: If any NTF API call did not return SA_AIS_OK
    """
    rc = _ntf_subscriber.subscribe(1, notification_types)
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    return rc
Ejemplo n.º 27
0
def get(object_name, attr_name_list=None, class_name=None):
    """ Obtain values of some attributes of the specified object

    Args:
        object_name (str): Object name
        attr_name_list (list): List of attributes
        class_name (str): Class name

    Returns:
        ImmObject: Imm object

    Raises:
        SafException: If any IMM OM API call did not return SA_AIS_OK
    """
    _accessor = ImmOmAccessor()
    _accessor.init()
    rc, imm_object = _accessor.get(object_name, attr_name_list, class_name)

    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    return imm_object
Ejemplo n.º 28
0
def send_security_alarm_notification(
        vendor_id,
        major_id,
        minor_id,
        severity,
        alarm_detector,
        user,
        provider,
        additional_text="",
        notification_object="",
        notifying_object="",
        event_type=saNtf.eSaNtfEventTypeT.SA_NTF_INTEGRITY_VIOLATION,
        event_time=saAis.SA_TIME_UNKNOWN,
        additional_info=None,
        probable_cause=saNtf.eSaNtfProbableCauseT.SA_NTF_SOFTWARE_ERROR):
    """ Send a security alarm notification

    Args:
        vendor_id (SaUint32T): Vendor id
        major_id (SaUint16T): Major id
        minor_id (SaUint16T): Minor id
        severity (SaNtfSeverityT): Severity
        alarm_detector (SecurityAlarmDetector): SecurityAlarmDetector
            information structure
        user (ServiceUser): ServiceUser information structure
        provider (ServiceProvider): ServiceProvider information structure
        additional_text (str): Additional text
        notification_object (str): Notification object's dn
        notifying_object (str): Notifying object's dn
        event_type (SaNtfEventTypeT): Event type
        event_time (SaTimeT): Event time
        additional_info (list(AdditionalInfo)): List of AdditionalInfo
            structures
        probable_cause (SaNtfProbableCauseT): Probable cause

    Returns:
        SaAisErrorT: Return code of the corresponding NTF API call(s)

    Raises:
        SafException: If any NTF API call did not return SA_AIS_OK
    """
    ntf_class_id = saNtf.SaNtfClassIdT(vendor_id, major_id, minor_id)
    if _ntf_producer is None:
        # SA_AIS_ERR_INIT is returned if user calls this function without first
        # calling initialize()
        return eSaAisErrorT.SA_AIS_ERR_INIT

    _ntf_producer.set_event_type(event_type)
    _ntf_producer.set_class_id(ntf_class_id)
    _ntf_producer.set_additional_text(additional_text)
    _ntf_producer.set_notification_object(notification_object)
    _ntf_producer.set_notifying_object(notifying_object)
    _ntf_producer.set_event_time(event_time)
    if additional_info:
        _ntf_producer.set_additional_info(additional_info)
    _ntf_producer.set_severity(severity)
    _ntf_producer.set_probable_cause(probable_cause)
    _ntf_producer.set_security_alarm_detector(alarm_detector)
    _ntf_producer.set_service_user(user)
    _ntf_producer.set_service_provider(provider)

    rc = _ntf_producer.send_security_alarm_notification()
    if rc != eSaAisErrorT.SA_AIS_OK:
        raise SafException(rc)

    # Clear the internally saved notification information
    _ntf_producer.clear_info()

    return rc
Ejemplo n.º 29
0
    def validate(self, all_instances, updated, created, deleted):
        ''' Validates the constraints in this Constraints instance '''

        def get_children_with_classname(parent_name, all_instances, class_name):
            ''' Helper method to count the number of children of the given class
                in the list of all instances '''
            current_children = []

            for child in all_instances:

                if not ',' in child.dn:
                    continue

                if immoi.get_parent_name_for_dn(child.dn) == parent_name and \
                   child.class_name == class_name:
                    current_children.append(child)

            return current_children

        def constraint_exists_for_child(class_name):
            ''' Returns true if there exists a constraint for the given class as
                a child
            '''

            for child_classes in self.containments.values():
                if class_name in child_classes:
                    return True

            return False

        # Validate containments affected by create or delete
        deleted_mos = [immoi.get_object_no_runtime(deleted_mo) \
                       for deleted_mo in deleted]

        for mo in itertools.chain(created, deleted_mos):

            parent_name = immoi.get_parent_name_for_dn(mo.dn)

            # Handle the case where there is no parent
            if not parent_name:

                if mo in created and \
                   constraint_exists_for_child(mo.class_name):
                    error_string = ("ERROR: Cannot create %s, %s must have a "
                                    "parent") % (mo.dn, mo.SaImmAttrClassName)
                    raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
                                       error_string)

                # Allow this operation and check the next one
                continue

            # Handle the case where the parent is also deleted
            if parent_name in deleted:
                continue

            # Avoid looking up the parent class in IMM if possible
            parent_mos = [x for x in all_instances if x.dn == parent_name]

            if parent_mos:
                parent_class = parent_mos[0].class_name
            else:
                parent_class = immoi.get_class_name_for_dn(parent_name)

            # Ignore children where no constraint is defined for the child or
            # the parent
            if not parent_class in self.containments and not \
               constraint_exists_for_child(mo.class_name):
                continue

            # Validate the containment if there is a parent
            child_classes = self.containments[parent_class]

            # Reject the create if the child's class is not part of the allowed
            # child classes
            if not mo.class_name in child_classes and mo in created:
                error_string = ("ERROR: Cannot create %s as a child under %s. "
                                "Possible children are %s") % \
                    (mo.dn, parent_class, child_classes)
                raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
                                   error_string)

            # Count current containments
            current_children = get_children_with_classname(parent_name,
                                                           all_instances,
                                                           mo.class_name)
            # Validate the number of children of the specific class to the given
            # parent
            lower, upper = self.cardinality[(parent_class, mo.class_name)]

            if lower and len(current_children) < lower:
                error_string = ("ERROR: Must have at least %s instances of %s "
                                "under %s") % \
                    (lower, mo.class_name, parent_class)
                raise SafException(eSaAisErrorT.SA_AIS_ERR_FAILED_OPERATION,
                                   error_string)

            if upper and len(current_children) > upper:
                error_string = ("ERROR: Must have at most %s instances of %s "
                                "under %s") % \
                    (upper, mo.class_name, parent_class)
                raise SafException(eSaAisErrorT.SA_AIS_ERR_FAILED_OPERATION,
                                   error_string)
Ejemplo n.º 30
0
    def validate(self, all_instances, updated, created, deleted):
        """ Validate the constraints in this Constraints instance

        Args:
            all_instances (list): List of instances to validate
            updated (list): List of updated objects
            created (list): List of created objects
            deleted (list): List of deleted objects
        """
        def get_children_with_class_name(_parent_name, _all_instances,
                                         _class_name):
            """ Helper method to count the number of children of the given
            class in the list of all instances
            """
            _current_children = []

            for child in _all_instances:

                if ',' not in child.dn:
                    continue

                if self.get_parent_name_for_dn(child.dn) == _parent_name \
                        and child.class_name == _class_name:
                    _current_children.append(child)

            return _current_children

        def constraint_exists_for_child(_class_name):
            """ Return True if there exists a constraint for the given class
            as a child
            """
            for _child_classes in list(self.containments.values()):
                if _class_name in _child_classes:
                    return True

            return False

        # Validate containments affected by create or delete
        deleted_objs = [self.get_object_no_runtime(dn) for dn in deleted]

        for obj in itertools.chain(created, deleted_objs):
            parent_name = self.get_parent_name_for_dn(obj.dn)

            # Handle the case where there is no parent
            if not parent_name:
                if obj in created \
                        and constraint_exists_for_child(obj.class_name):
                    error_string = "ERROR: Cannot create %s, %s must have a " \
                                   "parent" % (obj.dn, obj.SaImmAttrClassName)
                    raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
                                       error_string)
                # Allow this operation and check the next one
                continue

            # Handle the case where the parent is also deleted
            if parent_name in deleted:
                continue

            # Avoid looking up the parent class in IMM if possible
            parent_obj = [obj for obj in all_instances
                          if obj.dn == parent_name]
            if parent_obj:
                parent_class = parent_obj[0].class_name
            else:
                parent_class = self.get_class_name_for_dn(dn=parent_name)

            # Ignore children where no constraint is defined for the child or
            # the parent
            if parent_class not in self.containments \
                    and not constraint_exists_for_child(obj.class_name):
                continue

            # Validate the containment if there is a parent
            child_classes = self.containments[parent_class]

            # Reject the create if the child's class is not part of the allowed
            # child classes
            if obj.class_name not in child_classes and obj in created:
                error_string = "ERROR: Cannot create %s as a child under %s." \
                               " Possible children are %s" % \
                               (obj.dn, parent_class, child_classes)
                raise SafException(eSaAisErrorT.SA_AIS_ERR_INVALID_PARAM,
                                   error_string)

            # Count current containments
            current_children = get_children_with_class_name(parent_name,
                                                            all_instances,
                                                            obj.class_name)
            # Validate the number of children of the specific class to the
            # given parent
            lower, upper = self.cardinality[(parent_class, obj.class_name)]

            if lower and len(current_children) < lower:
                error_string = ("ERROR: Must have at least %s instances of %s "
                                "under %s") % \
                    (lower, obj.class_name, parent_class)
                raise SafException(eSaAisErrorT.SA_AIS_ERR_FAILED_OPERATION,
                                   error_string)

            if upper and len(current_children) > upper:
                error_string = ("ERROR: Must have at most %s instances of %s "
                                "under %s") % \
                    (upper, obj.class_name, parent_class)
                raise SafException(eSaAisErrorT.SA_AIS_ERR_FAILED_OPERATION,
                                   error_string)