1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

Merge branch 'feature-192' into feature-206

Conflicts:
	src/host/HostPool.cc
This commit is contained in:
Ruben S. Montero 2010-04-17 17:18:03 +02:00
commit e29f34cb4a
19 changed files with 2106 additions and 780 deletions

View File

@ -0,0 +1,64 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad #
# Complutense de Madrid (dsa-research.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")
from lex_bison import *
# This is the absolute path where the project is located
cwd="../../../"
# 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 + '/include',
'/usr/include/cppunit/'
])
# Library dirs
main_env.Append(LIBPATH=[
cwd + '/src/common',
])
main_env.Append(LIBS=[
'nebula_common',
'cppunit',
'dl',
'pthread'
])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g"])
main_env.Program('single_attribute.cc')
main_env.Program('vector_attribute.cc')
main_env.Program('action_manager.cc')

View File

@ -0,0 +1,183 @@
#include "ActionManager.h"
#include <string>
#include <iostream>
#include <map>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
using namespace std;
extern "C" void * addsub_loop(void *arg);
class AddSub : public ActionListener
{
public:
AddSub(int i):am(),counter(i)
{
am.addListener(this);
};
~AddSub(){};
void add(int i)
{
int * p;
p = new int(i);
am.trigger("ADD",(void *) p);
}
void sub(int i)
{
int * p;
p = new int(i);
am.trigger("SUB",(void *) p);
}
int value()
{
return counter;
}
pthread_t id()
{
return pid;
}
void start()
{
pthread_attr_t pattr;
pthread_attr_init (&pattr);
pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE);
pthread_create(&pid,&pattr,addsub_loop,(void *) this);
}
void end()
{
am.trigger(ActionListener::ACTION_FINALIZE,0);
}
private:
ActionManager am;
int counter;
pthread_t pid;
friend void * addsub_loop(void *arg);
void do_action(const string &action, void * arg)
{
int * i = static_cast<int *>(arg);
if ( i == 0 )
{
return;
}
else if ( action == "ADD" )
{
counter = counter + *i;
}
else if ( action == "SUB" )
{
counter = counter - *i;
}
delete i;
}
};
extern "C" void * addsub_loop(void *arg)
{
AddSub *as;
as = static_cast<AddSub *>(arg);
as->am.loop(0,0);
return 0;
};
class ActionManagerTest : public CppUnit::TestFixture
{
private:
AddSub *as;
public:
void setUp()
{
as = new AddSub(10);
as->start();
}
void tearDown()
{
delete as;
}
void test_add()
{
as->add(23);
as->add(5);
sleep(1);
CPPUNIT_ASSERT(as->value() == 38);
as->end();
pthread_join(as->id(),0);
CPPUNIT_ASSERT(as->value() == 38);
}
void test_sub()
{
as->sub(3);
as->sub(15);
sleep(1);
CPPUNIT_ASSERT(as->value() == -8);
as->end();
pthread_join(as->id(),0);
CPPUNIT_ASSERT(as->value() == -8);
}
static CppUnit::TestSuite * suite()
{
CppUnit::TestSuite *ts=new CppUnit::TestSuite("ActionManager Tests");
ts->addTest(new CppUnit::TestCaller<ActionManagerTest>(
"add() Test",
&ActionManagerTest::test_add));
ts->addTest(new CppUnit::TestCaller<ActionManagerTest>(
"sub() Test",
&ActionManagerTest::test_sub));
return ts;
}
};
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner tr;
tr.addTest(ActionManagerTest::suite());
tr.run();
return 0;
}

View File

@ -0,0 +1,131 @@
#include "Attribute.h"
#include <string>
#include <iostream>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
using namespace std;
class SingleAttributeTest : public CppUnit::TestFixture
{
private:
SingleAttribute *a, *b;
public:
void setUp()
{
string a_name = "single_a";
string b_name = "single_b";
string b_value= "value_b";
a = new SingleAttribute(a_name);
b = new SingleAttribute(b_name, b_value);
}
void tearDown()
{
delete a;
delete b;
}
void test_type()
{
CPPUNIT_ASSERT(a->type() == Attribute::SIMPLE);
CPPUNIT_ASSERT(b->type() == Attribute::SIMPLE);
}
void test_name()
{
CPPUNIT_ASSERT(a->name() == "SINGLE_A");
CPPUNIT_ASSERT(b->name() == "SINGLE_B");
}
void test_value()
{
CPPUNIT_ASSERT(a->value().empty() == true);
CPPUNIT_ASSERT(b->value() == "value_b");
}
void test_marshall()
{
string *am, *bm;
am = a->marshall();
bm = b->marshall();
CPPUNIT_ASSERT(am->empty() == true);
CPPUNIT_ASSERT(*bm == "value_b");
delete am;
delete bm;
}
void test_xml()
{
string *am, *bm;
am = a->to_xml();
bm = b->to_xml();
CPPUNIT_ASSERT(*am == "<SINGLE_A></SINGLE_A>");
CPPUNIT_ASSERT(*bm == "<SINGLE_B>value_b</SINGLE_B>");
delete am;
delete bm;
}
void test_replace()
{
string nv = "new_value_b";
b->replace(nv);
CPPUNIT_ASSERT(b->value() == "new_value_b");
}
static CppUnit::TestSuite * suite()
{
CppUnit::TestSuite *ts=new CppUnit::TestSuite("SingleAttribute Tests");
ts->addTest(new CppUnit::TestCaller<SingleAttributeTest>(
"type() Test",
&SingleAttributeTest::test_type));
ts->addTest(new CppUnit::TestCaller<SingleAttributeTest>(
"name() Test",
&SingleAttributeTest::test_name));
ts->addTest(new CppUnit::TestCaller<SingleAttributeTest>(
"value() Test",
&SingleAttributeTest::test_value));
ts->addTest(new CppUnit::TestCaller<SingleAttributeTest>(
"marshall() Test",
&SingleAttributeTest::test_marshall));
ts->addTest(new CppUnit::TestCaller<SingleAttributeTest>(
"to_xml() Test",
&SingleAttributeTest::test_xml));
ts->addTest(new CppUnit::TestCaller<SingleAttributeTest>(
"replace() Test",
&SingleAttributeTest::test_replace));
return ts;
}
};
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner tr;
tr.addTest(SingleAttributeTest::suite());
tr.run();
return 0;
}

View File

@ -0,0 +1,163 @@
#include "Attribute.h"
#include <string>
#include <iostream>
#include <map>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
using namespace std;
class VectorAttributeTest : public CppUnit::TestFixture
{
private:
VectorAttribute *a, *b;
map<string,string> b_value;
public:
void setUp()
{
string a_name = "vector_a";
string b_name = "vector_b";
b_value.insert(make_pair("attr1","val1"));
b_value.insert(make_pair("attr2","val2"));
b_value.insert(make_pair("attr3","val3"));
a = new VectorAttribute(a_name);
b = new VectorAttribute(b_name, b_value);
}
void tearDown()
{
delete a;
delete b;
}
void test_type()
{
CPPUNIT_ASSERT(a->type() == Attribute::VECTOR);
CPPUNIT_ASSERT(b->type() == Attribute::VECTOR);
}
void test_name()
{
CPPUNIT_ASSERT(a->name() == "VECTOR_A");
CPPUNIT_ASSERT(b->name() == "VECTOR_B");
}
void test_value()
{
CPPUNIT_ASSERT(a->value().empty() == true);
CPPUNIT_ASSERT(b->value() == b_value);
CPPUNIT_ASSERT(a->vector_value("NAME").empty() == true);
CPPUNIT_ASSERT(b->vector_value("NAME").empty() == true);
CPPUNIT_ASSERT(b->vector_value("attr1") == "val1");
CPPUNIT_ASSERT(b->vector_value("attr2") == "val2");
CPPUNIT_ASSERT(b->vector_value("attr3") == "val3");
}
void test_marshall()
{
string *am, *bm;
am = a->marshall();
bm = b->marshall();
CPPUNIT_ASSERT(am == 0);
CPPUNIT_ASSERT(*bm == "attr1=val1@^_^@attr2=val2@^_^@attr3=val3");
VectorAttribute c("vector_c");
c.unmarshall(*bm);
CPPUNIT_ASSERT(c.vector_value("attr1") == "val1");
CPPUNIT_ASSERT(c.vector_value("attr2") == "val2");
CPPUNIT_ASSERT(c.vector_value("attr3") == "val3");
delete am;
delete bm;
}
void test_xml()
{
string *am, *bm;
am = a->to_xml();
bm = b->to_xml();
CPPUNIT_ASSERT(*am == "<VECTOR_A></VECTOR_A>");
CPPUNIT_ASSERT(*bm == "<VECTOR_B><attr1>val1</attr1><attr2>val2</attr2>"
"<attr3>val3</attr3></VECTOR_B>");
delete am;
delete bm;
}
void test_replace()
{
map<string,string> nm;
string nv = "new_val1";
b->replace("attr1",nv);
CPPUNIT_ASSERT(b->vector_value("attr1") == "new_val1");
nm.insert(make_pair("other_attr1","other_val1"));
nm.insert(make_pair("other_attr2","other_val2"));
b->replace(nm);
CPPUNIT_ASSERT(b->vector_value("other_attr1") == "other_val1");
CPPUNIT_ASSERT(b->vector_value("other_attr2") == "other_val2");
CPPUNIT_ASSERT(b->vector_value("attr3").empty() == true);
CPPUNIT_ASSERT(b->value() == nm);
}
static CppUnit::TestSuite * suite()
{
CppUnit::TestSuite *ts=new CppUnit::TestSuite("VectorAttribute Tests");
ts->addTest(new CppUnit::TestCaller<VectorAttributeTest>(
"type() Test",
&VectorAttributeTest::test_type));
ts->addTest(new CppUnit::TestCaller<VectorAttributeTest>(
"name() Test",
&VectorAttributeTest::test_name));
ts->addTest(new CppUnit::TestCaller<VectorAttributeTest>(
"value() Test",
&VectorAttributeTest::test_value));
ts->addTest(new CppUnit::TestCaller<VectorAttributeTest>(
"marshall() Test",
&VectorAttributeTest::test_marshall));
ts->addTest(new CppUnit::TestCaller<VectorAttributeTest>(
"to_xml() Test",
&VectorAttributeTest::test_xml));
ts->addTest(new CppUnit::TestCaller<VectorAttributeTest>(
"replace() Test",
&VectorAttributeTest::test_replace));
return ts;
}
};
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner tr;
tr.addTest(VectorAttributeTest::suite());
tr.run();
return 0;
}

View File

@ -72,7 +72,6 @@ int HostPool::discover_cb(void * _map, int num, char **values, char **names)
int HostPool::discover(map<int, string> * discovered_hosts)
{
ostringstream sql;
int rc;
@ -82,7 +81,8 @@ int HostPool::discover(map<int, string> * discovered_hosts)
static_cast<void *>(discovered_hosts));
sql << "SELECT oid, im_mad FROM "
<< Host::table << " ORDER BY last_mon_time LIMIT 10";
<< Host::table << " WHERE state != "
<< Host::DISABLED << " ORDER BY last_mon_time LIMIT 10";
rc = db->exec(sql,this);

View File

@ -1,395 +0,0 @@
/*******************************************************************************
* 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.
******************************************************************************/
package org.opennebula.client.virtualMachine;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.PoolElement;
import org.w3c.dom.Node;
/**
* This class represents an OpenNebula VM.
* It also offers static XML-RPC call wrappers.
*/
public class VirtualMachine extends PoolElement{
private static final String METHOD_PREFIX = "vm.";
private static final String ALLOCATE = METHOD_PREFIX + "allocate";
private static final String INFO = METHOD_PREFIX + "info";
private static final String DEPLOY = METHOD_PREFIX + "deploy";
private static final String ACTION = METHOD_PREFIX + "action";
private static final String MIGRATE = METHOD_PREFIX + "migrate";
private static final String[] VM_STATES =
{
"INIT",
"PENDING",
"HOLD",
"ACTIVE",
"STOPPED",
"SUSPENDED",
"DONE",
"FAILED" };
private static final String[] SHORT_VM_STATES =
{
"init",
"pend",
"hold",
"actv",
"stop",
"susp",
"done",
"fail" };
private static final String[] LCM_STATE =
{
"LCM_INIT",
"PROLOG",
"BOOT",
"RUNNING",
"MIGRATE",
"SAVE_STOP",
"SAVE_SUSPEND",
"SAVE_MIGRATE",
"PROLOG_MIGRATE",
"PROLOG_RESUME",
"EPILOG_STOP",
"EPILOG",
"SHUTDOWN",
"CANCEL",
"FAILURE",
"DELETE",
"UNKNOWN" };
private static final String[] SHORT_LCM_STATES =
{
null,
"prol",
"boot",
"runn",
"migr",
"save",
"save",
"save",
"migr",
"prol",
"epil",
"epil",
"shut",
"shut",
"fail",
"dele",
"unkn" };
/**
* Creates a new VM representation.
*
* @param id The virtual machine Id (vid).
* @param client XML-RPC Client.
*/
public VirtualMachine(int id, Client client)
{
super(id, client);
}
/**
* @see PoolElement
*/
protected VirtualMachine(Node xmlElement, Client client)
{
super(xmlElement, client);
}
// =================================
// Static XML-RPC methods
// =================================
/**
* Allocates a new VM in OpenNebula.
*
* @param client XML-RPC Client.
* @param description A string containing the template of the vm.
* @return If successful the message contains the associated
* id generated for this VM.
*/
public static OneResponse allocate(Client client, String description)
{
return client.call(ALLOCATE, description);
}
/**
* Retrieves the information of the given VM.
*
* @param client XML-RPC Client.
* @param id The virtual machine id (vid) of the target instance.
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int id)
{
return client.call(INFO, id);
}
// =================================
// Instanced object XML-RPC methods
// =================================
/**
* Loads the xml representation of the virtual machine.
* The info is also stored internally.
*
* @see VirtualMachine#info(Client, int)
*/
public OneResponse info()
{
OneResponse response = info(client, id);
super.processInfo(response);
return response;
}
/**
* Initiates the instance of the VM on the target host.
*
* @param hostId The host id (hid) of the target host where
* the VM will be instantiated.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse deploy(int hostId)
{
return client.call(DEPLOY, id, hostId);
}
/**
* Submits an action to be performed on the virtual machine.
* <br/>
* It is recommended to use the helper methods instead:
* <ul>
* <li>{@link VirtualMachine#shutdown()}</li>
* <li>{@link VirtualMachine#cancel()}</li>
* <li>{@link VirtualMachine#hold()}</li>
* <li>{@link VirtualMachine#release()}</li>
* <li>{@link VirtualMachine#stop()}</li>
* <li>{@link VirtualMachine#suspend()}</li>
* <li>{@link VirtualMachine#resume()}</li>
* <li>{@link VirtualMachine#finalizeVM()}</li>
* <li>{@link VirtualMachine#restart()}</li>
* </ul>
*
* @param action The action name to be performed, can be:<br/>
* "shutdown", "hold", "release", "stop", "cancel", "suspend",
* "resume", "restart", "finalize".
* @return If an error occurs the error message contains the reason.
*/
protected OneResponse action(String action)
{
return client.call(ACTION, action, id);
}
/**
* Migrates the virtual machine to the target host (hid).
*
* @param hostId The target host id (hid) where we want to migrate
* the vm.
* @param live If true we are indicating that we want livemigration,
* otherwise false.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse migrate(int hostId, boolean live)
{
return client.call(MIGRATE, id, hostId, live);
}
// =================================
// Helpers
// =================================
/**
* Shuts down the already deployed VM.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse shutdown()
{
return action("shutdown");
}
/**
* Cancels the running VM.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse cancel()
{
return action("cancel");
}
/**
* Sets the VM to hold state. The VM will not be scheduled until it is
* released.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse hold()
{
return action("hold");
}
/**
* Releases a virtual machine from hold state.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse release()
{
return action("release");
}
/**
* Stops the virtual machine. The virtual machine state is transferred back
* to OpenNebula for a possible reschedule.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse stop()
{
return action("stop");
}
/**
* Suspends the virtual machine. The virtual machine state is left in the
* cluster node for resuming.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse suspend()
{
return action("suspend");
}
/**
* Resumes the execution of a saved VM.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse resume()
{
return action("resume");
}
/**
* Deletes the VM from the pool and database.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse finalizeVM()
{
return action("finalize");
}
/**
* Resubmits the virtual machine after failure.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse restart()
{
return action("shutdown");
}
/**
* Migrates the virtual machine to the target host (hid).
* <br/>
* It does the same as {@link VirtualMachine#migrate(int, boolean)}
* with live set to false.
*
* @param hostId The target host id (hid) where we want to migrate
* the vm.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse migrate(int hostId)
{
return migrate(hostId, false);
}
/**
* Performs a live migration of the virtual machine to the
* target host (hid).
* <br/>
* It does the same as {@link VirtualMachine#migrate(int, boolean)}
* with live set to true.
*
* @param hostId The target host id (hid) where we want to migrate
* the vm.
* @return If an error occurs the error message contains the reason.
*/
public OneResponse liveMigrate(int hostId)
{
return migrate(hostId, true);
}
public int state()
{
return super.state();
}
/**
* Returns the VM state of the VirtualMachine (string value).
* @return The VM state of the VirtualMachine (string value).
*/
public String stateStr()
{
int state = state();
return state != -1 ? VM_STATES[state()] : null;
}
/**
* Returns the LCM state of the VirtualMachine (numeric value).
* @return The LCM state of the VirtualMachine (numeric value).
*/
public int lcmState()
{
String state = xpath("LCM_STATE");
return state != null ? Integer.parseInt(state) : -1;
}
/**
* Returns the LCM state of the VirtualMachine (string value).
* @return The LCM state of the VirtualMachine (string value).
*/
public String lcmStateStr()
{
int state = lcmState();
return state != -1 ? LCM_STATE[state] : null;
}
/**
* Returns the short status string for the VirtualMachine.
* @return The short status string for the VirtualMachine.
*/
public String status()
{
int state = state();
String shortStateStr = null;
if(state != -1)
{
shortStateStr = SHORT_VM_STATES[state];
if(shortStateStr.equals("actv"))
{
int lcmState = lcmState();
if(lcmState != -1)
shortStateStr = SHORT_LCM_STATES[lcmState];
}
}
return shortStateStr;
}
}

