1
0
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:
Ruben S. Montero 2015-12-28 01:08:33 +01:00
parent 10b8699fdc
commit 49b9de94f5
8 changed files with 203 additions and 31 deletions

View File

@ -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

View File

@ -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

View File

@ -22,6 +22,7 @@
#include "SqlDB.h"
class SqlDB;
class MarketPlaceApp;
class MarketPlacePool : public PoolSQL
{

View File

@ -665,7 +665,7 @@ DATASTORE_MAD = [
MARKET_MAD = [
executable = "one_market",
arguments = "-t 15 -m http,s3"
arguments = "-t 15 -m http,s3,one"
]
#*******************************************************************************

View File

@ -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;
}

View File

@ -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())

View File

@ -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")
{

View File

@ -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?