1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-27 03:21:29 +03:00

feature #212: Initial Refactor of Scheduler code. Added XML base class to use the XML-RPC interface, the commit includes some tests for this class

This commit is contained in:
Ruben S. Montero 2010-05-09 01:51:01 +02:00
parent a8905b2704
commit a156dca7e3
8 changed files with 503 additions and 2 deletions

185
src/scheduler/ObjectXML.h Normal file
View File

@ -0,0 +1,185 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef OBJECT_XML_H_
#define OBJECT_XML_H_
#include <string>
#include <vector>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
using namespace std;
class ObjectXML
{
public:
ObjectXML(const string &xml_doc):xml(0),ctx(0)
{
xml = xmlParseMemory (xml_doc.c_str(),xml_doc.length());
if (xml == 0)
{
throw("Error parsing XML Document");
}
ctx = xmlXPathNewContext(xml);
if (ctx == 0)
{
xmlFreeDoc(xml);
throw("Unable to create new XPath context");
}
};
ObjectXML(const xmlNodePtr node):xml(0),ctx(0)
{
xml = xmlNewDoc(reinterpret_cast<const xmlChar *>("1.0"));
if (xml == 0)
{
throw("Error allocating XML Document");
}
ctx = xmlXPathNewContext(xml);
if (ctx == 0)
{
xmlFreeDoc(xml);
throw("Unable to create new XPath context");
}
xmlNodePtr root_node = xmlDocCopyNode(node,xml,1);
if (root_node == 0)
{
xmlXPathFreeContext(ctx);
xmlFreeDoc(xml);
throw("Unable to allocate node");
}
xmlDocSetRootElement(xml, root_node);
};
virtual ~ObjectXML()
{
if (xml != 0)
{
xmlFreeDoc(xml);
}
if ( ctx != 0)
{
xmlXPathFreeContext(ctx);
}
};
vector<string> operator[] (const char * xpath_expr)
{
xmlXPathObjectPtr obj;
vector<string> content;
obj = xmlXPathEvalExpression(
reinterpret_cast<const xmlChar *>(xpath_expr), ctx);
if (obj == 0 || obj->nodesetval == 0)
{
return content;
}
xmlNodeSetPtr ns = obj->nodesetval;
int size = ns->nodeNr;
xmlNodePtr cur;
xmlChar * str_ptr;
for(int i = 0; i < size; ++i)
{
cur = ns->nodeTab[i];
if ( cur == 0 || cur->type != XML_ELEMENT_NODE )
{
continue;
}
str_ptr = xmlNodeGetContent(cur);
if (str_ptr != 0)
{
string element_content = reinterpret_cast<char *>(str_ptr);
content.push_back(element_content);
xmlFree(str_ptr);
}
}
xmlXPathFreeObject(obj);
return content;
};
int get_nodes (const char * xpath_expr, vector<xmlNodePtr>& content)
{
xmlXPathObjectPtr obj;
obj = xmlXPathEvalExpression(
reinterpret_cast<const xmlChar *>(xpath_expr), ctx);
if (obj == 0 || obj->nodesetval == 0)
{
return 0;
}
xmlNodeSetPtr ns = obj->nodesetval;
int size = ns->nodeNr;
int num_nodes = 0;
xmlNodePtr cur;
for(int i = 0; i < size; ++i)
{
cur = ns->nodeTab[i];
if ( cur == 0 || cur->type != XML_ELEMENT_NODE )
{
continue;
}
content.push_back(cur);
num_nodes++;
}
xmlXPathFreeObject(obj);
return num_nodes;
};
private:
/**
* XML representation of the Object
*/
xmlDocPtr xml;
/**
* XPath Context to access Object elements
*/
xmlXPathContextPtr ctx;
};
#endif /*OBJECT_XML_H_*/

View File