View File

@ -1,129 +0,0 @@
/*******************************************************************************
* 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.
******************************************************************************/
package org.opennebula.client.virtualMachine;
import java.util.AbstractList;
import java.util.Iterator;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.Pool;
import org.opennebula.client.PoolElement;
import org.w3c.dom.Node;
/**
* This class represents an OpenNebula VM pool.
* It also offers static XML-RPC call wrappers.
*/
public class VirtualMachinePool extends Pool implements Iterable<VirtualMachine>{
private static final String ELEMENT_NAME = "VM";
private static final String INFO_METHOD = "vmpool.info";
private int filter;
/**
* Creates a new VM pool with the default filter flag value
* set to 0 (VMs belonging to user with UID 0)
*
* @param client XML-RPC Client.
*
* @see VirtualMachinePool#VirtualMachinePool(Client, int)
*/
public VirtualMachinePool(Client client)
{
super(ELEMENT_NAME, client);
this.filter = 0;
}
/**
* Creates a new VM pool.
*
* @param client XML-RPC Client.
* @param filter Filter flag used by default in the method
* {@link VirtualMachinePool#info()}. Possible values:
* <ul>
* <li><= -2: All VMs</li>
* <li>-1: Connected user's VMs</li>
* <li>>= 0: UID User's VMs</li>
* </ul>
*/
public VirtualMachinePool(Client client, int filter)
{
super(ELEMENT_NAME, client);
this.filter = filter;
}
@Override
public PoolElement factory(Node node)
{
return new VirtualMachine(node, client);
}
/**
* Retrieves all or part of the VMs in the pool.
*
* @param client XML-RPC Client.
* @param filter Filter flag. Possible values:
* <ul>
* <li><= -2: All VMs</li>
* <li>-1: Connected user's VMs</li>
* <li>>= 0: UID User's VMs</li>
* </ul>
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int filter)
{
return client.call(INFO_METHOD, filter);
}
/**
* Loads the xml representation of all or part of the
* VMs in the pool. The filter used is the one set in
* the constructor.
*
* @see VirtualMachinePool#info(Client, int)
*
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public OneResponse info()
{
OneResponse response = info(client, filter);
super.processInfo(response);
return response;
}
public Iterator<VirtualMachine> iterator()
{
AbstractList<VirtualMachine> ab = new AbstractList<VirtualMachine>()
{
public int size()
{
return getLength();
}
public VirtualMachine get(int index)
{
return (VirtualMachine) item(index);
}
};
return ab.iterator();
}
}

View File

@ -1,126 +0,0 @@
/*******************************************************************************
* 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.
******************************************************************************/
package org.opennebula.client.virtualNetwork;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.PoolElement;
import org.w3c.dom.Node;
/**
* This class represents an OpenNebula virtual network.
* It also offers static XML-RPC call wrappers.
*/
public class VirtualNetwork extends PoolElement{
private static final String METHOD_PREFIX = "vn.";
private static final String ALLOCATE = METHOD_PREFIX + "allocate";
private static final String INFO = METHOD_PREFIX + "info";
private static final String DELETE = METHOD_PREFIX + "delete";
/**
* Creates a new virtual network representation.
*
* @param id The virtual network id (nid) .
* @param client XML-RPC Client.
*/
public VirtualNetwork(int id, Client client)
{
super(id, client);
}
/**
* @see PoolElement
*/
protected VirtualNetwork(Node xmlElement, Client client)
{
super(xmlElement, client);
}
// =================================
// Static XML-RPC methods
// =================================
/**
* Allocates a new virtual network in OpenNebula.
*
* @param client XML-RPC Client.
* @param description A string containing the template
* of the virtual network.
* @return If successful the message contains the associated
* id generated for this virtual network.
*/
public static OneResponse allocate(Client client, String description)
{
return client.call(ALLOCATE, description);
}
/**
* Retrieves the information of the given virtual network
*
* @param client XML-RPC Client.
* @param id the virtual network id (nid) for the network to
* retrieve the information from.
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int id)
{
return client.call(INFO, id);
}
/**
* Deletes a network from OpenNebula.
*
* @param client XML-RPC Client.
* @param id The virtual network id (nid) of the target network.
* @return A encapsulated response.
*/
public static OneResponse delete(Client client, int id)
{
return client.call(DELETE, id);
}
// =================================
// Instanced object XML-RPC methods
// =================================
/**
* Loads the xml representation of the virtual network.
* The info is also stored internally.
*
* @see VirtualNetwork#info(Client, int)
*/
public OneResponse info()
{
OneResponse response = info(client, id);
super.processInfo(response);
return response;
}
/**
* Deletes the network from OpenNebula.
*
* @return A encapsulated response.
*/
public OneResponse delete()
{
return delete(client, id);
}
}

View File

@ -1,128 +0,0 @@
/*******************************************************************************
* 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.
******************************************************************************/
package org.opennebula.client.virtualNetwork;
import java.util.AbstractList;
import java.util.Iterator;
import org.opennebula.client.Client;
import org.opennebula.client.OneResponse;
import org.opennebula.client.Pool;
import org.opennebula.client.PoolElement;
import org.w3c.dom.Node;
/**
* This class represents an OpenNebula Virtual Network pool.
* It also offers static XML-RPC call wrappers.
*/
public class VirtualNetworkPool extends Pool implements Iterable<VirtualNetwork>{
private static final String ELEMENT_NAME = "VNET";
private static final String INFO_METHOD = "vnpool.info";
private int filter;
/**
* Creates a new VN pool with the default filter flag value
* set to 0 (VNs belonging to user with UID 0)
*
* @param client XML-RPC Client.
*
* @see VirtualNetworkPool#VirtualNetworkPool(Client, int)
*/
public VirtualNetworkPool(Client client)
{
super(ELEMENT_NAME, client);
this.filter = 0;
}
/**
* Creates a new VN pool.
*
* @param client XML-RPC Client.
* @param filter Filter flag used by default in the method
* {@link VirtualNetworkPool#info()}. Possible values:
* <ul>
* <li><= -2: All VNs</li>
* <li>-1: Connected user's VNs</li>
* <li>>= 0: UID User's VNs</li>
* </ul>
*/
public VirtualNetworkPool(Client client, int filter)
{
super(ELEMENT_NAME, client);
this.filter = filter;
}
@Override
public PoolElement factory(Node node)
{
return new VirtualNetwork(node, client);
}
/**
* Retrieves all or part of the VNs in the pool.
*
* @param client XML-RPC Client.
* @param filter Filter flag. Possible values:
* <ul>
* <li><= -2: All VNs</li>
* <li>-1: Connected user's VNs</li>
* <li>>= 0: UID User's VNs</li>
* </ul>
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info(Client client, int filter)
{
return client.call(INFO_METHOD, filter);
}
/**
* Loads the xml representation of all or part of the
* VNs in the pool. The filter used is the one set in
* the constructor.
*
* @see VirtualNetworkPool#info(Client, int)
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public OneResponse info()
{
OneResponse response = info(client, filter);
super.processInfo(response);
return response;
}
public Iterator<VirtualNetwork> iterator()
{
AbstractList<VirtualNetwork> ab = new AbstractList<VirtualNetwork>()
{
public int size()
{
return getLength();
}
public VirtualNetwork get(int index)
{
return (VirtualNetwork) item(index);
}
};
return ab.iterator();
}
}

68
src/pool/test/SConstruct Normal file
View File

@ -0,0 +1,68 @@
# --------------------------------------------------------------------------
# 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")
from lex_bison import *
# This is the absolute path where the project is located
cwd="../../../"
# 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 + '/include',
'/usr/include/cppunit/',
])
# Library dirs
main_env.Append(LIBPATH=[
cwd + '/src/common',
cwd + '/src/pool',
cwd + '/src/pool/test',
])
main_env.Append(LIBS=[
'nebula_pool',
'nebula_common',
'cppunit',
'dl',
'pthread',
'sqlite3',
'test_object'
])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g "])
main_env.StaticLibrary('test_object', ['TestPoolSQL.cc', 'TestPoolSQL.h'])
main_env.Program('pool.cc')
#

View File

@ -0,0 +1,131 @@
/* -------------------------------------------------------------------------- */
/* 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 <limits.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <openssl/evp.h>
#include <iomanip>
#include "TestPoolSQL.h"
/* ************************************************************************** */
/* Database Access Functions */
/* ************************************************************************** */
const char * TestObjectSQL::table = "test_pool";
const char * TestObjectSQL::db_names = "(oid,number,text)";
const char * TestObjectSQL::db_bootstrap = "CREATE TABLE test_pool ("
"oid INTEGER, number INTEGER, text TEXT, PRIMARY KEY(oid))";
/* -------------------------------------------------------------------------- */
int TestObjectSQL::unmarshall(void * nil, int num, char **values, char **names)
{
if ((!values[OID]) ||
(!values[NUMBER]) ||
(!values[TEXT]) ||
(num != LIMIT ))
{
return -1;
}
oid = atoi(values[OID]);
number = atoi(values[NUMBER]);
text = values[TEXT];
return 0;
}
/* -------------------------------------------------------------------------- */
int TestObjectSQL::select(SqlDB *db)
{
ostringstream oss;
int rc;
int boid;
set_callback(
static_cast<Callbackable::CallBack>(&TestObjectSQL::unmarshall),0);
oss << "SELECT * FROM " << table << " WHERE oid = " << oid;
boid = oid;
oid = -1;
rc = db->exec(oss, this);
if ((rc != 0) || (oid != boid ))
{
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
int TestObjectSQL::insert(SqlDB *db)
{
return update(db);
}
/* -------------------------------------------------------------------------- */
int TestObjectSQL::update(SqlDB *db)
{
ostringstream oss;
int rc;
char * sql_text;
sql_text = db->escape_str(text.c_str());
oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES ("
<< oid << ","
<< number << ","
<< "'" << sql_text << "')";
rc = db->exec(oss);
db->free_str(sql_text);
return rc;
}
/* -------------------------------------------------------------------------- */
int TestObjectSQL::drop(SqlDB * db)
{
ostringstream oss;
int rc;
oss << "DELETE FROM " << table << " WHERE oid=" << oid;
rc = db->exec(oss);
if ( rc == 0 )
{
set_valid(false);
}
return rc;
}

100
src/pool/test/TestPoolSQL.h Normal file
View File

@ -0,0 +1,100 @@
/* -------------------------------------------------------------------------- */
/* 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 TESTSQL_H_
#define TESTSQL_H_
#include <string>
#include "PoolSQL.h"
using namespace std;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
// THE OBJECT
class TestObjectSQL : public PoolObjectSQL
{
public:
//OBJECT ATTRIBUTES
TestObjectSQL(int n=-1, string t="default"):number(n),text(t){};
~TestObjectSQL(){};
int number;
string text;
// OBJECTSQL INTERFACE
int unmarshall(void * nil, int num, char **names, char ** values);
int select(SqlDB *db);
int insert(SqlDB *db);
int update(SqlDB *db);
int drop(SqlDB *db);
// DATABASE IMPLEMENTATION
enum ColNames
{
OID = 0,
NUMBER = 1,
TEXT = 2,
LIMIT = 3
};
static const char * db_names;
static const char * db_bootstrap;
static const char * table;
static void bootstrap(SqlDB * db)
{
ostringstream oss;
oss.str(TestObjectSQL::db_bootstrap);
db->exec(oss,0);
};
};
// THE POOL
class TestPool : public PoolSQL
{
public:
TestPool(SqlDB *db):PoolSQL(db,"test_pool"){};
~TestPool(){};
TestObjectSQL * get(
int oid,
bool lock)
{
return static_cast<TestObjectSQL *>(PoolSQL::get(oid,lock));;
}
private:
TestObjectSQL * create()
{
return new TestObjectSQL;
};
};
#endif

220
src/pool/test/pool.cc Normal file
View File

@ -0,0 +1,220 @@
/* -------------------------------------------------------------------------- */
/* 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 <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 "PoolSQL.h"
#include "TestPoolSQL.h"
#include "SqliteDB.h"
using namespace std;
/* ************************************************************************* */
/* ************************************************************************* */
class PoolTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (PoolTest);
CPPUNIT_TEST (allocate_get);
CPPUNIT_TEST (wrong_get);
CPPUNIT_TEST (search);
CPPUNIT_TEST (cache_test);
CPPUNIT_TEST_SUITE_END ();
private:
TestPool * pool;
SqliteDB * db;
int create_allocate(int n, string st)
{
TestObjectSQL *obj = new TestObjectSQL(n,st);
return pool->allocate(obj);
};
public:
PoolTest(){};
~PoolTest(){};
void setUp()
{
string db_name = "test.db";
unlink("test.db");
db = new SqliteDB(db_name);
TestObjectSQL::bootstrap(db);
pool = new TestPool(db);
};
void tearDown()
{
delete db;
delete pool;
};
/* ********************************************************************* */
/* ********************************************************************* */
// Try to allocate two objects, and retrieve them
void allocate_get()
{
int n1 = 3;
int n2 = 7;
string st1 = "text number one";
string st2 = "another text";
TestObjectSQL *obj;
int oid;
oid = create_allocate(n1,st1);
// first element in the pool should have oid=0
CPPUNIT_ASSERT(oid == 0);
oid = create_allocate(n2,st2);
// second element in the pool should have oid=1
CPPUNIT_ASSERT(oid == 1);
// ---------------------------------
obj = pool->get(0, false);
CPPUNIT_ASSERT(obj != 0);
CPPUNIT_ASSERT(obj->number == n1);
CPPUNIT_ASSERT(obj->text == st1);
// ---------------------------------
obj = pool->get(1, true);
CPPUNIT_ASSERT(obj != 0);
CPPUNIT_ASSERT(obj->number == n2);
CPPUNIT_ASSERT(obj->text == st2);
obj->unlock();
};
void wrong_get()
{
int n1 = 2;
string st1 = "object 2";
TestObjectSQL *obj;
int oid;
oid = create_allocate(n1,st1);
obj = pool->get(oid,true);
CPPUNIT_ASSERT(obj != 0);
obj->drop(db);
obj->unlock();
obj = pool->get(oid,true);
CPPUNIT_ASSERT(obj == 0);
pool->clean();
obj = pool->get(oid,true);
CPPUNIT_ASSERT(obj == 0);
};
void search()
{
int nA = 13;
int nB = 17;
string stA = "String value for number 13";
string stB = "String value for number 17";
int oidA = create_allocate(nA, stA);
int oidB = create_allocate(nB, stB);
vector<int> results;
const char * table = "test_pool";
string where = "text = '" + stB + "'";
int ret;
ret = pool->search(results, table, where);
CPPUNIT_ASSERT(ret == 0);
CPPUNIT_ASSERT(results.size() == 1);
CPPUNIT_ASSERT(results.at(0) == oidB);
results.erase(results.begin(), results.end());
where = "number < 18";
ret = pool->search(results, table, where);
CPPUNIT_ASSERT(ret == 0);
CPPUNIT_ASSERT(results.size() == 2);
CPPUNIT_ASSERT(results.at(0) == oidA);
CPPUNIT_ASSERT(results.at(1) == oidB);
};
void cache_test()
{
TestObjectSQL *obj;
TestObjectSQL *obj_lock;
//pin object in the cache, it can't be removed -
for (int i=0 ; i < 499 ; i++)
{
create_allocate(i,"A Test object");
obj_lock = pool->get(i, true);
CPPUNIT_ASSERT(obj_lock != 0);
}
for (int i=499 ; i < 2000 ; i++)
{
create_allocate(i,"A Test object");
}
for (int i=499; i < 2000 ; i++)
{
obj = pool->get(i, true);
CPPUNIT_ASSERT(obj != 0);
CPPUNIT_ASSERT(obj->number == i);
CPPUNIT_ASSERT(obj->text == "A Test object");
obj->unlock();
}
for (int i=0 ; i < 499 ; i++)
{
obj_lock = pool->get(i, false);//pin object in the cache, it can't be removed
obj_lock->unlock();
}
};
};
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner runner;
runner.addTest( PoolTest::suite() );
runner.run();
return 0;
}

View File

@ -0,0 +1,67 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad #
# Complutense de Madrid (dsa-research.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")
from lex_bison import *
# This is the absolute path where the project is located
cwd="../../../"
# 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 + '/include',
'/usr/include/cppunit/'
])
# Library dirs
main_env.Append(LIBPATH=[
cwd + '/src/common',
cwd + '/src/template',
])
main_env.Append(LIBS=[
'nebula_template',
'nebula_common',
'cppunit',
'dl',
'pthread',
'sqlite3'
])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g "])
main_env.Program('template.cc')
main_env.Program('template_sql.cc')
#

View File

@ -0,0 +1,319 @@
#include "Template.h"
#include <string>
#include <iostream>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
using namespace std;
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
class TemplateTest : public CppUnit::TestFixture
{
private:
Template *t, *tr, *t1;
string test_ok;
string test_ok_marshall;
string test_ok_xml;
string test_ok_str;
public:
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
TemplateTest()
{
test_ok =
"#This line is a comment\n"
" # Other comment\n"
"MEMORY=345 # more comments behind an attribute\n"
" CPU = 4\n"
"#------------------------------\n"
"#Comments in the middle\n"
"#------------------------------\n"
" empty_var = \n"
"REQUIREMENTS = \"HOSTNAME = \\\"host*.com\\\"\"\n"
" DISK= [file = path1, extra = \"disk attribute \"]\n"
"DISK =[ FILE = \"path2\", EXTRA = str, TYPE=disk]\n"
" graphics = [\n"
" VNC = \"127.0.0.1\",\n"
" PORT = 12\n"
" ]\n";
test_ok_marshall="CPU=4\nDISK=EXTRA=disk attribute @^_^@FILE=path1\n"
"DISK=EXTRA=str@^_^@FILE=path2@^_^@TYPE=disk\nEMPTY_VAR=\n"
"GRAPHICS=PORT=12@^_^@VNC=127.0.0.1\nMEMORY=345\n"
"REQUIREMENTS=HOSTNAME = \"host*.com\"\n";
test_ok_xml="<TEMPLATE><CPU>4</CPU><DISK><EXTRA>disk attribute </EXTRA>"
"<FILE>path1</FILE></DISK><DISK><EXTRA>str</EXTRA><FILE>path2</FILE>"
"<TYPE>disk</TYPE></DISK><EMPTY_VAR></EMPTY_VAR><GRAPHICS>"
"<PORT>12</PORT><VNC>127.0.0.1</VNC></GRAPHICS><MEMORY>345</MEMORY>"
"<REQUIREMENTS>HOSTNAME = \"host*.com\"</REQUIREMENTS></TEMPLATE>";
test_ok_str=
"\n\tCPU=4"
"\n\tDISK=EXTRA=disk attribute ,FILE=path1"
"\n\tDISK=EXTRA=str,FILE=path2,TYPE=disk"
"\n\tEMPTY_VAR="
"\n\tGRAPHICS=PORT=12,VNC=127.0.0.1"
"\n\tMEMORY=345"
"\n\tREQUIREMENTS=HOSTNAME = \"host*.com\"";
}
~TemplateTest(){};
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void setUp()
{
char *error = 0;
t = new Template();
tr= new Template(true);
tr->parse(test_ok,&error);
t1= new Template();
t1->parse(test_ok,&error);
}
void tearDown()
{
delete t;
delete tr;
delete t1;
}
/* ********************************************************************* */
/* ********************************************************************* */
void test_parser()
{
char * error = 0;
int rc;
string tmp;
rc = t->parse(test_ok,&error);
if ( error != 0 )
{
cerr << error << endl;
free(error);
}
CPPUNIT_ASSERT( rc == 0);
}
/* --------------------------------------------------------------------- */
void test_marshall()
{
string tmp;
t1->marshall(tmp);
CPPUNIT_ASSERT(test_ok_marshall == tmp);
}
/* --------------------------------------------------------------------- */
void test_xml()
{
string tmp;
t1->to_xml(tmp);
CPPUNIT_ASSERT(test_ok_xml == tmp);
}
/* --------------------------------------------------------------------- */
void test_str()
{
string tmp;
t1->to_str(tmp);
CPPUNIT_ASSERT(test_ok_str == tmp);
}
/* --------------------------------------------------------------------- */
void test_get()
{
vector<Attribute*> attrs;
string *tmp;
CPPUNIT_ASSERT(t1->get("DISK",attrs) == 2 );
CPPUNIT_ASSERT(attrs[0]->type() == Attribute::VECTOR);
tmp = attrs[0]->to_xml();
CPPUNIT_ASSERT( *tmp ==
"<DISK><EXTRA>disk attribute </EXTRA><FILE>path1</FILE></DISK>");
delete tmp;
CPPUNIT_ASSERT(attrs[1]->type() == Attribute::VECTOR);
tmp = attrs[1]->to_xml();
CPPUNIT_ASSERT( *tmp ==
"<DISK><EXTRA>str</EXTRA><FILE>path2</FILE><TYPE>disk</TYPE></DISK>");
delete tmp;
CPPUNIT_ASSERT(t1->get("CPU",attrs) == 1 );
CPPUNIT_ASSERT(attrs[2]->type() == Attribute::SIMPLE);
tmp = attrs[2]->to_xml();
CPPUNIT_ASSERT( *tmp == "<CPU>4</CPU>");
delete tmp;
string sval;
string sname = "REQUIREMENTS";
string iname = "MEMORY";
int ival;
t1->get(iname,ival);
t1->get(sname,sval);
CPPUNIT_ASSERT ( ival == 345 );
CPPUNIT_ASSERT ( sval == "HOSTNAME = \"host*.com\"");
}
/* --------------------------------------------------------------------- */
void test_remove()
{
vector<Attribute*> attrs;
string t1_xml;
string rm_xml="<TEMPLATE><CPU>4</CPU><EMPTY_VAR></EMPTY_VAR><GRAPHICS>"
"<PORT>12</PORT><VNC>127.0.0.1</VNC></GRAPHICS><MEMORY>345</MEMORY>"
"<REQUIREMENTS>HOSTNAME = \"host*.com\"</REQUIREMENTS></TEMPLATE>";
t1->remove("DISK",attrs);
t1->to_xml(t1_xml);
CPPUNIT_ASSERT(t1_xml == rm_xml);
delete attrs[0];
delete attrs[1];
}
/* --------------------------------------------------------------------- */
void test_set()
{
string t1_xml="<TEMPLATE><CPU>4</CPU><DISK><EXTRA>disk attribute </EXTRA>"
"<FILE>path1</FILE></DISK><DISK><EXTRA>str</EXTRA><FILE>path2</FILE>"
"<TYPE>disk</TYPE></DISK><EMPTY_VAR></EMPTY_VAR><GRAPHICS>"
"<PORT>12</PORT><VNC>127.0.0.1</VNC></GRAPHICS><MEMORY>345</MEMORY>"
"<REQUIREMENTS>HOSTNAME = \"host*.com\"</REQUIREMENTS>"
"<XTRA>44</XTRA></TEMPLATE>";
string xml;
string nattr = "XTRA";
string vattr = "44";
SingleAttribute *a = new SingleAttribute(nattr,vattr);
t1->set(a);
t1->to_xml(xml);
CPPUNIT_ASSERT(t1_xml == xml);
nattr = "CPU";
vattr = "5";
t1_xml="<TEMPLATE><CPU>4</CPU><CPU>5</CPU>"
"<DISK><EXTRA>disk attribute </EXTRA>"
"<FILE>path1</FILE></DISK><DISK><EXTRA>str</EXTRA><FILE>path2</FILE>"
"<TYPE>disk</TYPE></DISK><EMPTY_VAR></EMPTY_VAR><GRAPHICS>"
"<PORT>12</PORT><VNC>127.0.0.1</VNC></GRAPHICS><MEMORY>345</MEMORY>"
"<REQUIREMENTS>HOSTNAME = \"host*.com\"</REQUIREMENTS>"
"<XTRA>44</XTRA></TEMPLATE>";
SingleAttribute *b = new SingleAttribute(nattr,vattr);
t1->set(b);
t1->to_xml(xml);
CPPUNIT_ASSERT(t1_xml == xml);
string tr_xml="<TEMPLATE><CPU>5</CPU>"
"<DISK><EXTRA>str</EXTRA><FILE>path2</FILE>"
"<TYPE>disk</TYPE></DISK><EMPTY_VAR></EMPTY_VAR><GRAPHICS>"
"<PORT>12</PORT><VNC>127.0.0.1</VNC></GRAPHICS><MEMORY>345</MEMORY>"
"<REQUIREMENTS>HOSTNAME = \"host*.com\"</REQUIREMENTS></TEMPLATE>";
SingleAttribute *c = new SingleAttribute(nattr,vattr);
tr->set(c);
tr->to_xml(xml);
CPPUNIT_ASSERT(tr_xml == xml);
}
/* ********************************************************************* */
/* ********************************************************************* */
static CppUnit::TestSuite * suite()
{
CppUnit::TestSuite *ts=new CppUnit::TestSuite("Template Tests");
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"parse() Test",
&TemplateTest::test_parser));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"marshall() Test",
&TemplateTest::test_marshall));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"xml() Test",
&TemplateTest::test_xml));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"str() Test",
&TemplateTest::test_str));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"get() Test",
&TemplateTest::test_get));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"remove() Test",
&TemplateTest::test_remove));
ts->addTest(new CppUnit::TestCaller<TemplateTest>(
"set() Test",
&TemplateTest::test_set));
return ts;
}
};
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner tr;
tr.addTest(TemplateTest::suite());
tr.run();
return 0;
}

