Ack from me (4.2 patch 2). Zoran Milinkovic wrote: > osaf/tools/safimm/immcfg/imm_cfg.c | 31 ++++- > osaf/tools/safimm/immcfg/imm_import.cc | 178 > ++++++++++++++++++++++++++++++- > osaf/tools/safimm/immlist/imm_list.c | 6 - > osaf/tools/safimm/immload/imm_loader.cc | 150 +++++++++++++++++++++++++- > 4 files changed, 333 insertions(+), 32 deletions(-) > > > For forwards compatibility, OpenSAF schema, where unknown attribute flags are > defined, must be provided to immcfg using -X flag. > If immload finds unknown attribute flag, immload will try to find the > attribute flag in the schema defined in the top element of the loading IMM > XML file. > > 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 > @@ -56,7 +56,7 @@ typedef enum { > #define VERBOSE_INFO(format, args...) if (verbose) { fprintf(stderr, format, > ##args); } > > // The interface function which implements the -f opton (imm_import.cc) > -int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int > ccb_safe); > +int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int > ccb_safe, const char *xsdPath); > > const SaImmCcbFlagsT defCcbFlags = SA_IMM_CCB_REGISTERED_OI | > SA_IMM_CCB_ALLOW_NULL_OI; > > @@ -86,6 +86,7 @@ static void usage(const char *progname) > printf("\t--ignore-duplicates (only valid with -f/--file option, > default)\n"); > printf("\t--delete-class <classname> [classname2]... \n"); > printf("\t-u, --unsafe\n"); > + printf("\t-X, --xsd <path_to_schema.xsd>\n"); > > printf("\nEXAMPLE\n"); > printf("\timmcfg -a saAmfNodeSuFailoverMax=7 > safAmfNode=Node01,safAmfCluster=1\n"); > @@ -102,6 +103,10 @@ static void usage(const char *progname) > printf("\t\tremove a value from an attribute\n"); > printf("\timmcfg -u .....\n"); > printf("\t\tThe CCBs generated by immcfg will have > SA_IMM_CCB_REGISTERED_OI set to false, allowing ccb commit when OIs are > missing\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 */ > @@ -682,6 +687,7 @@ int main(int argc, char *argv[]) > {"timeout", required_argument, NULL, 't'}, > {"verbose", no_argument, NULL, 'v'}, > {"unsafe", no_argument, NULL, 'u'}, > + {"xsd", required_argument, NULL, 'X'}, > {0, 0, 0, 0} > }; > SaAisErrorT error; > @@ -703,9 +709,11 @@ int main(int argc, char *argv[]) > int i; > unsigned long timeoutVal = 60; > > + char *xsdPath = NULL; > + > while (1) { > int option_index = 0; > - c = getopt_long(argc, argv, "a:c:f:t:dhmvu", long_options, > &option_index); > + c = getopt_long(argc, argv, "a:c:f:t:dhmvuX:", long_options, > &option_index); > > if (c == -1) /* have all command-line options have been > parsed? */ > break; > @@ -751,6 +759,13 @@ int main(int argc, char *argv[]) > op = verify_setoption(op, MODIFY_OBJECT); > break; > } > + case 'X': > + if(xsdPath) { > + fprintf(stderr, "XSD path is already set\n"); > + exit(EXIT_FAILURE); > + } > + xsdPath = strdup(optarg); > + break; > default: > fprintf(stderr, "Try '%s --help' for more > information\n", argv[0]); > exit(EXIT_FAILURE); > @@ -767,7 +782,7 @@ int main(int argc, char *argv[]) > > if (op == LOAD_IMMFILE) { > VERBOSE_INFO("importImmXML(xmlFilename=%s, verbose=%d)\n", > xmlFilename, verbose); > - rc = importImmXML(xmlFilename, adminOwnerName, verbose, > ccb_safe); > + rc = importImmXML(xmlFilename, adminOwnerName, verbose, > ccb_safe, xsdPath); > exit(rc); > } > > @@ -854,10 +869,14 @@ int main(int argc, char *argv[]) > done_om_finalize: > error = immutil_saImmOmFinalize(immHandle); > if (SA_AIS_OK != error) { > - fprintf(stderr, "error - saImmOmFinalize FAILED: %s\n", > saf_error(error)); > - rc = EXIT_FAILURE; > - } > + fprintf(stderr, "error - saImmOmFinalize FAILED: %s\n", > saf_error(error)); > + rc = EXIT_FAILURE; > + } > > + if(xsdPath) { > + free(xsdPath); > + xsdPath = NULL; > + } > > exit(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,16 +30,14 @@ > #include <assert.h> > #include <syslog.h> > #include <configmake.h> > +#include <sys/stat.h> > +#include <errno.h> > > #include <saAis.h> > #include <saImmOm.h> > #include <immutil.h> > > > -#ifndef SA_IMM_ATTR_NO_DUPLICATES > -#define SA_IMM_ATTR_NO_DUPLICATES 0x0000000001000000 /* See: > http://devel.opensaf.org/ticket/1545 */ > -#endif > - > #ifndef SA_IMM_ATTR_NOTIFY > #define SA_IMM_ATTR_NOTIFY 0x0000000002000000 /* See: > http://devel.opensaf.org/ticket/2883 */ > #endif > @@ -68,7 +68,7 @@ static char base64_dec_table[] = { > > extern "C" > { > - int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int > ccb_safe); > + int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int > ccb_safe, const char *xsdPath); > } > > extern ImmutilErrorFnT immutilError; > @@ -141,6 +141,11 @@ typedef struct ParserStateStruct { > SaImmHandleT ccbHandle; > } ParserState; > > +bool isXsdLoaded = false; > +static const char *imm_xsd_file; > +typedef std::set<std::string> AttrFlagSet; > +AttrFlagSet attrFlagSet; > + > > /* Prototypes */ > > @@ -1001,6 +1006,143 @@ 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")) { > + 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 > */ > @@ -1125,6 +1267,12 @@ 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); > + exit(1); > + } > + } > } else { > LOG_ER("UNKNOWN TAG! (%s)", name); > exit(1); > @@ -1562,15 +1710,21 @@ static SaImmAttrFlagsT charsToFlagsHelpe > return SA_IMM_ATTR_PERSISTENT; > } else if (len == strlen("SA_CACHED") && strncmp((const char*)str, > "SA_CACHED", len) == 0) { > return SA_IMM_ATTR_CACHED; > - } else if (len == strlen("SA_NO_DUPLICATES") && strncmp((const > char*)str, "SA_NO_DUPLICATES", len) == 0) { > - return SA_IMM_ATTR_NO_DUPLICATES; > } else if (len == strlen("SA_NOTIFY") && strncmp((const char*)str, > "SA_NOTIFY", len) == 0) { > return SA_IMM_ATTR_NOTIFY; > } > > - LOG_ER("UNKNOWN FLAGS, %s", str); > + std::string flag((char *)str, len); > + if(isXsdLoaded) { > + AttrFlagSet::iterator it = attrFlagSet.find(flag); > + if(it != attrFlagSet.end()) { > + return 0; > + } > + } > > - exit(1); > + LOG_ER("UNKNOWN FLAGS, %s", flag.c_str()); > + > + exit(1); > } > > /** > @@ -2036,7 +2190,7 @@ int loadImmXML(std::string xmlfile) > // C and c++ caller wrapper > // 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) > +int importImmXML(char* xmlfileC, char* adminOwnerName, int verbose, int > ccb_safe, const char *xsdPath) > { > std::string xmlfile(xmlfileC); > imm_import_adminOwnerName = adminOwnerName; > @@ -2044,6 +2198,10 @@ int importImmXML(char* xmlfileC, char* a > imm_import_ccb_safe = ccb_safe; > LOG_IN("file: %s adminOwner: %s", xmlfileC, adminOwnerName); > > + imm_xsd_file = xsdPath; > + isXsdLoaded = false; > + attrFlagSet.clear(); > + > // assign own immutil errorhandler (no call to abort()) > immutilError = imm_importImmutilError; > > diff --git a/osaf/tools/safimm/immlist/imm_list.c > b/osaf/tools/safimm/immlist/imm_list.c > --- a/osaf/tools/safimm/immlist/imm_list.c > +++ b/osaf/tools/safimm/immlist/imm_list.c > @@ -324,9 +324,6 @@ static void display_class_definition(con > if (attrDefinition->attrFlags & SA_IMM_ATTR_NOTIFY) > printf(", NOTIFY"); > > - if (attrDefinition->attrFlags & > SA_IMM_ATTR_NO_DUPLICATES) > - printf(", NO_DUPLICATES"); > - > } else if (attrDefinition->attrFlags & SA_IMM_ATTR_RUNTIME) { > if (attrDefinition->attrDefaultValue != NULL) { > printf(" = "); > @@ -348,9 +345,6 @@ static void display_class_definition(con > > if (attrDefinition->attrFlags & SA_IMM_ATTR_NOTIFY) > printf(", NOTIFY"); > - > - if (attrDefinition->attrFlags & > SA_IMM_ATTR_NO_DUPLICATES) > - printf(", NO_DUPLICATES"); > } > > printf("}\n"); > diff --git a/osaf/tools/safimm/immload/imm_loader.cc > b/osaf/tools/safimm/immload/imm_loader.cc > --- a/osaf/tools/safimm/immload/imm_loader.cc > +++ b/osaf/tools/safimm/immload/imm_loader.cc > @@ -17,7 +17,9 @@ > > #include "imm_loader.hh" > #include <iostream> > +#include <set> > #include <libxml/parser.h> > +#include <libxml/xpath.h> > #include <stdio.h> > #include <stdlib.h> > #include <unistd.h> > @@ -26,11 +28,8 @@ > #include <configmake.h> > #include <logtrace.h> > #include <sys/stat.h> > - > - > -#ifndef SA_IMM_ATTR_NO_DUPLICATES > -#define SA_IMM_ATTR_NO_DUPLICATES 0x0000000001000000 /* See: > http://devel.opensaf.org/ticket/1545 */ > -#endif > +#include <errno.h> > + > > #ifndef SA_IMM_ATTR_NOTIFY > #define SA_IMM_ATTR_NOTIFY 0x0000000002000000 /* See: > http://devel.opensaf.org/ticket/2883 */ > @@ -121,6 +120,13 @@ typedef struct ParserStateStruct > SaImmHandleT ccbHandle; > } ParserState; > > +bool isXsdLoaded; > +std::string xsddir; > +std::string xsd; > +typedef std::set<std::string> AttrFlagSet; > +AttrFlagSet attrFlagSet; > + > + > /* Helper functions */ > > static void addToAttrTypeCache(ParserState*, SaImmValueTypeT); > @@ -884,6 +890,13 @@ static void startElementHandler(void* us > else if (strcmp((const char*)name, "imm:IMM-contents") == 0) > { > state->state[state->depth] = IMM_CONTENTS; > + char *schema = (char *)getAttributeValue(attrs, (xmlChar > *)"noNamespaceSchemaLocation"); > + if(!schema) { > + schema = (char *)getAttributeValue(attrs, (xmlChar > *)"xsi:noNamespaceSchemaLocation"); > + } > + if(schema) { > + xsd = schema; > + } > } > else > { > @@ -1426,6 +1439,105 @@ static xmlEntityPtr > return xmlGetPredefinedEntity(name); > } > > +static inline char *getAttrValue(xmlAttributePtr attr) { > + if(!attr || !attr->children) { > + return NULL; > + } > + > + return (char *)attr->children->content; > +} > + > +static bool loadXsd(const char *xsdFile) { > + struct stat st; > + if(stat(xsdFile, &st)) { > + if(errno == ENOENT) { > + LOG_ER("%s does not exist", xsdFile); > + } else { > + LOG_ER("stat of %s return error: %d", xsdFile, errno); > + } > + > + return false; > + } > + // It should be a file or a directory > + if(!S_ISREG(st.st_mode)) { > + LOG_ER("%s is not a file", xsdFile); > + return false; > + } > + > + xmlNodePtr xsdDocRoot; > + xmlDocPtr xsdDoc = xmlParseFile(xsdFile); > + 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")) { > + attrFlagSet.insert(value); > + } > + } > + } > + > + isXsdLoaded = true; > + > + xmlXPathFreeObject(xpathObj); > +freectx: > + if(ctx->nsNr) { > + free(ctx->namespaces); > + } > + xmlXPathFreeContext(ctx); > +freedoc: > + xmlFreeDoc(xsdDoc); > + > + return rc; > +} > + > /** > * Takes a string and returns the corresponding flag > */ > @@ -1463,16 +1575,29 @@ static SaImmAttrFlagsT charsToFlagsHelpe > { > return SA_IMM_ATTR_CACHED; > } > - else if (len == strlen("SA_NO_DUPLICATES") && strncmp((const char*)str, > "SA_NO_DUPLICATES", len) == 0) > - { > - return SA_IMM_ATTR_NO_DUPLICATES; > - } > else if (len == strlen("SA_NOTIFY") && strncmp((const char*)str, > "SA_NOTIFY", len) == 0) > { > return SA_IMM_ATTR_NOTIFY; > } > > - LOG_ER("UNKNOWN FLAGS, %s", str); > + std::string unflag((char *)str, len); > + if(!isXsdLoaded) { > + std::string xsdPath = xsddir; > + if(xsdPath.size() > 0) > + xsdPath.append("/"); > + xsdPath.append(xsd); > + LOG_WA("Found unknown flag (%s). Trying to load a schema %s", > unflag.c_str(), xsdPath.c_str()); > + loadXsd(xsdPath.c_str()); > + } > + > + if(isXsdLoaded) { > + AttrFlagSet::iterator it = attrFlagSet.find(unflag); > + if(it != attrFlagSet.end()) { > + return 0; > + } > + } > + > + LOG_ER("UNKNOWN FLAGS, %s", unflag.c_str()); > > exit(1); > } > @@ -1881,6 +2006,11 @@ int loadImmXML(std::string xmldir, std:: > state.adminInit = 0; > state.ccbInit = 0; > > + isXsdLoaded = false; > + xsddir = xmldir; > + xsd = ""; > + attrFlagSet.clear(); > + > /* Build the filename */ > filename = xmldir; > filename.append("/"); > > ------------------------------------------------------------------------------ > 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 >
------------------------------------------------------------------------------ Flow-based real-time traffic analytics software. Cisco certified tool. Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer Customize your own dashboards, set traffic alerts and generate reports. Network behavioral analysis & security monitoring. All-in-one tool. http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel