1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-08 21:17:43 +03:00

feature #4217: Export action for images.

This commit is contained in:
Ruben S. Montero 2015-12-23 00:26:54 +01:00
parent 1d464eec2f
commit eeb7c01ac0
12 changed files with 322 additions and 53 deletions

View File

@ -37,6 +37,7 @@ public:
READY = 1, /** < Ready to use */
LOCKED = 2, /** < Operation in process */
ERROR = 3, /** < Error state the operation failed*/
DISABLED = 4
};
/**
@ -48,10 +49,11 @@ public:
{
switch(state)
{
case INIT: return "INIT"; break;
case READY: return "READY"; break;
case LOCKED: return "LOCKED"; break;
case ERROR: return "ERROR"; break;
case INIT: return "INIT"; break;
case READY: return "READY"; break;
case LOCKED: return "LOCKED"; break;
case ERROR: return "ERROR"; break;
case DISABLED: return "DISABLED"; break;
default: return "";
}
};
@ -106,6 +108,15 @@ public:
*/
int from_xml(const std::string &xml_str);
/**
* Enable or disable the app. A disabled app cannot be exported
* @param enable true to enable
* @param error_str Returns the error reason, if any
*
* @return 0 on success
*/
int enable(bool enable, string& error_str);
/**
* Returns the marketplace ID
*/

View File

@ -70,29 +70,22 @@ private:
MarketPlaceManager * marketm;
/**
* Sends a stat request to the MAD.
* @param oid the id of the stat request
* Imports a new object into the marketplace
* @param oid of the app
* @param drv_msg xml data for the mad operation.
*/
void importapp(int oid, const std::string& drv_msg) const;
/**
* Sends a make filesystem request to the MAD.
* @param oid the image id.
* @param drv_msg xml data for the mad operation.
*/
void exportapp(int oid, const std::string& drv_msg) const;
/**
* Sends a delete request to the MAD: "DELETE IMAGE_ID PATH"
* @param oid the image id.
* Deletes an app from the marketplace
* @param oid of the app
* @param drv_msg xml data for the mad operation.
*/
void deleteapp(int oid, const std::string& drv_msg) const;
/**
* Sends a monitor request to the MAD: "MONITOR DS_ID DS_XML"
* @param oid the datastore id.
* Monitors the marketplace
* @param oid of the operation
* @param drv_msg xml data for the mad operation.
*/
void monitor(int oid, const std::string& drv_msg) const;

View File

@ -0,0 +1,66 @@
/* -------------------------------------------------------------------------- */
/* 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. */
/* -------------------------------------------------------------------------- */
#ifndef REQUEST_MANAGER_MARKETPLACEAPP_H
#define REQUEST_MANAGER_MARKETPLACEAPP_H
#include "Request.h"
#include "Nebula.h"
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerMarketPlaceApp: public Request
{
protected:
RequestManagerMarketPlaceApp(const std::string& method_name,
const std::string& help, const std::string& params) :
Request(method_name, params, help)
{
Nebula& nd = Nebula::instance();
pool = nd.get_apppool();
auth_object = PoolObjectSQL::MARKETPLACEAPP;
auth_op = AuthRequest::MANAGE;
};
~RequestManagerMarketPlaceApp(){};
/* --------------------------------------------------------------------- */
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) = 0;
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class MarketPlaceAppEnable : public RequestManagerMarketPlaceApp
{
public:
MarketPlaceAppEnable(): RequestManagerMarketPlaceApp("MarketPlaceAppEnable",
"Enables or disables a marketplace app", "A:sib"){};
~MarketPlaceAppEnable(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif

View File

@ -30,6 +30,7 @@ $: << RUBY_LIB_LOCATION+"/cli"
require 'command_parser'
require 'one_helper/onemarketapp_helper'
require 'one_helper/onemarket_helper'
require 'one_helper/onedatastore_helper'
CommandParser::CmdParser.new(ARGV) do
usage "`onemarket` <command> [<args>] [<options>]"
@ -52,6 +53,7 @@ CommandParser::CmdParser.new(ARGV) do
list_options << OpenNebulaHelper::DESCRIBE
CREATE_OPTIONS = [OneMarketPlaceHelper::MARKETPLACE]
EXPORT_OPTIONS = [OneDatastoreHelper::DATASTORE]
########################################################################
# Formatters for arguments
@ -103,12 +105,32 @@ CommandParser::CmdParser.new(ARGV) do
end
end
export_desc = <<-EOT.unindent
Exports the marketplace app to the OpenNebula cloud
EOT
command :export, export_desc, :appid, :name, :options=>EXPORT_OPTIONS do
helper.perform_action(args[0], options, "exported") do |obj|
rc = obj.export(:dsid=>options[:datastore], :name=>args[1])
next rc if OpenNebula.is_error?(rc)
rc.each { |key, value|
puts "#{key.to_s.upcase}"
value.each{ |id|
puts " ID: #{id}"
}
}
end
end
delete_desc = <<-EOT.unindent
Deletes the given marketplace app
EOT
command :delete, delete_desc, [:range, :appid_list] do
helper.perform_actions(args[0],options,"deleted") do |app|
helper.perform_actions(args[0], options, "deleted") do |app|
app.delete
end
end
@ -119,7 +141,8 @@ CommandParser::CmdParser.new(ARGV) do
EOT
command :update, update_desc, :appid, [:file, nil],
:options=>OpenNebulaHelper::APPEND do
:options=>OpenNebulaHelper::APPEND do
helper.perform_action(args[0],options,"modified") do |obj|
if options[:append]
str = OpenNebulaHelper.append_template(args[0], obj, args[1])
@ -136,7 +159,7 @@ CommandParser::CmdParser.new(ARGV) do
EOT
command :chgrp, chgrp_desc,[:range, :appid_list], :groupid do
helper.perform_actions(args[0],options,"Group changed") do |app|
helper.perform_actions(args[0], options, "Group changed") do |app|
app.chown(-1, args[1].to_i)
end
end
@ -146,10 +169,10 @@ CommandParser::CmdParser.new(ARGV) do
EOT
command :chown, chown_desc, [:range, :appid_list], :userid,
[:groupid,nil] do
[:groupid, nil] do
gid = args[2].nil? ? -1 : args[2].to_i
helper.perform_actions(args[0],options,
"Owner/Group changed") do |app|
helper.perform_actions(args[0], options, "Owner/Group changed") do |app|
app.chown(args[1].to_i, gid)
end
end
@ -159,8 +182,7 @@ CommandParser::CmdParser.new(ARGV) do
EOT
command :chmod, chmod_desc, [:range, :appid_list], :octet do
helper.perform_actions(args[0],options,
"Permissions changed") do |app|
helper.perform_actions(args[0], options, "Permissions changed") do |app|
app.chmod_octet(args[1])
end
end
@ -170,7 +192,7 @@ CommandParser::CmdParser.new(ARGV) do
EOT
command :rename, rename_desc, :appid, :name do
helper.perform_action(args[0],options,"renamed") do |o|
helper.perform_action(args[0], options, "renamed") do |o|
o.rename(args[1])
end
end
@ -188,6 +210,27 @@ CommandParser::CmdParser.new(ARGV) do
EOT
command :show, show_desc, :appid, :options=>OpenNebulaHelper::XML do
helper.show_resource(args[0],options)
helper.show_resource(args[0], options)
end
enable_desc = <<-EOT.unindent
Enables the marketplace app
EOT
command :enable, enable_desc, [:range, :appid_list] do
helper.perform_actions(args[0], options, "enabled") do |obj|
obj.enable
end
end
disable_desc = <<-EOT.unindent
Disables the marketplace app. A disabled marketplace app cannot be
exported to a cloud
EOT
command :disable, disable_desc, [:range, :appid_list] do
helper.perform_actions(args[0], options, "disabled") do |obj|
obj.disable
end
end
end

View File

@ -374,3 +374,31 @@ MarketPlaceApp::MarketPlaceAppType MarketPlaceApp::str_to_type(string& str_type)
return UNKNOWN;
}
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
int MarketPlaceApp::enable(bool enable, string& error_str)
{
switch(state)
{
case INIT:
case LOCKED:
case ERROR:
break;
case READY:
case DISABLED:
if (enable)
{
state = READY;
}
else
{
state = DISABLED;
}
break;
}
return 0;
}

View File

@ -198,6 +198,7 @@ int MarketPlaceManager::delete_app(int appid, const std::string& market_data,
case MarketPlaceApp::INIT:
case MarketPlaceApp::READY :
case MarketPlaceApp::ERROR:
case MarketPlaceApp::DISABLED:
break;
}
break;

View File

@ -33,17 +33,6 @@ void MarketPlaceManagerDriver::importapp(int oid, const std::string& msg) const
/* -------------------------------------------------------------------------- */
void MarketPlaceManagerDriver::exportapp(int oid, const std::string& msg) const
{
std::ostringstream os;
os << "EXPORT " << oid << " " << msg << endl;
write(os);
}
/* -------------------------------------------------------------------------- */
void MarketPlaceManagerDriver::deleteapp(int oid, const std::string& msg) const
{
std::ostringstream os;
@ -451,10 +440,6 @@ void MarketPlaceManagerDriver::protocol(const string& message) const
{
import_action(is, apppool, marketm, id, result);
}
else if (action == "EXPORT")
{
return;
}
else if (action == "DELETE")
{
delete_action(is, apppool, marketm, id, result);

View File

@ -148,6 +148,8 @@ class MarketPlaceDriver < OpenNebulaDriver
info_doc.initialize_xml(info, 'IMPORT_INFO')
#-----------------------------------------------------------------------
# Only IMAGE type is supported
# when "VMTEMPLATE"
# when "FLOW"
#-----------------------------------------------------------------------
else
failure(:import, id, "Type #{apptype} not supported")
@ -169,12 +171,8 @@ class MarketPlaceDriver < OpenNebulaDriver
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
# Deletes an app from the marketplace
############################################################################
def delete(id, drv_message)
xml = decode(drv_message)
@ -196,6 +194,9 @@ class MarketPlaceDriver < OpenNebulaDriver
send_message(ACTION[:delete], rc, id, info)
end
############################################################################
# Monitor the marketplace. It gathers information about usage and app status
############################################################################
def monitor(id, drv_message)
send_message(ACTION[:export], RESULT[:failure], id, "Not implemented")
end

View File

@ -29,16 +29,18 @@ module OpenNebula
:update => "marketapp.update",
:chown => "marketapp.chown",
:chmod => "marketapp.chmod",
:rename => "marketapp.rename"
:rename => "marketapp.rename",
:enable => "marketapp.enable"
}
MARKETPLACEAPP_STATES=%w{INIT READY LOCKED ERROR}
MARKETPLACEAPP_STATES=%w{INIT READY LOCKED ERROR DISABLED}
SHORT_MARKETPLACEAPP_STATES={
"INIT" => "init",
"INIT" => "ini",
"READY" => "rdy",
"LOCKED" => "lock",
"LOCKED" => "lck",
"ERROR" => "err",
"DISABLED" => "dis"
}
MARKETPLACEAPP_TYPES=%w{UNKNOWN IMAGE VMTEMPLATE FLOW}
@ -137,8 +139,8 @@ module OpenNebula
# otherwise
def chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u,
other_m, other_a)
super(MARKETPLACEAPP_METHODS[:chmod], owner_u, owner_m, owner_a, group_u,
group_m, group_a, other_u, other_m, other_a)
super(MARKETPLACEAPP_METHODS[:chmod], owner_u, owner_m, owner_a,
group_u, group_m, group_a, other_u, other_m, other_a)
end
# Renames this marketplace app
@ -151,6 +153,78 @@ module OpenNebula
return call(MARKETPLACEAPP_METHODS[:rename], @pe_id, name)
end
# Exports this app to a suitable OpenNebula object
# @param appid [Integer] id of the marketplace app
# @param options [Hash] to control the export behavior
# dsid [Integer] datastore to save images
# name [String] of the new object
#
# @return [Hash, OpenNebula::Error] with the ID and type of the created
# objects
# { :vm => [ vm ids ],
# :vmtemplate => [vmtemplates ids],
# :image => [ vm ids] }
def export(options={})
return Error.new("Missing datastore id") if options[:dsid].nil?
return Error.new("Missing name to export app") if options[:name].nil?
one = Client.new()
rc = info
return rc if OpenNebula.is_error?(rc)
return Error.new("App is not in READY state") if state_str!="READY"
case type_str
when "IMAGE"
if !self['APPTEMPLATE64'].nil?
tmpl=Base64::decode64(self['APPTEMPLATE64'])
else
tmpl=""
end
name = options[:name] || "marketapp-#{self.id}"
tmpl << "\n"
tmpl << "NAME=\"" << name << "\"\n"
tmpl << "PATH=" << self['SOURCE'] << "\n"
tmpl << "FORMAT=" << self['FORMAT'] << "\n"
tmpl << "MD5=" << self['MD5'] << "\n"
tmpl << "FROM_APP=\"" << self['ID'] << "\"\n"
tmpl << "FROM_APP_NAME=\"" << self['NAME'] << "\"\n"
image = Image.new(Image.build_xml, one)
rc = image.allocate(tmpl, options[:dsid])
return rc if OpenNebula.is_error?(rc)
if !self['TEMPLATE/VMTEMPLATE64'].nil?
tmpl=Base64::decode64(self['TEMPLATE/VMTEMPLATE64'])
tmpl << "\nNAME=#{name}\n"
tmpl << "DISK=[ IMAGE_ID = #{image.id} ]\n"
vmtpl = Template.new(Template.build_xml, one)
rc = vmtpl.allocate(tmpl)
return rc if OpenNebula.is_error?(rc)
end
return { :image => [image.id], :vmtemplate => [vmtpl.id] }
else
return Error.new("App type #{app.type_str} not supported")
end
end
# Enables this app
def enable
return call(MARKETPLACEAPP_METHODS[:enable], @pe_id, true)
end
# Enables this app
def disable
return call(MARKETPLACEAPP_METHODS[:enable], @pe_id, false)
end
# ---------------------------------------------------------------------
# Helpers to get information
# ---------------------------------------------------------------------

View File

@ -40,6 +40,7 @@
#include "RequestManagerGroup.h"
#include "RequestManagerVdc.h"
#include "RequestManagerDatastore.h"
#include "RequestManagerMarketPlaceApp.h"
#include "RequestManagerSystem.h"
#include "RequestManagerProxy.h"
@ -956,6 +957,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::method * marketapp_delete_pt;
xmlrpc_c::method * marketapp_chmod_pt;
xmlrpc_c::method * marketapp_chown_pt;
xmlrpc_c::method * marketapp_enable_pt;
if (nebula.is_federation_slave())
{
@ -964,6 +966,7 @@ void RequestManager::register_xml_methods()
marketapp_delete_pt = new RequestManagerProxy("one.marketapp.delete");
marketapp_chmod_pt = new RequestManagerProxy("one.marketapp.chmod");
marketapp_chown_pt = new RequestManagerProxy("one.marketapp.chown");
marketapp_enable_pt = new RequestManagerProxy("one.marketapp.enable");
}
else
{
@ -972,6 +975,7 @@ void RequestManager::register_xml_methods()
marketapp_delete_pt = new MarketPlaceAppDelete();
marketapp_chmod_pt = new MarketPlaceAppChmod();
marketapp_chown_pt = new MarketPlaceAppChown();
marketapp_enable_pt = new MarketPlaceAppEnable();
}
xmlrpc_c::methodPtr marketapp_allocate(marketapp_allocate_pt);
@ -979,6 +983,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr marketapp_delete(marketapp_delete_pt);
xmlrpc_c::methodPtr marketapp_chmod(marketapp_chmod_pt);
xmlrpc_c::methodPtr marketapp_chown(marketapp_chown_pt);
xmlrpc_c::methodPtr marketapp_enable(marketapp_enable_pt);
xmlrpc_c::methodPtr marketapp_info(new MarketPlaceAppInfo());
xmlrpc_c::methodPtr marketapp_rename(new MarketPlaceAppRename());
@ -989,6 +994,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.marketapp.delete", marketapp_delete);
RequestManagerRegistry.addMethod("one.marketapp.chmod", marketapp_chmod);
RequestManagerRegistry.addMethod("one.marketapp.chown", marketapp_chown);
RequestManagerRegistry.addMethod("one.marketapp.enable", marketapp_enable);
RequestManagerRegistry.addMethod("one.marketapp.info", marketapp_info);
RequestManagerRegistry.addMethod("one.marketapp.rename", marketapp_rename);

View File

@ -0,0 +1,60 @@
/* -------------------------------------------------------------------------- */
/* 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. */
/* -------------------------------------------------------------------------- */
#include "RequestManagerMarketPlaceApp.h"
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void MarketPlaceAppEnable::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int id = xmlrpc_c::value_int(paramList.getInt(1));
bool enable_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
int rc;
MarketPlaceApp * app;
std::string err_msg;
if ( basic_authorization(id, att) == false )
{
return;
}
app = static_cast<MarketPlaceApp *>(pool->get(id, true));
if ( app == 0 )
{
failure_response(NO_EXISTS,get_error(object_name(auth_object),id),att);
return;
}
rc = app->enable(enable_flag, err_msg);
if ( rc != 0 )
{
failure_response(INTERNAL, request_error(err_msg,""), att);
app->unlock();
return;
}
pool->update(app);
app->unlock();
success_response(id, att);
}

View File

@ -47,6 +47,7 @@ source_files=[
'RequestManagerVdc.cc',
'RequestManagerDatastore.cc',
'RequestManagerLock.cc',
'RequestManagerMarketPlaceApp.cc'
]
# Build library