1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-11 05:17:41 +03:00

feature #4127: Delete for marketplace apps, fix bug

This commit is contained in:
Ruben S. Montero 2015-12-21 13:23:22 +01:00
parent ade6513a0d
commit 21eb1b0803
13 changed files with 367 additions and 85 deletions

View File

@ -148,6 +148,16 @@ public:
return origin_id;
};
const string& get_source()
{
return source;
}
MarketPlaceAppState get_state()
{
return state;
}
//--------------------------------------------------------------------------
// Set Marketplace app attributes
//--------------------------------------------------------------------------
@ -171,6 +181,11 @@ public:
size_mb = _size_mb;
};
void set_format(const std::string& _format)
{
format = _format;
};
private:
friend class MarketPlaceAppPool;
@ -213,6 +228,11 @@ private:
*/
std::string version;
/**
* format of the disk images
*/
std::string format;
/**
* App template to import it
*/

View File

@ -108,12 +108,13 @@ public:
/**
* Deletes an app from the marketplace.
* @param iid id of image
* @param error_str Error reason, if any
* @param appid of the app
* @param market_data of the associated marketplace in XML format
* @param error descrition
*
* @return 0 on success
*/
int delete_app(int iid, std::string& error_str);
int delete_app(int appid, const std::string& market_data, std::string& err);
/**
* Trigger a monitor action for the marketplace .
@ -121,6 +122,12 @@ public:
*/
void monitor_market(int ds_id);
/**
* Relsease resources locked by this app during the import phase
* @param appid of the app
*/
void release_app_resources(int appid);
private:
/**
* Generic name for the marketplace driver

View File

@ -25,6 +25,7 @@
class MarketPlacePool;
class MarketPlaceAppPool;
class MarketPlaceManager;
/**
* ImageManagerDriver represents the basic abstraction for Image Repository
@ -38,8 +39,10 @@ public:
const std::map<string,string>& attrs,
bool sudo,
MarketPlacePool * _marketpool,
MarketPlaceAppPool * _apppool
):Mad(userid,attrs,sudo), marketpool(_marketpool), apppool(_apppool){};
MarketPlaceAppPool * _apppool,
MarketPlaceManager * _marketm
):Mad(userid,attrs,sudo), marketpool(_marketpool), apppool(_apppool),
marketm(_marketm){};
virtual ~MarketPlaceManagerDriver(){};
@ -64,6 +67,8 @@ private:
MarketPlaceAppPool * apppool;
MarketPlaceManager * marketm;
/**
* Sends a stat request to the MAD.
* @param oid the id of the stat request

View File

@ -137,9 +137,6 @@ public:
~ImageDelete(){};
/* -------------------------------------------------------------------- */
int drop(int oid, PoolObjectSQL * object, string& error_msg);
};
@ -406,6 +403,8 @@ public:
};
~MarketPlaceAppDelete(){};
int drop(int oid, PoolObjectSQL * object, string& error_msg);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -58,12 +58,12 @@ BRIDGE_LIST="${XPATH_ELEMENTS[i++]}"
INFO_SCRIPT=$(cat <<EOF
CHECKSUM=\$(${MD5SUM} ${SRC} | cut -f1 -d' ')
SIZE=\$(${DU} -LBM ${SRC} | cut -f1)
SIZE=\$(${DU} -Lm ${SRC} | cut -f1)
FORMAT=\$(${QEMU_IMG} info ${SRC} 2>/dev/null | grep -Po '(?<=file format: )\w+')
echo "<CHECKSUM>\$CHECKSUM</CHECKSUM>"
echo "<SIZE>\$SIZE</SIZE>"
echo "<FORMAT>\$FORMAT</FORMAT>"
echo "<FORMAT>\${FORMAT-"unknown"}</FORMAT>"
EOF
)

View File