View File

@ -0,0 +1,220 @@
#include "TemplateSQL.h"
#include "SqliteDB.h"
#include "Log.h"
#include <string>
#include <iostream>
#include <unistd.h>
#include <TestFixture.h>
#include <TestAssert.h>
#include <TestSuite.h>
#include <TestCaller.h>
#include <ui/text/TestRunner.h>
using namespace std;
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
/* --------------------------------------- */
/* WRAPPER TO ACCESS TEMPLATESQL CLASS */
/* --------------------------------------- */
class TSQL : public TemplateSQL
{
public:
TSQL(const char * _table,
int template_id = -1,
bool replace = false,
const char separator = '=',
const char * xml_root = "TEMPLATE"):
TemplateSQL(_table,template_id,replace,separator,xml_root){}
~TSQL(){}
/* --------------------------------------------------------------------- */
int insert(SqliteDB * db){return TemplateSQL::insert(db);}
int update(SqliteDB * db){return TemplateSQL::update(db);}
int select(SqliteDB * db){return TemplateSQL::select(db);}
int drop (SqliteDB * db){return TemplateSQL::drop(db);}
/* --------------------------------------------------------------------- */
int replace_attribute(SqliteDB * db, Attribute * attr)
{return TemplateSQL::replace_attribute(db,attr);}
int insert_attribute(SqliteDB * db, Attribute * attr)
{return TemplateSQL::insert_attribute(db,attr);}
/* --------------------------------------------------------------------- */
int id(){return TemplateSQL::id;};
};
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
class TemplateSQLTest : public CppUnit::TestFixture
{
private:
SqliteDB *db;
TSQL *t;
string filename;
string template_ok;
string template_xml;
static void log(
const char * module,
const Log::MessageType type,
const ostringstream& message,
const char * filename = 0,
Log::MessageType clevel = Log::ERROR)
{
cerr << message.str() << endl;
};
public:
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
TemplateSQLTest()
{
filename = "template_sql.db";
template_ok =
"#This line is a comment\n"
" # Other comment\n"
"MEMORY=345 # more comments behind an attribute\n"
" CPU = 4\n"
"#------------------------------\n"
"#Comments in the middle\n"
"#------------------------------\n"
" empty_var = \n"
"REQUIREMENTS = \"HOSTNAME = \\\"host*.com\\\"\"\n"
" DISK= [file = path1, extra = \"disk attribute \"]\n"
"DISK =[ FILE = \"path2\", EXTRA = str, TYPE=disk]\n"
" graphics = [\n"
" VNC = \"127.0.0.1\",\n"
" PORT = 12\n"
" ]\n";
template_xml =
"<TEMPLATE><CPU>4</CPU><DISK><EXTRA>disk "
"attribute </EXTRA><FILE>path1</FILE></DISK><DISK><EXTRA>str"
"</EXTRA><FILE>path2</FILE>"
"<TYPE>disk</TYPE></DISK><EMPTY_VAR></EMPTY_VAR><GRAPHICS>"
"<PORT>12</PORT><VNC>127.0.0.1</VNC></GRAPHICS><MEMORY>345</MEMORY>"
"<REQUIREMENTS>HOSTNAME = \"host*.com\"</REQUIREMENTS></TEMPLATE>";
}
~TemplateSQLTest()
{
unlink("template_sql.db");
}
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
void setUp()
{
db = new SqliteDB (filename , TemplateSQLTest::log);
t = new TSQL("template");
}
void tearDown()
{
delete db;
delete t;
}
/* ********************************************************************* */
/* ********************************************************************* */
void test_bootstrap()
{
const char * db_bs = "CREATE TABLE template"
" (id INTEGER, name TEXT, type INTEGER, value TEXT)";
CPPUNIT_ASSERT( db->exec(db_bs) == 0);
}
/* --------------------------------------------------------------------- */
void test_insert()
{
char * error = 0;
int rc;
string tmp;
rc = t->parse(template_ok,&error);
if ( error != 0 )
{
cerr << error << endl;
free(error);
}
CPPUNIT_ASSERT( rc == 0);
CPPUNIT_ASSERT( t->insert(db) == 0 );
CPPUNIT_ASSERT( t->id() == 0 );
CPPUNIT_ASSERT( t->insert(db) == 0 );
CPPUNIT_ASSERT( t->id() == 1 );
CPPUNIT_ASSERT( t->insert(db) == 0 );
CPPUNIT_ASSERT( t->id() == 2 );
}
/* --------------------------------------------------------------------- */
void test_select()
{
TSQL t2("template",1);
string t2_xml;
CPPUNIT_ASSERT( t2.select(db) == 0 );
t2.to_xml(t2_xml);
CPPUNIT_ASSERT( t2_xml == template_xml );
}
/* ********************************************************************* */
/* ********************************************************************* */
static CppUnit::TestSuite * suite()
{
CppUnit::TestSuite *ts=new CppUnit::TestSuite("TemplateSQL Tests");
ts->addTest(new CppUnit::TestCaller<TemplateSQLTest>(
"db() Test",
&TemplateSQLTest::test_bootstrap));
ts->addTest(new CppUnit::TestCaller<TemplateSQLTest>(
"insert() Test",
&TemplateSQLTest::test_insert));
ts->addTest(new CppUnit::TestCaller<TemplateSQLTest>(
"update() Test",
&TemplateSQLTest::test_select));
return ts;
}
};
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner tr;
tr.addTest(TemplateSQLTest::suite());
tr.run();
return 0;
}

