Revision ade6513a
include/ImageManager.h | ||
---|---|---|
115 | 115 |
|
116 | 116 |
/** |
117 | 117 |
* Closes any cloning operation on the image, updating the state if needed |
118 |
* @param iid image id of the image to be released
|
|
119 |
* @param clone_img_id image id of the image that was being cloned
|
|
118 |
* @param iid image id of the image to that was being cloned
|
|
119 |
* @param clone_img_id the cloned image (id > 0) or market app (id =< 0)
|
|
120 | 120 |
*/ |
121 | 121 |
void release_cloning_image(int iid, int clone_img_id); |
122 | 122 |
|
... | ... | |
147 | 147 |
* |
148 | 148 |
* @return 0 if the image can be cloned, -1 otherwise |
149 | 149 |
*/ |
150 |
int can_clone_image(int cloning_id, |
|
151 |
ostringstream& oss_error); |
|
150 |
int can_clone_image(int cloning_id, ostringstream& oss_error); |
|
151 |
|
|
152 |
/** |
|
153 |
* Sets the state to CLONE for the given image |
|
154 |
* @param new_id for the target image (new_id>0) or market app (new_id =<0) |
|
155 |
* @param clonning_id the ID of the image to be cloned |
|
156 |
* @param error if any |
|
157 |
* @return 0 if siccess |
|
158 |
*/ |
|
159 |
int set_clone_state(int new_id, int cloning_id, std::string& error); |
|
152 | 160 |
|
153 | 161 |
/** |
154 | 162 |
* Clone an existing image to the repository |
... | ... | |
162 | 170 |
int cloning_id, |
163 | 171 |
const string& ds_data, |
164 | 172 |
string& error); |
165 |
|
|
166 | 173 |
/** |
167 | 174 |
* Deletes an image from the repository and the DB. The Datastore image list |
168 | 175 |
* is also updated |
include/MarketPlaceApp.h | ||
---|---|---|
139 | 139 |
return type; |
140 | 140 |
}; |
141 | 141 |
|
142 |
/** |
|
143 |
* Returns the ID of the object originating this app |
|
144 |
* @return the image, vmtemplate or flow id |
|
145 |
*/ |
|
146 |
int get_origin_id() const |
|
147 |
{ |
|
148 |
return origin_id; |
|
149 |
}; |
|
150 |
|
|
142 | 151 |
//-------------------------------------------------------------------------- |
143 | 152 |
// Set Marketplace app attributes |
144 | 153 |
//-------------------------------------------------------------------------- |
... | ... | |
232 | 241 |
/** |
233 | 242 |
* Origin of this App |
234 | 243 |
*/ |
235 |
std::string origin;
|
|
244 |
int origin_id;
|
|
236 | 245 |
|
237 | 246 |
// ************************************************************************* |
238 | 247 |
// Constructor |
include/MarketPlaceManager.h | ||
---|---|---|
25 | 25 |
|
26 | 26 |
class MarketPlacePool; |
27 | 27 |
class MarketPlaceAppPool; |
28 |
class ImagePool; |
|
29 |
class DatastorePool; |
|
30 |
|
|
31 |
class ImageManager; |
|
28 | 32 |
|
29 | 33 |
class MarketPlaceManager : public MadManager, public ActionListener |
30 | 34 |
{ |
... | ... | |
36 | 40 |
* @param m, monitor_period to monitor marketplaces |
37 | 41 |
* @param mad, list of drivers for the manager |
38 | 42 |
*/ |
39 |
MarketPlaceManager( time_t t, time_t m, std::vector<const Attribute*>& mad);
|
|
43 |
MarketPlaceManager(time_t t, time_t m, std::vector<const Attribute*>& mad); |
|
40 | 44 |
|
41 | 45 |
~MarketPlaceManager(){}; |
42 | 46 |
|
43 | 47 |
/** |
48 |
* Initializes internal pointers to other managers. Must be called when |
|
49 |
* all the other managers exist in Nebula::instance |
|
50 |
*/ |
|
51 |
void init_managers(); |
|
52 |
|
|
53 |
/** |
|
44 | 54 |
* This functions starts the associated listener thread, and creates a |
45 | 55 |
* new thread for the MarketPlace Manager. This thread will wait in |
46 | 56 |
* an action loop till it receives ACTION_FINALIZE. |
... | ... | |
75 | 85 |
|
76 | 86 |
/** |
77 | 87 |
* Imports a new app into the marketplace. The marketplace app needs to |
78 |
* include the ORIGIN attribute so the driver can locate the app. An |
|
88 |
* include the ORIGIN_ID attribute so the driver can locate the app. An
|
|
79 | 89 |
* optional template maybe provided to export the app to a cloud. |
80 | 90 |
* @param appid of the app |
81 | 91 |
* @param market_data of the associated marketplace in XML format |
... | ... | |
142 | 152 |
*/ |
143 | 153 |
MarketPlaceAppPool * apppool; |
144 | 154 |
|
155 |
/** |
|
156 |
* Pointer to the image pool |
|
157 |
*/ |
|
158 |
ImagePool * ipool; |
|
159 |
|
|
160 |
/** |
|
161 |
* Pointer to the image pool |
|
162 |
*/ |
|
163 |
DatastorePool * dspool; |
|
164 |
|
|
165 |
/** |
|
166 |
* Pointer to the Image Manger |
|
167 |
*/ |
|
168 |
ImageManager * imagem; |
|
169 |
|
|
145 | 170 |
/** |
146 | 171 |
* Action engine for the Manager |
147 | 172 |
*/ |
install.sh | ||
---|---|---|
1207 | 1207 |
#------------------------------------------------------------------------------- |
1208 | 1208 |
# Marketplace drivers, to be installed under $REMOTES_LOCATION/market |
1209 | 1209 |
# - HTTP based marketplace, $REMOTES_LOCATION/market/http |
1210 |
# - S3-obeject based Image Repository, $REMOTES_LOCATION/datastore/fs |
|
1211 |
# - VMFS based Image Repository, $REMOTES_LOCATION/datastore/vmfs |
|
1212 |
# - LVM based Image Repository, $REMOTES_LOCATION/datastore/lvm |
|
1210 |
# - S3-obeject based marketplace, $REMOTES_LOCATION/market/s3 |
|
1213 | 1211 |
#------------------------------------------------------------------------------- |
1214 | 1212 |
|
1215 | 1213 |
MARKETPLACE_DRIVER_HTTP_SCRIPTS="src/market_mad/remotes/http/import \ |
src/cli/one_helper/onemarketapp_helper.rb | ||
---|---|---|
129 | 129 |
puts str % ["VERSION", app['VERSION']] |
130 | 130 |
puts str % ["DESCRIPTION", app['DESCRIPTION']] |
131 | 131 |
puts str % ["SIZE", OpenNebulaHelper.unit_to_str(app['SIZE'].to_i,{},'M')] |
132 |
puts str % ["ORIGIN_ID", app['ORIGIN_ID']] |
|
133 |
puts str % ["FORMAT", app['FORMAT']] |
|
132 | 134 |
|
133 | 135 |
puts |
134 | 136 |
|
src/cloud/marketplace/bin/onemarket | ||
---|---|---|
1 |
#!/usr/bin/env ruby |
|
2 |
|
|
3 |
# ---------------------------------------------------------------------------- # |
|
4 |
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems # |
|
5 |
# # |
|
6 |
# Licensed under the Apache License, Version 2.0 (the "License"); you may # |
|
7 |
# not use this file except in compliance with the License. You may obtain # |
|
8 |
# a copy of the License at # |
|
9 |
# # |
|
10 |
# http://www.apache.org/licenses/LICENSE-2.0 # |
|
11 |
# # |
|
12 |
# Unless required by applicable law or agreed to in writing, software # |
|
13 |
# distributed under the License is distributed on an "AS IS" BASIS, # |
|
14 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # |
|
15 |
# See the License for the specific language governing permissions and # |
|
16 |
# limitations under the License. # |
|
17 |
# ---------------------------------------------------------------------------- # |
|
18 |
|
|
19 |
ONE_LOCATION=ENV["ONE_LOCATION"] |
|
20 |
|
|
21 |
if !ONE_LOCATION |
|
22 |
RUBY_LIB_LOCATION="/usr/lib/one/ruby" |
|
23 |
else |
|
24 |
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" |
|
25 |
TEMPLATES_LOCATION=ONE_LOCATION+"/etc/occi_templates" |
|
26 |
CONF_LOCATION=ONE_LOCATION+"/etc" |
|
27 |
end |
|
28 |
|
|
29 |
$: << RUBY_LIB_LOCATION |
|
30 |
$: << RUBY_LIB_LOCATION+"/cloud" |
|
31 |
|
|
32 |
require 'marketplace/marketplace_client' |
|
33 |
|
|
34 |
require 'cli/command_parser' |
|
35 |
require 'cli/cli_helper' |
|
36 |
|
|
37 |
require 'rubygems' |
|
38 |
require 'json' |
|
39 |
|
|
40 |
USER_AGENT = "CLI" |
|
41 |
|
|
42 |
# |
|
43 |
# Options |
|
44 |
# |
|
45 |
|
|
46 |
DEFAULT_OPTIONS = [ |
|
47 |
ENDPOINT = { |
|
48 |
:name => "server", |
|
49 |
:short => "-s url", |
|
50 |
:large => "--server url", |
|
51 |
:format => String, |
|
52 |
:description => "Marketplace endpoint" |
|
53 |
}, |
|
54 |
USERNAME={ |
|
55 |
:name => "username", |
|
56 |
:short => "-u name", |
|
57 |
:large => "--username name", |
|
58 |
:format => String, |
|
59 |
:description => "User name" |
|
60 |
}, |
|
61 |
PASSWORD={ |
|
62 |
:name => "password", |
|
63 |
:short => "-p pass", |
|
64 |
:large => "--password pass", |
|
65 |
:format => String, |
|
66 |
:description => "User password" |
|
67 |
} |
|
68 |
] |
|
69 |
|
|
70 |
JSON_FORMAT={ |
|
71 |
:name => "json", |
|
72 |
:short => "-j", |
|
73 |
:large => "--json", |
|
74 |
:description => "Show in JSON format" |
|
75 |
} |
|
76 |
|
|
77 |
# |
|
78 |
# Table |
|
79 |
# |
|
80 |
|
|
81 |
TABLE = CLIHelper::ShowTable.new(nil, self) do |
|
82 |
column :ID, "Appliance", :size=>25 do |d| |
|
83 |
d["_id"]["$oid"] |
|
84 |
end |
|
85 |
|
|
86 |
column :NAME, "Name", :size=>50 do |d| |
|
87 |
d["name"] |
|
88 |
end |
|
89 |
|
|
90 |
column :PUBLISHER, "Publisher", :size=>15 do |d| |
|
91 |
d["publisher"] |
|
92 |
end |
|
93 |
|
|
94 |
default :ID, :NAME, :PUBLISHER |
|
95 |
end |
|
96 |
|
|
97 |
# |
|
98 |
# Commands |
|
99 |
# |
|
100 |
|
|
101 |
cmd=CommandParser::CmdParser.new(ARGV) do |
|
102 |
usage "`onemarket` <command> [<args>] [<options>]" |
|
103 |
|
|
104 |
set :option, DEFAULT_OPTIONS |
|
105 |
|
|
106 |
# |
|
107 |
# List |
|
108 |
# |
|
109 |
|
|
110 |
list_desc = <<-EOT.unindent |
|
111 |
List the available appliances in the Marketplace |
|
112 |
EOT |
|
113 |
|
|
114 |
command :list, list_desc, :options => JSON_FORMAT do |
|
115 |
client = Market::ApplianceClient.new( |
|
116 |
options[:username], |
|
117 |
options[:password], |
|
118 |
options[:server], |
|
119 |
USER_AGENT) |
|
120 |
|
|
121 |
response = client.list |
|
122 |
|
|
123 |
if CloudClient::is_error?(response) |
|
124 |
[response.code.to_i, response.to_s] |
|
125 |
else |
|
126 |
if options[:json] |
|
127 |
[0,response.body] |
|
128 |
else |
|
129 |
array_list = JSON.parse(response.body) |
|
130 |
TABLE.show(array_list['appliances']) |
|
131 |
0 |
|
132 |
end |
|
133 |
end |
|
134 |
end |
|
135 |
|
|
136 |
# |
|
137 |
# Create |
|
138 |
# |
|
139 |
|
|
140 |
create_desc = <<-EOT.unindent |
|
141 |
Create a new appliance in the Marketplace |
|
142 |
EOT |
|
143 |
|
|
144 |
command :create, create_desc, :file do |
|
145 |
client = Market::ApplianceClient.new( |
|
146 |
options[:username], |
|
147 |
options[:password], |
|
148 |
options[:server], |
|
149 |
USER_AGENT) |
|
150 |
|
|
151 |
response = client.create(File.read(args[0])) |
|
152 |
|
|
153 |
if CloudClient::is_error?(response) |
|
154 |
[response.code.to_i, response.to_s] |
|
155 |
else |
|
156 |
[0, response.body] |
|
157 |
end |
|
158 |
end |
|
159 |
|
|
160 |
# |
|
161 |
# Show |
|
162 |
# |
|
163 |
|
|
164 |
show_desc = <<-EOT.unindent |
|
165 |
Show detailed information of a given appliance |
|
166 |
EOT |
|
167 |
|
|
168 |
command :show, show_desc, :id, :options => JSON_FORMAT do |
|
169 |
client = Market::ApplianceClient.new( |
|
170 |
options[:username], |
|
171 |
options[:password], |
|
172 |
options[:server], |
|
173 |
USER_AGENT) |
|
174 |
|
|
175 |
response = client.show(args[0]) |
|
176 |
|
|
177 |
if CloudClient::is_error?(response) |
|
178 |
[response.code.to_i, response.to_s] |
|
179 |
else |
|
180 |
[0,response.body] |
|
181 |
end |
|
182 |
end |
|
183 |
end |
src/cloud/marketplace/lib/marketplace_client.rb | ||
---|---|---|
1 |
# ---------------------------------------------------------------------------- # |
|
2 |
# Copyright 2002-2015, OpenNebula Project, OpenNebula Systems # |
|
3 |
# # |
|
4 |
# Licensed under the Apache License, Version 2.0 (the "License"); you may # |
|
5 |
# not use this file except in compliance with the License. You may obtain # |
|
6 |
# a copy of the License at # |
|
7 |
# # |
|
8 |
# http://www.apache.org/licenses/LICENSE-2.0 # |
|
9 |
# # |
|
10 |
# Unless required by applicable law or agreed to in writing, software # |
|
11 |
# distributed under the License is distributed on an "AS IS" BASIS, # |
|
12 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # |
|
13 |
# See the License for the specific language governing permissions and # |
|
14 |
# limitations under the License. # |
|
15 |
# ---------------------------------------------------------------------------- # |
|
16 |
|
|
17 |
require 'uri' |
|
18 |
require 'cloud/CloudClient' |
|
19 |
|
|
20 |
require 'ostruct' |
|
21 |
|
|
22 |
module Market |
|
23 |
class Client |
|
24 |
def initialize(username, password, url, user_agent="Ruby") |
|
25 |
@username = username |
|
26 |
@password = password |
|
27 |
|
|
28 |
url ||= 'http://marketplace.opennebula.systems/' |
|
29 |
@uri = URI.parse(url) |
|
30 |
|
|
31 |
@user_agent = "OpenNebula #{CloudClient::VERSION} (#{user_agent})" |
|
32 |
|
|
33 |
@host = nil |
|
34 |
@port = nil |
|
35 |
|
|
36 |
if ENV['http_proxy'] |
|
37 |
uri_proxy = URI.parse(ENV['http_proxy']) |
|
38 |
@host = uri_proxy.host |
|
39 |
@port = uri_proxy.port |
|
40 |
end |
|
41 |
end |
|
42 |
|
|
43 |
def get(path) |
|
44 |
req = Net::HTTP::Proxy(@host, @port)::Get.new(@uri.path + path) |
|
45 |
do_request(req) |
|
46 |
end |
|
47 |
|
|
48 |
def post(path, body) |
|
49 |
req = Net::HTTP::Proxy(@host, @port)::Post.new(@uri.path + path) |
|
50 |
req.body = body |
|
51 |
|
|
52 |
do_request(req) |
|
53 |
end |
|
54 |
|
|
55 |
private |
|
56 |
|
|
57 |
def do_request(req) |
|
58 |
if @username && @password |
|
59 |
req.basic_auth @username, @password |
|
60 |
end |
|
61 |
|
|
62 |
req['User-Agent'] = @user_agent |
|
63 |
|
|
64 |
res = CloudClient::http_start(@uri, @timeout) do |http| |
|
65 |
http.request(req) |
|
66 |
end |
|
67 |
|
|
68 |
res |
|
69 |
end |
|
70 |
end |
|
71 |
|
|
72 |
|
|
73 |
class ApplianceClient < Client |
|
74 |
def initialize(user, password, url, agent) |
|
75 |
super(user, password, url, agent) |
|
76 |
end |
|
77 |
|
|
78 |
def list |
|
79 |
get("/appliance") |
|
80 |
end |
|
81 |
|
|
82 |
def create(body) |
|
83 |
post("/appliance", body) |
|
84 |
end |
|
85 |
|
|
86 |
def show(id) |
|
87 |
get("/appliance/#{id}") |
|
88 |
end |
|
89 |
end |
|
90 |
end |
src/datastore_mad/remotes/downloader.sh | ||
---|---|---|
176 | 176 |
|
177 | 177 |
command="curl $curl_args" |
178 | 178 |
;; |
179 |
ssh://*) |
|
180 |
# pseudo-url for ssh transfers ssh://user@host:path |
|
181 |
# -l to limit the bw |
|
182 |
ssh_src=$(echo $FROM | grep -Po '(?<=ssh://).+') |
|
183 |
ssh_arg=(${ssh_src//:/ }) |
|
184 |
|
|
185 |
rmt_cmd="'cat ${ssh_arg[1]}'" |
|
186 |
|
|
187 |
command="ssh ${ssh_arg[0]} $rmt_cmd" |
|
188 |
;; |
|
179 | 189 |
*) |
180 | 190 |
if [ ! -r $FROM ]; then |
181 | 191 |
echo "Cannot read from $FROM" >&2 |
src/datastore_mad/remotes/fs/export | ||
---|---|---|
45 | 45 |
while IFS= read -r -d '' element; do |
46 | 46 |
XPATH_ELEMENTS[i++]="$element" |
47 | 47 |
done < <($XPATH /DS_DRIVER_ACTION_DATA/IMAGE/SOURCE \ |
48 |
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST \ |
|
49 |
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/EXPORT_DIR \ |
|
50 |
/DS_DRIVER_ACTION_DATA/DATASTORE/BASE_PATH) |
|
48 |
/DS_DRIVER_ACTION_DATA/DATASTORE/TEMPLATE/BRIDGE_LIST) |
|
51 | 49 |
unset i |
52 | 50 |
|
53 | 51 |
SRC="${XPATH_ELEMENTS[i++]}" |
54 | 52 |
BRIDGE_LIST="${XPATH_ELEMENTS[i++]}" |
55 |
EXPORT_DIR="${XPATH_ELEMENTS[i++]}" |
|
56 |
BASE_PATH="${XPATH_ELEMENTS[i++]}" |
|
57 | 53 |
|
58 |
EXPORT_DIR="${EXPORT_DIR-$BASE_PATH}" |
|
59 |
|
|
60 |
# -------------------- Convert image to qcow2 format --------------------------- |
|
61 |
# TODO: |
|
62 |
# Export directories needs to be defined, probably in oned.conf |
|
63 |
# BRIDGE_LIST needs to be handled |
|
64 | 54 |
#------------------------------------------------------------------------------- |
55 |
# Output image source and format |
|
56 |
#------------------------------------------------------------------------------- |
|
57 |
|
|
58 |
INFO_SCRIPT=$(cat <<EOF |
|
59 |
|
|
60 |
CHECKSUM=\$(${MD5SUM} ${SRC} | cut -f1 -d' ') |
|
61 |
SIZE=\$(${DU} -LBM ${SRC} | cut -f1) |
|
62 |
FORMAT=\$(${QEMU_IMG} info ${SRC} 2>/dev/null | grep -Po '(?<=file format: )\w+') |
|
63 |
|
|
64 |
echo "<CHECKSUM>\$CHECKSUM</CHECKSUM>" |
|
65 |
echo "<SIZE>\$SIZE</SIZE>" |
|
66 |
echo "<FORMAT>\$FORMAT</FORMAT>" |
|
67 |
|
|
68 |
EOF |
|
69 |
) |
|
65 | 70 |
|
66 |
log "Removing $SRC from the image repository" |
|
71 |
if [ -n "$BRIDGE_LIST" ]; then |
|
72 |
HOST=`get_destination_host $ID` |
|
73 |
INFO=$(ssh_monitor_and_log "$HOST" "$INFO_SCRIPT" "Image info script" 2>&1) |
|
74 |
SRC="ssh://$HOST:$SRC" |
|
75 |
else |
|
76 |
INFO=$(monitor_and_log "$INFO_SCRIPT" "Image info script" 2>&1) |
|
77 |
fi |
|
78 |
|
|
79 |
INFO_STATUS=$? |
|
80 |
|
|
81 |
if [ "$INFO_STATUS" != "0" ]; then |
|
82 |
echo "$INFO" |
|
83 |
exit $INFO_STATUS |
|
84 |
fi |
|
67 | 85 |
|
68 |
exec_and_log "$QEMU_IMG convert -O qcow2 $SRC $SRC.export" \ |
|
69 |
"Error converting image to qcow2 format" |
|
86 |
echo "<IMPORT_INFO><IMPORT_SOURCE>$SRC</IMPORT_SOURCE> \ |
|
87 |
$INFO \ |
|
88 |
<DISPOSE>NO</DISPOSE></IMPORT_INFO>" |
|
70 | 89 |
|
71 |
echo "$SRC.export" |
src/datastore_mad/remotes/libfs.sh | ||
---|---|---|
53 | 53 |
} |
54 | 54 |
|
55 | 55 |
#------------------------------------------------------------------------------- |
56 |
# Get file format using qemu-img |
|
57 |
# @return string representation of the format, empty if error |
|
58 |
#------------------------------------------------------------------------------- |
|
59 |
function image_format { |
|
60 |
echo "$($QEMU_IMG info $1 2>/dev/null | grep -Po '(?<=file format: )\w+')" |
|
61 |
} |
|
62 |
|
|
63 |
#------------------------------------------------------------------------------- |
|
56 | 64 |
# Generates an unique image hash. Requires ID to be set |
57 | 65 |
# @return hash for the image (empty if error) |
58 | 66 |
#------------------------------------------------------------------------------- |
src/image/ImageManagerActions.cc | ||
---|---|---|
287 | 287 |
case Image::ERROR: |
288 | 288 |
case Image::USED_PERS: |
289 | 289 |
case Image::LOCKED: |
290 |
ostringstream oss; |
|
291 |
|
|
292 |
oss << "Releasing image in wrong state: " |
|
293 |
<< Image::state_to_str(img->get_state()); |
|
294 |
|
|
295 |
NebulaLog::log("ImM", Log::ERROR, oss.str()); |
|
290 |
NebulaLog::log("ImM", Log::ERROR, "Release cloning image" |
|
291 |
" in wrong state"); |
|
296 | 292 |
break; |
297 | 293 |
} |
298 | 294 |
|
... | ... | |
564 | 560 |
/* -------------------------------------------------------------------------- */ |
565 | 561 |
/* -------------------------------------------------------------------------- */ |
566 | 562 |
|
567 |
int ImageManager::can_clone_image( int cloning_id, |
|
568 |
ostringstream& oss_error) |
|
563 |
int ImageManager::can_clone_image(int cloning_id, ostringstream& oss_error) |
|
569 | 564 |
{ |
570 | 565 |
Image * img; |
571 | 566 |
|
... | ... | |
607 | 602 |
/* -------------------------------------------------------------------------- */ |
608 | 603 |
/* -------------------------------------------------------------------------- */ |
609 | 604 |
|
610 |
int ImageManager::clone_image(int new_id, |
|
611 |
int cloning_id, |
|
612 |
const string& ds_data, |
|
613 |
string& error) |
|
605 |
int ImageManager::set_clone_state(int new_id, int cloning_id, std::string& error) |
|
614 | 606 |
{ |
615 |
const ImageManagerDriver* imd = get(); |
|
616 |
|
|
617 |
ostringstream oss; |
|
618 |
Image * img; |
|
619 |
|
|
620 |
string path; |
|
621 |
string img_tmpl; |
|
622 |
string* drv_msg; |
|
623 |
|
|
624 |
if ( imd == 0 ) |
|
625 |
{ |
|
626 |
error = "Could not get datastore driver"; |
|
627 |
|
|
628 |
NebulaLog::log("ImM", Log::ERROR, error); |
|
629 |
return -1; |
|
630 |
} |
|
631 |
|
|
632 |
img = ipool->get(cloning_id, true); |
|
607 |
int rc = 0; |
|
608 |
Image * img = ipool->get(cloning_id, true); |
|
633 | 609 |
|
634 | 610 |
if (img == 0) |
635 | 611 |
{ |
... | ... | |
652 | 628 |
} |
653 | 629 |
|
654 | 630 |
ipool->update(img); |
655 |
|
|
656 |
img->unlock(); |
|
657 |
break; |
|
631 |
break; |
|
658 | 632 |
|
659 | 633 |
case Image::USED: |
660 | 634 |
case Image::CLONE: |
661 | 635 |
img->inc_cloning(new_id); |
662 |
|
|
663 | 636 |
ipool->update(img); |
664 |
|
|
665 |
img->unlock(); |
|
666 |
break; |
|
637 |
break; |
|
667 | 638 |
|
668 | 639 |
case Image::USED_PERS: |
669 | 640 |
case Image::INIT: |
... | ... | |
671 | 642 |
case Image::ERROR: |
672 | 643 |
case Image::DELETE: |
673 | 644 |
case Image::LOCKED: |
674 |
oss << "Cannot clone image in state: " |
|
675 |
<< Image::state_to_str(img->get_state()); |
|
645 |
error = "Cannot clone image in current state"; |
|
646 |
rc = -1; |
|
647 |
break; |
|
648 |
} |
|
676 | 649 |
|
677 |
error = oss.str(); |
|
678 |
img->unlock(); |
|
679 |
return -1; |
|
680 |
break; |
|
650 |
img->unlock(); |
|
651 |
|
|
652 |
return rc; |
|
653 |
} |
|
654 |
|
|
655 |
/* -------------------------------------------------------------------------- */ |
|
656 |
/* -------------------------------------------------------------------------- */ |
|
657 |
|
|
658 |
int ImageManager::clone_image(int new_id, |
|
659 |
int cloning_id, |
|
660 |
const string& ds_data, |
|
661 |
string& error) |
|
662 |
{ |
|
663 |
const ImageManagerDriver* imd = get(); |
|
664 |
|
|
665 |
ostringstream oss; |
|
666 |
Image * img; |
|
667 |
|
|
668 |
string path; |
|
669 |
string img_tmpl; |
|
670 |
string* drv_msg; |
|
671 |
|
|
672 |
if ( imd == 0 ) |
|
673 |
{ |
|
674 |
error = "Could not get datastore driver"; |
|
675 |
|
|
676 |
NebulaLog::log("ImM", Log::ERROR, error); |
|
677 |
return -1; |
|
678 |
} |
|
679 |
|
|
680 |
if ( set_clone_state(new_id, cloning_id, error) == -1 ) |
|
681 |
{ |
|
682 |
return -1; |
|
681 | 683 |
} |
682 | 684 |
|
683 | 685 |
img = ipool->get(new_id,true); |
684 | 686 |
|
685 |
if (img == 0) //TODO: Rollback cloning counter
|
|
687 |
if (img == 0) |
|
686 | 688 |
{ |
689 |
release_cloning_image(cloning_id, new_id); |
|
690 |
|
|
687 | 691 |
error = "Target image deleted during cloning operation"; |
688 | 692 |
return -1; |
689 | 693 |
} |
src/market/MarketPlaceApp.cc | ||
---|---|---|
99 | 99 |
type = IMAGE; |
100 | 100 |
|
101 | 101 |
//Known attributes |
102 |
//ORIGIN |
|
102 |
//ORIGIN_ID
|
|
103 | 103 |
//DESCRIPTION |
104 | 104 |
//APPTEMPLATE64 |
105 | 105 |
//PUBLISHER |
106 | 106 |
//VERSION |
107 |
erase_template_attribute("ORIGIN", origin); |
|
108 |
|
|
109 |
if (origin.empty()) |
|
107 |
if (!get_template_attribute("ORIGIN_ID", origin_id)) |
|
110 | 108 |
{ |
111 | 109 |
goto error_origin; |
112 | 110 |
} |
113 | 111 |
|
112 |
remove_template_attribute("ORIGIN_ID"); |
|
113 |
|
|
114 | 114 |
get_template_attribute("DESCRIPTION", description); |
115 | 115 |
|
116 | 116 |
get_template_attribute("APPTEMPLATE64", apptemplate64); |
... | ... | |
136 | 136 |
return insert_replace(db, false, error_str); |
137 | 137 |
|
138 | 138 |
error_origin: |
139 |
error_str = "Missing ORIGIN for the MARKETPLACEAPP"; |
|
139 |
error_str = "Missing ORIGIN_ID for the MARKETPLACEAPP";
|
|
140 | 140 |
NebulaLog::log("MKP", Log::ERROR, error_str); |
141 | 141 |
return -1; |
142 | 142 |
} |
... | ... | |
241 | 241 |
"<GNAME>" << gname << "</GNAME>" << |
242 | 242 |
"<DATE>" << date << "</DATE>" << |
243 | 243 |
"<NAME>" << name << "</NAME>" << |
244 |
"<ORIGIN>" << origin << "</ORIGIN>" <<
|
|
244 |
"<ORIGIN_ID>" << origin_id << "</ORIGIN_ID>" <<
|
|
245 | 245 |
"<SOURCE>" << source << "</SOURCE>" << |
246 | 246 |
"<CHECKSUM>" << checksum << "</CHECKSUM>" << |
247 | 247 |
"<SIZE>" << size_mb << "</SIZE>" << |
... | ... | |
283 | 283 |
rc += xpath(gname, "/MARKETPLACEAPP/GNAME", "not_found"); |
284 | 284 |
rc += xpath(name, "/MARKETPLACEAPP/NAME", "not_found"); |
285 | 285 |
rc += xpath(date, "/MARKETPLACEAPP/DATE", -1); |
286 |
rc += xpath(source, "/MARKETPLACEAPP/SOURCE","not_found"); |
|
287 |
rc += xpath(origin, "/MARKETPLACEAPP/ORIGIN","not_found");
|
|
286 |
rc += xpath(source, "/MARKETPLACEAPP/SOURCE", "not_found");
|
|
287 |
rc += xpath(origin_id, "/MARKETPLACEAPP/ORIGIN_ID", -1);
|
|
288 | 288 |
rc += xpath(istate, "/MARKETPLACEAPP/STATE", -1); |
289 | 289 |
rc += xpath(itype, "/MARKETPLACEAPP/TYPE", -1); |
290 | 290 |
rc += xpath(description, "/MARKETPLACEAPP/DESCRIPTION", "not_found"); |
src/market/MarketPlaceManager.cc | ||
---|---|---|
55 | 55 |
std::vector<const Attribute*>& _mads): |
56 | 56 |
MadManager(_mads), |
57 | 57 |
timer_period(_timer_period), |
58 |
monitor_period(_monitor_period) |
|
58 |
monitor_period(_monitor_period), |
|
59 |
imagem(0) |
|
59 | 60 |
{ |
60 | 61 |
Nebula& nd = Nebula::instance(); |
61 | 62 |
|
62 | 63 |
mppool = nd.get_marketpool(); |
63 | 64 |
apppool = nd.get_apppool(); |
65 |
dspool = nd.get_dspool(); |
|
66 |
ipool = nd.get_ipool(); |
|
64 | 67 |
|
65 | 68 |
am.addListener(this); |
66 | 69 |
}; |
... | ... | |
113 | 116 |
/* -------------------------------------------------------------------------- */ |
114 | 117 |
/* -------------------------------------------------------------------------- */ |
115 | 118 |
|
119 |
void MarketPlaceManager::init_managers() |
|
120 |
{ |
|
121 |
Nebula& nd = Nebula::instance(); |
|
122 |
|
|
123 |
imagem = nd.get_imagem(); |
|
124 |
} |
|
125 |
|
|
126 |
/* -------------------------------------------------------------------------- */ |
|
127 |
/* -------------------------------------------------------------------------- */ |
|
128 |
|
|
116 | 129 |
int MarketPlaceManager::start() |
117 | 130 |
{ |
118 | 131 |
int rc; |
src/market/MarketPlaceManagerActions.cc | ||
---|---|---|
19 | 19 |
#include "MarketPlaceAppPool.h" |
20 | 20 |
#include "MarketPlaceManagerDriver.h" |
21 | 21 |
|
22 |
#include "Image.h" |
|
23 |
#include "Datastore.h" |
|
24 |
#include "ImageManager.h" |
|
25 |
|
|
22 | 26 |
#include "NebulaLog.h" |
23 | 27 |
#include "Nebula.h" |
24 | 28 |
|
... | ... | |
31 | 35 |
const std::string& market_data, |
32 | 36 |
std::string& err) |
33 | 37 |
{ |
34 |
std::string app_data; |
|
38 |
std::string app_data, image_data, ds_data; |
|
39 |
std::string * msg; |
|
40 |
|
|
41 |
Image * image; |
|
42 |
Datastore * ds; |
|
43 |
|
|
44 |
int ds_id; |
|
45 |
|
|
46 |
const MarketPlaceManagerDriver* mpmd = get(); |
|
47 |
|
|
48 |
if ( mpmd == 0 ) |
|
49 |
{ |
|
50 |
err = "Error getting MarketPlaceManagerDriver"; |
|
51 |
return -1; |
|
52 |
} |
|
53 |
|
|
35 | 54 |
MarketPlaceApp * app = apppool->get(appid, true); |
36 | 55 |
|
37 | 56 |
if ( app == 0 ) |
... | ... | |
42 | 61 |
|
43 | 62 |
app->to_xml(app_data); |
44 | 63 |
|
45 |
app->unlock();
|
|
64 |
MarketPlaceApp::MarketPlaceAppType type = app->get_type();
|
|
46 | 65 |
|
47 |
std::string * msg = format_message(app_data, market_data, ""); |
|
66 |
int app_id = app->get_oid(); |
|
67 |
int origin_id = app->get_origin_id(); |
|
48 | 68 |
|
49 |
const MarketPlaceManagerDriver* mpmd = get();
|
|
69 |
app->unlock();
|
|
50 | 70 |
|
51 |
if ( mpmd == 0 )
|
|
71 |
switch (type)
|
|
52 | 72 |
{ |
53 |
err = "Error getting MarketPlaceManagerDriver"; |
|
54 |
return -1; |
|
73 |
case MarketPlaceApp::IMAGE: |
|
74 |
image = ipool->get(origin_id, true); |
|
75 |
|
|
76 |
if ( image == 0 ) |
|
77 |
{ |
|
78 |
err = "Image does not exist."; |
|
79 |
return -1; |
|
80 |
} |
|
81 |
|
|
82 |
image->to_xml(image_data); |
|
83 |
|
|
84 |
ds_id = image->get_ds_id(); |
|
85 |
|
|
86 |
image->unlock(); |
|
87 |
|
|
88 |
ds = dspool->get(ds_id, true); |
|
89 |
|
|
90 |
if ( ds == 0 ) |
|
91 |
{ |
|
92 |
err = "Image datastore no longer exists."; |
|
93 |
return -1; |
|
94 |
} |
|
95 |
|
|
96 |
ds->to_xml(ds_data); |
|
97 |
|
|
98 |
ds->unlock(); |
|
99 |
|
|
100 |
if (imagem->set_clone_state(-app_id, origin_id, err) != 0) |
|
101 |
{ |
|
102 |
return -1; |
|
103 |
} |
|
104 |
break; |
|
105 |
|
|
106 |
case MarketPlaceApp::VMTEMPLATE: |
|
107 |
case MarketPlaceApp::FLOW: |
|
108 |
case MarketPlaceApp::UNKNOWN: |
|
109 |
err = "Marketplace app type not supported."; |
|
110 |
return -1; |
|
55 | 111 |
} |
56 | 112 |
|
113 |
msg = format_message(app_data, market_data, image_data + ds_data); |
|
114 |
|
|
57 | 115 |
mpmd->importapp(appid, *msg); |
58 | 116 |
|
59 | 117 |
delete msg; |
src/market_mad/one_market.rb | ||
---|---|---|
93 | 93 |
end |
94 | 94 |
|
95 | 95 |
############################################################################ |
96 |
# Image Manager Protocol Actions (generic implementation) |
|
96 |
# Import a marketplace app into the marketplace. This is a two step process: |
|
97 |
# 1- The associated datastore_mad/export script is invoked to generate |
|
98 |
# a file representation of the app. |
|
99 |
# 2- The resulting file path is used to import it into the marketplace |
|
100 |
# invoking marketplace_mad/import. |
|
97 | 101 |
############################################################################ |
98 |
|
|
99 | 102 |
def import(id, drv_message) |
100 | 103 |
xml = decode(drv_message) |
101 | 104 |
|
... | ... | |
105 | 108 |
end |
106 | 109 |
|
107 | 110 |
type = xml['MARKETPLACEAPP/TYPE'] |
108 |
origin = xml['MARKETPLACEAPP/ORIGIN'] |
|
111 |
origin = xml['MARKETPLACEAPP/ORIGIN_ID']
|
|
109 | 112 |
mp_mad = xml['MARKETPLACE/MARKET_MAD'] |
110 | 113 |
|
111 | 114 |
if type.nil? || origin.nil? || mp_mad.nil? |
112 |
failure(:import, id,"Wrong driver message format") |
|
115 |
failure(:import, id, "Wrong driver message format")
|
|
113 | 116 |
return |
114 | 117 |
end |
115 | 118 |
|
119 |
case OpenNebula::MarketPlaceApp::MARKETPLACEAPP_TYPES[type.to_i] |
|
116 | 120 |
#----------------------------------------------------------------------- |
117 |
# Export origin to a path
|
|
121 |
# Export marketplace origin to a file path, IMAGE
|
|
118 | 122 |
#----------------------------------------------------------------------- |
119 |
case OpenNebula::MarketPlaceApp::MARKETPLACEAPP_TYPES[type.to_i] |
|
120 |
when "IMAGE" then |
|
121 |
if ( origin =~ /\d+$/ ) |
|
122 |
# Get the associated datastore ID |
|
123 |
image = OpenNebula::Image.new_with_id(origin, @one) |
|
124 |
rc = image.info |
|
125 |
|
|
126 |
if OpenNebula.is_error?(rc) |
|
127 |
failure(:import, id, "Cannot find information for image "\ |
|
128 |
"#{origin}: #{rc.to_str()}") |
|
129 |
return |
|
130 |
end |
|
131 |
|
|
132 |
ds_id = image['DATASTORE_ID'] |
|
133 |
|
|
134 |
if ds_id.nil? |
|
135 |
failure(:import, id, "Cannot find datastore for image #{origin}") |
|
136 |
return |
|
137 |
end |
|
138 |
|
|
139 |
ds = OpenNebula::Datastore.new_with_id(ds_id, @one) |
|
140 |
rc = ds.info |
|
141 |
|
|
142 |
if OpenNebula.is_error?(rc) |
|
143 |
failure(:import, id, "Datastore #{ds_id} not found: #{rc}") |
|
144 |
return |
|
145 |
end |
|
146 |
|
|
147 |
ds_mad = ds['DS_MAD'] |
|
148 |
|
|
149 |
if ds_mad.nil? |
|
150 |
failure(:import, id, "Cannot find datastore driver") |
|
151 |
return |
|
152 |
end |
|
153 |
|
|
154 |
#Execute export action from Datastore |
|
155 |
ds_msg = "<DS_DRIVER_ACTION_DATA>"\ |
|
156 |
"#{image.to_xml}"\ |
|
157 |
"#{ds.to_xml}"\ |
|
158 |
"</DS_DRIVER_ACTION_DATA>" |
|
159 |
ds_msg64 = Base64::strict_encode64(ds_msg) |
|
160 |
|
|
161 |
result, info = do_action(id, nil, ds_mad, :export, |
|
162 |
"#{ds_msg64} #{id}", false) |
|
163 |
|
|
164 |
if ( result == RESULT[:failure] ) |
|
165 |
failure(:import, id, "Error exporting image to file: #{info}") |
|
166 |
return |
|
167 |
end |
|
168 |
|
|
169 |
source = info |
|
170 |
elsif ( source =~ /\/.+|https?:\/\// ) |
|
171 |
source = origin |
|
172 |
else |
|
173 |
failure(:import, id, "Origin is not a valid ID, path or URL") |
|
123 |
when "IMAGE" then |
|
124 |
# ------------ Execute export action from Datastore ---------------- |
|
125 |
ds_mad = xml['DATASTORE/DS_MAD'] |
|
126 |
|
|
127 |
if ds_mad.nil? |
|
128 |
failure(:import, id, "Wrong driver message format") |
|
174 | 129 |
return |
175 | 130 |
end |
176 |
else # Only IMAGE type is supported |
|
177 |
failure(:import, id, "Type #{apptype} not supported") |
|
131 |
|
|
132 |
ds_msg = "<DS_DRIVER_ACTION_DATA>"\ |
|
133 |
"#{xml.element_xml('IMAGE')}"\ |
|
134 |
"#{xml.element_xml('DATASTORE')}"\ |
|
135 |
"</DS_DRIVER_ACTION_DATA>" |
|
136 |
|
|
137 |
ds_msg64 = Base64::strict_encode64(ds_msg) |
|
138 |
|
|
139 |
result, info = do_action(id, nil, ds_mad, :export, |
|
140 |
"#{ds_msg64} #{id}", false) |
|
141 |
|
|
142 |
if ( result == RESULT[:failure] ) |
|
143 |
failure(:import, id, "Error exporting image to file: #{info}") |
|
178 | 144 |
return |
145 |
end |
|
146 |
|
|
147 |
info_doc = OpenNebula::XMLElement.new |
|
148 |
info_doc.initialize_xml(info, 'IMPORT_INFO') |
|
149 |
#----------------------------------------------------------------------- |
|
150 |
# Only IMAGE type is supported |
|
151 |
#----------------------------------------------------------------------- |
|
152 |
else |
|
153 |
failure(:import, id, "Type #{apptype} not supported") |
|
154 |
return |
|
179 | 155 |
end |
180 | 156 |
|
157 |
# --------------- Import image app into the marketplace ---------------- |
|
181 | 158 |
xml.add_element('/MARKET_DRIVER_ACTION_DATA', |
182 |
'IMPORT_SOURCE' => "#{source}") |
|
159 |
'IMPORT_SOURCE' => "#{info_doc['IMPORT_SOURCE']}", |
|
160 |
'CHECKSUM' => "#{info_doc['CHECKSUM']}", |
|
161 |
'SIZE' => "#{info_doc['SIZE']}", |
|
162 |
'FORMAT' => "#{info_doc['FORMAT']}", |
|
163 |
'DISPOSE' => "#{info_doc['DISPOSE']}") |
|
164 |
|
|
183 | 165 |
mp_msg64 = Base64::strict_encode64(xml.to_xml) |
184 | 166 |
|
185 | 167 |
result, info = do_action(id, mp_mad, nil, :import, "#{mp_msg64} #{id}", |
... | ... | |
236 | 218 |
|
237 | 219 |
result, info = get_info_from_execution(rc) |
238 | 220 |
|
239 |
info = Base64::strict_encode64(info) if encode |
|
221 |
info = Base64::strict_encode64(info) if encode && result != RESULT[:failure]
|
|
240 | 222 |
|
241 | 223 |
return result, info |
242 | 224 |
end |
src/market_mad/remotes/http/import | ||
---|---|---|
35 | 35 |
DRIVER_PATH=$(dirname $0) |
36 | 36 |
source ${DRIVER_PATH}/../../datastore/libfs.sh |
37 | 37 |
|
38 |
XPATH_PATH="${DRIVER_PATH}/../../datastore"
|
|
38 |
UTILS_PATH="${DRIVER_PATH}/../../datastore"
|
|
39 | 39 |
|
40 | 40 |
# -------- Get arguments from OpenNebula core ------------ |
41 | 41 |
|
42 | 42 |
DRV_ACTION=$1 |
43 | 43 |
ID=$2 |
44 | 44 |
|
45 |
XPATH="$XPATH_PATH/xpath.rb -b $DRV_ACTION"
|
|
45 |
XPATH="$UTILS_PATH/xpath.rb -b $DRV_ACTION"
|
|
46 | 46 |
|
47 | 47 |
unset i XPATH_ELEMENTS |
48 | 48 |
|
49 | 49 |
while IFS= read -r -d '' element; do |
50 | 50 |
XPATH_ELEMENTS[i++]="$element" |
51 | 51 |
done < <($XPATH /MARKET_DRIVER_ACTION_DATA/IMPORT_SOURCE \ |
52 |
/MARKET_DRIVER_ACTION_DATA/FORMAT \ |
|
53 |
/MARKET_DRIVER_ACTION_DATA/DISPOSE \ |
|
54 |
/MARKET_DRIVER_ACTION_DATA/SIZE \ |
|
55 |
/MARKET_DRIVER_ACTION_DATA/CHECKSUM \ |
|
52 | 56 |
/MARKET_DRIVER_ACTION_DATA/MARKETPLACE/TEMPLATE/BASE_URL \ |
57 |
/MARKET_DRIVER_ACTION_DATA/MARKETPLACE/TEMPLATE/BRIDGE_LIST \ |
|
53 | 58 |
/MARKET_DRIVER_ACTION_DATA/MARKETPLACE/TEMPLATE/PUBLIC_DIR) |
54 | 59 |
unset i |
55 | 60 |
|
56 | 61 |
IMPORT_SOURCE="${XPATH_ELEMENTS[i++]}" |
62 |
FORMAT="${XPATH_ELEMENTS[i++]}" |
|
63 |
DISPOSE="${XPATH_ELEMENTS[i++]}" |
|
64 |
SIZE="${XPATH_ELEMENTS[i++]}" |
|
65 |
CHECKSUM="${XPATH_ELEMENTS[i++]}" |
|
57 | 66 |
BASE_URL="${XPATH_ELEMENTS[i++]}" |
67 |
BRIDGE_LIST="${XPATH_ELEMENTS[i++]}" |
|
58 | 68 |
PUBLIC_DIR="${XPATH_ELEMENTS[i++]}" |
59 | 69 |
|
60 | 70 |
# -------- Copy source to public folder an generarte App data ------------ |
... | ... | |
63 | 73 |
DST_PATH="${PUBLIC_DIR}/${APPNAME}" |
64 | 74 |
SOURCE="${BASE_URL}/${APPNAME}" |
65 | 75 |
|
66 |
if [ ! -f ${IMPORT_SOURCE} ]; then |
|
67 |
log_error "File ${IMPORT_SOURCE} does not exits" |
|
68 |
exit -1 |
|
69 |
fi |
|
76 |
if [ -n "$BRIDGE_LIST" ]; then |
|
77 |
DST_HOST=`get_destination_host $ID` |
|
78 |
CP_CMD="$UTILS_PATH/downloader.sh ${IMPORT_SOURCE} -" |
|
70 | 79 |
|
71 |
CHECKSUM=$(${MD5SUM} ${IMPORT_SOURCE} | cut -f1 -d' ') |
|
80 |
exec_and_log "eval $CP_CMD | $SSH ${DST_HOST} $DD of=${DST_PATH} bs=64k" \ |
|
81 |
"Error dumping ${IMPORT_SOURCE} to ${DST_HOST}:${DST_PATH}" |
|
72 | 82 |
|
73 |
SIZE=$(fs_size ${IMPORT_SOURCE}) |
|
83 |
#if [ "${DISPOSE}" = "YES" ]; then |
|
84 |
#TODO This should call a ds operation |
|
85 |
#fi |
|
86 |
else |
|
87 |
CP_CMD="$UTILS_PATH/downloader.sh ${IMPORT_SOURCE} ${DST_PATH}" |
|
88 |
exec_and_log "$CP_CMD" "Error copying ${IMPORT_SOURCE} to ${DST_PATH}" |
|
74 | 89 |
|
75 |
if [ "$SIZE" = "0" ]; then |
|
76 |
log_error "Cannot determine size for ${IMPORT_SOURCE}" |
|
77 |
exit -1 |
|
90 |
if [ "${DISPOSE}" = "YES" ]; then |
|
91 |
#TODO This should call a ds operation |
|
92 |
exec_and_log "$RM ${IMPORT_SOURCE}" "Error removing ${IMPORT_SOURCE}" |
|
93 |
fi |
|
78 | 94 |
fi |
79 | 95 |
|
80 |
exec_and_log "$CP ${IMPORT_SOURCE} ${DST_PATH}" \ |
|
81 |
"Error copying ${IMPORT_SOURCE} to ${DST_PATH}. ${IMPORT_SOURCE} not removed" |
|
82 |
|
|
83 |
exec_and_log "$RM ${IMPORT_SOURCE}" "Error removing ${IMPORT_SOURCE}" |
|
84 |
|
|
85 | 96 |
RESPONSE=$(cat << EOF |
86 | 97 |
SOURCE="$SOURCE" |
87 | 98 |
CHECKSUM="$CHECKSUM" |
88 | 99 |
SIZE="$SIZE" |
100 |
FORMAT="$FORMAT" |
|
89 | 101 |
EOF |
90 | 102 |
) |
91 | 103 |
|
src/nebula/Nebula.cc | ||
---|---|---|
936 | 936 |
|
937 | 937 |
lcm->init_managers(); |
938 | 938 |
|
939 |
marketm->init_managers(); |
|
940 |
|
|
939 | 941 |
// ---- Start the Request Manager ---- |
940 | 942 |
|
941 | 943 |
rc = rm->start(); |
Also available in: Unified diff