Statistics
| Branch: | Tag: | Revision:

one / src / rm / RequestManagerImage.cc @ 0fa579fd

History | View | Annotate | Download (16.2 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 "RequestManagerImage.h"
18

    
19
using namespace std;
20

    
21
/* ------------------------------------------------------------------------- */
22
/* ------------------------------------------------------------------------- */
23

    
24
void ImageEnable::request_execute(xmlrpc_c::paramList const& paramList,
25
                                  RequestAttributes& att)
26
{
27
    int     id          = xmlrpc_c::value_int(paramList.getInt(1));
28
    bool    enable_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
29
    int     rc;
30

    
31
    Nebula&          nd     = Nebula::instance();
32
    ImageManager *   imagem = nd.get_imagem();
33

    
34
    if ( basic_authorization(id, att) == false )
35
    {
36
        return;
37
    }
38

    
39
    rc = imagem->enable_image(id,enable_flag, att.resp_msg);
40

    
41
    if( rc < 0 )
42
    {
43
        if (enable_flag == true)
44
        {
45
            att.resp_msg = "Could not enable image: " + att.resp_msg;
46
        }
47
        else
48
        {
49
            att.resp_msg = "Could not disable image: " + att.resp_msg;
50
        }
51

    
52
        failure_response(INTERNAL, att);
53
        return;
54
    }
55

    
56
    success_response(id, att);
57
}
58

    
59
/* ------------------------------------------------------------------------- */
60
/* ------------------------------------------------------------------------- */
61

    
62
void ImagePersistent::request_execute(xmlrpc_c::paramList const& paramList,
63
                                      RequestAttributes& att)
64
{
65
    int     id              = xmlrpc_c::value_int(paramList.getInt(1));
66
    bool    persistent_flag = xmlrpc_c::value_boolean(paramList.getBoolean(2));
67

    
68
    ErrorCode ec = request_execute(id, persistent_flag, att);
69

    
70
    if ( ec == SUCCESS )
71
    {
72
        success_response(id, att);
73
    }
74
    else
75
    {
76
        failure_response(ec, att);
77
    }
78
}
79

    
80
/* ------------------------------------------------------------------------- */
81
/* ------------------------------------------------------------------------- */
82

    
83
Request::ErrorCode ImagePersistent::request_execute(
84
            int     id,
85
            bool    persistent_flag,
86
            RequestAttributes& att)
87
{
88
    int     rc;
89

    
90
    int ds_id;
91
    int ds_persistent_only;
92

    
93
    Nebula&  nd = Nebula::instance();
94
    ImagePool *     ipool  = nd.get_ipool();
95
    DatastorePool * dspool = nd.get_dspool();
96

    
97
    Datastore * ds;
98
    Image * image;
99

    
100
    ErrorCode ec;
101

    
102
    ec = basic_authorization(ipool, id,
103
            AuthRequest::MANAGE, PoolObjectSQL::IMAGE, att);
104

    
105
    if ( ec != SUCCESS)
106
    {
107
        return ec;
108
    }
109

    
110
    image = ipool->get(id,true);
111

    
112
    if ( image == 0 )
113
    {
114
        att.resp_id = id;
115

    
116
        return NO_EXISTS;
117
    }
118

    
119
    ds_id = image->get_ds_id();
120

    
121
    if ( !image->is_managed() )
122
    {
123
        att.resp_msg = "Cannot change persistent state for non-managed images";
124

    
125
        image->unlock();
126

    
127
        return ACTION;
128
    }
129

    
130
    image->unlock();
131

    
132
    ds = dspool->get(ds_id, true);
133

    
134
    if ( ds == 0 )
135
    {
136
        att.resp_msg = "Datastore no longer exists.";
137

    
138
        return INTERNAL;
139
    }
140

    
141
    ds_persistent_only = ds->is_persistent_only();
142

    
143
    ds->unlock();
144

    
145
    image = ipool->get(id,true);
146

    
147
    if ( image == 0 )
148
    {
149
        att.resp_id = id;
150

    
151
        return NO_EXISTS;
152
    }
153

    
154
    switch (image->get_type())
155
    {
156
        case Image::OS:
157
        case Image::DATABLOCK:
158
        case Image::CDROM:
159
        break;
160

    
161
        case Image::KERNEL:
162
        case Image::RAMDISK:
163
        case Image::CONTEXT:
164
            att.resp_msg = "KERNEL, RAMDISK and CONTEXT must be non-persistent";
165
            image->unlock();
166

    
167
            return ACTION;
168
    }
169

    
170
    /* Check if datastore allows the operation */
171
    if ( ds_persistent_only && persistent_flag == false )
172
    {
173
        att.resp_msg = "This Datastore only accepts persistent images.";
174

    
175
        image->unlock();
176

    
177
        return INTERNAL;
178
    }
179

    
180
    rc = image->persistent(persistent_flag, att.resp_msg);
181

    
182
    if ( rc != 0  )
183
    {
184
        if (persistent_flag == true)
185
        {
186
            att.resp_msg = "Could not make image persistent: " + att.resp_msg;
187
        }
188
        else
189
        {
190
            att.resp_msg = "Could not make image non-persistent: " + att.resp_msg;
191
        }
192

    
193
        image->unlock();
194

    
195
        return INTERNAL;
196
    }
197

    
198
    ipool->update(image);
199

    
200
    image->unlock();
201

    
202
    return SUCCESS;
203
}
204

    
205
/* ------------------------------------------------------------------------- */
206
/* ------------------------------------------------------------------------- */
207

    
208
void ImageChangeType::request_execute(xmlrpc_c::paramList const& paramList,
209
                                      RequestAttributes& att)
210
{
211
    int     id   = xmlrpc_c::value_int(paramList.getInt(1));
212
    string  type = xmlrpc_c::value_string(paramList.getString(2));
213
    int     rc;
214

    
215
    Image::ImageType itype;
216

    
217
    Image * image;
218

    
219
    if ( basic_authorization(id, att) == false )
220
    {
221
        return;
222
    }
223

    
224
    image = static_cast<Image *>(pool->get(id,true));
225

    
226
    if ( image == 0 )
227
    {
228
        att.resp_id = id;
229
        failure_response(NO_EXISTS, att);
230
        return;
231
    }
232

    
233
    itype = Image::str_to_type(type);
234

    
235
    switch (image->get_type())
236
    {
237
        case Image::OS:
238
        case Image::DATABLOCK:
239
        case Image::CDROM:
240
            if ((itype != Image::OS) && (itype != Image::DATABLOCK)&&
241
                (itype != Image::CDROM))
242
            {
243
                att.resp_msg = "Cannot change image type to an incompatible type"
244
                    " for the current datastore.";
245
                failure_response(ACTION, att);
246

    
247
                image->unlock();
248
                return;
249
            }
250
        break;
251

    
252
        case Image::KERNEL:
253
        case Image::RAMDISK:
254
        case Image::CONTEXT:
255
            if ((itype != Image::KERNEL) &&
256
                (itype != Image::RAMDISK)&&
257
                (itype != Image::CONTEXT) )
258
            {
259
                att.resp_msg = "Cannot change image type to an incompatible type"
260
                    " for the current datastore.";
261
                failure_response(ACTION, att);
262

    
263
                image->unlock();
264
                return;
265
            }
266
        break;
267
    }
268

    
269
    rc = image->set_type(type, att.resp_msg);
270

    
271
    if ( rc != 0  )
272
    {
273
        failure_response(INTERNAL, att);
274

    
275
        image->unlock();
276
        return;
277
    }
278

    
279
    pool->update(image);
280

    
281
    image->unlock();
282

    
283
    success_response(id, att);
284
}
285

    
286
/* -------------------------------------------------------------------------- */
287
/* -------------------------------------------------------------------------- */
288

    
289
void ImageClone::request_execute(
290
        xmlrpc_c::paramList const&  paramList,
291
        RequestAttributes&          att)
292
{
293
    int    clone_id = xmlrpc_c::value_int(paramList.getInt(1));
294
    string name     = xmlrpc_c::value_string(paramList.getString(2));
295

    
296
    int new_id;
297

    
298
    int ds_id = -1;
299

    
300
    if (paramList.size() > 3)
301
    {
302
        ds_id = xmlrpc_c::value_int(paramList.getInt(3));
303
    }
304

    
305
    ErrorCode ec = request_execute(clone_id, name, ds_id, new_id, att);
306

    
307
    if ( ec == SUCCESS )
308
    {
309
        success_response(new_id, att);
310
    }
311
    else
312
    {
313
        failure_response(ec, att);
314
    }
315
}
316

    
317
/* -------------------------------------------------------------------------- */
318
/* -------------------------------------------------------------------------- */
319

    
320
Request::ErrorCode ImageClone::request_execute(
321
        int             clone_id,
322
        const string&   name,
323
        int             ds_id,
324
        int             &new_id,
325
        RequestAttributes& att)
326
{
327
    long long       avail, size;
328
    int             rc, ds_id_orig;
329
    string          ds_name, ds_data, ds_mad, tm_mad;
330
    bool            ds_check;
331

    
332
    Image::DiskType disk_type;
333
    PoolObjectAuth  perms, ds_perms, ds_perms_orig;
334

    
335
    ImageTemplate * tmpl;
336
    Template        img_usage;
337
    Image *         img;
338
    Datastore *     ds;
339

    
340
    Nebula&  nd = Nebula::instance();
341

    
342
    DatastorePool * dspool = nd.get_dspool();
343
    ImagePool *     ipool  = nd.get_ipool();
344

    
345
    // ------------------------- Get source Image info -------------------------
346

    
347
    img = ipool->get(clone_id, true);
348

    
349
    if ( img == 0 )
350
    {
351
        att.resp_id = clone_id;
352
        return NO_EXISTS;
353
    }
354

    
355
    switch (img->get_type())
356
    {
357
        case Image::OS:
358
        case Image::DATABLOCK:
359
        case Image::CDROM:
360
        break;
361

    
362
        case Image::KERNEL:
363
        case Image::RAMDISK:
364
        case Image::CONTEXT:
365
            att.resp_msg = "KERNEL, RAMDISK and CONTEXT cannot be cloned.";
366
            img->unlock();
367
        return ACTION;
368
    }
369

    
370
    const Snapshots& snaps = img->get_snapshots();
371

    
372
    if (snaps.size () > 0)
373
    {
374
        att.resp_msg = "Cannot clone images with snapshots";
375
        img->unlock();
376
        return ACTION;
377
    }
378

    
379
    tmpl = img->clone_template(name);
380

    
381
    img->get_permissions(perms);
382

    
383
    if (ds_id == -1) //Target Datastore not set, use the current one
384
    {
385
        ds_id = img->get_ds_id();
386
    }
387

    
388
    ds_id_orig = img->get_ds_id();
389

    
390
    size = img->get_size();
391

    
392
    img->unlock();
393

    
394
    //Update persistent attribute from base image if needed
395
    Image::test_set_persistent(tmpl, att.uid, att.gid, false);
396

    
397
    // ----------------------- Get target Datastore info -----------------------
398

    
399
    ds = dspool->get(ds_id, true);
400

    
401
    if ( ds == 0 )
402
    {
403
        att.resp_obj = PoolObjectSQL::DATASTORE;
404
        att.resp_id  = ds_id;
405

    
406
        delete tmpl;
407
        return NO_EXISTS;
408
    }
409

    
410
    if ( ds->get_type() != Datastore::IMAGE_DS )
411
    {
412
        att.resp_msg = "Clone only supported for IMAGE_DS Datastores";
413

    
414
        ds->unlock();
415

    
416
        delete tmpl;
417
        return ACTION;
418
    }
419

    
420
    ds->get_permissions(ds_perms);
421

    
422
    disk_type = ds->get_disk_type();
423

    
424
    ds->to_xml(ds_data);
425

    
426
    ds_check = ds->get_avail_mb(avail);
427
    ds_name  = ds->get_name();
428
    ds_mad   = ds->get_ds_mad();
429
    tm_mad   = ds->get_tm_mad();
430

    
431
    ds->unlock();
432

    
433
    if (ds_id != ds_id_orig) //check same DS_MAD
434
    {
435
        ds = dspool->get(ds_id_orig, true);
436

    
437
        if (ds == 0)
438
        {
439
            att.resp_obj = PoolObjectSQL::DATASTORE;
440
            att.resp_id  = ds_id_orig;
441

    
442
            delete tmpl;
443
            return NO_EXISTS;
444
        }
445

    
446
        if (ds->get_type() != Datastore::IMAGE_DS)
447
        {
448
            att.resp_msg = "Clone only supported for IMAGE_DS Datastores";
449

    
450
            ds->unlock();
451

    
452
            delete tmpl;
453
            return ACTION;
454
        }
455

    
456
        if (ds->get_ds_mad() != ds_mad)
457
        {
458
            att.resp_msg = "Clone only supported to same DS_MAD Datastores";
459

    
460
            ds->unlock();
461

    
462
            delete tmpl;
463
            return ACTION;
464
        }
465

    
466
        ds->get_permissions(ds_perms_orig);
467

    
468
        ds->unlock();
469
    }
470

    
471
    // ------------- Set authorization request ---------------------------------
472

    
473
    img_usage.add("DATASTORE", ds_id);
474
    img_usage.add("SIZE", size);
475

    
476
    if (ds_check && (size > avail))
477
    {
478
        att.resp_msg = "Not enough space in datastore";
479

    
480
        delete tmpl;
481
        return ACTION;
482
    }
483

    
484
    if ( att.uid != 0 )
485
    {
486
        AuthRequest ar(att.uid, att.group_ids);
487
        string      tmpl_str;
488

    
489
        // ------------------ Check permissions and ACLs  ----------------------
490
        // Create image
491
        // Use original image
492
        // Use target datastore
493
        // Use original datastore, if different
494
        // ---------------------------------------------------------------------
495
        tmpl->to_xml(tmpl_str);
496

    
497
        ar.add_create_auth(att.uid, att.gid, PoolObjectSQL::IMAGE, tmpl_str);
498

    
499
        ar.add_auth(AuthRequest::USE, perms);
500

    
501
        ar.add_auth(AuthRequest::USE, ds_perms);
502

    
503
        if (ds_id != ds_id_orig)
504
        {
505
            ar.add_auth(AuthRequest::USE, ds_perms_orig);
506
        }
507

    
508
        if (UserPool::authorize(ar) == -1)
509
        {
510
            att.resp_msg = ar.message;
511

    
512
            delete tmpl;
513
            return AUTHORIZATION;
514
        }
515

    
516
        // -------------------------- Check Quotas  ----------------------------
517

    
518
        if ( quota_authorization(&img_usage, Quotas::DATASTORE, att,
519
                    att.resp_msg) == false )
520
        {
521
            delete tmpl;
522
            return AUTHORIZATION;
523
        }
524
    }
525

    
526
    rc = ipool->allocate(att.uid,
527
                         att.gid,
528
                         att.uname,
529
                         att.gname,
530
                         att.umask,
531
                         tmpl,
532
                         ds_id,
533
                         ds_name,
534
                         disk_type,
535
                         ds_data,
536
                         Datastore::IMAGE_DS,
537
                         ds_mad,
538
                         tm_mad,
539
                         "",
540
                         clone_id,
541
                         &new_id,
542
                         att.resp_msg);
543
    if ( rc < 0 )
544
    {
545
        quota_rollback(&img_usage, Quotas::DATASTORE, att);
546

    
547
        return ALLOCATE;
548
    }
549

    
550
    ds = dspool->get(ds_id, true);
551

    
552
    if ( ds != 0 )  // TODO: error otherwise or leave image in ERROR?
553
    {
554
        ds->add_image(new_id);
555

    
556
        dspool->update(ds);
557

    
558
        ds->unlock();
559
    }
560

    
561
    return SUCCESS;
562
}
563

    
564
/* ------------------------------------------------------------------------- */
565
/* ------------------------------------------------------------------------- */
566

    
567
void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList,
568
                                  RequestAttributes& att)