@ -1,5 +1,3 @@
# SConstruct for src/nebula
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
@ -17,6 +15,79 @@
#--------------------------------------------------------------------------- #
import os
import sys
import shutil
sys.path.append("../../share/scons")
from lex_bison import *
# This is the absolute path where the project is located
cwd=os.getcwd()
# Environment that will be applied to each scons child
main_env=Environment()
main_env['ENV']['PATH']=os.environ['PATH']
# Add builders for flex and bison
add_lex(main_env)
add_bison(main_env)
# Include dirs
main_env.Append(CPPPATH=[
cwd+'./',
])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g"])
################################################################################
# EXTRA CONFIGURATION
################################################################################
#-------------------------------------------------------------------------------
# xmlrpc
#-------------------------------------------------------------------------------
xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none')
if xmlrpc_dir!='none':
main_env.Append(LIBPATH=[xmlrpc_dir+"/lib"])
main_env.Append(CPPPATH=[xmlrpc_dir+"/include"])
main_env.ParseConfig('../../share/scons/get_xmlrpc_config client')
#-------------------------------------------------------------------------------
# build lex/bison
#-------------------------------------------------------------------------------
build_parsers=ARGUMENTS.get('parsers', 'no')
if build_parsers=='yes':
main_env.Append(parsers='yes')
else:
main_env.Append(parsers='no')
#-------------------------------------------------------------------------------
# libxml2
#-------------------------------------------------------------------------------
main_env.ParseConfig('xml2-config --libs --cflags')
Import('env')
cwd=os.getcwd()

View File

@ -0,0 +1,158 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include <string>
#include <iostream>
#include <stdlib.h>
#include <stdexcept>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <unistd.h>
#include "ObjectXML.h"
/* ************************************************************************* */
/* ************************************************************************* */
class ObjectXMLTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( ObjectXMLTest );
CPPUNIT_TEST( xpath_access );
CPPUNIT_TEST( node_constructor );
CPPUNIT_TEST_SUITE_END ();
public:
void setUp()
{
xmlInitParser();
};
void tearDown()
{
xmlCleanupParser();
};
ObjectXMLTest(){};
~ObjectXMLTest(){};
/* ********************************************************************* */
/* ********************************************************************* */
void xpath_access()
{
try
{
ObjectXML obj(xml_history_dump);
vector<string> hostnames;
hostnames = obj["/VM_POOL/VM/HISTORY/HOSTNAME"];
CPPUNIT_ASSERT(hostnames.size() == 2);
CPPUNIT_ASSERT(hostnames[0] == "A_hostname");
CPPUNIT_ASSERT(hostnames[1] == "C_hostname");
}
catch(runtime_error& re)
{
cerr << re.what() << endl;
CPPUNIT_ASSERT(1 == 0);
}
};
void node_constructor()
{
try
{
ObjectXML obj(xml_history_dump);
vector<xmlNodePtr> vms;
int num_vms;
num_vms = obj.get_nodes("/VM_POOL/VM",vms);
CPPUNIT_ASSERT(num_vms == 3);
ObjectXML obj_vm_1(vms[0]);
ObjectXML obj_vm_2(vms[1]);
vector<string> results;
results = obj_vm_1["/VM/HISTORY/HOSTNAME"];
CPPUNIT_ASSERT(results.size() == 0);
results.clear();
results = obj_vm_2["/VM/HISTORY/HOSTNAME"];
CPPUNIT_ASSERT(results.size() == 1);
CPPUNIT_ASSERT(results[0] == "A_hostname");
}
catch(runtime_error& re)
{
cerr << re.what() << endl;
CPPUNIT_ASSERT(1 == 0);
}
};
static const string xml_history_dump;
};
/* ************************************************************************* */
/* ************************************************************************* */
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner runner;
runner.addTest(ObjectXMLTest::suite());
runner.run();
return 0;
}
// ----------------------------------------------------------------------------
const string ObjectXMLTest::xml_history_dump =
"<VM_POOL><VM><ID>0</ID><UID>0</UID><USERNAME>one_user_test</USERNAME>"
"<NAME>VM one</NAME><LAST_POLL>0</LAST_POLL><STATE>1</STATE><LCM_STATE>"
"0</LCM_STATE><STIME>0000000000</STIME><ETIME>0</ETIME><DEPLOY_ID>"
"</DEPLOY_ID><MEMORY>0</MEMORY><CPU>0</CPU><NET_TX>0</NET_TX><NET_RX>"
"0</NET_RX></VM><VM><ID>1</ID><UID>0</UID><USERNAME>"
"one_user_test</USERNAME><NAME>Second VM</NAME><LAST_POLL>0</LAST_POLL>"
"<STATE>2</STATE><LCM_STATE>0</LCM_STATE><STIME>0000000000</STIME>"
"<ETIME>0</ETIME><DEPLOY_ID></DEPLOY_ID><MEMORY>0</MEMORY><CPU>0</CPU>"
"<NET_TX>0</NET_TX><NET_RX>0</NET_RX><HISTORY><SEQ>0</SEQ><HOSTNAME>"
"A_hostname</HOSTNAME><HID>0</HID><STIME>0</STIME><ETIME>0</ETIME><PSTIME>"
"0</PSTIME><PETIME>0</PETIME><RSTIME>0</RSTIME><RETIME>0</RETIME><ESTIME>"
"0</ESTIME><EETIME>0</EETIME><REASON>0</REASON></HISTORY></VM><VM><ID>2"
"</ID><UID>0</UID><USERNAME>one_user_test</USERNAME><NAME>VM one</NAME>"
"<LAST_POLL>0</LAST_POLL><STATE>2</STATE><LCM_STATE>0</LCM_STATE><STIME>"
"0000000000</STIME><ETIME>0</ETIME><DEPLOY_ID></DEPLOY_ID><MEMORY>0"
"</MEMORY><CPU>0</CPU><NET_TX>0</NET_TX><NET_RX>0</NET_RX><HISTORY><SEQ>1"
"</SEQ><HOSTNAME>C_hostname</HOSTNAME><HID>2</HID><STIME>0</STIME><ETIME>0"
"</ETIME><PSTIME>0</PSTIME><PETIME>0</PETIME><RSTIME>0</RSTIME><RETIME>0"
"</RETIME><ESTIME>0</ESTIME><EETIME>0</EETIME><REASON>0</REASON></HISTORY>"
"</VM></VM_POOL>";