@ -93,6 +93,7 @@ int MarketPlaceApp::insert(SqlDB *db, string& error_str)
remove_template_attribute("SOURCE");
remove_template_attribute("SIZE");
remove_template_attribute("CHECKSUM");
remove_template_attribute("FORMAT");
date = time(NULL);
@ -248,6 +249,7 @@ std::string& MarketPlaceApp::to_xml(std::string& xml) const
"<DESCRIPTION>" << description << "</DESCRIPTION>" <<
"<PUBLISHER>" << publisher << "</PUBLISHER>" <<
"<VERSION>" << version << "</VERSION>" <<
"<FORMAT>" << format << "</FORMAT>" <<
"<APPTEMPLATE64>" << apptemplate64 << "</APPTEMPLATE64>" <<
"<MARKETPLACE_ID>" << market_id << "</MARKETPLACE_ID>" <<
"<MARKETPLACE>" << market_name << "</MARKETPLACE>" <<
@ -292,6 +294,7 @@ int MarketPlaceApp::from_xml(const std::string &xml_str)
rc += xpath(version, "/MARKETPLACEAPP/VERSION", "not_found");
rc += xpath(checksum, "/MARKETPLACEAPP/CHECKSUM", "not_found");
rc += xpath(publisher, "/MARKETPLACEAPP/PUBLISHER", "not_found");
rc += xpath(format, "/MARKETPLACEAPP/FORMAT", "not_found");
rc += xpath(apptemplate64,"/MARKETPLACEAPP/APPTEMPLATE64", "not_found");
rc += xpath(market_name, "/MARKETPLACEAPP/MARKETPLACE", "not_found");
rc += xpath(market_id, "/MARKETPLACEAPP/MARKETPLACE_ID", -1);

View File

@ -98,7 +98,7 @@ int MarketPlaceManager::load_mads(int uid)
market_conf.replace("NAME", market_driver_name);
marketm_mad= new MarketPlaceManagerDriver(0, market_conf.value(), false,
mppool, apppool);
mppool, apppool, this);
rc = add(marketm_mad);

View File

