Statistics
| Branch: | Tag: | Revision:

one / src / market / MarketPlaceManagerDriver.cc @ 6368bb51

History | View | Annotate | Download (12.3 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2017, 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
#include "MarketPlaceManagerDriver.h"
18
#include "Nebula.h"
19
#include <sstream>
20

    
21
/* ************************************************************************** */
22
/* Driver ASCII Protocol Implementation                                       */
23
/* ************************************************************************** */
24

    
25
void MarketPlaceManagerDriver::importapp(int oid, const std::string& msg) const
26
{
27
    std::ostringstream os;
28

    
29
    os << "IMPORT " << oid << " " << msg << endl;
30

    
31
    write(os);
32
}
33

    
34
/* -------------------------------------------------------------------------- */
35

    
36
void MarketPlaceManagerDriver::deleteapp(int oid, const std::string& msg) const
37
{
38
    std::ostringstream os;
39

    
40
    os << "DELETE " << oid << " " << msg << endl;
41

    
42
    write(os);
43
}
44

    
45
/* -------------------------------------------------------------------------- */
46

    
47
void MarketPlaceManagerDriver::monitor(int oid, const std::string& msg) const
48
{
49
    std::ostringstream os;
50

    
51
    os << "MONITOR " << oid << " " << msg << endl;
52

    
53
    write(os);
54
}
55

    
56
/* ************************************************************************** */
57
/* MAD Interface                                                              */
58
/* ************************************************************************** */
59

    
60
static void monitor_action(
61
        std::istringstream&  is,
62
        MarketPlacePool *    marketpool,
63
        MarketPlaceAppPool * apppool,
64
        MarketPlaceManager * marketm,
65
        int                  id,
66
        const std::string&   result)
67
{
68
    std::string  info64;
69
    std::string* info = 0;
70

    
71
    std::ostringstream oss;
72

    
73
    getline (is, info64);
74

    
75
    if (is.fail())
76
    {
77
        oss << "Error monitoring marketplace " << id << ". Bad monitor data: "
78
            << info64;
79

    
80
        NebulaLog::log("MKP", Log::ERROR, oss);
81
        return;
82
    }
83

    
84
    if (result != "SUCCESS")
85
    {
86
        oss << "Error monitoring marketplace " << id << ": " << info64;
87
        NebulaLog::log("MKP", Log::ERROR, oss);
88

    
89
        delete info;
90
        return;
91
    }
92

    
93
    info = one_util::base64_decode(info64);
94

    
95
    if (info == 0)
96
    {
97
        oss << "Error monitoring marketplace " << id << ". Bad monitor data: "
98
            << info64;
99

    
100
        NebulaLog::log("MKP", Log::ERROR, oss);
101
        return;
102
    }
103

    
104

    
105
    Template monitor_data;
106

    
107
    char * error_msg;
108
    int    rc = monitor_data.parse(*info, &error_msg);
109

    
110
    delete info;
111

    
112
    if ( rc != 0 )
113
    {
114
        oss << "Error parsing marketplace information: " << error_msg
115
            << ". Monitoring information: " << endl << info64;
116

    
117
        NebulaLog::log("MKP", Log::ERROR, oss);
118

    
119
        free(error_msg);
120
        return;
121
    }
122

    
123
    MarketPlace * market = marketpool->get(id, true);
124

    
125
    if (market == 0 )
126
    {
127
        return;
128
    }
129

    
130
    set<int> apps_mp = market->get_marketapp_ids();
131
    std::string name = market->get_name();
132

    
133
    market->update_monitor(monitor_data);
134

    
135
    marketpool->update(market);
136

    
137
    market->unlock();
138

    
139
    std::vector<SingleAttribute *> apps;
140
    std::string err;
141

    
142
    int num = monitor_data.get("APP", apps);
143

    
144
    for (int i=0; i< num ; i++)
145
    {
146
        int app_id;
147
        int rc = apppool->import(apps[i]->value(), id, name, app_id, err);
148

    
149
        if ( rc == -1 )
150
        {
151
            NebulaLog::log("MKP", Log::ERROR, "Error importing app: " + err);
152
        }
153
        else if ( rc >= 0 ) //-2 means app already imported
154
        {
155
            MarketPlace * market = marketpool->get(id, true);
156

    
157
            if ( market != 0 )
158
            {
159
                market->add_marketapp(rc);
160

    
161
                marketpool->update(market);
162

    
163
                market->unlock();
164
            }
165
        }
166

    
167
        apppool->reset_map_check(app_id);
168

    
169
        apps_mp.erase(app_id);
170
    }
171

    
172
    for (set<int>::iterator i = apps_mp.begin(); i != apps_mp.end(); ++i)
173
    {
174
        if (apppool->test_map_check(*i)) //delete app
175
        { 
176
            std::string error;
177

    
178
            MarketPlaceApp * app = apppool->get(*i, true);
179

    
180
            if ( app == 0 )
181
            {
182
                continue;
183
            }
184

    
185
            rc = apppool->drop(app, error);
186

    
187
            app->unlock();
188

    
189
            market = marketpool->get(id, true);
190

    
191
            market->del_marketapp(*i);
192

    
193
            marketpool->update(market);
194

    
195
            market->unlock();
196
        }
197
    }
198

    
199
    oss << "Marketplace " << name << " (" << id << ") successfully monitored.";
200

    
201
    NebulaLog::log("MKP", Log::DEBUG, oss);
202

    
203
    return;
204
}
205

    
206
/* -------------------------------------------------------------------------- */
207
/* Helper functions for failure and error conditions                          */
208
/* -------------------------------------------------------------------------- */
209

    
210
static void set_failure_response(
211
        std::istringstream * is,
212
        PoolObjectSQL *     obj,
213
        const std::string&  msg)
214
{
215
    std::ostringstream oss;
216
    std::string        info;
217

    
218
    oss << msg;
219

    
220
    getline(*is, info);
221

    
222
    if (!info.empty() && (info[0] != '-'))
223
    {
224
        oss << ": " << info;
225
    }
226

    
227
    if (obj != 0)
228
    {
229
        obj->set_template_error_message(oss.str());
230
    }
231

    
232
    NebulaLog::log("MKP", Log::ERROR, oss);
233
}
234

    
235
static void app_failure_action(
236
        std::istringstream * is,
237
        MarketPlaceAppPool * apppool,
238
        int                  id,
239
        const std::string&   msg)
240
{
241
    MarketPlaceApp * app = apppool->get(id, true);
242

    
243
    if (app == 0)
244
    {
245
        return;
246
    }
247

    
248
    if ( is == 0)
249
    {
250
        app->set_template_error_message(msg);
251

    
252
        NebulaLog::log("MKP", Log::ERROR, msg);
253
    }
254
    else
255
    {
256
        set_failure_response(is, app, msg);
257
    }
258

    
259
    app->set_state(MarketPlaceApp::ERROR);
260

    
261
    apppool->update(app);
262

    
263
    app->unlock();
264
}
265

    
266
/* -------------------------------------------------------------------------- */
267
/* -------------------------------------------------------------------------- */
268

    
269
static int import_action(
270
        std::istringstream&  is,
271
        MarketPlaceAppPool * apppool,
272
        MarketPlaceManager * marketm,
273
        int                  id,
274
        const std::string&   result)
275
{
276
    bool rc;
277
    int  rci;
278

    
279
    std::string   error;
280
    std::string   info64;
281
    std::string * info;
282

    
283
    MarketPlaceApp *       app;
284
    MarketPlaceAppTemplate tmpl;
285

    
286
    std::string source;
287
    std::string checksum;
288
    std::string format;
289
    long long   size_mb;
290

    
291
    marketm->release_app_resources(id);
292

    
293
    if ( result == "FAILURE" )
294
    {
295
        app_failure_action(&is, apppool, id, "Error importing app into marketplace");
296
        return -1;
297
    }
298

    
299
    getline(is, info64);
300

    
301
    if (is.fail())
302
    {
303
        goto error_parse;
304
    }
305

    
306
    info = one_util::base64_decode(info64);
307

    
308
    if ( info == 0 )
309
    {
310
        goto error_decode64;
311
    }
312

    
313
    rci = tmpl.parse_str_or_xml(*info, error);
314

    
315
    delete info;
316

    
317
    if ( rci != 0 )
318
    {
319
        goto error_parse_template;
320
    }
321

    
322
    tmpl.get("SOURCE", source);
323
    tmpl.get("MD5", checksum);
324
    tmpl.get("FORMAT", format);
325
    rc = tmpl.get("SIZE", size_mb);
326

    
327
    if ( source.empty() || checksum.empty() || format.empty() || rc == false )
328
    {
329
        goto error_attributes;
330
    }
331

    
332
    app = apppool->get(id, true);
333

    
334
    if (app == 0)
335
    {
336
        goto error_app;
337
    }
338

    
339
    app->set_source(source);
340
    app->set_md5(checksum);
341
    app->set_size(size_mb);
342
    app->set_format(format);
343

    
344
    app->set_state(MarketPlaceApp::READY);
345

    
346
    apppool->update(app);
347

    
348
    app->unlock();
349

    
350
    NebulaLog::log("MKP", Log::INFO, "Marketplace app successfully imported");
351

    
352
    return 0;
353

    
354
error_parse:
355
    app_failure_action(0, apppool, id,
356
        "Error importing app into marketplace. Wrong message from driver.");
357
    return -1;
358

    
359
error_decode64:
360
    app_failure_action(0, apppool, id,
361
        "Error importing app into marketplace. Bad base64 encoding.");
362
    return -1;
363

    
364
error_parse_template:
365
    app_failure_action(0, apppool, id,
366
        "Error importing app into marketplace. Parse error: " + error);
367
    return -1;
368

    
369
error_attributes:
370
    app_failure_action(0, apppool, id,
371
        "Error importing app into marketplace. Missing app attributes.");
372
    return -1;
373

    
374
error_app:
375
    NebulaLog::log("MKP", Log::ERROR, "Marketplace app successfully imported "
376
        "but it no longer exists. You may need to manually remove: " + source);
377
    return -1;
378
}
379

    
380
/* -------------------------------------------------------------------------- */
381
/* -------------------------------------------------------------------------- */
382

    
383
static int delete_action(
384
        std::istringstream&  is,
385
        MarketPlaceAppPool * apppool,
386
        MarketPlaceManager * marketm,
387
        int                  id,
388
        const std::string&   result)
389
{
390
    int rc;
391

    
392
    std::string source;
393
    std::string error;
394

    
395
    std::ostringstream eoss("Error removing app from marketplace", std::ios::ate);
396

    
397
    MarketPlaceApp * app = apppool->get(id, true);
398

    
399
    if ( app == 0 )
400
    {
401
        return -1;
402
    }
403

    
404
    source = app->get_source();
405

    
406
    rc = apppool->drop(app, error);
407

    
408
    app->unlock();
409

    
410
    if ( result == "FAILURE" )
411
    {
412
        std::string info;
413

    
414
        getline(is, info);
415

    
416
        if (!info.empty() && (info[0] != '-'))
417
        {
418
            eoss << ": " << info;
419
        }
420

    
421
        eoss << ".";
422
    }
423

    
424
    if ( rc < 0 )
425
    {
426
        eoss << " Error removing app from DB: " << error
427
             << ". Remove app manually, source is: " << source;
428
    }
429

    
430
    if ( rc < 0 || result == "FAILURE" )
431
    {
432
        NebulaLog::log("MKP", Log::ERROR, eoss.str());
433
    }
434
    else
435
    {
436
        NebulaLog::log("MKP",Log::INFO,"Marketplace app successfully removed.");
437
    }
438

    
439
    return rc;
440
}
441

    
442
/* -------------------------------------------------------------------------- */
443
/* -------------------------------------------------------------------------- */
444

    
445
void MarketPlaceManagerDriver::protocol(const string& message) const
446
{
447
    std::istringstream is(message);
448
    std::ostringstream oss;
449

    
450
    std::string action;
451
    std::string result;
452
    std::string info;
453

    
454
    int id;
455

    
456
    oss << "Message received: " << message;
457
    NebulaLog::log("MKP", Log::DDEBUG, oss);
458

    
459
    // --------------------- Parse the driver message --------------------------
460

    
461
    if ( is.good() )
462
        is >> action >> ws;
463
    else
464
        return;
465

    
466
    if ( is.good() )
467
        is >> result >> ws;
468
    else
469
        return;
470

    
471
    if ( is.good() )
472
    {
473
        is >> id >> ws;
474

    
475
        if ( is.fail() )
476
        {
477
            if ( action == "LOG" )
478
            {
479
                is.clear();
480
                getline(is,info);
481

    
482
                NebulaLog::log("MKP",log_type(result[0]), info.c_str());
483
            }
484

    
485
            return;
486
        }
487
    }
488
    else
489
        return;
490

    
491
    if (action == "IMPORT")
492
    {
493
        import_action(is, apppool, marketm, id, result);
494
    }
495
    else if (action == "DELETE")
496
    {
497
        delete_action(is, apppool, marketm, id, result);
498
    }
499
    else if (action == "MONITOR")
500
    {
501
        monitor_action(is, marketpool, apppool, marketm, id, result);
502
    }
503
    else if (action == "LOG")
504
    {
505
        getline(is,info);
506
        NebulaLog::log("MKP", log_type(result[0]), info.c_str());
507
    }
508

    
509
    return;
510
}
511

    
512
/* -------------------------------------------------------------------------- */
513
/* -------------------------------------------------------------------------- */
514

    
515
void MarketPlaceManagerDriver::recover()
516
{
517
    NebulaLog::log("MKP",Log::INFO,"Recovering MarketPlace drivers");
518
}
519