osaf/tools/safimm/immcfg/imm_cfg.c | 31 +++-
osaf/tools/safimm/immcfg/imm_import.cc | 196 ++++++++++++++++++++++++++++-
osaf/tools/safimm/immdump/imm_dumper.cc | 170 +++++++++++++++++++++++-
osaf/tools/safimm/immdump/imm_dumper.hh | 2 +
osaf/tools/safimm/immdump/imm_xmlw_dump.cc | 13 +-
osaf/tools/safimm/immlist/Makefile.am | 4 +
osaf/tools/safimm/immlist/imm_list.c | 191 ++++++++++++++++++++++++++++-
osaf/tools/safimm/immload/imm_loader.cc | 164 ++++++++++++++++++++++++-
8 files changed, 749 insertions(+), 22 deletions(-)
For forwards compatibility, OpenSAF schema, where unknown attribute flags are
defined, must be provided to IMM tools (immcfg, immlist, immfind) 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,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>
@@ -68,7 +72,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 +145,20 @@ typedef struct ParserStateStruct {
SaImmHandleT ccbHandle;
} ParserState;
+bool isXsdLoaded = false;
+static const char *imm_xsd_file;
+typedef std::map<std::string, SaImmAttrFlagsT> AttrFlagMap;
+AttrFlagMap attrFlagMap;
+
+static SaImmAttrFlagsT attrFlagMask = (SA_IMM_ATTR_RUNTIME
+ | SA_IMM_ATTR_CONFIG
+ | SA_IMM_ATTR_MULTI_VALUE
+ | SA_IMM_ATTR_WRITABLE
+ | SA_IMM_ATTR_INITIALIZED
+ | SA_IMM_ATTR_PERSISTENT
+ | SA_IMM_ATTR_CACHED
+ | SA_IMM_ATTR_NOTIFY
+ | SA_IMM_ATTR_NO_DUPLICATES);
/* Prototypes */
@@ -1001,6 +1019,160 @@ 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 *id;
+ char *value;
+ int size;
+
+ size = xpathObj->nodesetval->nodeNr;
+ for(int i=0; i<size; i++) {
+ id = NULL;
+ value = NULL;
+ element = (xmlElementPtr)xpathObj->nodesetval->nodeTab[i];
+ attr = element->attributes;
+ while(attr) {
+ if(!strcmp((char *)attr->name, "ID")) {
+ id = getAttrValue(attr);
+ } else if(!strcmp((char *)attr->name, "value")) {
+ value = getAttrValue(attr);
+ }
+
+ if(id && value) {
+ break;
+ }
+
+ attr = (xmlAttributePtr)attr->next;
+ }
+
+ if(value) {
+ SaImmAttrFlagsT attrFlag = 0;
+
+ if(id) {
+ char *end;
+ if(!strncmp(id, "0x", 2)) {
+ attrFlag = strtoull(id, &end, 16);
+ } else {
+ attrFlag = strtoull(id, &end, 10);
+ }
+
+ if(*end) {
+ LOG_WA("INVALID ID(%s) FOR FLAG %s.
Attribute flag is set to 0", id, value);
+ attrFlag = 0;
+ }
+ }
+
+ if((attrFlag & ~attrFlagMask) || attrFlag == 0) {
+ attrFlagMap[value] = attrFlag;
+ }
+ }
+ }
+
+ 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 +1297,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);
@@ -1568,7 +1746,15 @@ static SaImmAttrFlagsT charsToFlagsHelpe
return SA_IMM_ATTR_NOTIFY;
}
- LOG_ER("UNKNOWN FLAGS, %s", str);
+ std::string flag((char *)str, len);
+ if(isXsdLoaded) {
+ AttrFlagMap::iterator it = attrFlagMap.find(flag);
+ if(it != attrFlagMap.end()) {
+ return it->second;
+ }
+ }
+
+ LOG_ER("UNKNOWN FLAGS, %s", flag.c_str());
exit(1);
}
@@ -2036,7 +2222,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 +2230,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;
+ attrFlagMap.clear();
+
// assign own immutil errorhandler (no call to abort())
immutilError = imm_importImmutilError;
diff --git a/osaf/tools/safimm/immdump/imm_dumper.cc
b/osaf/tools/safimm/immdump/imm_dumper.cc
--- a/osaf/tools/safimm/immdump/imm_dumper.cc
+++ b/osaf/tools/safimm/immdump/imm_dumper.cc
@@ -24,16 +24,31 @@
#include <limits.h>
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
+#include <libxml/xpath.h>
#include <getopt.h>
#include <assert.h>
#include <libgen.h>
#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
#define XML_VERSION "1.0"
/* Prototypes */
static std::map<std::string, std::string> cacheRDNs(SaImmHandleT);
+AttrFlagMap attrFlagMap;
+
+static SaImmAttrFlagsT attrFlagMask = (SA_IMM_ATTR_RUNTIME
+ | SA_IMM_ATTR_CONFIG
+ | SA_IMM_ATTR_MULTI_VALUE
+ | SA_IMM_ATTR_WRITABLE
+ | SA_IMM_ATTR_INITIALIZED
+ | SA_IMM_ATTR_PERSISTENT
+ | SA_IMM_ATTR_CACHED
+ | SA_IMM_ATTR_NO_DUPLICATES);
+
static void usage(const char *progname)
{
printf("\nNAME\n");
@@ -54,6 +69,9 @@ static void usage(const char *progname)
printf("\t-p, --pbe {<file name>}\n");
printf("\t\tInstead of xml file, generate/populate persistent back-end
database/file\n");
+ printf("\t-X, --xsd {<file name>}\n");
+ printf("\t\tLoad missing data from IMM schema\n\n");
+
printf("\nEXAMPLE\n");
printf("\timmdump /tmp/imm.xml\n");
}
@@ -84,6 +102,122 @@ static const SaImmCallbacksT callbacks =
saImmOmAdminOperationInvokeCallback
};
+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 *id;
+ char *value;
+ int size;
+
+ size = xpathObj->nodesetval->nodeNr;
+ for(int i=0; i<size; i++) {
+ id = NULL;
+ value = NULL;
+ element = (xmlElementPtr)xpathObj->nodesetval->nodeTab[i];
+ attr = element->attributes;
+ while(attr) {
+ if(!strcmp((char *)attr->name, "ID")) {
+ id = getAttrValue(attr);
+ } else if(!strcmp((char *)attr->name, "value")) {
+ value = getAttrValue(attr);
+ }
+
+ if(id && value) {
+ break;
+ }
+
+ attr = (xmlAttributePtr)attr->next;
+ }
+
+ if(id && value) {
+ SaImmAttrFlagsT attrFlag;
+ char *end;
+ if(!strncmp(id, "0x", 2)) {
+ attrFlag = strtoull(id, &end, 16);
+ } else {
+ attrFlag = strtoull(id, &end, 10);
+ }
+
+ if(*end) {
+ LOG_WA("INVALID ID(%s) FOR FLAG %s.", id, value);
+ attrFlagMap.clear();
+ rc = false;
+ goto freexpath;
+ } else if(((attrFlag & ~attrFlagMask) || (attrFlag == 0)) &&
+ 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")) {
+ attrFlagMap[value] = attrFlag;
+ }
+ }
+ }
+
+freexpath:
+ xmlXPathFreeObject(xpathObj);
+freectx:
+ if(ctx->nsNr) {
+ free(ctx->namespaces);
+ }
+ xmlXPathFreeContext(ctx);
+freedoc:
+ xmlFreeDoc(xsdDoc);
+
+ return rc;
+}
/* Functions */
int main(int argc, char* argv[])
@@ -95,6 +229,7 @@ int main(int argc, char* argv[])
{"pbe", required_argument, 0, 'p'},
{"recover", no_argument, 0, 'r'},
{"xmlwriter", no_argument, 0, 'x'},
+ {"xsd", required_argument, 0, 'X'},
{0, 0, 0, 0}
};
SaImmHandleT immHandle;
@@ -129,6 +264,8 @@ int main(int argc, char* argv[])
const char* trace_label = dump_trace_label;
ClassMap classIdMap;
unsigned int objCount=0;
+ std::string xsd;
+ std::string schema = "SAI-AIS-IMM-XSD-A.02.12.xsd";
unsigned int retryInterval = 1000000; /* 1 sec */
unsigned int maxTries = 70; /* 70 times == max 70 secs
*/
@@ -151,12 +288,12 @@ int main(int argc, char* argv[])
if ((argc < 2) || (argc > 5))
{
printf("Usage: %s <xmldumpfile>\n", argv[0]);
- usage(argv[0]);
+ usage(argv[0]);
exit(1);
}
while (1) {
- if ((c = getopt_long(argc, argv, "hdrp:x:y:", long_options, NULL)) == -1)
+ if ((c = getopt_long(argc, argv, "hdrp:x:y:X:", long_options, NULL)) == -1)
break;
switch (c) {
@@ -171,22 +308,26 @@ int main(int argc, char* argv[])
break;
case 'p':
- if(!pbeRecoverFile) {
- pbeDumpCase = true;
- }
+ if(!pbeRecoverFile) {
+ pbeDumpCase = true;
+ }
- filename.append(optarg);
+ filename.append(optarg);
break;
case 'r':
- pbeDumpCase = false;
- pbeRecoverFile = true;
+ pbeDumpCase = false;
+ pbeRecoverFile = true;
break;
case 'x':
filename.append(optarg);
break;
+ case 'X':
+ xsd = optarg;
+ break;
+
default:
fprintf(stderr, "Try '%s --help' for more information\n",
argv[0]);
@@ -196,7 +337,7 @@ int main(int argc, char* argv[])
}
if(filename.empty()) {
- filename.append(argv[1]);
+ filename.append(argv[optind]);
}
version.releaseCode = RELEASE_CODE;
@@ -217,6 +358,15 @@ int main(int argc, char* argv[])
exit(1);
}
+ if(xsd.size() > 0) {
+ if(!loadXsd(xsd.c_str())) {
+ std::cerr << "Failed to load schema - exiting\n";
+ exit(1);
+ }
+
+ schema = basename((char *)xsd.c_str());
+ }
+
if(pbeDaemonCase && !pbeDumpCase && pbeRecoverFile) {
/* This is the re-attachement case.
The PBE has crashed,
@@ -378,7 +528,7 @@ int main(int argc, char* argv[])
if(xmlTextWriterWriteAttributeNS(writer,
(xmlChar*)"xsi",(xmlChar *)"noNamespaceSchemaLocation", NULL,
- (xmlChar*)"SAI-AIS-IMM-XSD-A.01.02.xsd") < 0) {
+ (xmlChar*)schema.c_str()) < 0) {
std::cout <<"Error at xmlTextWriterWriteAttribute (attribute
2)" << std::endl;
exit(1);
}
diff --git a/osaf/tools/safimm/immdump/imm_dumper.hh
b/osaf/tools/safimm/immdump/imm_dumper.hh
--- a/osaf/tools/safimm/immdump/imm_dumper.hh
+++ b/osaf/tools/safimm/immdump/imm_dumper.hh
@@ -106,6 +106,8 @@ SaAisErrorT getCcbOutcomeFromPbe(void* d
void discardPbeFile(std::string filename);
void fsyncPbeJournalFile();
+typedef std::map<std::string, SaImmAttrFlagsT> AttrFlagMap;
+
/* XML-Writer related functions */
void dumpClassesXMLw(SaImmHandleT, xmlTextWriterPtr);
diff --git a/osaf/tools/safimm/immdump/imm_xmlw_dump.cc
b/osaf/tools/safimm/immdump/imm_xmlw_dump.cc
--- a/osaf/tools/safimm/immdump/imm_xmlw_dump.cc
+++ b/osaf/tools/safimm/immdump/imm_xmlw_dump.cc
@@ -23,6 +23,7 @@
#include <osaf_unicode.h>
+extern AttrFlagMap attrFlagMap;
/* Functions */
@@ -490,7 +491,17 @@ void flagsToXMLw(SaImmAttrDefinitionT_2*
exit(1);
}
}
-
+
+ AttrFlagMap::iterator it;
+ for(it = attrFlagMap.begin(); it != attrFlagMap.end(); ++it) {
+ if(flags & it->second) {
+ if(xmlTextWriterWriteElement(writer, (xmlChar*) "flag",
+ (xmlChar*) it->first.c_str()) < 0 ) {
+ std::cout << "Error at xmlTextWriterWriteElement (flag - " <<
it->first << ")" << std::endl;
+ exit(1);
+ }
+ }
+ }
}
void typeToXMLw(SaImmAttrDefinitionT_2* p, xmlTextWriterPtr writer)
diff --git a/osaf/tools/safimm/immlist/Makefile.am
b/osaf/tools/safimm/immlist/Makefile.am
--- a/osaf/tools/safimm/immlist/Makefile.am
+++ b/osaf/tools/safimm/immlist/Makefile.am
@@ -20,6 +20,8 @@ MAINTAINERCLEANFILES = Makefile.in
bin_PROGRAMS = immlist
+immlist_CFLAGS = $(AM_CFLAGS) @XML2_CFLAGS@
+
immlist_CPPFLAGS = \
$(AM_CPPFLAGS) \
-I$(top_srcdir)/osaf/tools/safimm/include \
@@ -30,6 +32,8 @@ immlist_SOURCES = \
$(top_srcdir)/osaf/tools/safimm/src/saf_error.c \
imm_list.c
+immlist_LDFLAGS = @XML2_LIBS@
+
immlist_LDADD = \
$(top_builddir)/osaf/libs/core/libopensaf_core.la \
$(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOm.la \
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
@@ -36,6 +36,10 @@
#include <libgen.h>
#include <time.h>
#include <signal.h>
+#include <sys/stat.h>
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xpath.h>
#include <saAis.h>
#include <saImmOm.h>
@@ -55,6 +59,23 @@
static SaVersionT immVersion = { 'A', 2, 11 };
extern struct ImmutilWrapperProfile immutilWrapperProfile;
+typedef struct AttrFlagList {
+ char *name;
+ SaImmAttrFlagsT value;
+ struct AttrFlagList *next;
+} AttrFlagList;
+AttrFlagList *attrFlagList = NULL;
+
+static SaImmAttrFlagsT attrFlagMask = (SA_IMM_ATTR_RUNTIME
+ | SA_IMM_ATTR_CONFIG
+ | SA_IMM_ATTR_MULTI_VALUE
+ | SA_IMM_ATTR_WRITABLE
+ | SA_IMM_ATTR_INITIALIZED
+ | SA_IMM_ATTR_PERSISTENT
+ | SA_IMM_ATTR_CACHED
+ | SA_IMM_ATTR_NOTIFY
+ | SA_IMM_ATTR_NO_DUPLICATES);
+
/* signal handler for SIGALRM */
void sigalarmh(int sig)
{
@@ -81,6 +102,7 @@ static void usage(const char *progname)
printf("\t-p, --pretty-print=<yes|no> - select pretty print, default
yes\n");
printf("\t-t, --timeout <sec>\n");
printf("\t\tutility timeout in seconds\n");
+ printf("\t-X, --xsd <schema.xsd>\n");
printf("\nEXAMPLE\n");
printf("\timmlist -a saAmfApplicationAdminState safApp=OpenSAF\n");
@@ -353,6 +375,14 @@ static void display_class_definition(con
printf(", NO_DUPLICATES");
}
+ AttrFlagList *attrFlag = attrFlagList;
+ while(attrFlag) {
+ if(attrFlag->value & attrDefinition->attrFlags) {
+ printf(", %s", attrFlag->name);
+ }
+ attrFlag = attrFlag->next;
+ }
+
printf("}\n");
}
@@ -411,6 +441,138 @@ static void display_object(const char *n
}
}
+static inline char *getAttrValue(xmlAttributePtr attr) {
+ if(!attr || !attr->children) {
+ return NULL;
+ }
+
+ return (char *)attr->children->content;
+}
+
+static int loadXsd(const char *xsdFile) {
+ struct stat st;
+ if(stat(xsdFile, &st)) {
+ if(errno == ENOENT) {
+ fprintf(stderr, "%s does not exist", xsdFile);
+ } else {
+ fprintf(stderr, "stat of %s return error: %d", xsdFile,
errno);
+ }
+
+ return 0;
+ }
+ // It should be a file or a directory
+ if(!S_ISREG(st.st_mode)) {
+ fprintf(stderr, "%s is not a file", xsdFile);
+ return 0;
+ }
+
+ xmlNodePtr xsdDocRoot;
+ xmlDocPtr xsdDoc = xmlParseFile(xsdFile);
+ if(!xsdDoc) {
+ return 0;
+ }
+
+ int rc = 1;
+ xmlXPathContextPtr ctx = xmlXPathNewContext(xsdDoc);
+ if(!ctx) {
+ rc = 0;
+ 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 = 0;
+ goto freectx;
+ }
+
+ xmlElementPtr element;
+ xmlAttributePtr attr;
+ char *id;
+ char *value;
+ int size;
+ int i;
+
+ size = xpathObj->nodesetval->nodeNr;
+ for(i=0; i<size; i++) {
+ id = NULL;
+ value = NULL;
+ element = (xmlElementPtr)xpathObj->nodesetval->nodeTab[i];
+ attr = element->attributes;
+ while(attr) {
+ if(!strcmp((char *)attr->name, "ID")) {
+ id = getAttrValue(attr);
+ } else if(!strcmp((char *)attr->name, "value")) {
+ value = getAttrValue(attr);
+ }
+
+ if(id && value) {
+ break;
+ }
+
+ attr = (xmlAttributePtr)attr->next;
+ }
+
+ if(id && value) {
+ AttrFlagList *flag;
+ SaImmAttrFlagsT attrFlag;
+ char *end;
+ if(!strncmp(id, "0x", 2)) {
+ attrFlag = strtoull(id, &end, 16);
+ } else {
+ attrFlag = strtoull(id, &end, 10);
+ }
+
+ if(*end) {
+ fprintf(stdout, "INVALID ID(%s) FOR FLAG %s.",
id, value);
+
+ AttrFlagList *tmp;
+ flag = attrFlagList;
+ while(flag) {
+ tmp = flag->next;
+ free(flag->name);
+ free(flag);
+ flag = tmp;
+ }
+ attrFlagList = NULL;
+ rc = 0;
+ goto freexpath;
+ } else if(((attrFlag & ~attrFlagMask) || (attrFlag ==
0)) &&
+ 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")) {
+ flag = (AttrFlagList
*)malloc(sizeof(AttrFlagList));
+ flag->name = strdup(value);
+ flag->value = attrFlag;
+ flag->next = attrFlagList;
+ attrFlagList = flag;
+ }
+ }
+ }
+
+freexpath:
+ xmlXPathFreeObject(xpathObj);
+freectx:
+ if(ctx->nsNr) {
+ free(ctx->namespaces);
+ }
+ xmlXPathFreeContext(ctx);
+freedoc:
+ xmlFreeDoc(xsdDoc);
+
+ return rc;
+}
+
int main(int argc, char *argv[])
{
int c;
@@ -420,6 +582,7 @@ int main(int argc, char *argv[])
{"timeout", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{"pretty-print", required_argument, 0, 'p'},
+ {"xsd", required_argument, 0, 'X'},
{0, 0, 0, 0}
};
SaAisErrorT error;
@@ -431,9 +594,10 @@ int main(int argc, char *argv[])
int class_desc_print = 0;
int rc = EXIT_SUCCESS;
unsigned long timeoutVal = 60;
+ char *xsd = NULL;
while (1) {
- c = getopt_long(argc, argv, "a:p:t:ch", long_options, NULL);
+ c = getopt_long(argc, argv, "a:p:t:cX:h", long_options, NULL);
if (c == -1) /* have all command-line options have been
parsed? */
break;
@@ -459,6 +623,13 @@ int main(int argc, char *argv[])
if (!strcasecmp(optarg, "no"))
pretty_print = 0;
break;
+ case 'X':
+ if(xsd) {
+ fprintf(stderr, "Cannot set more then one
schema\n");
+ exit(EXIT_FAILURE);
+ }
+ xsd = strdup(optarg);
+ break;
default:
fprintf(stderr, "Try '%s --help' for more
information\n", argv[0]);
exit(EXIT_FAILURE);
@@ -487,6 +658,13 @@ int main(int argc, char *argv[])
goto done;
}
+ if(xsd) {
+ if(!loadXsd(xsd)) {
+ rc = EXIT_FAILURE;
+ goto done;
+ }
+ }
+
if (class_desc_print) {
while (optind < argc) {
display_class_definition(argv[optind], immHandle);
@@ -515,6 +693,17 @@ int main(int argc, char *argv[])
}
done_finalize:
+
+ if(attrFlagList) {
+ AttrFlagList *attrFlag;
+ while(attrFlagList) {
+ attrFlag = attrFlagList->next;
+ free(attrFlagList->name);
+ free(attrFlagList);
+ attrFlagList = attrFlag;
+ }
+ }
+
error = immutil_saImmOmFinalize(immHandle);
if (SA_AIS_OK != error) {
fprintf(stderr, "error - saImmOmFinalize FAILED: %s\n",
saf_error(error));
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
@@ -18,6 +18,7 @@
#include "imm_loader.hh"
#include <iostream>
#include <libxml/parser.h>
+#include <libxml/xpath.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -26,6 +27,7 @@
#include <configmake.h>
#include <logtrace.h>
#include <sys/stat.h>
+#include <errno.h>
#ifndef SA_IMM_ATTR_NO_DUPLICATES
@@ -121,6 +123,22 @@ typedef struct ParserStateStruct
SaImmHandleT ccbHandle;
} ParserState;
+bool isXsdLoaded;
+std::string xsddir;
+std::string xsd;
+typedef std::map<std::string, SaImmAttrFlagsT> AttrFlagMap;
+AttrFlagMap attrFlagMap;
+
+static SaImmAttrFlagsT attrFlagMask = (SA_IMM_ATTR_RUNTIME
+ | SA_IMM_ATTR_CONFIG
+ | SA_IMM_ATTR_MULTI_VALUE
+ | SA_IMM_ATTR_WRITABLE
+ | SA_IMM_ATTR_INITIALIZED
+ | SA_IMM_ATTR_PERSISTENT
+ | SA_IMM_ATTR_CACHED
+ | SA_IMM_ATTR_NOTIFY
+ | SA_IMM_ATTR_NO_DUPLICATES);
+
/* Helper functions */
static void addToAttrTypeCache(ParserState*, SaImmValueTypeT);
@@ -884,6 +902,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 +1451,121 @@ 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 *id;
+ char *value;
+ int size;
+
+ size = xpathObj->nodesetval->nodeNr;
+ for(int i=0; i<size; i++) {
+ id = NULL;
+ value = NULL;
+ element = (xmlElementPtr)xpathObj->nodesetval->nodeTab[i];
+ attr = element->attributes;
+ while(attr) {
+ if(!strcmp((char *)attr->name, "ID")) {
+ id = getAttrValue(attr);
+ } else if(!strcmp((char *)attr->name, "value")) {
+ value = getAttrValue(attr);
+ }
+
+ if(id && value) {
+ break;
+ }
+
+ attr = (xmlAttributePtr)attr->next;
+ }
+
+ if(value) {
+ char *end;
+ SaImmAttrFlagsT attrFlag = 0;
+ if(id) {
+ if(!strncmp(id, "0x", 2)) {
+ attrFlag = strtoull(id, &end, 16);
+ } else {
+ attrFlag = strtoull(id, &end, 10);
+ }
+
+ if(*end) {
+ LOG_WA("INVALID ID(%s) FOR FLAG %s.
Unknown attribute flag is set to 0", id, value);
+ attrFlag = 0;
+ }
+ }
+
+ if((attrFlag & ~attrFlagMask) || (attrFlag == 0)) {
+ attrFlagMap[value] = attrFlag;
+ }
+ }
+ }
+
+ 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
*/
@@ -1472,7 +1612,24 @@ static SaImmAttrFlagsT charsToFlagsHelpe
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) {
+ AttrFlagMap::iterator it = attrFlagMap.find(unflag);
+ if(it != attrFlagMap.end()) {
+ return it->second;
+ }
+ }
+
+ LOG_ER("UNKNOWN FLAGS, %s", unflag.c_str());
exit(1);
}
@@ -1881,6 +2038,11 @@ int loadImmXML(std::string xmldir, std::
state.adminInit = 0;
state.ccbInit = 0;
+ isXsdLoaded = false;
+ xsddir = xmldir;
+ xsd = "";
+ attrFlagMap.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
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel