Comments inline.

On 09/18/2015 09:11 AM, Hung Nguyen wrote:
>   osaf/services/saf/immsv/immloadd/imm_loader.cc             |   10 +-
>   osaf/services/saf/immsv/immloadd/imm_pbe_load.cc           |    2 +-
>   osaf/services/saf/immsv/immnd/ImmModel.cc                  |   81 +++++-
>   osaf/services/saf/immsv/immnd/immnd_evt.c                  |   17 +
>   osaf/services/saf/immsv/schema/SAI-AIS-IMM-XSD-A.02.16.xsd |  182 
> +++++++++++++
>   5 files changed, 284 insertions(+), 8 deletions(-)
>
>
> DEFAULT_REMOVED is not allowed for creating new class, only support for 
> schema change.
> After removing default values, the default values can be set again by using 
> schema change.
> When an object is created with default-removed attribute set to empty, a 
> notice message will be written to syslog.
>
> diff --git a/osaf/services/saf/immsv/immloadd/imm_loader.cc 
> b/osaf/services/saf/immsv/immloadd/imm_loader.cc
> --- a/osaf/services/saf/immsv/immloadd/imm_loader.cc
> +++ b/osaf/services/saf/immsv/immloadd/imm_loader.cc
> @@ -1720,7 +1720,7 @@ static bool loadXsd(const char *xsdFile)
>                       strcmp(value, "SA_INITIALIZED") && strcmp(value, 
> "SA_PERSISTENT") &&
>                       strcmp(value, "SA_CACHED") && strcmp(value, 
> "SA_NOTIFY") &&
>                       strcmp(value, "SA_NO_DUPLICATES") && strcmp(value, 
> "SA_NO_DANGLING") &&
> -                    strcmp(value, "SA_DN")) {
> +                    strcmp(value, "SA_DN") && strcmp(value, 
> "SA_DEFAULT_REMOVED")) {
>                   attrFlagSet.insert(value);
>               }
>           }
> @@ -1793,6 +1793,10 @@ static SaImmAttrFlagsT charsToFlagsHelpe
>       {
>           return SA_IMM_ATTR_DN;
>       }
> +    else if (len == strlen("SA_DEFAULT_REMOVED") && strncmp((const 
> char*)str, "SA_DEFAULT_REMOVED", len) == 0)
> +    {
> +        return SA_IMM_ATTR_DEFAULT_REMOVED;
> +    }
>   
>       std::string unflag((char *)str, len);
>       if(!isXsdLoaded) {
> @@ -2183,7 +2187,7 @@ int loadImmXML(std::string xmldir, std::
>   
>       version.releaseCode   = 'A';
>       version.majorVersion  = 2;
> -    version.minorVersion  = 15;
> +    version.minorVersion  = 16;
>   
>       TRACE("Loading from %s/%s", xmldir.c_str(), file.c_str());
>   
> @@ -2634,7 +2638,7 @@ int immsync(int maxBatchSize)
>   
>       version.releaseCode   = 'A';
>       version.majorVersion  = 2;
> -    version.minorVersion  = 15;
> +    version.minorVersion  = 16;
>   
>       int retries = 0;
>       do
> diff --git a/osaf/services/saf/immsv/immloadd/imm_pbe_load.cc 
> b/osaf/services/saf/immsv/immloadd/imm_pbe_load.cc
> --- a/osaf/services/saf/immsv/immloadd/imm_pbe_load.cc
> +++ b/osaf/services/saf/immsv/immloadd/imm_pbe_load.cc
> @@ -745,7 +745,7 @@ bool loadObjectsFromPbe(void* pbeHandle,
>   
>   int loadImmFromPbe(void* pbeHandle, bool preload)
>   {
> -     SaVersionT             version = {'A', 2, 15};
> +     SaVersionT             version = {'A', 2, 16};
>       SaImmHandleT           immHandle=0LL;
>       SaImmAdminOwnerHandleT ownerHandle=0LL;
>       SaImmCcbHandleT        ccbHandle=0LL;
> diff --git a/osaf/services/saf/immsv/immnd/ImmModel.cc 
> b/osaf/services/saf/immsv/immnd/ImmModel.cc
> --- a/osaf/services/saf/immsv/immnd/ImmModel.cc
> +++ b/osaf/services/saf/immsv/immnd/ImmModel.cc
> @@ -3003,6 +3003,8 @@ ImmModel::classCreate(const ImmsvOmClass
>       AttrMap newAttrs;
>       AttrMap changedAttrs;
>       ImmsvAttrDefList* list = req->attrDefinitions;
> +    bool isLoading = (sImmNodeState == IMM_NODE_LOADING ||  /* 
> LOADING-SEVER, LOADING-CLIENT */
> +            sImmNodeState == IMM_NODE_W_AVAILABLE);         /* SYNC-CLIENT */
>   
>       TRACE_ENTER2("cont:%p connp:%p nodep:%p", continuationIdPtr, 
> pbeConnPtr, pbeNodeIdPtr);
>       size_t sz = strnlen((char *) req->className.buf, 
> (size_t)req->className.size);
> @@ -3180,6 +3182,11 @@ ImmModel::classCreate(const ImmsvOmClass
>                       attNm);
>                   illegal = 1;
>               }
> +
> +            if(attr->attrFlags & SA_IMM_ATTR_DEFAULT_REMOVED) {
> +                LOG_NO("ERR_INVALID_PARAM: RDN '%s' cannot have 
> SA_IMM_ATTR_DEFAULT_REMOVED flag", attNm);
> +                illegal = 1;
> +            }
>           }
>   
>           if(attr->attrFlags & SA_IMM_ATTR_NO_DANGLING) {
> @@ -3209,6 +3216,13 @@ ImmModel::classCreate(const ImmsvOmClass
>               illegal = 1;
>           }
>   
> +        if ((attr->attrFlags & SA_IMM_ATTR_DEFAULT_REMOVED) &&
> +            !isLoading && !schemaChange) {
> +            LOG_NO("ERR_INVALID_PARAM: Attribute '%s' has 
> SA_IMM_ATTR_DEFAULT_REMOVED flag, "
> +                    "but this flag is only available for schema changes", 
> attNm);
> +            illegal = 1;
> +        }
> +
>           if(attr->attrDefaultValue) {
>               if(attr->attrFlags & SA_IMM_ATTR_RDN) {
>                   LOG_NO("ERR_INVALID_PARAM: RDN '%s' can not have a 
> default", attNm);
> @@ -3230,6 +3244,11 @@ ImmModel::classCreate(const ImmsvOmClass
>                   illegal = 1;
>               }
>   
> +            if (attr->attrFlags & SA_IMM_ATTR_DEFAULT_REMOVED) {
> +                LOG_NO("ERR_INVALID_PARAM: Attribute '%s' can not have a 
> default with SA_IMM_ATTR_DEFAULT_REMOVED", attNm);
> +                illegal = 1;
> +            }
> +
>               if(attr->attrValueType == SA_IMM_ATTR_SANAMET) {
>                   immsv_edu_attr_val* v = attr->attrDefaultValue;
>                   if(!getLongDnsAllowed()
> @@ -3973,6 +3992,32 @@ ImmModel::notCompatibleAtt(const std::st
>                       "SA_IMM_ATTR_DN", className.c_str(), attName.c_str());
>                   return true;
>               }
> +
> +            if (!(oldAttr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED) &&
> +                (newAttr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED)) {
> +                if (oldAttr->mDefaultValue.empty()) {
> +                    LOG_NO("Impossible upgrade, attribute %s:%s doesn't have 
> default, "
> +                       "can not add SA_IMM_ATTR_DEFAULT_REMOVED", 
> className.c_str(), attName.c_str());
> +                    return true;
> +                } else {
> +                    LOG_NO("Allowed upgrade, attribute %s:%s adds flag "
> +                       "SA_IMM_ATTR_DEFAULT_REMOVED", className.c_str(), 
> attName.c_str());
> +                    change = true;
> +                }
> +            }
> +
> +            if ((oldAttr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED) &&
> +                !(newAttr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED)) {
> +                if (newAttr->mDefaultValue.empty()) {
> +                    LOG_NO("Impossible upgrade, can not remove 
> SA_IMM_ATTR_DEFAULT_REMOVED "
> +                            "without adding new default for attribute 
> %s:%s", className.c_str(), attName.c_str());
> +                    return true;
> +                } else {
> +                    LOG_NO("Allowed upgrade, attribute %s:%s removes flag "
> +                       "SA_IMM_ATTR_DEFAULT_REMOVED", className.c_str(), 
> attName.c_str());
> +                    change = true;
> +                }
> +            }
>           }
>   
>           osafassert(!checkNoDup || checkCcb); //Duplicate-check implies 
> ccb-check
> @@ -4113,9 +4158,15 @@ ImmModel::notCompatibleAtt(const std::st
>           }
>   
>           if(!oldAttr->mDefaultValue.empty() && 
> newAttr->mDefaultValue.empty()) {
> -            LOG_NO("Impossible upgrade, attribute %s:%s removes default 
> value",
> -                className.c_str(), attName.c_str());
> -            return true;
> +            if (newAttr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED) {
> +                LOG_NO("Allowed upgrade, attribute %s:%s removes default 
> value",
> +                    className.c_str(), attName.c_str());
> +                change = true;
> +            } else {
> +                LOG_NO("Impossible upgrade, attribute %s:%s removes default 
> value",
> +                    className.c_str(), attName.c_str());
> +                return true;
> +            }
>           }
>   
>           /* Default value may change, this will only affect new instances. */
> @@ -4154,6 +4205,12 @@ ImmModel::notCompatibleAtt(const std::st
>                   className.c_str(), attName.c_str());
>               return true;
>           }
> +
> +        if (newAttr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED) {
> +            LOG_NO("Impossible upgrade, new attribute %s:%s has 
> SA_IMM_ATTR_DEFAULT_REMOVED "
> +                "flag set", className.c_str(), attName.c_str());
> +            return true;
> +        }
>       }
>   
>       return false;
> @@ -4285,7 +4342,8 @@ ImmModel::attrCreate(ClassInfo* classInf
>               SA_IMM_ATTR_NO_DUPLICATES |
>               SA_IMM_ATTR_NOTIFY |
>               SA_IMM_ATTR_NO_DANGLING |
> -            SA_IMM_ATTR_DN);
> +            SA_IMM_ATTR_DN |
> +            SA_IMM_ATTR_DEFAULT_REMOVED);
>   
>           if(unknownFlags) {
>               /* This error means that at least one attribute flag is not 
> supported by this
> @@ -7401,6 +7459,8 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>           //Also: append missing attributes and default values to 
> immsv_attr_values_list
>           //so the generated SaImmOiCcbObjectCreateCallbackT_2 will be 
> complete. See #847.
>           //But dont append non persistent runtime attributes.
> +        //
> +        //Also: Write notice message for default removed attributes which 
> are empty
>           isSpecialApplForClass = specialApplyForClass(classInfo);
>   
>           for(i6=object->mAttrValueMap.begin();
> @@ -7413,6 +7473,12 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>               osafassert(i4!=classInfo->mAttrMap.end());
>               AttrInfo* attr = i4->second;
>               
> +            if ((attr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED) &&
> +                attrValue->empty()) {
> +                LOG_NO("Attribute %s has a removed default, the value will 
> be empty",
> +                   attrName.c_str());
> +            }
> +
>               if((attr->mFlags & SA_IMM_ATTR_INITIALIZED) &&
>                   attrValue->empty()) {
>                   LOG_NO("ERR_INVALID_PARAM: attr '%s' must be initialized "
> @@ -14555,6 +14621,8 @@ ImmModel::rtObjectCreate(struct ImmsvOmC
>           //Also: append missing cached RTAs with default values to 
> immsv_attr_values_list
>           //if there is a special-applier locally attached. This so the 
> special applier will
>           //get informed of the initial value of all cached RTAs and system 
> attributes. See #2873.
> +        //
> +        //Also: Write notice message for default removed attributes which 
> are empty
>            
>           isSpecialApplForClass = specialApplyForClass(classInfo);
>   
> @@ -14613,6 +14681,11 @@ ImmModel::rtObjectCreate(struct ImmsvOmC
>               osafassert(i4!=classInfo->mAttrMap.end());
>               AttrInfo* attr = i4->second;
>               
> +            if ((attr->mFlags & SA_IMM_ATTR_DEFAULT_REMOVED) &&  
> attrValue->empty()) {
> +                LOG_NO("Attribute %s has a removed default, the value will 
> be empty",
> +                   attrName.c_str());
> +            }
> +
>               if((attr->mFlags & SA_IMM_ATTR_CACHED) && attrValue->empty()) {
>                   /* #1531 Check that the attribute was at least in the input 
> list.
>                      This is a questionable rule from the standard (still in 
> A.03.01),
> diff --git a/osaf/services/saf/immsv/immnd/immnd_evt.c 
> b/osaf/services/saf/immsv/immnd/immnd_evt.c
> --- a/osaf/services/saf/immsv/immnd/immnd_evt.c
> +++ b/osaf/services/saf/immsv/immnd/immnd_evt.c
> @@ -3255,6 +3255,23 @@ static SaAisErrorT immnd_fevs_local_chec
>                       /* Regular class create attempted during sync. */
>                       error = SA_AIS_ERR_TRY_AGAIN;
>               }
> +             if (!immModel_protocol47Allowed(cb) &&                          
>         /* proto47 is not enabled */
> +                     !immModel_immNotWritable(cb) && 
> !immModel_readyForLoading(cb)) {    /* not loading and not sync */
Skip the check for immNotWritable and readyForLoading above, just check 
for protocol 47 not allowed and ....
> +                     /* IMM supports creating classes with unknown flags.
> +                      * When the upgrade process is not completed, a 
> class-create request (with DEFAULT_REMOVED flag)
> +                      * may be accepted on nodes with old version and 
> rejected on nodes with new version.
> +                      * That will cause an inconsistency between nodes. */
> +                     IMMSV_ATTR_DEF_LIST* list = 
> frwrd_evt.info.immnd.info.classDescr.attrDefinitions;
> +                     while(list) {
> +                             if (list->d.attrFlags & 
> SA_IMM_ATTR_DEFAULT_REMOVED) {
...the error code should be ERR_TRY_AGAIN. One could possibly also use 
ERR_NO_RESOURCES but I prefer TRY_AGAIN here.
This is caught in fevs_local checks which is done before sending over 
fevs and with error it does not go over fevs.
That is in fact the main purpose of fevs_local_checks, to protect the 
IMMND cluster from problems by having the IMMND colocated
with the client do some screening before allowing the message to go over 
fevs.

That was it.

/AndersBj

> +                                     LOG_WA("ERR_LIBRARY: Can not create 
> class with SA_IMM_ATTR_DEFAULT_REMOVED "
> +                                                     "when proto47 is not 
> enabled");
> +                                     error = SA_AIS_ERR_LIBRARY;
> +                                     break; /* while */
> +                             }
> +                             list = list->next;
> +                     }
> +             }
>   
>               break;
>   
> diff --git a/osaf/services/saf/immsv/schema/SAI-AIS-IMM-XSD-A.02.16.xsd 
> b/osaf/services/saf/immsv/schema/SAI-AIS-IMM-XSD-A.02.16.xsd
> new file mode 100644
> --- /dev/null
> +++ b/osaf/services/saf/immsv/schema/SAI-AIS-IMM-XSD-A.02.16.xsd
> @@ -0,0 +1,182 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!-- edited with XMLSpy v2006 sp1 U (http://www.altova.com) by Maria Toeroe 
> (Ericsson Canada/Open Systems Research) -->
> +<xs:schema xmlns:imm="http://www.saforum.org/IMMSchema"; 
> xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
> targetNamespace="http://www.saforum.org/IMMSchema"; 
> elementFormDefault="unqualified" attributeFormDefault="unqualified">
> +     <!--
> +   OWNERSHIP OF SPECIFICATION AND COPYRIGHTS
> +
> +   Copyright(c) 2009, Service Availability(TM) Forum. All rights reserved.
> +
> +   Permission to use, copy, modify, and distribute this software for any
> +   purpose without fee is hereby granted, provided that this entire notice
> +   is included in all copies of any software which is or includes a copy
> +   or modification of this software and in all copies of the supporting
> +   documentation for such software.
> +
> +   THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
> +   WARRANTY.  IN PARTICULAR, THE SERVICE AVAILABILITY FORUM DOES NOT MAKE ANY
> +   REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
> +   OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
> +
> +  -->
> +     <!-- PART I - DEFINITION OF AN IMM OBJECT CLASS -->
> +     <!--
> +       Various types of IMM object attributes (SaImmValueTypeT)
> +    -->
> +     <xs:simpleType name="attr-value-type">
> +             <xs:annotation>
> +                     <xs:documentation>Types of attribute's 
> values</xs:documentation>
> +             </xs:annotation>
> +             <xs:restriction base="xs:string">
> +                     <xs:enumeration value="SA_INT32_T"/>
> +                     <xs:enumeration value="SA_UINT32_T"/>
> +                     <xs:enumeration value="SA_INT64_T"/>
> +                     <xs:enumeration value="SA_UINT64_T"/>
> +                     <xs:enumeration value="SA_NAME_T"/>
> +                     <xs:enumeration value="SA_TIME_T"/>
> +                     <xs:enumeration value="SA_FLOAT_T"/>
> +                     <xs:enumeration value="SA_DOUBLE_T"/>
> +                     <xs:enumeration value="SA_STRING_T"/>
> +                     <xs:enumeration value="SA_ANY_T"/>
> +             </xs:restriction>
> +     </xs:simpleType>
> +     <!--
> +       Two categories of IMM classes & attributes)
> +    -->
> +     <xs:simpleType name="category">
> +             <xs:annotation>
> +                     <xs:documentation>Class or attribute 
> category</xs:documentation>
> +             </xs:annotation>
> +             <xs:restriction base="xs:string">
> +                     <xs:enumeration value="SA_CONFIG"/>
> +                     <xs:enumeration value="SA_RUNTIME"/>
> +             </xs:restriction>
> +     </xs:simpleType>
> +     <!--
> +       Flags for object attributes (SaImmAttrFlagsT)
> +    -->
> +     <xs:simpleType name="attr-flags">
> +             <xs:annotation>
> +                     <xs:documentation>Attribute flags</xs:documentation>
> +             </xs:annotation>
> +             <xs:restriction base="xs:string">
> +                     <xs:enumeration value="SA_MULTI_VALUE"/>
> +                     <xs:enumeration value="SA_WRITABLE"/>
> +                     <xs:enumeration value="SA_INITIALIZED"/>
> +                     <xs:enumeration value="SA_PERSISTENT"/>
> +                     <xs:enumeration value="SA_CACHED"/>
> +                     <xs:enumeration value="SA_NO_DUPLICATES"/>
> +                     <xs:enumeration value="SA_NOTIFY"/>
> +                     <xs:enumeration value="SA_NO_DANGLING"/>
> +                     <xs:enumeration value="SA_DN"/>
> +                     <xs:enumeration value="SA_DEFAULT_REMOVED"/>
> +             </xs:restriction>
> +     </xs:simpleType>
> +     <!--
> +       Union of types for "value" and "default-value" elements
> +    -->
> +     <xs:simpleType name="value-type">
> +             <xs:annotation>
> +                     <xs:documentation>Value type</xs:documentation>
> +             </xs:annotation>
> +             <xs:union memberTypes="xs:string xs:base64Binary"/>
> +     </xs:simpleType>
> +     <!--
> +      Group of XML elements common to RDN and other object attributes
> +    -->
> +     <xs:group name="attr-elements">
> +             <xs:annotation>
> +                     <xs:documentation>Common elements to RDN and other 
> attributes</xs:documentation>
> +             </xs:annotation>
> +             <xs:sequence>
> +                     <xs:element name="name" type="xs:string"/>
> +                     <xs:element name="type" type="imm:attr-value-type"/>
> +                     <xs:element name="category" type="imm:category"/>
> +                     <xs:element name="flag" type="imm:attr-flags" 
> minOccurs="0" maxOccurs="5"/>
> +                     <xs:element name="ntfid" type="xs:unsignedInt" 
> default="0" minOccurs="0"/>
> +             </xs:sequence>
> +     </xs:group>
> +     <!--
> +      Definition of an object's RDN attribute
> +    -->
> +     <xs:complexType name="rdn-def">
> +             <xs:annotation>
> +                     <xs:documentation>RDN attribute 
> definition</xs:documentation>
> +             </xs:annotation>
> +             <xs:sequence>
> +                     <xs:group ref="imm:attr-elements"/>
> +             </xs:sequence>
> +     </xs:complexType>
> +     <!--
> +      Definition of an object's attribute (other than RDN)
> +      In addition to an RDN attribute, other attributes can be multi-value 
> and can have a default value.
> +    -->
> +     <xs:complexType name="attr-def">
> +             <xs:annotation>
> +                     <xs:documentation>Attribute 
> definition</xs:documentation>
> +             </xs:annotation>
> +             <xs:sequence>
> +                     <xs:group ref="imm:attr-elements"/>
> +                     <xs:element name="default-value" type="imm:value-type" 
> minOccurs="0"/>
> +             </xs:sequence>
> +     </xs:complexType>
> +     <!--
> +      Definition of an object class
> +    -->
> +     <xs:complexType name="class-def">
> +             <xs:annotation>
> +                     <xs:documentation>Object class 
> definition</xs:documentation>
> +             </xs:annotation>
> +             <xs:sequence>
> +                     <xs:element name="category" type="imm:category"/>
> +                     <xs:element name="rdn" type="imm:rdn-def"/>
> +                     <xs:element name="attr" type="imm:attr-def" 
> minOccurs="0" maxOccurs="unbounded"/>
> +             </xs:sequence>
> +             <xs:attribute name="name" type="xs:string"/>
> +     </xs:complexType>
> +     <!-- PART II - DEFINITION OF AN IMMS OBJECT INSTANCE -->
> +     <!--
> +      The object is defined by:
> +          - its object class
> +          - its DN (XML attribute)
> +          - all its attributes (name/values)
> +    -->
> +     <xs:complexType name="object-def">
> +             <xs:annotation>
> +                     <xs:documentation>Object instance 
> definition</xs:documentation>
> +             </xs:annotation>
> +             <xs:sequence>
> +                     <xs:element name="dn" type="xs:string">
> +                             <xs:annotation>
> +                                     <xs:documentation>Object Distinguished 
> Name</xs:documentation>
> +                             </xs:annotation>
> +                     </xs:element>
> +                     <xs:element name="attr" minOccurs="0" 
> maxOccurs="unbounded">
> +                             <xs:annotation>
> +                                     <xs:documentation>Object's 
> attributes</xs:documentation>
> +                             </xs:annotation>
> +                             <xs:complexType>
> +                                     <xs:sequence>
> +                                             <xs:element name="name" 
> type="xs:string"/>
> +                                             <xs:element name="value" 
> type="imm:value-type" maxOccurs="unbounded"/>
> +                                     </xs:sequence>
> +                             </xs:complexType>
> +                     </xs:element>
> +             </xs:sequence>
> +             <xs:attribute name="class" type="xs:string"/>
> +     </xs:complexType>
> +     <!-- PART III- DEFINITION OF IMM Service CONTENTS-->
> +     <!--
> +        The IMM Service contents is defined as a list of class definitions 
> followed by a list of objects
> +     -->
> +     <xs:element name="IMM-contents">
> +             <xs:annotation>
> +                     <xs:documentation>IMM Service 
> contents</xs:documentation>
> +             </xs:annotation>
> +             <xs:complexType>
> +                     <xs:sequence>
> +                             <xs:element name="class" type="imm:class-def" 
> maxOccurs="unbounded"/>
> +                             <xs:element name="object" type="imm:object-def" 
> minOccurs="0" maxOccurs="unbounded"/>
> +                     </xs:sequence>
> +             </xs:complexType>
> +     </xs:element>
> +</xs:schema>


------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to