@ -122,3 +122,108 @@ int MarketPlaceManager::import_app(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void MarketPlaceManager::release_app_resources(int appid)
{
MarketPlaceApp * app = apppool->get(appid, true);
if (app == 0)
{
return;
}
MarketPlaceApp::MarketPlaceAppType type = app->get_type();
int iid = app->get_origin_id();
app->unlock();
switch (type)
{
case MarketPlaceApp::IMAGE:
imagem->release_cloning_image(iid, -appid);
return;
case MarketPlaceApp::VMTEMPLATE:
case MarketPlaceApp::FLOW:
case MarketPlaceApp::UNKNOWN:
return;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int MarketPlaceManager::delete_app(int appid, const std::string& market_data,
std::string& error_str)
{
MarketPlaceApp * app;
MarketPlace * mp;
std::string app_data;
std::string * msg;
const MarketPlaceManagerDriver* mpmd = get();
if ( mpmd == 0 )
{
error_str = "Error getting MarketPlaceManagerDriver";
return -1;
}
app = apppool->get(appid, true);
if (app == 0)
{
error_str = "Marketplace app no longer exists";
return -1;
}
app->to_xml(app_data);
MarketPlaceApp::MarketPlaceAppType type = app->get_type();
MarketPlaceApp::MarketPlaceAppState state = app->get_state();
int market_id = app->get_market_id();
app->unlock();
switch (type)
{
case MarketPlaceApp::IMAGE:
switch (state)
{
case MarketPlaceApp::LOCKED:
release_app_resources(appid);
break;
case MarketPlaceApp::INIT:
case MarketPlaceApp::READY :
case MarketPlaceApp::ERROR:
break;
}
break;
case MarketPlaceApp::VMTEMPLATE:
case MarketPlaceApp::FLOW:
case MarketPlaceApp::UNKNOWN:
return -1;
}
mp = mppool->get(market_id, true);
if ( mp != 0 )
{
mp->del_marketapp(appid);
mppool->update(mp);
mp->unlock();
}
msg = format_message(app_data, market_data, "");
mpmd->deleteapp(appid, *msg);
delete msg;
return 0;
}

View File

@ -68,70 +68,6 @@ void MarketPlaceManagerDriver::monitor(int oid, const std::string& msg) const
/* MAD Interface */
/* ************************************************************************** */
/*
static int delete_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
int rc;
int ds_id = -1;
string tmp_error;
string source;
string info;
Image * image;
ostringstream oss;
image = ipool->get(id, true);
if ( image == 0 )
{
return ds_id;
}
ds_id = image->get_ds_id();
source = image->get_source();
rc = ipool->drop(image, tmp_error);
image->unlock();
if ( result == "FAILURE" )
{
goto error;
}
else if ( rc < 0 )
{
goto error_drop;
}
NebulaLog::log("ImM", Log::INFO, "Image successfully removed.");
return ds_id;
error_drop:
oss << "Error removing image from DB: " << tmp_error
<< ". Remove image source " << source << " to completely delete image.";
NebulaLog::log("ImM", Log::ERROR, oss);
return ds_id;
error:
oss << "Error removing image from datastore. Manually remove image source "
<< source << " to completely delete the image";
getline(is,info);
if (!info.empty() && (info[0] != '-'))
{
oss << ": " << info;
}
NebulaLog::log("ImM", Log::ERROR, oss);
return ds_id;
}
*/
/* -------------------------------------------------------------------------- */
/*
@ -286,11 +222,13 @@ static void app_failure_action(
app->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static int import_action(
std::istringstream& is,
MarketPlaceAppPool * apppool,
MarketPlaceManager * marketm,
int id,
const std::string& result)
{
@ -306,12 +244,14 @@ static int import_action(
std::string source;
std::string checksum;
std::string format;
long long size_mb;
marketm->release_app_resources(id);
if ( result == "FAILURE" )
{
app_failure_action(&is, apppool, id,
"Error importing app into marketplace");
app_failure_action(&is, apppool, id, "Error importing app into marketplace");
return -1;
}
@ -340,9 +280,10 @@ static int import_action(
tmpl.get("SOURCE", source);
tmpl.get("CHECKSUM", checksum);
tmpl.get("FORMAT", format);
rc = tmpl.get("SIZE", size_mb);
if ( source.empty() || checksum.empty() || rc == false )
if ( source.empty() || checksum.empty() || format.empty() || rc == false )
{
goto error_attributes;
}
@ -357,6 +298,7 @@ static int import_action(
app->set_source(source);
app->set_checksum(checksum);
app->set_size(size_mb);
app->set_format(format);
app->set_state(MarketPlaceApp::READY);
@ -397,6 +339,68 @@ error_app:
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static int delete_action(
std::istringstream& is,
MarketPlaceAppPool * apppool,
MarketPlaceManager * marketm,
int id,
const std::string& result)
{
int rc;
std::string source;
std::string error;
std::ostringstream eoss("Error removing app from marketplace");
MarketPlaceApp * app = apppool->get(id, true);
if ( app == 0 )
{
return -1;
}
source = app->get_source();
rc = apppool->drop(app, error);
app->unlock();
if ( result == "FAILURE" )
{
std::string info;
getline(is, info);
if (!info.empty() && (info[0] != '-'))
{
eoss << ": " << info;
}
eoss << ".";
}
if ( rc < 0 )
{
eoss << " Error removing app from DB: " << error
<< ". Remove app manually, source is: " << source;
}
if ( rc < 0 || result == "FAILURE" )
{
NebulaLog::log("MKP", Log::ERROR, eoss.str());
}
else
{
NebulaLog::log("MKP",Log::INFO,"Marketplace app successfully removed.");
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void MarketPlaceManagerDriver::protocol(const string& message) const
{
std::istringstream is(message);
@ -445,7 +449,7 @@ void MarketPlaceManagerDriver::protocol(const string& message) const
if (action == "IMPORT")
{
import_action(is, apppool, id, result);
import_action(is, apppool, marketm, id, result);
}
else if (action == "EXPORT")
{
@ -453,7 +457,7 @@ void MarketPlaceManagerDriver::protocol(const string& message) const
}
else if (action == "DELETE")
{
return;
delete_action(is, apppool, marketm, id, result);
}
else if (action == "MONITOR")
{

View File

@ -164,18 +164,36 @@ class MarketPlaceDriver < OpenNebulaDriver
mp_msg64 = Base64::strict_encode64(xml.to_xml)
result, info = do_action(id, mp_mad, nil, :import, "#{mp_msg64} #{id}",
true)
rc, info = do_action(id, mp_mad, nil, :import, "#{mp_msg64} #{id}",true)
send_message(ACTION[:import], result, id, info)
send_message(ACTION[:import], rc, id, info)
end
def export(id, drv_message)
send_message(ACTION[:export], RESULT[:failure], id, "Not implemented")
end
############################################################################
# Deletes an app from the marketplace by freeing the underlying resources
############################################################################
def delete(id, drv_message)
send_message(ACTION[:export], RESULT[:failure], id, "Not implemented")
xml = decode(drv_message)
if xml.nil?
failure(:import, id, "Cannot decode driver message")
return
end
mp_mad = xml['MARKETPLACE/MARKET_MAD']
if mp_mad.nil?
failure(:import, id, "Wrong driver message format")
return
end
rc, info = do_action(id,mp_mad,nil,:delete,"#{drv_message} #{id}",false)
send_message(ACTION[:delete], rc, id, info)
end
def monitor(id, drv_message)
@ -230,6 +248,8 @@ class MarketPlaceDriver < OpenNebulaDriver
doc = OpenNebula::XMLElement.new
doc.initialize_xml(msg, 'MARKET_DRIVER_ACTION_DATA')
doc = nil if doc.xml_nil?
return doc
end

81
src/market_mad/remotes/http/delete Normal file → Executable file
View File

@ -0,0 +1,81 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems #
# #
# 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. #
# -------------------------------------------------------------------------- #
###############################################################################
# This script is used to import a file into the marketplace. The source file
# is an opaque representation of an OpenNebula object, like a image file or a
# tar.gz with several vm template or flow disk images
###############################################################################
# -------- Set up the environment to source common tools & conf ------------
if [ -z "${ONE_LOCATION}" ]; then
LIB_LOCATION=/usr/lib/one
else
LIB_LOCATION=$ONE_LOCATION/lib
fi
. $LIB_LOCATION/sh/scripts_common.sh
DRIVER_PATH=$(dirname $0)
source ${DRIVER_PATH}/../../datastore/libfs.sh
UTILS_PATH="${DRIVER_PATH}/../../datastore"
# -------- Get arguments from OpenNebula core ------------
DRV_ACTION=$1
ID=$2
XPATH="$UTILS_PATH/xpath.rb -b $DRV_ACTION"
unset i XPATH_ELEMENTS
while IFS= read -r -d '' element; do
XPATH_ELEMENTS[i++]="$element"
done < <($XPATH /MARKET_DRIVER_ACTION_DATA/MARKETPLACEAPP/SOURCE \
/MARKET_DRIVER_ACTION_DATA/MARKETPLACE/TEMPLATE/BASE_URL \
/MARKET_DRIVER_ACTION_DATA/MARKETPLACE/TEMPLATE/BRIDGE_LIST \
/MARKET_DRIVER_ACTION_DATA/MARKETPLACE/TEMPLATE/PUBLIC_DIR)
unset i
SOURCE="${XPATH_ELEMENTS[i++]}"
BASE_URL="${XPATH_ELEMENTS[i++]}"
BRIDGE_LIST="${XPATH_ELEMENTS[i++]}"
PUBLIC_DIR="${XPATH_ELEMENTS[i++]}"
# ----------------- Delete the app source from public folder -------------------
APPNAME=${SOURCE##${BASE_URL}}
DST_PATH="${PUBLIC_DIR}/${APPNAME}"
if [ -n "$BRIDGE_LIST" ]; then
DST_HOST=`get_destination_host $ID`
ssh_exec_and_log "${DST_HOST}" "[ -f ${DST_PATH} ] && rm -rf ${DST_PATH}" \
"Error deleting ${DST_PATH} in ${DST_HOST}"
else
if [ -f ${DST_PATH} ]
then
log "Removing ${DST_PATH} from the marketplace"
exec_and_log "rm -rf ${DST_PATH}" "Error deleting ${DST_PATH}"
else
log_error "Bad formed or unavailable app source: ${DST_PATH}"
exit 1
fi
fi

View File

@ -66,7 +66,7 @@ module OpenNebula
end
# Checks if the internal XML representation is valid
def nil?
def xml_nil?
return @xml.nil?
end

View File

@ -363,3 +363,41 @@ int SecurityGroupDelete::drop(int oid, PoolObjectSQL * object, string& error_msg
return RequestManagerDelete::drop(oid, object, error_msg);
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
int MarketPlaceAppDelete::drop(int oid, PoolObjectSQL * object, string& emsg)
{
Nebula& nd = Nebula::instance();
MarketPlaceManager * marketm = nd.get_marketm();
MarketPlacePool * marketpool = nd.get_marketpool();
MarketPlaceApp * app = static_cast<MarketPlaceApp *>(object);
int mp_id = app->get_market_id();
app->unlock();
MarketPlace * mp = marketpool->get(mp_id, true);
if ( mp == 0 )
{
emsg = "Cannot find associated MARKETPLACE";
return -1;
}
std::string mp_name = mp->get_name();
std::string mp_data;
mp->to_xml(mp_data);
mp->unlock();
return marketm->delete_app(oid, mp_data, emsg);
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */