mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-25 02:50:08 +03:00
feature #4217: Monitor external marketplaces. Import functionality for
existing apps. Drivers for OpenNebula public marketplace
This commit is contained in:
parent
10b8699fdc
commit
49b9de94f5
@ -108,6 +108,15 @@ public:
|
||||
*/
|
||||
int from_xml(const std::string &xml_str);
|
||||
|
||||
/**
|
||||
* Rebuilds the object from base64 encoded template representation
|
||||
* @param str The template string, base64 encoded
|
||||
* @param error_str Returns the error reason, if any
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int from_template64(const std::string &xml_str, std::string& error_str);
|
||||
|
||||
/**
|
||||
* Enable or disable the app. A disabled app cannot be exported
|
||||
* @param enable true to enable
|
||||
@ -115,7 +124,7 @@ public:
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int enable(bool enable, string& error_str);
|
||||
int enable(bool enable, std::string& error_str);
|
||||
|
||||
/**
|
||||
* Returns the marketplace ID
|
||||
|
@ -60,6 +60,17 @@ public:
|
||||
const std::string& mp_data,
|
||||
int * oid,
|
||||
std::string& error_str);
|
||||
/**
|
||||
* Imports an app into the marketplace, as reported by the monitor driver
|
||||
* @param template to generate app with the from_template64 function
|
||||
* @param mp_id of the MarketPlace to store de App
|
||||
* @param mp_name of the MarketPlace
|
||||
* @param error_str Returns the error reason, if any
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int import(const std::string& t64, int mp_id, const std::string& mp_name,
|
||||
std::string& error_str);
|
||||
|
||||
/**
|
||||
* Function to get a MarketPlaceApp from the pool
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "SqlDB.h"
|
||||
|
||||
class SqlDB;
|
||||
class MarketPlaceApp;
|
||||
|
||||
class MarketPlacePool : public PoolSQL
|
||||
{
|
||||
|
@ -665,7 +665,7 @@ DATASTORE_MAD = [
|
||||
|
||||
MARKET_MAD = [
|
||||
executable = "one_market",
|
||||
arguments = "-t 15 -m http,s3"
|
||||
arguments = "-t 15 -m http,s3,one"
|
||||
]
|
||||
|
||||
#*******************************************************************************
|
||||
|
@ -81,6 +81,12 @@ MarketPlaceApp::~MarketPlaceApp()
|
||||
int MarketPlaceApp::insert(SqlDB *db, string& error_str)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
bool imported;
|
||||
|
||||
if (get_template_attribute("IMPORTED", imported) && imported)
|
||||
{
|
||||
return insert_replace(db, false, error_str);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check default marketplace app attributes
|
||||
@ -402,3 +408,61 @@ int MarketPlaceApp::enable(bool enable, string& error_str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
int MarketPlaceApp::from_template64(const std::string &info64, std::string& err)
|
||||
{
|
||||
std::string * info = one_util::base64_decode(info64);
|
||||
std::string sdate;
|
||||
|
||||
if (info == 0)
|
||||
{
|
||||
err = "Error decoding driver message";
|
||||
return -1;
|
||||
}
|
||||
|
||||
char * error_msg;
|
||||
|
||||
int rc = obj_template->parse(*info, &error_msg);
|
||||
|
||||
delete info;
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
err = error_msg;
|
||||
|
||||
free(error_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
state = READY;
|
||||
|
||||
type = IMAGE;
|
||||
origin_id = -1;
|
||||
remove_template_attribute("TYPE");
|
||||
remove_template_attribute("ORIGIN_ID");
|
||||
|
||||
erase_template_attribute("NAME", name);
|
||||
erase_template_attribute("SOURCE", source);
|
||||
erase_template_attribute("DESCRIPTION", description);
|
||||
erase_template_attribute("SIZE", size_mb);
|
||||
erase_template_attribute("VERSION", version);
|
||||
erase_template_attribute("MD5", md5);
|
||||
erase_template_attribute("PUBLISHER", publisher);
|
||||
erase_template_attribute("FORMAT", format);
|
||||
erase_template_attribute("APPTEMPLATE64", apptemplate64);
|
||||
|
||||
erase_template_attribute("DATE", sdate);
|
||||
std::istringstream iss(sdate);
|
||||
iss >> date;
|
||||
|
||||
if ( date == 0 )
|
||||
{
|
||||
date = time(NULL);
|
||||
}
|
||||
|
||||
replace_template_attribute("IMPORTED", "YES");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,8 @@ int MarketPlaceAppPool:: allocate(
|
||||
|
||||
mp->state = MarketPlaceApp::INIT;
|
||||
|
||||
mp->remove_template_attribute("IMPORTED");
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check name & duplicates
|
||||
// -------------------------------------------------------------------------
|
||||
@ -104,6 +106,53 @@ error_name:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int MarketPlaceAppPool::import(const std::string& t64, int mp_id,
|
||||
const std::string& mp_name, std::string& error_str)
|
||||
{
|
||||
MarketPlaceApp * app = new MarketPlaceApp(UserPool::ONEADMIN_ID,
|
||||
GroupPool::ONEADMIN_ID, UserPool::oneadmin_name,
|
||||
GroupPool::ONEADMIN_NAME, 0133, 0);
|
||||
|
||||
int rc = app->from_template64(t64, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
delete app;
|
||||
return -1;
|
||||
}
|
||||
|
||||
app->market_id = mp_id;
|
||||
app->market_name = mp_name;
|
||||
|
||||
if ( !PoolObjectSQL::name_is_valid(app->name, error_str) )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << "imported-" << app->get_origin_id();
|
||||
app->name = oss.str();
|
||||
|
||||
if ( !PoolObjectSQL::name_is_valid(app->name, error_str) )
|
||||
{
|
||||
error_str = "Cannot generate a valida name for app";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
MarketPlaceApp * mp_aux = get(app->name, 0, false);
|
||||
|
||||
if( mp_aux != 0 )
|
||||
{
|
||||
//Marketplace app already imported
|
||||
delete app;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return PoolSQL::allocate(app, error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int MarketPlaceAppPool::update(PoolObjectSQL * objsql)
|
||||
{
|
||||
if (Nebula::instance().is_federation_slave())
|
||||
|
@ -60,6 +60,7 @@ void MarketPlaceManagerDriver::monitor(int oid, const std::string& msg) const
|
||||
static void monitor_action(
|
||||
std::istringstream& is,
|
||||
MarketPlacePool * marketpool,
|
||||
MarketPlaceAppPool * apppool,
|
||||
MarketPlaceManager * marketm,
|
||||
int id,
|
||||
const std::string& result)
|
||||
@ -80,6 +81,15 @@ static void monitor_action(
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != "SUCCESS")
|
||||
{
|
||||
oss << "Error monitoring datastore " << id << ": " << info64;
|
||||
NebulaLog::log("MKP", Log::ERROR, oss);
|
||||
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
|
||||
info = one_util::base64_decode(info64);
|
||||
|
||||
if (info == 0)
|
||||
@ -91,14 +101,6 @@ static void monitor_action(
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != "SUCCESS")
|
||||
{
|
||||
oss << "Error monitoring datastore " << id << ": " << *info;
|
||||
NebulaLog::log("MKP", Log::ERROR, oss);
|
||||
|
||||
delete info;
|
||||
return;
|
||||
}
|
||||
|
||||
Template monitor_data;
|
||||
|
||||
@ -134,10 +136,29 @@ static void monitor_action(
|
||||
|
||||
market->unlock();
|
||||
|
||||
std::vector<Attribute *> apps;
|
||||
std::string err;
|
||||
|
||||
int num = monitor_data.get("APP", apps);
|
||||
|
||||
for (int i=0; i< num ; i++)
|
||||
{
|
||||
SingleAttribute * sa = static_cast<SingleAttribute *>(apps[i]);
|
||||
|
||||
if ( sa == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( apppool->import(sa->value(), id, name, err) == -1 )
|
||||
{
|
||||
NebulaLog::log("MKP", Log::ERROR, "Error importing app: " + err);
|
||||
}
|
||||
}
|
||||
|
||||
oss << "Marketplace " << name << " (" << id << ") successfully monitored.";
|
||||
|
||||
NebulaLog::log("ImM", Log::DEBUG, oss);
|
||||
NebulaLog::log("MKP", Log::DEBUG, oss);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -437,7 +458,7 @@ void MarketPlaceManagerDriver::protocol(const string& message) const
|
||||
}
|
||||
else if (action == "MONITOR")
|
||||
{
|
||||
monitor_action(is, marketpool, marketm, id, result);
|
||||
monitor_action(is, marketpool, apppool, marketm, id, result);
|
||||
}
|
||||
else if (action == "LOG")
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ require 'base64'
|
||||
class OneMarket
|
||||
ONE_MARKET_URL = 'http://marketplace.opennebula.systems/'
|
||||
AGENT = 'Market Driver'
|
||||
VERSION = '../../VERSION'
|
||||
VERSION = File.dirname(__FILE__) + '/../../VERSION'
|
||||
|
||||
def initialize(url=ONE_MARKET_URL)
|
||||
@url = url
|
||||
@ -59,39 +59,49 @@ class OneMarket
|
||||
appstr = ""
|
||||
|
||||
applist['appliances'].each { |app|
|
||||
tmpl = "NAME =\"#{app["name"]}\"\n"
|
||||
tmpl << "IMPORT_ID =\"#{app["_id"]["$oid"]}\"\n"
|
||||
tmpl << "TYPE = IMAGE\n"
|
||||
tmpl << "PUBLISHER = #{app["publisher"]}\n"
|
||||
tmpl << "FORMAT = #{app["format"]}\n"
|
||||
tmpl << "DESCRIPTION = \"#{app["short_description"]}\"\n"
|
||||
tmpl << "VERSION = #{app["version"]}\n"
|
||||
tmpl << "TAGS = \"#{app["tags"].join(', ')}\"\n"
|
||||
tmpl << "DATE = #{app["creation_time"]}\n"
|
||||
id = app["_id"]["$oid"]
|
||||
source = "#{@url}/appliance/#{id}/download/0"
|
||||
|
||||
tmpl = ""
|
||||
|
||||
print_var(tmpl, "NAME", app["name"])
|
||||
print_var(tmpl, "SOURCE", source)
|
||||
print_var(tmpl, "IMPORT_ID", id)
|
||||
print_var(tmpl, "ORIGIN_ID", "-1")
|
||||
print_var(tmpl, "TYPE", "IMAGE")
|
||||
print_var(tmpl, "PUBLISHER", app["publisher"])
|
||||
print_var(tmpl, "FORMAT", app["format"])
|
||||
print_var(tmpl, "DESCRIPTION", app["short_description"])
|
||||
print_var(tmpl, "VERSION", app["version"])
|
||||
print_var(tmpl, "TAGS", app["tags"].join(', '))
|
||||
print_var(tmpl, "DATE", app["creation_time"])
|
||||
|
||||
if !app["files"].nil? && !app["files"][0].nil?
|
||||
file = app["files"][0]
|
||||
size = 0
|
||||
|
||||
tmpl << "SIZE = #{app["files"][0]["size"]}\n"
|
||||
tmpl << "MD5 = #{app["files"][0]["md5"]}\n"
|
||||
if (file["size"].to_i != 0)
|
||||
size = file["size"].to_i / (2**20)
|
||||
end
|
||||
|
||||
print_var(tmpl, "SIZE", size)
|
||||
print_var(tmpl, "MD5", file["md5"])
|
||||
|
||||
tmpl64 = ""
|
||||
tmpl64 << "DEV_PREFIX = #{file["dev_prefix"]}\n" if file["dev_prefix"]
|
||||
tmpl64 << "DRIVER = #{file["driver"]}\n" if file["driver"]
|
||||
tmpl64 << "TYPE = #{file["type"]}\n" if file["type"]
|
||||
print_var(tmpl64, "DEV_PREFIX", file["dev_prefix"])
|
||||
print_var(tmpl64, "DRIVER", file["driver"])
|
||||
print_var(tmpl64, "TYPE", file["type"])
|
||||
|
||||
if !tmpl64.empty?
|
||||
tmpl << "APPTEMPLATE64 = \"#{Base64::strict_encode64(tmpl64)}\"\n"
|
||||
print_var(tmpl64, "APPTEMPLATE64", Base64::strict_encode64(tmpl64))
|
||||
end
|
||||
end
|
||||
|
||||
if !app["opennebula_template"].nil?
|
||||
vmtmpl64 = template_to_str(JSON.parse(app["opennebula_template"]))
|
||||
tmpl << "VMTEMPLATE64 = \"#{Base64::strict_encode64(vmtmpl64)}\"\n"
|
||||
print_var(tmpl, "VMTEMPLATE64", Base64::strict_encode64(vmtmpl64))
|
||||
end
|
||||
|
||||
tmpl << "APPTEMPLATE64 = \"#{Base64::strict_encode64(tmpl64)}\"\n"
|
||||
|
||||
appstr << "APP=\"#{Base64::strict_encode64(tmpl)}\"\n"
|
||||
}
|
||||
|
||||
@ -100,6 +110,13 @@ class OneMarket
|
||||
|
||||
private
|
||||
|
||||
def print_var(str, name, val)
|
||||
return if val.nil?
|
||||
return if val.class == String && val.empty?
|
||||
|
||||
str << "#{name}=\"#{val}\"\n"
|
||||
end
|
||||
|
||||
def template_to_str(thash)
|
||||
thash.collect do |key, value|
|
||||
next if value.nil? || value.empty?
|
||||
|
Loading…
x
Reference in New Issue
Block a user