569
{
570
    int id      = xmlrpc_c::value_int(paramList.getInt(1));
571
    int snap_id = xmlrpc_c::value_int(paramList.getInt(2));
572

    
573
    Nebula&        nd     = Nebula::instance();
574
    ImageManager * imagem = nd.get_imagem();
575

    
576
    if ( basic_authorization(id, att) == false )
577
    {
578
        return;
579
    }
580

    
581
    int rc = imagem->delete_snapshot(id, snap_id, att.resp_msg);
582

    
583
    if ( rc < 0 )
584
    {
585
        failure_response(ACTION, att);
586
        return;
587
    }
588

    
589
    success_response(snap_id, att);
590
}
591

    
592
/* ------------------------------------------------------------------------- */
593
/* ------------------------------------------------------------------------- */
594

    
595
void ImageSnapshotRevert::request_execute(xmlrpc_c::paramList const& paramList,
596
                                  RequestAttributes& att)
597
{
598
    int id      = xmlrpc_c::value_int(paramList.getInt(1));
599
    int snap_id = xmlrpc_c::value_int(paramList.getInt(2));
600

    
601
    Nebula&        nd     = Nebula::instance();
602
    ImageManager * imagem = nd.get_imagem();
603

    
604
    if ( basic_authorization(id, att) == false )
605
    {
606
        return;
607
    }
608

    
609
    int rc = imagem->revert_snapshot(id, snap_id, att.resp_msg);
610

    
611
    if ( rc < 0 )
612
    {
613
        failure_response(ACTION, att);
614
        return;
615
    }
616

    
617
    success_response(snap_id, att);
618
}
619

    
620
/* ------------------------------------------------------------------------- */
621
/* ------------------------------------------------------------------------- */
622

    
623
void ImageSnapshotFlatten::request_execute(xmlrpc_c::paramList const& paramList,
624
                                  RequestAttributes& att)
625
{
626
    int id      = xmlrpc_c::value_int(paramList.getInt(1));
627
    int snap_id = xmlrpc_c::value_int(paramList.getInt(2));
628

    
629
    Nebula&        nd     = Nebula::instance();
630
    ImageManager * imagem = nd.get_imagem();
631

    
632
    if ( basic_authorization(id, att) == false )
633
    {
634
        return;
635
    }
636

    
637
    int rc = imagem->flatten_snapshot(id, snap_id, att.resp_msg);
638

    
639
    if ( rc < 0 )
640
    {
641
        failure_response(ACTION, att);
642
        return;
643
    }
644

    
645
    success_response(snap_id, att);
646
}
647