osaf/tools/safimm/immcfg/imm_cfg.c     |   29 ++++-
 osaf/tools/safimm/immcfg/imm_import.cc |  191 ++++++++++++++++++++++++++++++--
 2 files changed, 200 insertions(+), 20 deletions(-)


For forwards compatibility, OpenSAF schema, where unknown attribute flags are 
defined, must be provided to immcfg using -X flag.

diff --git a/osaf/tools/safimm/immcfg/imm_cfg.c 
b/osaf/tools/safimm/immcfg/imm_cfg.c
--- a/osaf/tools/safimm/immcfg/imm_cfg.c
+++ b/osaf/tools/safimm/immcfg/imm_cfg.c
@@ -80,7 +80,8 @@ typedef enum {
 
 // Interface functions which implement -f and -L options (imm_import.cc)
 int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int 
ccb_safe,
-               SaImmHandleT *immHandle, SaImmAdminOwnerHandleT *ownerHandle, 
SaImmCcbHandleT *ccbHandle, int mode);
+               SaImmHandleT *immHandle, SaImmAdminOwnerHandleT *ownerHandle,
+               SaImmCcbHandleT *ccbHandle, int mode, const char *xsdPath);
 int validateImmXML(const char *xmlfile, int verbose, int mode);
 static int imm_operation(int argc, char *argv[]);
 
@@ -129,6 +130,7 @@ static void usage(const char *progname)
        printf("\t--admin-owner-clear\n");
        printf("\t--ccb-apply (only in a transaction mode)\n");
        printf("\t--ccb-abort (only in a transaction mode)\n");