71
src/um/test/SConstruct Executable file
View File

@ -0,0 +1,71 @@
# --------------------------------------------------------------------------
# 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")
from lex_bison import *
# This is the absolute path where the project is located
cwd="../../../"
# 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 + '/include',
'/usr/include/cppunit/',
])
# Library dirs
main_env.Append(LIBPATH=[
cwd + '/src/common',
cwd + '/src/nebula',
cwd + '/src/pool',
cwd + '/src/um',
'/usr/include/openssl/',
])
main_env.Append(LIBS=[
'nebula_um',
'nebula_pool',
'nebula_common',
'nebula_core',
'cppunit',
'dl',
'pthread',
'sqlite3',
'crypto'
])
# Compile flags
main_env.Append(CPPFLAGS=[
"-g",
"-Wall"
])
# Linking flags
main_env.Append(LDFLAGS=["-g "])
main_env.Program('UserPoolTest.cc')

366
src/um/test/UserPoolTest.cc Executable file
View File

@ -0,0 +1,366 @@
/* -------------------------------------------------------------------------- */
/* 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 <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 "UserPool.h"
using namespace std;
/* ************************************************************************* */
/* ************************************************************************* */
class UserPoolTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (UserPoolTest);
CPPUNIT_TEST (sha1_digest);
CPPUNIT_TEST (initial_user);
CPPUNIT_TEST (authenticate);
CPPUNIT_TEST (get_from_cache);
CPPUNIT_TEST (get_from_db);
CPPUNIT_TEST (drop_and_get);
CPPUNIT_TEST (update);
CPPUNIT_TEST (dump);
CPPUNIT_TEST_SUITE_END ();
private:
UserPool * pool;
SqliteDB * db;
User* user;
public:
UserPoolTest(){};
~UserPoolTest(){};
void setUp()
{
string db_name = "test.db";
unlink("test.db");
db = new SqliteDB(db_name);
UserPool::bootstrap(db);
// The UserPool constructor checks if the DB contains at least
// one user, and adds one automatically from the ONE_AUTH file.
// So the ONE_AUTH environment is forced to point to a test one_auth
// file.
string pwd = getenv("PWD");
const char * auth = (pwd + "/one_auth").c_str();
setenv("ONE_AUTH", auth, 1);
pool = new UserPool(db);
};
void tearDown()
{
delete db;
delete pool;
remove ("test.db");
};
/* ********************************************************************* */
/* ********************************************************************* */
void sha1_digest()
{
string st = "top_secret_string";
string sha1 = "773260f433f7fd6f89c1f1bfc32e080fc0748478";
CPPUNIT_ASSERT( sha1 == User::sha1_digest(st) );
}
void initial_user()
{
// When creating a new pool, the constructor will check if the DB
// contains at least one user.
// If it doesn't, it adds one automatically from:
// * The $ONE_AUTH file.
// * The ~/.one/one_auth file.
// The ONE_AUTH environment variable was forced to point to a prepared
// one_auth file at set-up, so the pool should contain the user
// one_user_test:password
user = pool->get(0, false);
CPPUNIT_ASSERT(user != 0);
CPPUNIT_ASSERT( user->get_uid() == 0 );
CPPUNIT_ASSERT( user->get_username() == "one_user_test" );
CPPUNIT_ASSERT( user->get_password() == User::sha1_digest("password") );
}
void authenticate()
{
// There is an initial user, created with the one_auth file:
// one_user_test:password
string session =
"one_user_test:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8";
int oid = pool->authenticate( session );
CPPUNIT_ASSERT( oid == 0 );
session = "one_user_test:wrong_password";
oid = pool->authenticate( session );
CPPUNIT_ASSERT( oid == -1 );
session =
"unknown_user:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8";
oid = pool->authenticate( session );
CPPUNIT_ASSERT( oid == -1 );
}
// Try to allocate two objects, and retrieve them
void get_from_cache()
{
string username_1 = "A user";
string username_2 = "B user";
string pass_1 = "A pass";
string pass_2 = "B pass";
int oid_1, oid_2;
pool->allocate(&oid_1, username_1, pass_1, true);
// first element in the pool should have oid=1 (the 0th one is created
// by the UserPool constructor)
CPPUNIT_ASSERT(oid_1 == 1);
pool->allocate(&oid_2, username_2, pass_2, true);
// second element in the pool should have oid=2
CPPUNIT_ASSERT(oid_2 == 2);
// ---------------------------------
user = pool->get(oid_1, false);
CPPUNIT_ASSERT(user != 0);
CPPUNIT_ASSERT( user->get_uid() == 1 );
CPPUNIT_ASSERT( user->get_username() == username_1 );
CPPUNIT_ASSERT( user->get_password() == pass_1 );
// ---------------------------------
user = pool->get(oid_2, true);
CPPUNIT_ASSERT(user != 0);
CPPUNIT_ASSERT( user->get_uid() == 2 );
CPPUNIT_ASSERT( user->get_username() == username_2 );
CPPUNIT_ASSERT( user->get_password() == pass_2 );
user->unlock();
};
// Try to allocate two objects, and retrieve them
void get_from_db()
{
string username_1 = "A user";
string username_2 = "B user";
string pass_1 = "A pass";
string pass_2 = "B pass";
int oid_1, oid_2;
pool->allocate(&oid_1, username_1, pass_1, true);
pool->allocate(&oid_2, username_2, pass_2, true);
string str;
// Get the xml representation of the two users
string xml_1 = pool->get(oid_1, false)->to_xml(str);
string xml_2 = pool->get(oid_2, false)->to_xml(str);
// Clean the users from the cache, forcing the pool to read them from
// the DB when we retrieve them
pool->clean();
// ---------------------------------
user = pool->get(oid_1, false);
CPPUNIT_ASSERT(user != 0);
// The user objects constructed from the data in the DB should be the
// same as the previous ones
CPPUNIT_ASSERT(user->to_xml(str) == xml_1);
CPPUNIT_ASSERT(user->get_uid() == oid_1);
CPPUNIT_ASSERT(user->get_username() == username_1);
CPPUNIT_ASSERT(user->get_password() == pass_1);
// ---------------------------------
user = pool->get(oid_2, true);
CPPUNIT_ASSERT(user != 0);
CPPUNIT_ASSERT(user->to_xml(str) == xml_2);
CPPUNIT_ASSERT(user->get_uid() == oid_2);
CPPUNIT_ASSERT(user->get_username() == username_2);
CPPUNIT_ASSERT(user->get_password() == pass_2);
user->unlock();
};
void drop_and_get()
{
string username_1 = "A user";
string username_2 = "B user";
string pass_1 = "A pass";
string pass_2 = "B pass";
int oid_1, oid_2;
pool->allocate(&oid_1, username_1, pass_1, true);
pool->allocate(&oid_2, username_2, pass_2, true);
// Get the first user (A)
user = pool->get(oid_1,true);
CPPUNIT_ASSERT(user != 0);
// Delete it
pool->drop(user);
user->unlock();
// It should be gone now
user = pool->get(oid_1,true);
CPPUNIT_ASSERT(user == 0);
// The cache is cleaned, the user should be also gone from the DB
pool->clean();
user = pool->get(oid_1,true);
CPPUNIT_ASSERT(user == 0);
// But the other user must be accessible
user = pool->get(oid_2,false);
CPPUNIT_ASSERT(user != 0);
};
void update()
{
string username_1 = "A user";
string pass_1 = "A pass";
int oid_1, oid_2;
// Allocate some users, to popullate the DB
pool->allocate(&oid_2, "someone", pass_1, true);
pool->allocate(&oid_2, "some_user", pass_1, true);
// The user we are interested in
pool->allocate(&oid_1, username_1, pass_1, true);
// Some more users...
pool->allocate(&oid_2, "not_used", pass_1, true);
pool->allocate(&oid_2, "no_name", pass_1, true);
user = pool->get(oid_1, true);
// User object should be cached. Let's update its status
user->disable();
pool->update(user);
user->unlock();
// When the user is updated, there should be only one entry at the DB
vector<int> results;
int rc;
ostringstream oss;
oss << "oid = " << oid_1;
rc = pool->search(results,"user_pool", oss.str());
CPPUNIT_ASSERT(rc == 0);
CPPUNIT_ASSERT(results.size() == 1);
CPPUNIT_ASSERT(results.at(0) == oid_1);
user = pool->get(oid_1,false);
CPPUNIT_ASSERT( user->isEnabled() == false );
//Now force access to DB
pool->clean();
user = pool->get(oid_1,false);
CPPUNIT_ASSERT( user->isEnabled() == false );
};
void dump()
{
string xml_result =
"<USER_POOL><USER><ID>0</ID><NAME>one_user_test</NAME>"
"<PASSWORD>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</PASSWORD>"
"<ENABLED>True</ENABLED></USER><USER><ID>1</ID><NAME>a</NAME>"
"<PASSWORD>p</PASSWORD><ENABLED>True</ENABLED></USER><USER>"
"<ID>2</ID><NAME>a name</NAME><PASSWORD>pass</PASSWORD>"
"<ENABLED>True</ENABLED></USER><USER><ID>3</ID><NAME>a_name</NAME>"
"<PASSWORD>password</PASSWORD><ENABLED>True</ENABLED></USER><USER>"
"<ID>4</ID><NAME>another name</NAME><PASSWORD>secret</PASSWORD>"
"<ENABLED>True</ENABLED></USER><USER><ID>5</ID><NAME>user</NAME>"
"<PASSWORD>1234</PASSWORD><ENABLED>True</ENABLED></USER>"
"</USER_POOL>";
string names[] = {"a", "a name", "a_name", "another name", "user"};
string pass[] = {"p", "pass", "password", "secret", "1234"};
int oid;
for(int i=0; i<5; i++)
{
pool->allocate(&oid, names[i], pass[i], true);
}
ostringstream oss;
pool->dump(oss, "");
CPPUNIT_ASSERT( oss.str() == xml_result );
// Allocate and delete a new user
pool->allocate(&oid, "new name", "new pass", true);
user = pool->get(oid, true);
pool->drop(user);
user->unlock();
ostringstream new_oss;
pool->dump(new_oss, "");
CPPUNIT_ASSERT( new_oss.str() == xml_result );
}
};
/* ************************************************************************* */
/* ************************************************************************* */
/* ************************************************************************* */
int main(int argc, char ** argv)
{
CppUnit::TextUi::TestRunner runner;
runner.addTest( UserPoolTest::suite() );
runner.run();
return 0;
}

1
src/um/test/one_auth Normal file
View File

@ -0,0 +1 @@
one_user_test:password