View File

@ -0,0 +1,87 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
import os
import sys
import shutil
sys.path.append("../../../share/scons")
# This is the absolute path where the project is located
cwd=os.getcwd()
# Environment that will be applied to each scons child
main_env=Environment()
main_env['ENV']['PATH']=os.environ['PATH']
# Include dirs
main_env.Append(CPPPATH=[
cwd+'/../',
'/usr/include/cppunit/'
])
# Library dirs
main_env.Append(LIBPATH=[
'../'
])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g"])
# Libraries
main_env.Append(LIBS=[
'cppunit'
])
main_env.Program('test_xml','ObjectXMLTest.cc')
################################################################################
# EXTRA CONFIGURATION
################################################################################
#-------------------------------------------------------------------------------
# xmlrpc
#-------------------------------------------------------------------------------
xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none')
if xmlrpc_dir!='none':
main_env.Append(LIBPATH=[xmlrpc_dir+"/lib"])
main_env.Append(CPPPATH=[xmlrpc_dir+"/include"])
main_env.ParseConfig('../../../share/scons/get_xmlrpc_config client')
#-------------------------------------------------------------------------------
# build lex/bison
#-------------------------------------------------------------------------------
build_parsers=ARGUMENTS.get('parsers', 'no')
if build_parsers=='yes':
main_env.Append(parsers='yes')
else:
main_env.Append(parsers='no')
#-------------------------------------------------------------------------------
# libxml2
#-------------------------------------------------------------------------------
main_env.ParseConfig('xml2-config --libs --cflags')