diff --git a/include/Cluster.h b/include/Cluster.h
index d1c10c0760..a6e8415e06 100644
--- a/include/Cluster.h
+++ b/include/Cluster.h
@@ -20,6 +20,7 @@
#include "PoolSQL.h"
#include "ObjectCollection.h"
#include "DatastorePool.h"
+#include "ClusterTemplate.h"
using namespace std;
@@ -30,6 +31,23 @@ class Cluster : public PoolObjectSQL
{
public:
+ /**
+ * Returns the SYSTEM_DS attribute, or the system DS id if it is not defined
+ *
+ * @return the SYSTEM_DS attribute, or the system DS id if it is not defined
+ */
+ int get_ds_id()
+ {
+ int ds_id;
+
+ if ( obj_template->get("SYSTEM_DS", ds_id) == false )
+ {
+ ds_id = DatastorePool::SYSTEM_DS_ID;
+ }
+
+ return ds_id;
+ }
+
// *************************************************************************
// Object Collections (Public)
// *************************************************************************
@@ -78,6 +96,7 @@ public:
*/
int add_datastore(int id, string& error_msg)
{
+ // TODO: should fail for any system DS?
if ( id == DatastorePool::SYSTEM_DS_ID )
{
ostringstream oss;
@@ -184,11 +203,9 @@ private:
// Constructor
// *************************************************************************
- Cluster(int id, const string& name):
- PoolObjectSQL(id,CLUSTER,name,-1,-1,"","",table),
- hosts("HOSTS"),
- datastores("DATASTORES"),
- vnets("VNETS"){};
+ Cluster(int id,
+ const string& name,
+ ClusterTemplate* cl_template);
virtual ~Cluster(){};
@@ -259,6 +276,14 @@ private:
* @return 0 if cluster can be dropped, -1 otherwise
*/
int check_drop(string& error_msg);
+
+ /**
+ * Factory method for cluster templates
+ */
+ Template * get_new_template() const
+ {
+ return new ClusterTemplate;
+ }
};
#endif /*CLUSTER_H_*/
diff --git a/include/ClusterPool.h b/include/ClusterPool.h
index 365dac64e3..35712708ed 100644
--- a/include/ClusterPool.h
+++ b/include/ClusterPool.h
@@ -151,7 +151,7 @@ private:
*/
PoolObjectSQL * create()
{
- return new Cluster(-1,"");
+ return new Cluster(-1,"",0);
};
};
diff --git a/include/ClusterTemplate.h b/include/ClusterTemplate.h
new file mode 100644
index 0000000000..b317b2e592
--- /dev/null
+++ b/include/ClusterTemplate.h
@@ -0,0 +1,39 @@
+/* -------------------------------------------------------------------------- */
+/* Copyright 2002-2012, 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 CLUSTER_TEMPLATE_H_
+#define CLUSTER_TEMPLATE_H_
+
+#include "Template.h"
+
+using namespace std;
+
+/**
+ * Cluster Template class
+ */
+class ClusterTemplate : public Template
+{
+public:
+ ClusterTemplate():
+ Template(false,'=',"TEMPLATE"){};
+
+ ~ClusterTemplate(){};
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+#endif /*CLUSTER_TEMPLATE_H_*/
diff --git a/include/Datastore.h b/include/Datastore.h
index a18408b4df..2b03953032 100644
--- a/include/Datastore.h
+++ b/include/Datastore.h
@@ -91,6 +91,16 @@ public:
{
return disk_type;
};
+
+ /**
+ * Returns true if this is a system datastore
+ * @return true if this is a system datastore
+ */
+ bool is_system() const
+ {
+ return system_ds == 1;
+ };
+
/**
* Modifies the given VM disk attribute adding the relevant datastore
* attributes
@@ -134,6 +144,11 @@ private:
*/
string base_path;
+ /**
+ * 1 if this is a system DS
+ */
+ int system_ds;
+
/**
* Disk types for the Images created in this datastore
*/
@@ -203,7 +218,7 @@ private:
}
/**
- * Factory method for virtual network templates
+ * Factory method for datastore templates
*/
Template * get_new_template() const
{
diff --git a/include/History.h b/include/History.h
index 952320e62c..f9a9dd9b71 100644
--- a/include/History.h
+++ b/include/History.h
@@ -46,6 +46,8 @@ public:
const string& hostname,
const string& vmm,
const string& vnm,
+ const string& tmm,
+ int ds_id,
const string& vm_info);
~History(){};
@@ -89,6 +91,9 @@ private:
string vmm_mad_name;
string vnm_mad_name;
+ string tm_mad_name;
+
+ int ds_id;
time_t stime;
time_t etime;
diff --git a/include/Nebula.h b/include/Nebula.h
index 1bab2d21b6..a3aa35b781 100644
--- a/include/Nebula.h
+++ b/include/Nebula.h
@@ -243,30 +243,6 @@ public:
return ds_location;
};
- /**
- * Returns the Transfer Manager for the system datastore
- * @return the tm name.
- */
- string get_system_ds_tm_mad()
- {
- Datastore * ds;
- string tm_mad = "";
-
- ds = dspool->get(DatastorePool::SYSTEM_DS_ID, true);
-
- if ( ds == 0 )
- {
- NebulaLog::log("DaS", Log::ERROR, "Can not get system datastore");
- return tm_mad;
- }
-
- tm_mad = ds->get_tm_mad();
-
- ds->unlock();
-
- return tm_mad;
- };
-
/**
* Returns the path of the log file for a VM, depending where OpenNebula is
* installed,
diff --git a/include/RequestManagerUpdateTemplate.h b/include/RequestManagerUpdateTemplate.h
index 73880f540e..511f149ce7 100644
--- a/include/RequestManagerUpdateTemplate.h
+++ b/include/RequestManagerUpdateTemplate.h
@@ -170,6 +170,24 @@ public:
~DocumentUpdateTemplate(){};
};
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+
+class ClusterUpdateTemplate : public RequestManagerUpdateTemplate
+{
+public:
+ ClusterUpdateTemplate():
+ RequestManagerUpdateTemplate("ClusterUpdateTemplate",
+ "Updates a cluster template")
+ {
+ Nebula& nd = Nebula::instance();
+ pool = nd.get_clpool();
+ auth_object = PoolObjectSQL::CLUSTER;
+ };
+
+ ~ClusterUpdateTemplate(){};
+};
+
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h
index 10b415352d..284469508e 100644
--- a/include/RequestManagerVirtualMachine.h
+++ b/include/RequestManagerVirtualMachine.h
@@ -57,13 +57,16 @@ protected:
AuthRequest::Operation op);
int get_host_information(int hid, string& name, string& vmm, string& vnm,
- RequestAttributes& att, PoolObjectAuth& host_perms);
+ string& tm, int& ds_id, RequestAttributes& att,
+ PoolObjectAuth& host_perms);
int add_history(VirtualMachine * vm,
int hid,
const string& hostname,
const string& vmm_mad,
const string& vnm_mad,
+ const string& tm_mad,
+ int ds_id,
RequestAttributes& att);
VirtualMachine * get_vm(int id, RequestAttributes& att);
diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h
index 7a16a92e3a..8902f58913 100644
--- a/include/VirtualMachine.h
+++ b/include/VirtualMachine.h
@@ -242,7 +242,9 @@ public:
int hid,
const string& hostname,
const string& vmm_mad,
- const string& vnm_mad);
+ const string& vnm_mad,
+ const string& tm_mad,
+ int ds_id);
/**
* Duplicates the last history record. Only the host related fields are
@@ -318,6 +320,55 @@ public:
return previous_history->vnm_mad_name;
};
+
+ /**
+ * Returns the datastore ID of the system DS for the host. The hasHistory()
+ * function MUST be called before this one.
+ * @return the ds id
+ */
+ string get_ds_id() const
+ {
+ ostringstream oss;
+
+ oss << history->ds_id;
+
+ return oss.str();
+ };
+
+ /**
+ * Returns the datastore ID of the system DS for the previous host.
+ * The hasPreviousHistory() function MUST be called before this one.
+ * @return the TM mad name
+ */
+ string get_previous_ds_id() const
+ {
+ ostringstream oss;
+
+ oss << previous_history->ds_id;
+
+ return oss.str();
+ };
+
+ /**
+ * Returns the TM driver name for the current host. The hasHistory()
+ * function MUST be called before this one.
+ * @return the TM mad name
+ */
+ const string & get_tm_mad() const
+ {
+ return history->tm_mad_name;
+ };
+
+ /**
+ * Returns the TM driver name for the previous host. The
+ * hasPreviousHistory() function MUST be called before this one.
+ * @return the TM mad name
+ */
+ const string & get_previous_tm_mad() const
+ {
+ return previous_history->tm_mad_name;
+ };
+
/**
* Returns the transfer filename. The transfer file is in the form:
* $ONE_LOCATION/var/$VM_ID/transfer.$SEQ
diff --git a/install.sh b/install.sh
index 02743f1165..c0bc6a0712 100755
--- a/install.sh
+++ b/install.sh
@@ -925,6 +925,7 @@ ONEDB_MIGRATOR_FILES="src/onedb/2.0_to_2.9.80.rb \
src/onedb/3.3.80_to_3.4.0.rb \
src/onedb/3.4.0_to_3.4.1.rb \
src/onedb/3.4.1_to_3.5.80.rb \
+ src/onedb/3.5.80_to_3.6.0.rb \
src/onedb/onedb.rb \
src/onedb/onedb_backend.rb"
diff --git a/share/doc/xsd/acct.xsd b/share/doc/xsd/acct.xsd
index 3a96b5d37a..e8ff06e4c9 100644
--- a/share/doc/xsd/acct.xsd
+++ b/share/doc/xsd/acct.xsd
@@ -21,6 +21,8 @@
+
+
diff --git a/share/doc/xsd/cluster.xsd b/share/doc/xsd/cluster.xsd
index 17df53e31f..7fdacacb8d 100644
--- a/share/doc/xsd/cluster.xsd
+++ b/share/doc/xsd/cluster.xsd
@@ -27,6 +27,7 @@
+
diff --git a/share/doc/xsd/datastore.xsd b/share/doc/xsd/datastore.xsd
index c1f5dfac98..e3a0788e83 100644
--- a/share/doc/xsd/datastore.xsd
+++ b/share/doc/xsd/datastore.xsd
@@ -28,6 +28,7 @@
+
diff --git a/share/doc/xsd/test.sh b/share/doc/xsd/test.sh
index ede292192a..50d77e06a5 100755
--- a/share/doc/xsd/test.sh
+++ b/share/doc/xsd/test.sh
@@ -33,8 +33,8 @@ onegroup create newgroup
# Host
-onehost create host01 --im im_test --vm vmm_test --net dummy
-onehost create host02 --im im_test --vm vmm_test --net dummy
+onehost create host01 --im im_dummy --vm vmm_dummy --net dummy
+onehost create host02 --im im_dummy --vm vmm_dummy --net dummy
onecluster addhost newcluster host02
diff --git a/share/doc/xsd/vm.xsd b/share/doc/xsd/vm.xsd
index 134f196d2d..81155bd02b 100644
--- a/share/doc/xsd/vm.xsd
+++ b/share/doc/xsd/vm.xsd
@@ -95,6 +95,8 @@
+
+
diff --git a/src/cli/one_helper/onecluster_helper.rb b/src/cli/one_helper/onecluster_helper.rb
index aca9f36d6c..41028cb90a 100644
--- a/src/cli/one_helper/onecluster_helper.rb
+++ b/src/cli/one_helper/onecluster_helper.rb
@@ -99,6 +99,11 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper
puts str % ["NAME", cluster.name]
puts
+ CLIHelper.print_header(str_h1 % "CLUSTER TEMPLATE", false)
+ puts cluster.template_str
+
+ puts
+
CLIHelper.print_header("%-15s" % ["HOSTS"])
cluster.host_ids.each do |id|
puts "%-15s" % [id]
diff --git a/src/cli/onecluster b/src/cli/onecluster
index 8cb5ac0dd3..6497e6b34e 100755
--- a/src/cli/onecluster
+++ b/src/cli/onecluster
@@ -173,4 +173,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
cluster.delvnet(args[1].to_i)
end
end
+
+ update_desc = <<-EOT.unindent
+ Update the template contents. If a path is not provided the editor will
+ be launched to modify the current content.
+ EOT
+
+ command :update, update_desc, :clusterid, [:file, nil] do
+ helper.perform_action(args[0],options,"modified") do |obj|
+ str = OpenNebulaHelper.update_template(args[0], obj, args[1])
+ obj.update(str)
+ end
+ end
end
diff --git a/src/cluster/Cluster.cc b/src/cluster/Cluster.cc
index 78b93ddd28..501c9fa5a2 100644
--- a/src/cluster/Cluster.cc
+++ b/src/cluster/Cluster.cc
@@ -33,6 +33,29 @@ const char * Cluster::db_bootstrap = "CREATE TABLE IF NOT EXISTS cluster_pool ("
"gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, "
"UNIQUE(name))";
+/* ************************************************************************ */
+/* Cluster :: Constructor/Destructor */
+/* ************************************************************************ */
+
+Cluster::Cluster(
+ int id,
+ const string& name,
+ ClusterTemplate* cl_template):
+ PoolObjectSQL(id,CLUSTER,name,-1,-1,"","",table),
+ hosts("HOSTS"),
+ datastores("DATASTORES"),
+ vnets("VNETS")
+{
+ if (cl_template != 0)
+ {
+ obj_template = cl_template;
+ }
+ else
+ {
+ obj_template = new ClusterTemplate;
+ }
+}
+
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
@@ -170,6 +193,7 @@ string& Cluster::to_xml(string& xml) const
string host_collection_xml;
string ds_collection_xml;
string vnet_collection_xml;
+ string template_xml;
oss <<
"" <<
@@ -179,7 +203,7 @@ string& Cluster::to_xml(string& xml) const
hosts.to_xml(host_collection_xml) <<
datastores.to_xml(ds_collection_xml) <<
vnets.to_xml(vnet_collection_xml) <<
-
+ obj_template->to_xml(template_xml) <<
"";
xml = oss.str();
@@ -256,6 +280,18 @@ int Cluster::from_xml(const string& xml)
ObjectXML::free_nodes(content);
content.clear();
+ // Get associated classes
+ ObjectXML::get_nodes("/CLUSTER/TEMPLATE", content);
+
+ if (content.empty())
+ {
+ return -1;
+ }
+
+ rc += obj_template->from_xml_node(content[0]);
+
+ ObjectXML::free_nodes(content);
+
if (rc != 0)
{
return -1;
diff --git a/src/cluster/ClusterPool.cc b/src/cluster/ClusterPool.cc
index 61d48d2aea..b3ff69e26c 100644
--- a/src/cluster/ClusterPool.cc
+++ b/src/cluster/ClusterPool.cc
@@ -72,7 +72,7 @@ int ClusterPool::allocate(string name, int * oid, string& error_str)
}
// Build a new Cluster object
- cluster = new Cluster(-1, name);
+ cluster = new Cluster(-1, name, 0);
// Insert the Object in the pool
*oid = PoolSQL::allocate(cluster, error_str);
diff --git a/src/datastore/Datastore.cc b/src/datastore/Datastore.cc
index 8b40ddc925..bfed67afaa 100644
--- a/src/datastore/Datastore.cc
+++ b/src/datastore/Datastore.cc
@@ -19,6 +19,8 @@
#include "NebulaLog.h"
#include "Nebula.h"
+#define TO_UPPER(S) transform(S.begin(),S.end(),S.begin(),(int(*)(int))toupper)
+
const char * Datastore::table = "datastore_pool";
const char * Datastore::db_names =
@@ -47,7 +49,8 @@ Datastore::Datastore(
Clusterable(cluster_id, cluster_name),
ds_mad(""),
tm_mad(""),
- base_path("")
+ base_path(""),
+ system_ds(0)
{
group_u = 1;
@@ -97,6 +100,7 @@ int Datastore::insert(SqlDB *db, string& error_str)
int rc;
ostringstream oss;
string s_disk_type;
+ string s_system_ds;
Nebula& nd = Nebula::instance();
@@ -108,8 +112,22 @@ int Datastore::insert(SqlDB *db, string& error_str)
// NAME is checked in DatastorePool::allocate
get_template_attribute("DS_MAD", ds_mad);
+ get_template_attribute("SYSTEM", s_system_ds);
- if ( ds_mad.empty() == true )
+ TO_UPPER(s_system_ds);
+
+ system_ds = (s_system_ds == "YES");
+
+ if ( system_ds == 1 )
+ {
+ if ( !ds_mad.empty() )
+ {
+ goto error_exclusive;
+ }
+
+ ds_mad = "-";
+ }
+ else if ( ds_mad.empty() == true )
{
goto error_ds;
}
@@ -152,6 +170,10 @@ int Datastore::insert(SqlDB *db, string& error_str)
return rc;
+error_exclusive:
+ error_str = "SYSTEM datastores cannot have DS_MAD defined.";
+ goto error_common;
+
error_ds:
error_str = "No DS_MAD in template.";
goto error_common;
@@ -273,6 +295,7 @@ string& Datastore::to_xml(string& xml) const
"" << ds_mad << "" <<
"" << tm_mad << "" <<
"" << base_path << "" <<
+ "" << system_ds << "" <<
"" << disk_type << "" <<
"" << cluster_id << "" <<
"" << cluster << "" <<
@@ -307,6 +330,7 @@ int Datastore::from_xml(const string& xml)
rc += xpath(ds_mad, "/DATASTORE/DS_MAD", "not_found");
rc += xpath(tm_mad, "/DATASTORE/TM_MAD", "not_found");
rc += xpath(base_path, "/DATASTORE/BASE_PATH", "not_found");
+ rc += xpath(system_ds, "/DATASTORE/SYSTEM", -1);
rc += xpath(int_disk_type,"/DATASTORE/DISK_TYPE", -1);
rc += xpath(cluster_id, "/DATASTORE/CLUSTER_ID", -1);
@@ -354,14 +378,15 @@ int Datastore::from_xml(const string& xml)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-int Datastore::replace_template(const string& tmpl_str, string& error)
+int Datastore::replace_template(const string& tmpl_str, string& error_str)
{
string new_ds_mad;
string new_tm_mad;
+ string s_system_ds;
int rc;
- rc = PoolObjectSQL::replace_template(tmpl_str, error);
+ rc = PoolObjectSQL::replace_template(tmpl_str, error_str);
if ( rc != 0 )
{
@@ -369,15 +394,37 @@ int Datastore::replace_template(const string& tmpl_str, string& error)
}
get_template_attribute("DS_MAD", new_ds_mad);
+ get_template_attribute("SYSTEM", s_system_ds);
+
+
+ if ( oid == DatastorePool::SYSTEM_DS_ID )
+ {
+ system_ds = 1;
+ }
+ else if ( !s_system_ds.empty() )
+ {
+ TO_UPPER(s_system_ds);
+
+ system_ds = (s_system_ds == "YES");
+ }
+
+ if ( system_ds == 1 )
+ {
+ replace_template_attribute("SYSTEM", "YES");
+
+ new_ds_mad = "-";
+ }
+ else
+ {
+ obj_template->erase("SYSTEM");
+ }
if ( !new_ds_mad.empty() )
{
ds_mad = new_ds_mad;
}
- else
- {
- replace_template_attribute("DS_MAD", ds_mad);
- }
+
+ replace_template_attribute("DS_MAD", ds_mad);
get_template_attribute("TM_MAD", new_tm_mad);
diff --git a/src/datastore/DatastorePool.cc b/src/datastore/DatastorePool.cc
index b38318fc04..c8639eca69 100644
--- a/src/datastore/DatastorePool.cc
+++ b/src/datastore/DatastorePool.cc
@@ -53,7 +53,7 @@ DatastorePool::DatastorePool(SqlDB * db):
// ---------------------------------------------------------------------
oss << "NAME = " << SYSTEM_DS_NAME << endl
- << "DS_MAD = -" << endl
+ << "SYSTEM = YES" << endl
<< "TM_MAD = shared";
ds_tmpl = new DatastoreTemplate;
diff --git a/src/oca/java/src/org/opennebula/client/cluster/Cluster.java b/src/oca/java/src/org/opennebula/client/cluster/Cluster.java
index fdf1b75703..1edbe4a934 100644
--- a/src/oca/java/src/org/opennebula/client/cluster/Cluster.java
+++ b/src/oca/java/src/org/opennebula/client/cluster/Cluster.java
@@ -30,6 +30,7 @@ public class Cluster extends PoolElement{
private static final String ALLOCATE = METHOD_PREFIX + "allocate";
private static final String DELETE = METHOD_PREFIX + "delete";
private static final String INFO = METHOD_PREFIX + "info";
+ private static final String UPDATE = METHOD_PREFIX + "update";
private static final String ADDHOST = METHOD_PREFIX + "addhost";
private static final String DELHOST = METHOD_PREFIX + "delhost";
private static final String ADDDATASTORE = METHOD_PREFIX + "adddatastore";
@@ -99,6 +100,19 @@ public class Cluster extends PoolElement{
return client.call(DELETE, id);
}
+ /**
+ * Replaces the cluster contents.
+ *
+ * @param client XML-RPC Client.
+ * @param id The id of the target cluster we want to modify.
+ * @param new_template New template contents.
+ * @return If successful the message contains the cluster id.
+ */
+ public static OneResponse update(Client client, int id, String new_template)
+ {
+ return client.call(UPDATE, id, new_template);
+ }
+
/**
* Adds a Host to this Cluster
*
@@ -210,6 +224,17 @@ public class Cluster extends PoolElement{
return delete(client, id);
}
+ /**
+ * Replaces the cluster template.
+ *
+ * @param new_template New cluster template.
+ * @return If successful the message contains the cluster id.
+ */
+ public OneResponse update(String new_template)
+ {
+ return update(client, id, new_template);
+ }
+
/**
* Adds a Host to this Cluster
*
diff --git a/src/oca/ruby/OpenNebula/Cluster.rb b/src/oca/ruby/OpenNebula/Cluster.rb
index cdec2f5703..e6abb4c7a3 100644
--- a/src/oca/ruby/OpenNebula/Cluster.rb
+++ b/src/oca/ruby/OpenNebula/Cluster.rb
@@ -32,7 +32,8 @@ module OpenNebula
:adddatastore => "cluster.adddatastore",
:deldatastore => "cluster.deldatastore",
:addvnet => "cluster.addvnet",
- :delvnet => "cluster.delvnet"
+ :delvnet => "cluster.delvnet",
+ :update => "cluster.update",
}
# Creates a Cluster description with just its identifier
@@ -156,6 +157,16 @@ module OpenNebula
return rc
end
+ # Replaces the template contents
+ #
+ # @param new_template [String] New template contents
+ #
+ # @return [nil, OpenNebula::Error] nil in case of success, Error
+ # otherwise
+ def update(new_template)
+ super(CLUSTER_METHODS[:update], new_template)
+ end
+
# ---------------------------------------------------------------------
# Helpers to get information
# ---------------------------------------------------------------------
diff --git a/src/onedb/3.5.80_to_3.6.0.rb b/src/onedb/3.5.80_to_3.6.0.rb
new file mode 100644
index 0000000000..cf8b892eb9
--- /dev/null
+++ b/src/onedb/3.5.80_to_3.6.0.rb
@@ -0,0 +1,146 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2002-2012, 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. #
+#--------------------------------------------------------------------------- #
+
+require "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.6.0"
+ end
+
+ def one_version
+ "OpenNebula 3.6.0"
+ end
+
+ def up
+
+ @db.run "ALTER TABLE cluster_pool RENAME TO old_cluster_pool;"
+ @db.run "CREATE TABLE cluster_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_cluster_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("TEMPLATE")
+
+ @db[:cluster_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_cluster_pool;"
+
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ system_tm = ""
+
+ @db.fetch("SELECT * FROM old_datastore_pool WHERE oid = 0") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.each_element("TM_MAD") { |e|
+ system_tm = e.text
+ }
+
+ doc.root.add_element("SYSTEM").text = "1"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.fetch("SELECT * FROM old_datastore_pool WHERE oid > 0") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("SYSTEM").text = "0"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.each_element("HISTORY_RECORDS/HISTORY") { |e|
+ e.add_element("TMMAD").text = system_tm
+ e.add_element("DS_ID").text = "0"
+ }
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body TEXT, stime INTEGER, etime INTEGER, PRIMARY KEY(vid,seq));"
+
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("TMMAD").text = system_tm
+ doc.root.add_element("DS_ID").text = "0"
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => row[:stime],
+ :etime => row[:etime])
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+ return true
+ end
+end
diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc
index a349134855..4c2135785b 100644
--- a/src/rm/RequestManager.cc
+++ b/src/rm/RequestManager.cc
@@ -268,6 +268,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr user_update(new UserUpdateTemplate());
xmlrpc_c::methodPtr datastore_update(new DatastoreUpdateTemplate());
xmlrpc_c::methodPtr doc_update(new DocumentUpdateTemplate());
+ xmlrpc_c::methodPtr cluster_update(new ClusterUpdateTemplate());
// Allocate Methods
xmlrpc_c::methodPtr vm_allocate(new VirtualMachineAllocate());
@@ -468,6 +469,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.cluster.allocate",cluster_allocate);
RequestManagerRegistry.addMethod("one.cluster.delete", cluster_delete);
RequestManagerRegistry.addMethod("one.cluster.info", cluster_info);
+ RequestManagerRegistry.addMethod("one.cluster.update", cluster_update);
RequestManagerRegistry.addMethod("one.cluster.addhost", cluster_addhost);
RequestManagerRegistry.addMethod("one.cluster.delhost", cluster_delhost);
diff --git a/src/rm/RequestManagerAllocate.cc b/src/rm/RequestManagerAllocate.cc
index 3f05704c5f..2da96e857b 100644
--- a/src/rm/RequestManagerAllocate.cc
+++ b/src/rm/RequestManagerAllocate.cc
@@ -322,17 +322,6 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
// ------------------------- Check Datastore exists ------------------------
- if ( ds_id == DatastorePool::SYSTEM_DS_ID )
- {
- ostringstream oss;
-
- oss << "New images cannot be allocated in the system datastore.";
- failure_response(INTERNAL, allocate_error(oss.str()), att);
-
- delete tmpl;
- return;
- }
-
if ((ds = dspool->get(ds_id,true)) == 0 )
{
failure_response(NO_EXISTS,
@@ -343,6 +332,20 @@ void ImageAllocate::request_execute(xmlrpc_c::paramList const& params,
return;
}
+ if ( ds->is_system() )
+ {
+ ostringstream oss;
+
+ ds->unlock();
+
+ oss << "New images cannot be allocated in a system datastore.";
+ failure_response(INTERNAL, allocate_error(oss.str()), att);
+
+ delete tmpl;
+
+ return;
+ }
+
ds->get_permissions(ds_perms);
ds_name = ds->get_name();
diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc
index d4d7e7cd39..eea341cfc6 100644
--- a/src/rm/RequestManagerVirtualMachine.cc
+++ b/src/rm/RequestManagerVirtualMachine.cc
@@ -99,13 +99,19 @@ int RequestManagerVirtualMachine::get_host_information(int hid,
string& name,
string& vmm,
string& vnm,
+ string& tm,
+ int& ds_id,
RequestAttributes& att,
PoolObjectAuth& host_perms)
{
Nebula& nd = Nebula::instance();
HostPool * hpool = nd.get_hpool();
- Host * host;
+ Host * host;
+ Cluster * cluster;
+ Datastore * ds;
+
+ int cluster_id;
host = hpool->get(hid,true);
@@ -124,8 +130,65 @@ int RequestManagerVirtualMachine::get_host_information(int hid,
host->get_permissions(host_perms);
+ cluster_id = host->get_cluster_id();
+
host->unlock();
+ if ( cluster_id != -1 )
+ {
+ cluster = nd.get_clpool()->get(cluster_id, true);
+
+ if ( cluster == 0 )
+ {
+ failure_response(NO_EXISTS,
+ get_error(object_name(PoolObjectSQL::CLUSTER),cluster_id),
+ att);
+
+ return -1;
+ }
+
+ ds_id = cluster->get_ds_id();
+
+ cluster->unlock();
+ }
+ else
+ {
+ ds_id = DatastorePool::SYSTEM_DS_ID;
+ }
+
+ ds = nd.get_dspool()->get(ds_id, true);
+
+ if ( ds == 0 )
+ {
+ failure_response(NO_EXISTS,
+ get_error(object_name(PoolObjectSQL::DATASTORE),ds_id),
+ att);
+
+ return -1;
+ }
+
+ if ( ds->is_system() == false )
+ {
+ ostringstream oss;
+
+ ds->unlock();
+
+ oss << object_name(PoolObjectSQL::CLUSTER)
+ << " [" << cluster_id << "] has its SYSTEM_DS set to "
+ << object_name(PoolObjectSQL::DATASTORE)
+ << " [" << ds_id << "], but it is not a system one.";
+
+ failure_response(INTERNAL,
+ request_error(oss.str(),""),
+ att);
+
+ return -1;
+ }
+
+ tm = ds->get_tm_mad();
+
+ ds->unlock();
+
return 0;
}
@@ -156,6 +219,8 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm,
const string& hostname,
const string& vmm_mad,
const string& vnm_mad,
+ const string& tm_mad,
+ int ds_id,
RequestAttributes& att)
{
string vmdir;
@@ -163,7 +228,7 @@ int RequestManagerVirtualMachine::add_history(VirtualMachine * vm,
VirtualMachinePool * vmpool = static_cast(pool);
- vm->add_history(hid,hostname,vmm_mad,vnm_mad);
+ vm->add_history(hid,hostname,vmm_mad,vnm_mad,tm_mad,ds_id);
rc = vmpool->update_history(vm);
@@ -308,13 +373,16 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
string hostname;
string vmm_mad;
string vnm_mad;
+ string tm_mad;
+ int ds_id;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
bool auth = false;
- if (get_host_information(hid,hostname,vmm_mad,vnm_mad,att, host_perms) != 0)
+ if (get_host_information(
+ hid,hostname,vmm_mad,vnm_mad,tm_mad, ds_id, att, host_perms) != 0)
{
return;
}
@@ -341,7 +409,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
return;
}
- if ( add_history(vm,hid,hostname,vmm_mad,vnm_mad,att) != 0)
+ if ( add_history(vm,hid,hostname,vmm_mad,vnm_mad,tm_mad,ds_id,att) != 0)
{
vm->unlock();
return;
@@ -369,6 +437,8 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
string hostname;
string vmm_mad;
string vnm_mad;
+ string tm_mad;
+ int ds_id;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int hid = xmlrpc_c::value_int(paramList.getInt(2));
@@ -376,7 +446,8 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
bool auth = false;
- if (get_host_information(hid,hostname,vmm_mad,vnm_mad,att, host_perms) != 0)
+ if (get_host_information(
+ hid,hostname,vmm_mad,vnm_mad,tm_mad,ds_id, att, host_perms) != 0)
{
return;
}
@@ -405,7 +476,7 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
return;
}
- if ( add_history(vm,hid,hostname,vmm_mad,vnm_mad,att) != 0)
+ if ( add_history(vm,hid,hostname,vmm_mad,vnm_mad,tm_mad,ds_id,att) != 0)
{
vm->unlock();
return;
diff --git a/src/tm/TransferManager.cc b/src/tm/TransferManager.cc
index 1862dbaf3b..d31f81cd2e 100644
--- a/src/tm/TransferManager.cc
+++ b/src/tm/TransferManager.cc
@@ -212,7 +212,7 @@ void TransferManager::do_action(const string &action, void * arg)
int TransferManager::prolog_transfer_command(
VirtualMachine * vm,
const VectorAttribute * disk,
- string& system_tm_mad,
+ string& vm_tm_mad,
string& opennebula_hostname,
ostream& xfr,
ostringstream& os)
@@ -248,7 +248,7 @@ int TransferManager::prolog_transfer_command(
//MKSWAP tm_mad size host:remote_system_dir/disk.i vmid dsid(=0)
xfr << "MKSWAP "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< size << " "
<< vm->get_hostname() << ":"
<< vm->get_remote_system_dir() << "/disk." << disk_index << " "
@@ -273,7 +273,7 @@ int TransferManager::prolog_transfer_command(
//MKIMAGE tm_mad size format host:remote_system_dir/disk.i vmid dsid(=0)
xfr << "MKIMAGE "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< size << " "
<< format << " "
<< vm->get_hostname() << ":"
@@ -356,7 +356,7 @@ void TransferManager::prolog_action(int vid)
const VectorAttribute * disk;
string files;
- string system_tm_mad;
+ string vm_tm_mad;
string opennebula_hostname;
int rc;
string error_str;
@@ -374,17 +374,6 @@ void TransferManager::prolog_action(int vid)
// -------------------------------------------------------------------------
// Setup & Transfer script
// -------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "prolog, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -397,6 +386,14 @@ void TransferManager::prolog_action(int vid)
goto error_history;
}
+ vm_tm_mad = vm->get_tm_mad();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() )
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".prolog";
xfr.open(xfr_name.c_str(), ios::out | ios::trunc);
@@ -423,7 +420,7 @@ void TransferManager::prolog_action(int vid)
rc = prolog_transfer_command(vm,
disk,
- system_tm_mad,
+ vm_tm_mad,
opennebula_hostname,
xfr,
os);
@@ -447,7 +444,7 @@ void TransferManager::prolog_action(int vid)
{
//CONTEXT tm_mad files hostname:remote_system_dir/disk.i vmid dsid(=0)
xfr << "CONTEXT "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< vm->get_context_file() << " ";
if (!files.empty())
@@ -472,6 +469,11 @@ error_history:
os << "VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "prolog, error getting drivers.";
+ goto error_common;
+
error_file:
os << "could not open file: " << xfr_name;
goto error_common;
@@ -497,6 +499,19 @@ error_common:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
+static bool isVolatile(const VectorAttribute * disk)
+{
+ string type;
+
+ type = disk->vector_value("TYPE");
+ transform(type.begin(),type.end(),type.begin(),(int(*)(int))toupper);
+
+ return ( type == "SWAP" || type == "FS");
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
void TransferManager::prolog_migr_action(int vid)
{
ofstream xfr;
@@ -505,7 +520,8 @@ void TransferManager::prolog_migr_action(int vid)
const VectorAttribute * disk;
string tm_mad;
- string system_tm_mad;
+ string vm_tm_mad;
+ string vm_ds_id;
string ds_id;
int disk_id;
@@ -520,17 +536,6 @@ void TransferManager::prolog_migr_action(int vid)
// -------------------------------------------------------------------------
// Setup & Transfer script
// -------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "prolog_migr, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -538,11 +543,20 @@ void TransferManager::prolog_migr_action(int vid)
return;
}
- if (!vm->hasHistory())
+ if (!vm->hasHistory() || !vm->hasPreviousHistory())
{
goto error_history;
}
+ vm_tm_mad = vm->get_tm_mad();
+ vm_ds_id = vm->get_ds_id();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() || vm_ds_id.empty())
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".migrate";
xfr.open(xfr_name.c_str(), ios::out | ios::trunc);
@@ -566,13 +580,22 @@ void TransferManager::prolog_migr_action(int vid)
continue;
}
- tm_mad = disk->vector_value("TM_MAD");
- ds_id = disk->vector_value("DATASTORE_ID");
disk->vector_value_str("DISK_ID", disk_id);
- if ( tm_mad.empty() || ds_id.empty() )
+ if ( isVolatile(disk) == true )
{
- continue;
+ tm_mad = vm_tm_mad;
+ ds_id = vm_ds_id;
+ }
+ else
+ {
+ tm_mad = disk->vector_value("TM_MAD");
+ ds_id = disk->vector_value("DATASTORE_ID");
+
+ if ( tm_mad.empty() || ds_id.empty() )
+ {
+ continue;
+ }
}
//MV tm_mad prev_host:remote_system_dir/disk.i host:remote_system_dir/disk.i vmid dsid
@@ -588,13 +611,13 @@ void TransferManager::prolog_migr_action(int vid)
//MV tm_mad prev_host:remote_system_dir host:remote_system_dir VMID 0
xfr << "MV "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< vm->get_previous_hostname() << ":"
<< vm->get_remote_system_dir() << " "
<< vm->get_hostname() << ":"
<< vm->get_remote_system_dir() << " "
<< vm->get_oid() << " "
- << "0" << endl;
+ << vm_ds_id << endl;
xfr.close();
@@ -608,6 +631,11 @@ error_history:
os << "prolog_migr, VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "prolog_migr, error getting drivers.";
+ goto error_common;
+
error_file:
os.str("");
os << "prolog_migr, could not open file: " << xfr_name;
@@ -632,7 +660,8 @@ void TransferManager::prolog_resume_action(int vid)
const VectorAttribute * disk;
string tm_mad;
- string system_tm_mad;
+ string vm_tm_mad;
+ string vm_ds_id;
string ds_id;
int disk_id;
@@ -647,17 +676,6 @@ void TransferManager::prolog_resume_action(int vid)
// -------------------------------------------------------------------------
// Setup & Transfer script
// -------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "prolog_resume, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::PROLOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -670,6 +688,15 @@ void TransferManager::prolog_resume_action(int vid)
goto error_history;
}
+ vm_tm_mad = vm->get_tm_mad();
+ vm_ds_id = vm->get_ds_id();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() || vm_ds_id.empty())
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".resume";
xfr.open(xfr_name.c_str(), ios::out | ios::trunc);
@@ -692,13 +719,22 @@ void TransferManager::prolog_resume_action(int vid)
continue;
}
- tm_mad = disk->vector_value("TM_MAD");
- ds_id = disk->vector_value("DATASTORE_ID");
disk->vector_value_str("DISK_ID", disk_id);
- if ( tm_mad.empty() || ds_id.empty() )
+ if ( isVolatile(disk) == true )
{
- continue;
+ tm_mad = vm_tm_mad;
+ ds_id = vm_ds_id;
+ }
+ else
+ {
+ tm_mad = disk->vector_value("TM_MAD");
+ ds_id = disk->vector_value("DATASTORE_ID");
+
+ if ( tm_mad.empty() || ds_id.empty() )
+ {
+ continue;
+ }
}
//MV tm_mad fe:system_dir/disk.i host:remote_system_dir/disk.i vmid dsid
@@ -714,11 +750,11 @@ void TransferManager::prolog_resume_action(int vid)
//MV tm_mad fe:system_dir host:remote_system_dir vmid 0
xfr << "MV "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< nd.get_nebula_hostname() << ":"<< vm->get_system_dir() << " "
<< vm->get_hostname() << ":" << vm->get_remote_system_dir()<< " "
<< vm->get_oid() << " "
- << "0" << endl;
+ << vm_ds_id << endl;
xfr.close();
@@ -732,6 +768,11 @@ error_history:
os << "prolog_resume, VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "prolog_resume, error getting drivers.";
+ goto error_common;
+
error_file:
os.str("");
os << "prolog_resume, could not open file: " << xfr_name;
@@ -758,13 +799,22 @@ void TransferManager::epilog_transfer_command(
string ds_id;
int disk_index;
- save = disk->vector_value("SAVE");
- ds_id = disk->vector_value("DATASTORE_ID");
- tm_mad = disk->vector_value("TM_MAD");
-
- if ( save.empty() || ds_id.empty() || tm_mad.empty() )
+ if ( isVolatile(disk) == true )
{
- return;
+ save = "NO";
+ tm_mad = vm->get_tm_mad();
+ ds_id = vm->get_ds_id();
+ }
+ else
+ {
+ save = disk->vector_value("SAVE");
+ tm_mad = disk->vector_value("TM_MAD");
+ ds_id = disk->vector_value("DATASTORE_ID");
+
+ if ( save.empty() || ds_id.empty() || tm_mad.empty() )
+ {
+ return;
+ }
}
disk->vector_value("DISK_ID", disk_index);
@@ -820,9 +870,10 @@ void TransferManager::epilog_action(int vid)
{
ofstream xfr;
ostringstream os;
- string xfr_name;
- string system_tm_mad;
- string error_str;
+ string xfr_name;
+ string vm_tm_mad;
+ string vm_ds_id;
+ string error_str;
const VectorAttribute * disk;
@@ -837,17 +888,6 @@ void TransferManager::epilog_action(int vid)
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "epilog, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -860,6 +900,15 @@ void TransferManager::epilog_action(int vid)
goto error_history;
}
+ vm_tm_mad = vm->get_tm_mad();
+ vm_ds_id = vm->get_ds_id();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() || vm_ds_id.empty())
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".epilog";
xfr.open(xfr_name.c_str(), ios::out | ios::trunc);
@@ -885,12 +934,12 @@ void TransferManager::epilog_action(int vid)
epilog_transfer_command(vm, disk, xfr);
}
- //DELETE system_tm_mad hostname:remote_system_dir vmid ds_id
+ //DELETE vm_tm_mad hostname:remote_system_dir vmid ds_id
xfr << "DELETE "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< vm->get_hostname() << ":" << vm->get_remote_system_dir() << " "
<< vm->get_oid() << " "
- << "0" << endl;
+ << vm_ds_id << endl;
xfr.close();
@@ -904,6 +953,11 @@ error_history:
os << "epilog, VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "epilog, error getting drivers.";
+ goto error_common;
+
error_file:
os.str("");
os << "epilog, could not open file: " << xfr_name;
@@ -924,11 +978,14 @@ void TransferManager::epilog_stop_action(int vid)
{
ofstream xfr;
ostringstream os;
- string xfr_name;
- string tm_mad;
- string system_tm_mad;
- string ds_id;
- int disk_id;
+
+ string xfr_name;
+ string tm_mad;
+ string vm_tm_mad;
+ string vm_ds_id;
+ string ds_id;
+
+ int disk_id;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
@@ -942,17 +999,6 @@ void TransferManager::epilog_stop_action(int vid)
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "epilog_stop, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -965,6 +1011,15 @@ void TransferManager::epilog_stop_action(int vid)
goto error_history;
}
+ vm_tm_mad = vm->get_tm_mad();
+ vm_ds_id = vm->get_ds_id();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() || vm_ds_id.empty())
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".stop";
xfr.open(xfr_name.c_str(), ios::out | ios::trunc);
@@ -987,13 +1042,22 @@ void TransferManager::epilog_stop_action(int vid)
continue;
}
- tm_mad = disk->vector_value("TM_MAD");
- ds_id = disk->vector_value("DATASTORE_ID");
disk->vector_value_str("DISK_ID", disk_id);
- if (tm_mad.empty() || ds_id.empty())
+ if ( isVolatile(disk) == true )
{
- continue;
+ tm_mad = vm_tm_mad;
+ ds_id = vm_ds_id;
+ }
+ else
+ {
+ tm_mad = disk->vector_value("TM_MAD");
+ ds_id = disk->vector_value("DATASTORE_ID");
+
+ if ( tm_mad.empty() || ds_id.empty() )
+ {
+ continue;
+ }
}
//MV tm_mad host:remote_system_dir/disk.i fe:system_dir/disk.i vmid dsid
@@ -1007,13 +1071,13 @@ void TransferManager::epilog_stop_action(int vid)
<< ds_id << endl;
}
- //MV system_tm_mad hostname:remote_system_dir fe:system_dir
+ //MV vm_tm_mad hostname:remote_system_dir fe:system_dir
xfr << "MV "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< vm->get_hostname() << ":" << vm->get_remote_system_dir() << " "
<< nd.get_nebula_hostname() << ":" << vm->get_system_dir() << " "
<< vm->get_oid() << " "
- << "0" << endl;
+ << vm_ds_id << endl;
xfr.close();
@@ -1028,6 +1092,11 @@ error_history:
os << "epilog_stop, VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "epilog_stop, error getting drivers.";
+ goto error_common;
+
error_file:
os.str("");
os << "epilog_stop, could not open file: " << xfr_name;
@@ -1048,11 +1117,14 @@ void TransferManager::epilog_delete_action(bool local, int vid)
{
ofstream xfr;
ostringstream os;
- string xfr_name;
- string system_tm_mad;
- string tm_mad;
- string ds_id;
- int disk_id;
+
+ string xfr_name;
+ string vm_tm_mad;
+ string tm_mad;
+ string vm_ds_id;
+ string ds_id;
+
+ int disk_id;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
@@ -1066,17 +1138,6 @@ void TransferManager::epilog_delete_action(bool local, int vid)
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "epilog_delete, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -1088,7 +1149,16 @@ void TransferManager::epilog_delete_action(bool local, int vid)
{
goto error_history;
}
-
+
+ vm_tm_mad = vm->get_tm_mad();
+ vm_ds_id = vm->get_ds_id();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() || vm_ds_id.empty())
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".delete";
xfr.open(xfr_name.c_str(), ios::out | ios::trunc);
@@ -1111,13 +1181,22 @@ void TransferManager::epilog_delete_action(bool local, int vid)
continue;
}
- tm_mad = disk->vector_value("TM_MAD");
- ds_id = disk->vector_value("DATASTORE_ID");
disk->vector_value_str("DISK_ID", disk_id);
- if ( tm_mad.empty() || ds_id.empty() )
+ if ( isVolatile(disk) == true )
{
- continue;
+ tm_mad = vm_tm_mad;
+ ds_id = vm_ds_id;
+ }
+ else
+ {
+ tm_mad = disk->vector_value("TM_MAD");
+ ds_id = disk->vector_value("DATASTORE_ID");
+
+ if ( tm_mad.empty() || ds_id.empty() )
+ {
+ continue;
+ }
}
if ( local )
@@ -1144,21 +1223,21 @@ void TransferManager::epilog_delete_action(bool local, int vid)
if ( local )
{
- //DELETE system_tm_mad fe:system_dir vmid dsid(=0)
+ //DELETE vm_tm_mad fe:system_dir vmid dsid(=0)
xfr << "DELETE "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< nd.get_nebula_hostname() <<":"<< vm->get_system_dir() << " "
<< vm->get_oid() << " "
- << "0";
+ << vm_ds_id;
}
else
{
- //DELETE system_tm_mad hostname:remote_system_dir vmid dsid(=0)
+ //DELETE vm_tm_mad hostname:remote_system_dir vmid dsid(=0)
xfr << "DELETE "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< vm->get_hostname() <<":"<< vm->get_remote_system_dir() << " "
<< vm->get_oid() << " "
- << "0";
+ << vm_ds_id;
}
xfr.close();
@@ -1173,6 +1252,11 @@ error_history:
os << "epilog_delete, VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "epilog_delete, error getting drivers.";
+ goto error_common;
+
error_file:
os.str("");
os << "epilog_delete, could not open file: " << xfr_name;
@@ -1195,11 +1279,14 @@ void TransferManager::epilog_delete_previous_action(int vid)
{
ofstream xfr;
ostringstream os;
- string xfr_name;
- string system_tm_mad;
- string tm_mad;
- string ds_id;
- int disk_id;
+
+ string xfr_name;
+ string vm_tm_mad;
+ string tm_mad;
+ string vm_ds_id;
+ string ds_id;
+
+ int disk_id;
VirtualMachine * vm;
Nebula& nd = Nebula::instance();
@@ -1213,17 +1300,6 @@ void TransferManager::epilog_delete_previous_action(int vid)
// ------------------------------------------------------------------------
// Setup & Transfer script
// ------------------------------------------------------------------------
- system_tm_mad = nd.get_system_ds_tm_mad();
- tm_md = get();
-
- if ( tm_md == 0 || system_tm_mad.empty() )
- {
- NebulaLog::log("TM", Log::ERROR, "epilog_delete, error getting drivers.");
- (nd.get_lcm())->trigger(LifeCycleManager::EPILOG_FAILURE,vid);
-
- return;
- }
-
vm = vmpool->get(vid,true);
if (vm == 0)
@@ -1236,6 +1312,15 @@ void TransferManager::epilog_delete_previous_action(int vid)
goto error_history;
}
+ vm_tm_mad = vm->get_previous_tm_mad();
+ vm_ds_id = vm->get_previous_ds_id();
+ tm_md = get();
+
+ if ( tm_md == 0 || vm_tm_mad.empty() || vm_ds_id.empty() )
+ {
+ goto error_drivers;
+ }
+
xfr_name = vm->get_transfer_file() + ".delete_prev";
xfr.open(xfr_name.c_str(),ios::out | ios::trunc);
@@ -1258,13 +1343,22 @@ void TransferManager::epilog_delete_previous_action(int vid)
continue;
}
- tm_mad = disk->vector_value("TM_MAD");
- ds_id = disk->vector_value("DATASTORE_ID");
disk->vector_value_str("DISK_ID", disk_id);
- if (tm_mad.empty() || ds_id.empty())
+ if ( isVolatile(disk) == true )
{
- continue;
+ tm_mad = vm_tm_mad;
+ ds_id = vm_ds_id;
+ }
+ else
+ {
+ tm_mad = disk->vector_value("TM_MAD");
+ ds_id = disk->vector_value("DATASTORE_ID");
+
+ if ( tm_mad.empty() || ds_id.empty() )
+ {
+ continue;
+ }
}
//DELETE tm_mad prev_host:remote_system_dir/disk.i vmid ds_id
@@ -1276,12 +1370,12 @@ void TransferManager::epilog_delete_previous_action(int vid)
<< ds_id << endl;
}
- //DELTE system_tm_mad prev_host:remote_system_dir vmid ds_id(=0)
+ //DELTE vm_tm_mad prev_host:remote_system_dir vmid ds_id(=0)
xfr << "DELETE "
- << system_tm_mad << " "
+ << vm_tm_mad << " "
<< vm->get_previous_hostname() <<":"<< vm->get_remote_system_dir()
<< " " << vm->get_oid() << " "
- << "0" << endl;
+ << vm_ds_id << endl;
xfr.close();
@@ -1295,9 +1389,14 @@ error_history:
os << "epilog_delete_previous, VM " << vid << " has no history";
goto error_common;
+error_drivers:
+ os.str("");
+ os << "epilog_delete_previous, error getting drivers.";
+ goto error_common;
+
error_file:
os.str("");
- os << "epilog_delete, could not open file: " << xfr_name;
+ os << "epilog_delete_previous, could not open file: " << xfr_name;
os << ". You may need to manually clean " << vm->get_previous_hostname()
<< ":" << vm->get_remote_system_dir();
goto error_common;
diff --git a/src/vm/History.cc b/src/vm/History.cc
index 4d7580aba9..cbbe4ba072 100644
--- a/src/vm/History.cc
+++ b/src/vm/History.cc
@@ -44,6 +44,8 @@ History::History(
hid(-1),
vmm_mad_name(""),
vnm_mad_name(""),
+ tm_mad_name(""),
+ ds_id(0),
stime(0),
etime(0),
prolog_stime(0),
@@ -64,6 +66,8 @@ History::History(
const string& _hostname,
const string& _vmm,
const string& _vnm,
+ const string& _tmm,
+ int _ds_id,
const string& _vm_info):
oid(_oid),
seq(_seq),
@@ -71,6 +75,8 @@ History::History(
hid(_hid),
vmm_mad_name(_vmm),
vnm_mad_name(_vnm),
+ tm_mad_name(_tmm),
+ ds_id(_ds_id),
stime(0),
etime(0),
prolog_stime(0),
@@ -123,7 +129,7 @@ void History::non_persistent_data()
os.str("");
nd.get_configuration_attribute("DATASTORE_LOCATION", ds_location);
- os << ds_location << "/" << DatastorePool::SYSTEM_DS_ID << "/" << oid;
+ os << ds_location << "/" << ds_id << "/" << oid;
vm_rhome = os.str();
@@ -292,6 +298,8 @@ string& History::to_xml(string& xml, bool database) const
"" << etime << "" <<
"" << vmm_mad_name << ""<<
"" << vnm_mad_name << ""<<
+ "" << tm_mad_name << "" <<
+ "" << ds_id << "" <<
"" << prolog_stime << ""<<
"" << prolog_etime << ""<<
"" << running_stime << ""<<
@@ -328,6 +336,8 @@ int History::rebuild_attributes()
rc += xpath(etime , "/HISTORY/ETIME", 0);
rc += xpath(vmm_mad_name , "/HISTORY/VMMMAD", "not_found");
xpath(vnm_mad_name , "/HISTORY/VNMMAD", "dummy");
+ rc += xpath(tm_mad_name , "/HISTORY/TMMAD", "not_found");
+ rc += xpath(ds_id , "/HISTORY/DS_ID", 0);
rc += xpath(prolog_stime , "/HISTORY/PSTIME", 0);
rc += xpath(prolog_etime , "/HISTORY/PETIME", 0);
rc += xpath(running_stime , "/HISTORY/RSTIME", 0);
diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc
index 54fa086a92..2080ca731b 100644
--- a/src/vm/VirtualMachine.cc
+++ b/src/vm/VirtualMachine.cc
@@ -826,7 +826,9 @@ void VirtualMachine::add_history(
int hid,
const string& hostname,
const string& vmm_mad,
- const string& vnm_mad)
+ const string& vnm_mad,
+ const string& tm_mad,
+ int ds_id)
{
ostringstream os;
int seq;
@@ -851,6 +853,8 @@ void VirtualMachine::add_history(
hostname,
vmm_mad,
vnm_mad,
+ tm_mad,
+ ds_id,
vm_xml);
history_records.push_back(history);
@@ -877,6 +881,8 @@ void VirtualMachine::cp_history()
history->hostname,
history->vmm_mad_name,
history->vnm_mad_name,
+ history->tm_mad_name,
+ history->ds_id,
vm_xml);
previous_history = history;
@@ -906,6 +912,8 @@ void VirtualMachine::cp_previous_history()
previous_history->hostname,
previous_history->vmm_mad_name,
previous_history->vnm_mad_name,
+ previous_history->tm_mad_name,
+ previous_history->ds_id,
vm_xml);
previous_history = history;
@@ -1980,7 +1988,7 @@ string VirtualMachine::get_remote_system_dir() const
Nebula& nd = Nebula::instance();
nd.get_configuration_attribute("DATASTORE_LOCATION", ds_location);
- oss << ds_location << "/" << DatastorePool::SYSTEM_DS_ID << "/" << oid;
+ oss << ds_location << "/" << history->ds_id << "/" << oid;
return oss.str();
}
@@ -1993,7 +2001,7 @@ string VirtualMachine::get_system_dir() const
ostringstream oss;
Nebula& nd = Nebula::instance();
- oss << nd.get_ds_location() << DatastorePool::SYSTEM_DS_ID << "/"<< oid;
+ oss << nd.get_ds_location() << history->ds_id << "/"<< oid;
return oss.str();
};
diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc
index ecd651acc1..1565dabfd0 100644
--- a/src/vmm/VirtualMachineManager.cc
+++ b/src/vmm/VirtualMachineManager.cc
@@ -1313,7 +1313,7 @@ void VirtualMachineManager::attach_action(
string vm_tmpl;
string* drv_msg;
string tm_command;
- string system_tm_mad;
+ string vm_tm_mad;
string opennebula_hostname;
string prolog_cmd;
string disk_path;
@@ -1352,13 +1352,13 @@ void VirtualMachineManager::attach_action(
goto error_disk;
}
- system_tm_mad = nd.get_system_ds_tm_mad();
+ vm_tm_mad = vm->get_tm_mad();
opennebula_hostname = nd.get_nebula_hostname();
rc = Nebula::instance().get_tm()->prolog_transfer_command(
vm,
disk,
- system_tm_mad,
+ vm_tm_mad,
opennebula_hostname,
os,
error_os);
@@ -1445,7 +1445,7 @@ void VirtualMachineManager::detach_action(
string vm_tmpl;
string * drv_msg;
string tm_command;
- string system_tm_mad;
+ string vm_tm_mad;
string opennebula_hostname;
string epilog_cmd;
string disk_path;
@@ -1484,7 +1484,7 @@ void VirtualMachineManager::detach_action(
goto error_disk;
}
- system_tm_mad = nd.get_system_ds_tm_mad();
+ vm_tm_mad = vm->get_tm_mad();
opennebula_hostname = nd.get_nebula_hostname();
disk->vector_value("DISK_ID", disk_id);