1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-19 06:50:07 +03:00

Merge branch 'master' into feature-1540-2

This commit is contained in:
Tino Vazquez 2019-01-31 10:46:08 +01:00
commit ac38218d5e
No known key found for this signature in database
GPG Key ID: 2FE9C32E94AEABBE
32 changed files with 771 additions and 182 deletions

View File

@ -83,7 +83,11 @@ public:
* by the calling function.
* @return a string (allocated in the heap) holding the attribute value.
*/
virtual string * to_xml() const = 0;
virtual void to_xml(std::ostringstream& s) const = 0;
virtual void to_json(std::ostringstream& s) const = 0;
virtual void to_token(std::ostringstream& s) const = 0;
/**
* Builds a new attribute from a string.
@ -158,17 +162,31 @@ public:
*
* <attribute_name>attribute_value</attribute_name>
*
* The string MUST be freed by the calling function.
* @return a string (allocated in the heap) holding the attribute value.
* @paran s the stream to write the attribute.
*/
string * to_xml() const
void to_xml(std::ostringstream& s) const
{
string * xml = new string;
s << "<" << attribute_name << ">" << one_util::escape_xml(attribute_value)
<< "</"<< attribute_name << ">";
*xml = "<" + name() + ">" + one_util::escape_xml(attribute_value) +
"</"+ name() + ">";
}
return xml;
void to_json(std::ostringstream& s) const
{
one_util::escape_json(attribute_value, s);
}
void to_token(std::ostringstream& s) const
{
if (attribute_name.empty() || attribute_value.empty())
{
return;
}
one_util::escape_token(attribute_name, s);
s << "=";
one_util::escape_token(attribute_value, s);
s << std::endl;
}
/**
@ -350,12 +368,11 @@ public:
* The string MUST be freed by the calling function.
* @return a string (allocated in the heap) holding the attribute value.
*/
string * to_xml() const;
void to_xml(std::ostringstream& s) const;
/**
* Same as above but the attribute is written in an string stream;
*/
void to_xml(ostringstream &oss) const;
void to_json(std::ostringstream& s) const;
void to_token(std::ostringstream& s) const;
/**
* Builds a new attribute from a string of the form:

View File

@ -92,9 +92,19 @@ protected:
return va->marshall(_sep);
};
string * to_xml() const
void to_xml(std::ostringstream& s) const
{
return va->to_xml();
return va->to_xml(s);
};
void to_json(std::ostringstream& s) const
{
return va->to_json(s);
};
void to_token(std::ostringstream& s) const
{
return va->to_token(s);
};
void unmarshall(const std::string& sattr, const char * _sep = 0)

View File

@ -258,6 +258,10 @@ private:
*/
string& to_xml(string& xml, bool database) const;
string& to_json(string& json) const;
string& to_token(string& text) const;
/**
* Rebuilds the object from an xml node
* @param node The xml node pointer

View File

@ -371,7 +371,7 @@ public:
*/
static string shared_db_version()
{
return "5.7.80";
return "5.6.0";
}
/**
@ -578,6 +578,15 @@ public:
return nebula_configuration->to_xml(xml);
};
/**
* Gets the database backend type
* @return database backend type
*/
string get_db_backend() const
{
return db_backend_type;
}
// -----------------------------------------------------------------------
// Default Quotas
// -----------------------------------------------------------------------
@ -695,7 +704,7 @@ private:
"/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA",
"/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA",
"/DEFAULT_GROUP_QUOTAS/VM_QUOTA"),
system_db(0), logdb(0), fed_logdb(0),
system_db(0), db_backend_type("sqlite"), logdb(0), fed_logdb(0),
vmpool(0), hpool(0), vnpool(0), upool(0), ipool(0), gpool(0), tpool(0),
dspool(0), clpool(0), docpool(0), zonepool(0), secgrouppool(0),
vdcpool(0), vrouterpool(0), marketpool(0), apppool(0), vmgrouppool(0),
@ -819,6 +828,7 @@ private:
// ---------------------------------------------------------------
SystemDB * system_db;
string db_backend_type;
// ---------------------------------------------------------------
// Nebula Pools

View File

@ -208,6 +208,11 @@ namespace one_util
{
return escape(v, "'", "'");
}
void escape_json(const std::string& str, std::ostringstream& s);
void escape_token(const std::string& str, std::ostringstream& s);
/**
* Checks if a strings matches a regular expression
*
@ -236,7 +241,8 @@ namespace one_util
const std::string& replacement);
template <class T>
std::set<T> set_intersection(const std::set<T> &first, const std::set<T> &second)
std::set<T> set_intersection(const std::set<T> &first, const std::set<T>
&second)
{
std::set<T> output;
@ -247,48 +253,48 @@ namespace one_util
return output;
}
/**
/**
* Compress the input string unsing zlib
* @param in input string
* @param bool64 true to base64 encode output
* @return pointer to the compressed sting (must be freed) or 0 in case
* of error
*/
std::string * zlib_compress(const std::string& in, bool base64);
std::string * zlib_compress(const std::string& in, bool base64);
/**
/**
* Decompress the input string unsing zlib
* @param in input string
* @param base64 true if the input is base64 encoded
* @return pointer to the decompressed sting (must be freed) or 0 in case
* of error
*/
std::string * zlib_decompress(const std::string& in, bool base64);
std::string * zlib_decompress(const std::string& in, bool base64);
extern "C" void sslmutex_lock_callback(int mode, int type, char *file,
int line);
extern "C" void sslmutex_lock_callback(int mode, int type, char *file,
int line);
extern "C" unsigned long sslmutex_id_callback();
extern "C" unsigned long sslmutex_id_callback();
class SSLMutex
{
public:
static void initialize();
class SSLMutex
{
public:
static void initialize();
static void finalize();
static void finalize();
private:
friend void sslmutex_lock_callback(int mode, int type, char *file,
int line);
private:
friend void sslmutex_lock_callback(int mode, int type, char *file,
int line);
SSLMutex();
SSLMutex();
~SSLMutex();
~SSLMutex();
static SSLMutex * ssl_mutex;
static SSLMutex * ssl_mutex;
static std::vector<pthread_mutex_t *> vmutex;
};
static std::vector<pthread_mutex_t *> vmutex;
};
};
#endif /* _NEBULA_UTIL_H_ */

View File

@ -251,6 +251,28 @@ public:
static void oid_filter(int start_id,
int end_id,
string& filter);
/**
* This function returns a legal SQL string that can be used in an SQL
* statement. The string is encoded to an escaped SQL string, taking into
* account the current character set of the connection.
* @param str the string to be escaped
* @return a valid SQL string or NULL in case of failure
*/
char * escape_str(const string& str)
{
return db->escape_str(str);
}
/**
* Frees a previously scaped string
* @param str pointer to the str
*/
void free_str(char * str)
{
db->free_str(str);
}
protected:
/**

View File

@ -113,7 +113,7 @@ public:
VirtualMachinePoolInfo():
RequestManagerPoolInfoFilter("one.vmpool.info",
"Returns the virtual machine instances pool",
"A:siiii")
"A:siiiis")
{
Nebula& nd = Nebula::instance();
pool = nd.get_vmpool();

View File

@ -170,6 +170,10 @@ public:
*/
string& to_xml(string& xml) const;
string& to_json(string& xml) const;
string& to_token(string& xml) const;
/**
* Writes the template in a plain text string
* @param str string that hold the template representation

View File

@ -1884,6 +1884,10 @@ private:
*/
string& to_xml_extended(string& xml, int n_history) const;
string& to_json(string& json) const;
string& to_token(string& text) const;
// -------------------------------------------------------------------------
// Attribute Parser
// -------------------------------------------------------------------------

View File

@ -1000,6 +1000,7 @@ IM_PROBES_LXD_PROBES_FILES="src/im_mad/remotes/lxd-probes.d/lxd.rb \
src/im_mad/remotes/lxd-probes.d/pci.rb \
src/im_mad/remotes/lxd-probes.d/monitor_ds.sh \
src/im_mad/remotes/lxd-probes.d/version.sh \
src/im_mad/remotes/lxd-probes.d/profiles.sh \
src/im_mad/remotes/lxd-probes.d/collectd-client-shepherd.sh"
IM_PROBES_LXD_FILES="src/im_mad/remotes/lxd.d/collectd-client_control.sh \
@ -1458,8 +1459,7 @@ ONEDB_SHARED_MIGRATOR_FILES="src/onedb/shared/2.0_to_2.9.80.rb \
src/onedb/shared/5.3.80_to_5.4.0.rb \
src/onedb/shared/5.4.0_to_5.4.1.rb \
src/onedb/shared/5.4.1_to_5.5.80.rb \
src/onedb/shared/5.5.80_to_5.6.0.rb \
src/onedb/shared/5.6.0_to_5.7.80.rb"
src/onedb/shared/5.5.80_to_5.6.0.rb"
ONEDB_LOCAL_MIGRATOR_FILES="src/onedb/local/4.5.80_to_4.7.80.rb \
src/onedb/local/4.7.80_to_4.9.80.rb \

View File

@ -198,6 +198,13 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
:format => String
}
SEARCH = {
:name => "search",
:large => "--search search",
:description=> "query in KEY=VALUE format",
:format => String
}
def self.rname
"VM"
end

View File

@ -1047,8 +1047,28 @@ CommandParser::CmdParser.new(ARGV) do
command :list, list_desc, [:filterflag, nil],
:options => CLIHelper::OPTIONS + OpenNebulaHelper::OPTIONS +
[OpenNebulaHelper::DESCRIBE] do
helper.list_pool(options, false, args[0])
[OpenNebulaHelper::DESCRIBE] + [OneVMHelper::SEARCH] do
if !options[:search]
helper.list_pool(options, false, args[0])
else
table = helper.format_pool(options)
pool = OpenNebula::VirtualMachinePool.new(OneVMHelper.get_client)
rc = pool.info_search(:query => options[:search])
if !rc.nil?
puts rc.message
exit(-1)
end
if options[:xml]
puts pool.to_xml
else
table.show(pool.to_hash, options)
end
return 0
end
end
show_desc = <<-EOT.unindent

View File

@ -30,7 +30,6 @@ $LOAD_PATH << RUBY_LIB_LOCATION + '/cli'
require 'command_parser'
require 'one_helper/onevntemplate_helper'
require 'one_helper/onevnet_helper'
require 'pry'
CommandParser::CmdParser.new(ARGV) do
usage '`onevntemplate` <command> [<args>] [<options>]'

View File