+       printf("\t-X, --xsd <path_to_schema.xsd>\n");
 
        printf("\nEXAMPLE\n");
        printf("\timmcfg -a saAmfNodeSuFailoverMax=7 
safAmfNode=Node01,safAmfCluster=1\n");
@@ -160,6 +162,10 @@ static void usage(const char *progname)
        printf("\timmcfg\n");
        printf("\t\tRunning immcfg in explicit commit mode where immcfg accepts 
immcfg commands from command line\n");
        printf("\t\tCtrl+D - commit changes and exit, Ctrl+C - abort CCB and 
exit\n");
+       printf("\timmcfg -X /etc/opensaf/schema.xsd -f imm.xml\n");
+       printf("\t\timmcfg will load unsupported attribute flags in the current 
OpenSAF version from /etc/opensaf/schema.xsd, and use them to successfully 
import imm.xml");
+       printf("\timmcfg -X /etc/opensaf -f imm.xml\n");
+       printf("\t\timmcfg will load unsupported attribute flags in the current 
OpenSAF version from the schema specified in imm.xml which is stored in 
/etc/opensaf, and use loaded flags to successfully import imm.xml");
 }
 
 /* signal handler for SIGALRM */
@@ -1093,6 +1099,7 @@ static int imm_operation(int argc, char 
                {"admin-owner-clear", no_argument, NULL, 0},
                {"ccb-apply", no_argument, NULL, 0},
                {"ccb-abort", no_argument, NULL, 0},
+               {"xsd", required_argument, NULL, 'X'},
                {0, 0, 0, 0}
        };
        SaAisErrorT error;
@@ -1115,9 +1122,11 @@ static int imm_operation(int argc, char 
        unsigned long timeoutVal = 60;
        attr_notify_t attrNotify = NOTIFY_UNDEFINED;
 
+       char *xsdPath = NULL;
+
        while (1) {
                int option_index = 0;
-               c = getopt_long(argc, argv, "a:c:f:t:dhmvuL:o:", long_options, 
&option_index);
+               c = getopt_long(argc, argv, "a:c:f:t:dhmvuL:o:X:", 
long_options, &option_index);
 
                if (c == -1)    /* have all command-line options have been 
parsed? */
                        break;
@@ -1225,6 +1234,16 @@ static int imm_operation(int argc, char 
                        adminOwnerName = 
(SaImmAdminOwnerNameT)malloc(strlen(optarg) + 1);
                        strcpy(adminOwnerName, optarg);
                        break;
+               case 'X':
+                       if(xsdPath) {
+                               fprintf(stderr, "XSD path is already set\n");
+                               if(transaction_mode)
+                                       return -1;
+                               else
+                                       exit(EXIT_FAILURE);
+                       }
+                       xsdPath = strdup(optarg);
+                       break;
                default:
                        fprintf(stderr, "Try '%s --help' for more 
information\n", argv[0]);
                        if(transaction_mode)
@@ -1270,7 +1289,7 @@ static int imm_operation(int argc, char 
        if (op == LOAD_IMMFILE) {
                VERBOSE_INFO("importImmXML(xmlFilename=%s, verbose=%d)\n", 
xmlFilename, verbose);
                rc = importImmXML(xmlFilename, adminOwnerName, verbose, 
ccb_safe,
-                               &immHandle, &ownerHandle, &ccbHandle, 
transaction_mode);
+                               &immHandle, &ownerHandle, &ccbHandle, 
transaction_mode, xsdPath);
                if(transaction_mode) {
                        if(rc) {
                                fprintf(stderr, "CCB is aborted\n");
@@ -1478,6 +1497,10 @@ static int imm_operation(int argc, char 
                        }
                }
        }
+       if(xsdPath) {
+               free(xsdPath);
+               xsdPath = NULL;
+       }
 
        return rc;
 }
diff --git a/osaf/tools/safimm/immcfg/imm_import.cc 
b/osaf/tools/safimm/immcfg/imm_import.cc
--- a/osaf/tools/safimm/immcfg/imm_import.cc
+++ b/osaf/tools/safimm/immcfg/imm_import.cc
@@ -21,6 +21,8 @@
 #include <set>
 #include <string>
 #include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -28,6 +30,8 @@
 #include <assert.h>
 #include <syslog.h>
 #include <configmake.h>
+#include <sys/stat.h>
+#include <errno.h>
 
 #include <saAis.h>
 #include <saImmOm.h>
@@ -59,7 +63,8 @@ static char base64_dec_table[] = {
 extern "C"
 {
        int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int 
ccb_safe,
-                       SaImmHandleT *immHandle, SaImmAdminOwnerHandleT 
*ownerHandle, SaImmCcbHandleT *ccbHandle, int mode);
+                       SaImmHandleT *immHandle, SaImmAdminOwnerHandleT 
*ownerHandle,
+                       SaImmCcbHandleT *ccbHandle, int mode, const char 
*xsdPath);
        int validateImmXML(const char *xmlfile, int verbose, int mode);
 }
 
@@ -143,6 +148,10 @@ typedef struct ParserStateStruct {
        int parsingStatus;              /* 0 = ok */
 } ParserState;
 
+bool isXsdLoaded = false;
+static const char *imm_xsd_file;
+typedef std::set<std::string> AttrFlagSet;
+AttrFlagSet attrFlagSet;
 
 /* Prototypes */
 
@@ -1228,6 +1237,144 @@ static inline bool isBase64Encoded(const
        return isB64;
 }
 
+static inline char *getAttrValue(xmlAttributePtr attr) {
+    if(!attr || !attr->children) {
+        return NULL;
+    }
+
+    return (char *)attr->children->content;
+}
+
+static bool loadXsd(const xmlChar** attrs) {
+    if(!imm_xsd_file) {
+        return true;
+    }
+
+    // Check if schema path exist
+    struct stat st;
+    if(stat(imm_xsd_file, &st)) {
+        if(errno == ENOENT) {
+            LOG_ER("%s does not exist", imm_xsd_file);
+        } else {
+            LOG_ER("stat of %s return error: %d", imm_xsd_file, errno);
+        }
+
+        return false;
+    }
+    // It should be a file or a directory
+    if(!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
+        LOG_ER("%s is not a file or directory", imm_xsd_file);
+        return false;
+    }
+
+    std::string xsdFile = imm_xsd_file;
+    if(S_ISDIR(st.st_mode)) {
+        // Schema path is a directory, so we shall add a schema file from XML 
file
+        if(xsdFile.at(xsdFile.size() - 1) != '/') {
+            xsdFile.append("/");
+        }
+        char *xsd = (char *)getAttributeValue(attrs, (xmlChar 
*)"noNamespaceSchemaLocation");
+        if(!xsd) {
+            // try with a namespace
+            xsd = (char *)getAttributeValue(attrs, (xmlChar 
*)"xsi:noNamespaceSchemaLocation");
+            if(!xsd) {
+                LOG_ER("Schema is not defined in XML file");
+                return false;
+            }
+        }
+        xsdFile.append(xsd);
+
+        // Check if schema file exists and that it's a file
+        if(stat(xsdFile.c_str(), &st)) {
+            if(errno == ENOENT) {
+                LOG_ER("XSD file %s does not exist", imm_xsd_file);
+            } else {
+                LOG_ER("Stat of XSD file %s return error: %d", imm_xsd_file, 
errno);
+            }
+
+            return false;
+        }
+        if(!S_ISREG(st.st_mode)) {
+            LOG_ER("Schema %s is not a file", xsdFile.c_str());
+            return false;
+        }
+    }
+
+    xmlNodePtr xsdDocRoot;
+    xmlDocPtr xsdDoc = xmlParseFile(xsdFile.c_str());
+    if(!xsdDoc) {
+        return false;
+    }
+
+    bool rc = true;
+    xmlXPathContextPtr ctx = xmlXPathNewContext(xsdDoc);
+    if(!ctx) {
+        rc = false;
+        goto freedoc;
+    }
+
+    //    Add namespace of the first element
+    xsdDocRoot = xmlDocGetRootElement(xsdDoc);
+    if(xsdDocRoot->ns) {
+        ctx->namespaces = (xmlNsPtr *)malloc(sizeof(xmlNsPtr));
+        ctx->namespaces[0] = xsdDocRoot->ns;
+        ctx->nsNr = 1;
+    }
+
+    xmlXPathObjectPtr xpathObj;
+    xpathObj = xmlXPathEval((const 
xmlChar*)"/xs:schema/xs:simpleType[@name=\"attr-flags\"]/xs:restriction/xs:enumeration",
 ctx);
+    if(!xpathObj || !xpathObj->nodesetval) {
+        rc = false;
+        goto freectx;
+    }
+
+    xmlElementPtr element;
+    xmlAttributePtr attr;
+    char *value;
+    int size;
+
+    size = xpathObj->nodesetval->nodeNr;
+    for(int i=0; i<size; i++) {
+        value = NULL;
+        element = (xmlElementPtr)xpathObj->nodesetval->nodeTab[i];
+        attr = element->attributes;
+        while(attr) {
+            if(!strcmp((char *)attr->name, "value")) {
+                value = getAttrValue(attr);
+            }
+
+            if(value) {
+                break;
+            }
+
+            attr = (xmlAttributePtr)attr->next;
+        }
+
+        if(value) {
+            if(strcmp(value, "SA_RUNTIME") && strcmp(value, "SA_CONFIG") &&
+                    strcmp(value, "SA_MULTI_VALUE") && strcmp(value, 
"SA_WRITABLE") &&
+                    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")) {
+                attrFlagSet.insert(value);
+            }
+        }
+    }
+
+    isXsdLoaded = true;
+
+    xmlXPathFreeObject(xpathObj);
+freectx:
+    if(ctx->nsNr) {
+        free(ctx->namespaces);
+    }
+    xmlXPathFreeContext(ctx);
+freedoc:
+    xmlFreeDoc(xsdDoc);
+
+    return rc;
+}
+
 /**
  * This is the handler for start tags
  */
@@ -1360,6 +1507,13 @@ static void startElementHandler(void* us
                /* <imm:IMM-contents> */
        } else if (strcmp((const char*)name, "imm:IMM-contents") == 0) {
                state->state[state->depth] = IMM_CONTENTS;
+               if(imm_xsd_file) {
+                       if(!loadXsd(attrs)) {
+                               LOG_ER("Failed to load XML schema", name);
+                               stopParser(state);
+                               state->parsingStatus = 1;
+                       }
+               }
        } else {
                LOG_ER("UNKNOWN TAG! (%s)", name);
                stopParser(state);
@@ -1776,11 +1930,11 @@ static void charactersHandler(void* user
        case FLAG:
                {
                        SaImmAttrFlagsT flg = charsToFlagsHelper(chars, 
(size_t)len);
-                       if(flg)
-                               state->attrFlags |= flg;
-                       else {
+                       if(flg == 0xffffffffffffffff) {
                                stopParser(state);
                                state->parsingStatus = 1;
+                       } else {
+                               state->attrFlags |= flg;
                        }
                }
                break;
@@ -1839,18 +1993,17 @@ static SaImmAttrFlagsT charsToFlagsHelpe
                return SA_IMM_ATTR_NO_DANGLING;
        }
 
-       /* strlen("SA_NO_DUPLICATES") == 16 (the longest flag name)
-        * A bit longer string is taken to log, max 20 characters.
-        */
-       char unknown[21];
-       if(len > 20)
-               len = 20;
-       memcpy(unknown, str, len);
-       unknown[len] = 0;
-
-       LOG_ER("UNKNOWN FLAGS, %s", unknown);
-
-       return 0;
+       std::string flag((char *)str, len);
+       if(isXsdLoaded) {
+               AttrFlagSet::iterator it = attrFlagSet.find(flag);
+               if(it != attrFlagSet.end()) {
+                       return 0;
+               }
+       }
+
+       LOG_ER("UNKNOWN FLAGS, %s", flag.c_str());
+
+       return 0xffffffffffffffff;
 }
 
 /**
@@ -2506,7 +2659,8 @@ int loadImmXML(const char *xmlfile)
 //  The objective is to keep the code copied from imm_load.cc as close to 
original as possible
 //  to ease a future refactoring towards common codebase
 int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int 
ccb_safe,
-               SaImmHandleT *immHandle, SaImmAdminOwnerHandleT *ownerHandle, 
SaImmCcbHandleT *ccbHandle, int mode)
+               SaImmHandleT *immHandle, SaImmAdminOwnerHandleT *ownerHandle,
+               SaImmCcbHandleT *ccbHandle, int mode, const char *xsdPath)
 {
        imm_import_adminOwnerName = adminOwnerName;
        imm_import_verbose = verbose;
@@ -2517,6 +2671,9 @@ int importImmXML(char* xmlfileC, char* a
        imm_import_ccbHandle = ccbHandle;
 
        transaction_mode = mode;
+       imm_xsd_file = xsdPath;
+       isXsdLoaded = false;
+       attrFlagSet.clear();
 
        LOG_IN("file: %s adminOwner: %s", xmlfileC, adminOwnerName);
 

------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121054471&iu=/4140/ostg.clktrk
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to