@ -65,25 +65,9 @@ string * VectorAttribute::marshall(const char * _sep) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string * VectorAttribute::to_xml() const
{
ostringstream oss;
to_xml(oss);
string * xml = new string;
*xml = oss.str();
return xml;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VectorAttribute::to_xml(ostringstream &oss) const
{
map<string,string>::const_iterator it;
map<string,string>::const_iterator it;
oss << "<" << name() << ">";
@ -102,6 +86,60 @@ void VectorAttribute::to_xml(ostringstream &oss) const
oss << "</"<< name() << ">";
}
void VectorAttribute::to_json(std::ostringstream& s) const
{
if ( attribute_value.empty() )
{
s << "{}";
return;
}
map<string,string>::const_iterator it = attribute_value.begin();
bool is_first = true;
s << "{";
for (++it; it!=attribute_value.end(); it++)
{
if ( it->first.empty() )
{
continue;
}
if ( !is_first )
{
s << ",";
}
else
{
is_first = false;
}
s << "\"" << it->first << "\": ";
one_util::escape_json(it->second, s);
}
s << "}";
}
void VectorAttribute::to_token(std::ostringstream& s) const
{
map<string,string>::const_iterator it;
for (it=attribute_value.begin(); it!=attribute_value.end(); it++)
{
if (it->first.empty() || it->second.empty())
{
continue;
}
one_util::escape_token(it->first, s);
s << "=";
one_util::escape_token(it->second, s);
s << std::endl;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -380,6 +380,57 @@ std::string one_util::gsub(const std::string& st, const std::string& sfind,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void one_util::escape_json(const std::string& str, std::ostringstream& s)
{
std::string::const_iterator it;
s << "\"";
for (it = str.begin(); it != str.end(); ++it)
{
switch (*it)
{
case '\\': s << "\\\\"; break;
case '"' : s << "\\\""; break;
case '/' : s << "\\/"; break;
case '\b': s << "\\b"; break;
case '\f': s << "\\f"; break;
case '\n': s << "\\n"; break;
case '\r': s << "\\r"; break;
case '\t': s << "\\t"; break;
default : s << *it;
}
}
s << "\"";
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void one_util::escape_token(const std::string& str, std::ostringstream& s)
{
std::string::const_iterator it;
for (it = str.begin(); it != str.end(); ++it)
{
switch (*it)
{
case '-':
case '_':
case '.':
case ':':
s << '_';
break;
default :
s << *it;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
namespace one_util
{
template<>

View File

@ -0,0 +1,19 @@
#!/bin/bash
cmd='lxc profile list'
profiles=$($cmd | grep -v -- -+- | grep -v NAME | grep -v default | awk '{print $2}')
if [ "$?" -ne "0" ]; then
profiles=$(sudo $cmd | grep -v -- -+- | grep -v NAME | grep -v default | awk '{print $2}')
fi
tmpfile=$(mktemp /tmp/lxd_probe.XXXXXX)
echo "$profiles" > "$tmpfile"
out=$(tr '\n' ',' < "$tmpfile")
out=${out::-1}
echo -e LXD_PROFILES=\""$out"\"
rm "$tmpfile"

View File

@ -252,8 +252,6 @@ void Nebula::start(bool bootstrap_only)
// -----------------------------------------------------------
try
{
bool db_is_sqlite = true;
string server;
int port;
string user;
@ -265,12 +263,7 @@ void Nebula::start(bool bootstrap_only)
if ( _db != 0 )
{
string value = _db->vector_value("BACKEND");
if (value == "mysql")
{
db_is_sqlite = false;
}
db_backend_type = _db->vector_value("BACKEND");
if (_db->vector_value("SERVER", server) == -1)
{
@ -303,7 +296,7 @@ void Nebula::start(bool bootstrap_only)
}
}
if ( db_is_sqlite )
if ( db_backend_type == "sqlite" )
{
db_backend = new SqliteDB(var_location + "one.db");
}

View File

@ -177,6 +177,36 @@ public class VirtualMachinePool extends Pool implements Iterable<VirtualMachine>
return client.call(INFO_METHOD, filter, startId, endId, state);
}
/**
* Retrieves all or part of the Virtual Machines in the pool. The
* Virtual Machines to retrieve can be also filtered by Id, specifying the
* first and last Id to include; and by state.
*
* @param client XML-RPC Client.
* @param filter Filter flag to use. Possible values:
* <ul>
* <li>{@link Pool#ALL}: All Virtual Machines</li>
* <li>{@link Pool#MINE}: Connected user's Virtual Machines</li>
* <li>{@link Pool#MINE_GROUP}: Connected user's Virtual Machines, and the ones in
* his group</li>
* <li>{@link Pool#GROUP}: User's primary group Virtual Machines</li>
* <li>&gt;= 0 UID User's Virtual Machines</li>
* </ul>
* @param startId Lowest Id to retrieve
* @param endId Biggest Id to retrieve
* @param state Numeric state of the Virtual Machines wanted, or one
* of {@link VirtualMachinePool#ALL_VM} or
* {@link VirtualMachinePool#NOT_DONE}
* @param query query for FTS
* @return If successful the message contains the string
* with the information returned by OpenNebula.
*/
public static OneResponse info_search(Client client, int filter,
int startId, int endId, int state, String query)
{
return client.call(INFO_METHOD, filter, startId, endId, state, query);
}
/**
* Retrieves the monitoring data for all or part of the Virtual
* Machines in the pool.

View File

@ -115,6 +115,23 @@ module OpenNebula
INFO_NOT_DONE)
end
def info_search(args = {})
default_args = {
:who => INFO_ALL,
:start_id => -1,
:end_id => -1,
:state => INFO_NOT_DONE,
:query => ""
}.merge!(args)
return info_filter(VM_POOL_METHODS[:info],
default_args[:who],
default_args[:start_id],
default_args[:end_id],
default_args[:state],
default_args[:query])
end
alias_method :info!, :info
alias_method :info_all!, :info_all
alias_method :info_mine!, :info_mine
@ -458,8 +475,8 @@ module OpenNebula
data_hash
end
def info_filter(xml_method, who, start_id, end_id, state)
return xmlrpc_info(xml_method, who, start_id, end_id, state)
def info_filter(xml_method, who, start_id, end_id, state, query="")
return xmlrpc_info(xml_method, who, start_id, end_id, state, query)
end
end
end

View File

@ -91,8 +91,15 @@ class OneDBBacKEnd
vm_pool: "oid INTEGER PRIMARY KEY, name VARCHAR(128), " <<
"body MEDIUMTEXT, uid INTEGER, gid INTEGER, " <<
"last_poll INTEGER, state INTEGER, lcm_state INTEGER, " <<
"owner_u INTEGER, group_u INTEGER, other_u INTEGER, short_body MEDIUMTEXT",
"owner_u INTEGER, group_u INTEGER, other_u INTEGER, short_body MEDIUMTEXT, " <<
"search_token MEDIUMTEXT, FULLTEXT ftidx(search_token)",
vm_pool_sqlite: "oid INTEGER PRIMARY KEY, name VARCHAR(128), " <<
"body MEDIUMTEXT, uid INTEGER, gid INTEGER, " <<
"last_poll INTEGER, state INTEGER, lcm_state INTEGER, " <<
"owner_u INTEGER, group_u INTEGER, other_u INTEGER, short_body MEDIUMTEXT, " <<
"search_token MEDIUMTEXT",
vn_template_pool: "oid INTEGER PRIMARY KEY, name VARCHAR(128), " <<
"body MEDIUMTEXT, uid INTEGER, gid INTEGER," <<
"owner_u INTEGER, group_u INTEGER, other_u INTEGER"

View File

@ -52,7 +52,7 @@ require 'fsck/template'
require 'fsck/quotas'
module OneDBFsck
VERSION = "5.7.80"
VERSION = "5.6.0"
LOCAL_VERSION = "5.7.80"
def db_version

View File

@ -38,7 +38,7 @@ module Migrator
def up
bug_2687 # MUST be run before 2489, which generates short body
feature_2253
feature_2489
feature_2489_2671
feature_826
true
end
@ -104,10 +104,15 @@ module Migrator
@db.run 'DROP TABLE old_vm_pool;'
end
def feature_2489
def feature_2489_2671
@db.run 'DROP TABLE IF EXISTS old_vm_pool;'
@db.run 'ALTER TABLE vm_pool RENAME TO old_vm_pool;'
create_table(:vm_pool, nil, db_version)
if @backend.class == BackEndSQLite
create_table(:vm_pool_sqlite, nil, db_version)
elsif
create_table(:vm_pool, nil, db_version)
end
@db.transaction do
@db.fetch('SELECT * FROM old_vm_pool') do |row|
@ -116,6 +121,7 @@ module Migrator
end
row[:short_body] = gen_short_body(doc)
row[:search_token] = gen_search_body(doc)
@db[:vm_pool].insert(row)
end
@ -135,6 +141,67 @@ module Migrator
end
end
def gen_search_body(body)
search_body = "UNAME=" + escape_token(body.root.xpath('UNAME').text) + "\n" +
"GNAME=" + escape_token(body.root.xpath('GNAME').text) + "\n" +
"NAME=" + escape_token(body.root.xpath('NAME').text) + "\n" +
"LAST_POLL=" + escape_token(body.root.xpath('LAST_POLL').text) + "\n" +
"PREV_STATE=" + escape_token(body.root.xpath('PREV_STATE').text) + "\n" +
"PREV_LCM_STATE=" + escape_token(body.root.xpath('PREV_LCM_STATE').text) + "\n" +
"RESCHED=" + escape_token(body.root.xpath('RESCHED').text) + "\n" +
"STIME=" + escape_token(body.root.xpath('STIME').text) + "\n" +
"ETIME=" + escape_token(body.root.xpath('ETIME').text) + "\n" +
"DEPLOY_ID=" + escape_token(body.root.xpath('DEPLOY_ID').text) + "\n"
body.root.xpath("//TEMPLATE/*").each do |node|
search_body += to_token(node)
end
node = Nokogiri::XML(body.root.xpath("//HISTORY_RECORDS/HISTORY[last()]").to_s)
if !node.root.nil?
search_body += history_to_token(node)
end
return search_body
end
def to_token(node)
search_body = ""
if node.children.size > 1
node.children.each do |child|
search_body += to_token(child)
end
elsif
search_body += node.name + "=" + escape_token(node.children.text) + "\n"
end
return search_body
end
def history_to_token(hr)
hr_token = "HOSTNAME=" + escape_token(hr.xpath("//HOSTNAME").text) + "\n" +
"HID=" + hr.xpath("//HID").text + "\n" +
"CID=" + hr.xpath("//CID").text + "\n" +
"DS_ID=" + hr.xpath("//DS_ID").text + "\n"
end
def escape_token(str)
str_scaped = ""
str.split("").each do |c|
case c
when '-', '_', '.', ':'
str_scaped += '_'
else
str_scaped += c
end
end
return str_scaped
end
def gen_short_body(body)
short_body = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
xml.VM{

View File

@ -96,12 +96,30 @@ void VirtualMachinePoolInfo::request_execute(
int end_id = xmlrpc_c::value_int(paramList.getInt(3));
int state = xmlrpc_c::value_int(paramList.getInt(4));
ostringstream state_filter;
std::string fts_query;
if (paramList.size() > 5)
{
fts_query = xmlrpc_c::value_string(paramList.getString(5));
std::string backend = Nebula::instance().get_db_backend();
if (!fts_query.empty() && backend == "sqlite")
{
att.resp_msg = "Full text search is not allowed with sqlite backend";
failure_response(INTERNAL, att);
return;
}
}
ostringstream and_filter;
if (( state < VirtualMachinePoolInfo::ALL_VM ) ||
( state > VirtualMachine::CLONING_FAILURE ))
{
att.resp_msg = "Incorrect filter_flag, state";
failure_response(XML_RPC_API, att);
return;
}
@ -112,15 +130,39 @@ void VirtualMachinePoolInfo::request_execute(
break;
case VirtualMachinePoolInfo::NOT_DONE:
state_filter << "state <> " << VirtualMachine::DONE;
and_filter << "state <> " << VirtualMachine::DONE;
break;
default:
state_filter << "state = " << state;
and_filter << "state = " << state;
break;
}
dump(att, filter_flag, start_id, end_id, state_filter.str(), "");
if (!fts_query.empty())
{
char * _fts_query = pool->escape_str(fts_query);
if ( _fts_query == 0 )
{
att.resp_msg = "Error building search query";
failure_response(INTERNAL, att);
return;
}
if (!and_filter.str().empty())
{
and_filter << " AND ";
}
and_filter << "MATCH(search_token) AGAINST ('+\"";
one_util::escape_token(_fts_query, and_filter);
and_filter << "\"' in boolean mode)";
pool->free_str(_fts_query);
}
dump(att, filter_flag, start_id, end_id, and_filter.str(), "");
}
/* ------------------------------------------------------------------------- */
@ -471,7 +513,7 @@ void RequestManagerPoolInfoFilter::dump(
limit_clause = oss.str();
}
Nebula::instance().get_configuration_attribute(att.uid, att.gid,
Nebula::instance().get_configuration_attribute(att.uid, att.gid,
"API_LIST_ORDER", desc);
rc = pool->dump(str, where_string, limit_clause,

View File

@ -386,19 +386,14 @@ bool Template::get(const string& name, bool& value) const
string& Template::to_xml(string& xml) const
{
multimap<string,Attribute *>::const_iterator it;
ostringstream oss;
string * s;
multimap<string,Attribute *>::const_iterator it;
ostringstream oss;
oss << "<" << xml_root << ">";
for ( it = attributes.begin(); it!=attributes.end(); it++)
{
s = it->second->to_xml();
oss << *s;
delete s;
it->second->to_xml(oss);
}
oss << "</" << xml_root << ">";
@ -407,6 +402,81 @@ string& Template::to_xml(string& xml) const
return xml;
}
string& Template::to_json(string& json) const
{
multimap<string, Attribute *>::const_iterator it;
ostringstream oss;
bool is_first = true;
oss << "\"" << xml_root << "\": {";
for ( it = attributes.begin(); it!=attributes.end(); )
{
if (!is_first)
{
oss << ",";
}
else
{
is_first = false;
}
oss << "\"" << it->first << "\": ";
if ( attributes.count(it->first) == 1 )
{
it->second->to_json(oss);
++it;
}
else
{
std::string jelem = it->first;
bool is_array_first = true;
oss << "[ ";
for ( ; it->first == jelem && it != attributes.end() ; ++it )
{
if ( !is_array_first )
{
oss << ",";
}
else
{
is_array_first = false;
}
it->second->to_json(oss);
}
oss << "]";
}
}
oss << "}";
json = oss.str();
return json;
}
string& Template::to_token(string& str) const
{
ostringstream os;
multimap<string,Attribute *>::const_iterator it;
for ( it = attributes.begin(); it!=attributes.end(); it++)
{
it->second->to_token(os);
}
str = os.str();
return str;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -341,6 +341,62 @@ string& History::to_xml(string& xml, bool database) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& History::to_json(string& json) const
{
ostringstream oss;
oss << "\"HISTORY\": {" <<
"\"OID\": \"" << oid << "\"," <<
"\"SEQ\": \"" << seq << "\"," <<
"\"HOSTNAME\": \"" << hostname << "\"," <<
"\"HID\": \"" << hid << "\"," <<
"\"CID\": \"" << cid << "\"," <<
"\"STIME\": \"" << stime << "\"," <<
"\"ETIME\": \"" << etime << "\"," <<
"\"VM_MAD\": \"" << vmm_mad_name << "\"," <<
"\"TM_MAD\": \"" << tm_mad_name << "\"," <<
"\"DS_ID\": \"" << ds_id << "\"," <<
"\"PSTIME\": \"" << prolog_stime << "\"," <<
"\"PETIME\": \"" << prolog_etime << "\"," <<
"\"RSTIME\": \"" << running_stime << "\"," <<
"\"RETIME\": \"" << running_etime << "\"," <<
"\"ESTIME\": \"" << epilog_stime << "\"," <<
"\"EETIME\": \"" << epilog_etime << "\"," <<
"\"ACTION\": \"" << action << "\"," <<
"\"UID\": \"" << uid << "\"," <<
"\"GID\": \"" << gid << "\"," <<
"\"REQUEST_ID\": \"" << req_id << "\",";
oss << "}";
json = oss.str();
return json;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& History::to_token(string& text) const
{
ostringstream oss;
oss << "HOSTNAME=";
one_util::escape_token(hostname, oss);
oss << "\n";
oss << "HID=" << hid << "\n" <<
"CID=" << cid << "\n" <<
"DS_ID=" << ds_id << "\n";
text = oss.str();
return text;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& History::to_xml_short(string& xml) const
{
ostringstream oss;

View File

@ -457,13 +457,13 @@ const char * VirtualMachine::table = "vm_pool";
const char * VirtualMachine::db_names =
"oid, name, body, uid, gid, last_poll, state, lcm_state, "
"owner_u, group_u, other_u, short_body";
"owner_u, group_u, other_u, short_body, search_token";
const char * VirtualMachine::db_bootstrap = "CREATE TABLE IF NOT EXISTS "
"vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, uid INTEGER, "
"gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, "
"owner_u INTEGER, group_u INTEGER, other_u INTEGER, short_body MEDIUMTEXT)";
"vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, "
"uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, "
"lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, "
"short_body MEDIUMTEXT, search_token MEDIUMTEXT";
const char * VirtualMachine::monit_table = "vm_monitoring";
@ -489,7 +489,21 @@ int VirtualMachine::bootstrap(SqlDB * db)
{
int rc;
ostringstream oss_vm(VirtualMachine::db_bootstrap);
string backend = Nebula::instance().get_db_backend();
ostringstream oss_vm;
oss_vm << VirtualMachine::db_bootstrap;
if (backend == "mysql")
{
oss_vm << ", FULLTEXT ftidx(search_token))";
}
else
{
oss_vm << ")";
}
ostringstream oss_monit(VirtualMachine::monit_db_bootstrap);
ostringstream oss_hist(History::db_bootstrap);
ostringstream oss_showback(VirtualMachine::showback_db_bootstrap);
@ -1662,10 +1676,12 @@ int VirtualMachine::insert_replace(SqlDB *db, bool replace, string& error_str)
ostringstream oss;
int rc;
string xml_body, short_xml_body;
string xml_body, short_xml_body, text;
char * sql_name;
char * sql_xml;
char * sql_short_xml;
char * sql_text;
sql_name = db->escape_str(name.c_str());
@ -1698,6 +1714,13 @@ int VirtualMachine::insert_replace(SqlDB *db, bool replace, string& error_str)
goto error_xml_short;
}
sql_text = db->escape_str(to_token(text).c_str());
if ( sql_text == 0 )
{
goto error_text;
}
if(replace)
{
oss << "REPLACE";
@ -1719,17 +1742,21 @@ int VirtualMachine::insert_replace(SqlDB *db, bool replace, string& error_str)
<< owner_u << ","
<< group_u << ","
<< other_u << ","
<< "'" << sql_short_xml << "'"
<< "'" << sql_short_xml << "',"
<< "'" << sql_text << "'"
<< ")";
db->free_str(sql_name);
db->free_str(sql_xml);
db->free_str(sql_short_xml);
db->free_str(sql_text);
rc = db->exec_wr(oss);
return rc;
error_text:
db->free_str(sql_text);
error_xml_short:
db->free_str(sql_short_xml);
error_xml:
@ -2145,7 +2172,7 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
string snap_xml;
string lock_str;
ostringstream oss;
ostringstream oss;
oss << "<VM>"
<< "<ID>" << oid << "</ID>"
@ -2215,6 +2242,91 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& VirtualMachine::to_json(string& json) const
{
string template_json;
string user_template_json;
string history_json;
ostringstream oss;
oss << "{\"VM\":{"
<< "\"ID\": \""<< oid << "\","
<< "\"UID\": \""<< uid << "\","
<< "\"GID\": \""<< gid << "\","
<< "\"UNAME\": \""<< uname << "\","
<< "\"GNAME\": \""<< gname << "\","
<< "\"NAME\": \""<< name << "\","
<< "\"LAST_POLL\": \""<< last_poll << "\","
<< "\"STATE\": \""<< state << "\","
<< "\"LCM_STATE\": \""<< lcm_state << "\","
<< "\"PREV_STATE\": \""<< prev_state << "\","
<< "\"PREV_LCM_STATE\": \""<< prev_lcm_state << "\","
<< "\"RESCHED\": \""<< resched << "\","
<< "\"STIME\": \""<< stime << "\","
<< "\"ETIME\": \""<< etime << "\","
<< "\"DEPLOY_ID\": \""<< deploy_id << "\","
<< obj_template->to_json(template_json) << ","
<< user_obj_template->to_json(user_template_json);
if ( hasHistory() )
{
oss << ",\"HISTORY_RECORDS\": [";
oss << history->to_json(history_json);
oss << "]";
}
oss << "}}";
json = oss.str();
return json;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& VirtualMachine::to_token(string& text) const
{
string template_text;
string user_template_text;
string history_text;
ostringstream oss;
oss << "UNAME="<< uname << "\n"
<< "GNAME="<< gname << "\n";
oss << "NAME=";
one_util::escape_token(name, oss);
oss << "\n";
oss << "LAST_POLL="<< last_poll << "\n"
<< "PREV_STATE="<< prev_state << "\n"
<< "PREV_LCM_STATE="<< prev_lcm_state << "\n"
<< "RESCHED="<< resched << "\n"
<< "STIME="<< stime << "\n"
<< "ETIME="<< etime << "\n"
<< "DEPLOY_ID="<< deploy_id << "\n"
<< obj_template->to_token(template_text) << "\n"
<< user_obj_template->to_token(user_template_text);
if ( hasHistory() )
{
oss << "\n" << history->to_token(history_text);
}
text = oss.str();
return text;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
string& VirtualMachine::to_xml_short(string& xml)
{
string disks_xml, monitoring_xml, user_template_xml, history_xml, nics_xml;

View File

@ -16,8 +16,8 @@
# Default configuration attributes for the vCenter driver
# (all domains will use these values as defaults)
# Valid atributes:
# Valid attributes:
# - nic[model]
NIC=[MODEL="VirtualE1000"]
# WARNING: Do not use!!
# Not honored due to https://github.com/OpenNebula/one/issues/2855

View File

@ -135,10 +135,15 @@ end
# Error used for raising LXDClient exception when response is error return value
class LXDError < StandardError
attr_reader :body
attr_reader :body, :error, :error_code, :type
def initialize(msg = 'LXD API error')
@body = msg
@error = @body['error']
@error_code = @body['error_code']
@type = @body['type']
super
end
end

View File

@ -340,7 +340,19 @@ class OpenNebulaVM
def profile(hash)
profile = @xml['//USER_TEMPLATE/LXD_PROFILE']
profile = 'default' if profile.empty?
if profile.empty?
profile = 'default'
else
begin
LXDClient.new.get("profiles/#{profile}")
rescue LXDError => e
raise e unless e.error_code == 404
OpenNebula.log_error "Profile \"#{profile}\" not found\n#{e}"
profile = 'default'
end
end
hash['profiles'] = [profile]
end

View File

@ -1163,8 +1163,8 @@ class VirtualMachine < VCenterDriver::Template
return RbVmomi::VIM::VirtualVmxnet2
when 'virtualvmxnet3', 'vmxnet3'
return RbVmomi::VIM::VirtualVmxnet3
else # If none matches, use VirtualE1000
return RbVmomi::VIM::VirtualE1000
else # If none matches, use vmxnet3
return RbVmomi::VIM::VirtualVmxnet3
end
end
@ -1238,20 +1238,20 @@ class VirtualMachine < VCenterDriver::Template
}
unmanaged_nics.each do |unic|
vnic = select_net.call(unic['VCENTER_NET_REF'])
vcenter_nic_class = vnic.class
new_model = unic['MODEL'] && !unic['MODEL'].empty? && !unic['MODEL'].nil?
opennebula_nic_class = nic_model_class(unic['MODEL']) if new_model
vnic = select_net.call(unic['VCENTER_NET_REF'])
nic_class = vnic.class
new_model = nic_model_class(unic['MODEL']) if unic['MODEL']
if new_model && opennebula_nic_class != vcenter_nic_class
# delete actual nic and update the new one.
# delete actual nic and update the new one.
if new_model && new_model != nic_class
device_change << { :device => vnic, :operation => :remove }
device_change << calculate_add_nic_spec(unic)
device_change << calculate_add_nic_spec(unic, vnic.unitNumber)
else
vnic.macAddress = unic['MAC']
device_change << { :device => vnic, :operation => :edit }
end
end
end
rescue Exception => e
raise "There is a problem with your vm NICS, make sure that they are working properly. Error: #{e.message}"
@ -1370,14 +1370,21 @@ class VirtualMachine < VCenterDriver::Template
device_change = []
if option == :all
dchange = []
# detached? condition indicates that the nic exists in OpeNebula but not
# in vCenter
nics_each(:detached?) do |nic|
device_change << {
dchange << {
:operation => :remove,
:device => nic.vc_item
}
end
if !dchange.empty?
dspec_hash = { :deviceChange => dchange }
dspec = RbVmomi::VIM.VirtualMachineConfigSpec(dspec_hash)
@item.ReconfigVM_Task(:spec => dspec).wait_for_completion
end
end
# no_exits? condition indicates that the nic does not exist in vCenter
@ -1499,21 +1506,15 @@ class VirtualMachine < VCenterDriver::Template
end
# Returns an array of actions to be included in :deviceChange
def calculate_add_nic_spec(nic)
def calculate_add_nic_spec(nic, unumber = nil)
mac = nic["MAC"]
pg_name = nic["BRIDGE"]
model = ''
default = VCenterDriver::VIHelper.get_default('VM/TEMPLATE/NIC/MODEL')
tmodel = one_item['USER_TEMPLATE/NIC_DEFAULT/MODEL']
model = nic['MODEL'] || tmodel || default
raise 'nic model cannot be empty!' if model == ''
if !one_item.retrieve_xmlelements('TEMPLATE/NIC_DEFAULT/MODEL').nil? &&
!one_item.retrieve_xmlelements('TEMPLATE/NIC_DEFAULT/MODEL').empty?
model = one_item['TEMPLATE/NIC_DEFAULT/MODEL']
elsif (model.nil? || model.empty?) &&
!nic['MODEL'].nil? &&
!nic['MODEL'].empty?
model = nic['MODEL']
else
model = VCenterDriver::VIHelper.get_default('VM/TEMPLATE/NIC/MODEL')
end
vnet_ref = nic["VCENTER_NET_REF"]
backing = nil
@ -1546,24 +1547,7 @@ class VirtualMachine < VCenterDriver::Template
card_num += 1 if is_nic?(dv)
end
nic_card = case model
when "virtuale1000", "e1000"
RbVmomi::VIM::VirtualE1000
when "virtuale1000e", "e1000e"
RbVmomi::VIM::VirtualE1000e
when "virtualpcnet32", "pcnet32"
RbVmomi::VIM::VirtualPCNet32
when "virtualsriovethernetcard", "sriovethernetcard"
RbVmomi::VIM::VirtualSriovEthernetCard
when "virtualvmxnetm", "vmxnetm"
RbVmomi::VIM::VirtualVmxnetm
when "virtualvmxnet2", "vmnet2"
RbVmomi::VIM::VirtualVmxnet2
when "virtualvmxnet3", "vmxnet3"
RbVmomi::VIM::VirtualVmxnet3
else # If none matches, use VirtualE1000
RbVmomi::VIM::VirtualE1000
end
nic_card = nic_model_class(model)
if network.class == RbVmomi::VIM::Network
backing = RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(
@ -1580,7 +1564,13 @@ class VirtualMachine < VCenterDriver::Template
end
# grab the last unitNumber to ensure the nic to be added at the end
@unic = @unic || get_vcenter_nics.map{|d| d.unitNumber}.max || 0
if !unumber
@unic = @unic || get_vcenter_nics.map{|d| d.unitNumber}.max || 0
unumber = @unic += 1
else
@unic = unumber
end
card_spec = {
:key => 0,
:deviceInfo => {
@ -1590,7 +1580,7 @@ class VirtualMachine < VCenterDriver::Template
:backing => backing,
:addressType => mac ? 'manual' : 'generated',
:macAddress => mac,
:unitNumber => @unic+=1
:unitNumber => unumber
}
if (limit || rsrv) && (limit > 0)
@ -1616,17 +1606,11 @@ class VirtualMachine < VCenterDriver::Template
def calculate_add_nic_spec_autogenerate_mac(nic)
pg_name = nic["BRIDGE"]
model = ''
default = VCenterDriver::VIHelper.get_default('VM/TEMPLATE/NIC/MODEL')
tmodel = one_item['USER_TEMPLATE/NIC_DEFAULT/MODEL']
model = nic['MODEL'] || tmodel || default
if !one_item.retrieve_xmlelements('TEMPLATE/NIC_DEFAULT/MODEL').nil? &&
!one_item.retrieve_xmlelements('TEMPLATE/NIC_DEFAULT/MODEL').empty?
model = one_item['TEMPLATE/NIC_DEFAULT/MODEL']
elsif (model.nil? || model.empty?) &&
!nic['MODEL'].nil? &&
!nic['MODEL'].empty?
model = nic['MODEL']
else
model = VCenterDriver::VIHelper.get_default('VM/TEMPLATE/NIC/MODEL')
end
vnet_ref = nic["VCENTER_NET_REF"]
backing = nil
@ -1658,24 +1642,7 @@ class VirtualMachine < VCenterDriver::Template
card_num += 1 if is_nic?(dv)
end
nic_card = case model
when "virtuale1000", "e1000"
RbVmomi::VIM::VirtualE1000
when "virtuale1000e", "e1000e"
RbVmomi::VIM::VirtualE1000e
when "virtualpcnet32", "pcnet32"
RbVmomi::VIM::VirtualPCNet32
when "virtualsriovethernetcard", "sriovethernetcard"
RbVmomi::VIM::VirtualSriovEthernetCard
when "virtualvmxnetm", "vmxnetm"
RbVmomi::VIM::VirtualVmxnetm
when "virtualvmxnet2", "vmnet2"
RbVmomi::VIM::VirtualVmxnet2
when "virtualvmxnet3", "vmxnet3"
RbVmomi::VIM::VirtualVmxnet3
else # If none matches, use VirtualE1000
RbVmomi::VIM::VirtualE1000
end
nic_card = nic_model_class(model)
if network.class == RbVmomi::VIM::Network
backing = RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(

View File

@ -14,10 +14,10 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
# No : VCENTER_IMPORTED attribute will be set on imported images
# no : VCENTER_IMPORTED attribute will be set on imported images
# this attribute prevents the image to be deleted.
# Yes : You can delete the images using OpenNebula.
:delete_images: No
# yes : You can delete the images using OpenNebula.
:delete_images: no
# Default timeout to complete deploy
:vm_poweron_wait_default: 300

View File

@ -26,13 +26,13 @@
int AddressRangeIPAM::from_vattr(VectorAttribute * attr, std::string& error_msg)
{
std::ostringstream oss;
IPAMManager * ipamm = Nebula::instance().get_ipamm();
std::string * ar_xml = attr->to_xml();
attr->to_xml(oss);
IPAMRequest ir(*ar_xml);
free(ar_xml);
IPAMRequest ir(oss.str());
ipamm->trigger(IPMAction::REGISTER_ADDRESS_RANGE, &ir);