image-resize.patch

Simon Boulet, 01/14/2013 11:48 PM

Download (15.4 KB)

View differences:

opennebula-3.8.1.resize/include/ImageManager.h 2013-01-14 14:04:13.000000000 -0500
168 168
     *         occurred describing the error.
169 169
     *  @result 0 on success
170 170
     */
171
     int stat_image(Template* img_tmpl, const string& ds_tmpl, string& res);
171
    int stat_image(Template* img_tmpl, const string& ds_tmpl, string& res);
172

  
173
    /**
174
     *  Resizes the image
175
     *    @param iid id of image
176
     *    @param new_size new size of the image in MB
177
     *    @return 0 on success
178
     */
179
    int resize_image(int iid, int new_size, const string& ds_data, string& error);
172 180

  
173 181
private:
174 182
    /**
opennebula-3.8.1.resize/include/ImageManagerDriver.h 2013-01-14 12:18:25.000000000 -0500
99 99
     *    @param drv_msg xml data for the mad operation.
100 100
     */
101 101
    void rm(int oid, const string& drv_msg) const;
102

  
103
    /**
104
     *  Sends a resize request to the MAD: "RESIZE IMAGE_ID PATH"
105
     *    @param oid the image id.
106
     *    @param drv_msg xml data for the mad operation.
107
     */
108
    void resize(int oid, const string& drv_msg) const;
102 109
};
103 110

  
104 111
/* -------------------------------------------------------------------------- */
opennebula-3.8.1.resize/include/RequestManagerImage.h 2013-01-14 12:17:40.000000000 -0500
121 121

  
122 122
/* -------------------------------------------------------------------------- */
123 123
/* -------------------------------------------------------------------------- */
124

  
125
class ImageResize : public RequestManagerImage
126
{
127
public:
128
    ImageResize():
129
        RequestManagerImage("ImageResize",
130
                "Changes the size of an image",
131
                "A:sii"){};
132

  
133
    ~ImageResize(){};
134

  
135
    void request_execute(xmlrpc_c::paramList const& _paramList,
136
                         RequestAttributes& att);
137
};
138

  
139
/* -------------------------------------------------------------------------- */
140
/* -------------------------------------------------------------------------- */
124 141
/* -------------------------------------------------------------------------- */
125 142

  
126 143
#endif
opennebula-3.8.1.resize/src/datastore_mad/one_datastore.rb 2013-01-14 15:15:05.000000000 -0500
44 44

  
45 45
    # Image Driver Protocol constants
46 46
    ACTION = {
47
        :cp    => "CP",
48
        :rm    => "RM",
49
        :mkfs  => "MKFS",
50
        :log   => "LOG",
51
        :stat  => "STAT",
52
        :clone => "CLONE"
47
        :cp     => "CP",
48
        :rm     => "RM",
49
        :mkfs   => "MKFS",
50
        :log    => "LOG",
51
        :stat   => "STAT",
52
        :clone  => "CLONE",
53
        :resize => "RESIZE"
53 54
    }
54 55

  
55 56
    # Register default actions for the protocol
......
59 60
            :threaded => true,
60 61
            :retries => 0,
61 62
            :local_actions => {
62
                ACTION[:stat] => nil,
63
                ACTION[:cp]   => nil,
64
                ACTION[:rm]   => nil,
65
                ACTION[:mkfs] => nil,
66
                ACTION[:clone]=> nil
63
                ACTION[:stat]  => nil,
64
                ACTION[:cp]    => nil,
65
                ACTION[:rm]    => nil,
66
                ACTION[:mkfs]  => nil,
67
                ACTION[:clone] => nil,
68
                ACTION[:resize]=> nil
67 69
            }
68 70
        }.merge!(options)
69 71

  
......
84 86
        register_action(ACTION[:mkfs].to_sym, method("mkfs"))
85 87
        register_action(ACTION[:stat].to_sym, method("stat"))
86 88
        register_action(ACTION[:clone].to_sym,method("clone"))
89
        register_action(ACTION[:resize].to_sym,method("resize"))
87 90
    end
88 91

  
89 92
    ############################################################################
......
115 118
        do_image_action(id, ds, :clone, "#{drv_message} #{id}")
116 119
    end
117 120

  
121
    def resize(id, drv_message)
122
        ds = get_ds_type(drv_message)
123
        do_image_action(id, ds, :resize, "#{drv_message} #{id}")
124
    end
125

  
118 126
    private
119 127

  
120 128
    def is_available?(ds, id, action)
opennebula-3.8.1.resize/src/image/ImageManagerActions.cc 2013-01-14 15:00:41.000000000 -0500
737 737

  
738 738
    return rc;
739 739
}
740
/* -------------------------------------------------------------------------- */
741
/* -------------------------------------------------------------------------- */
742

  
743
int ImageManager::resize_image(int   iid,
744
                               int   new_size,
745
                               const string& ds_data,
746
                               string& error)
747
{
748
    const ImageManagerDriver* imd = get();
749

  
750
    ostringstream oss;
751
    Image *       img;
752

  
753
    string   img_tmpl;
754
    string * drv_msg;
755

  
756
    if ( imd == 0 )
757
    {
758
        error = "Could not get datastore driver";
759

  
760
        NebulaLog::log("ImM",Log::ERROR, error);
761
        return -1;
762
    }
763

  
764
    img = ipool->get(iid, true);
765

  
766
    if (img == 0)
767
    {
768
        error = "Cannot resize image, it does not exist";
769
        return -1;
770
    }
771

  
772
    if (img->get_state() != Image::READY )
773
    {
774
        oss << "Cannot resize image in state: "
775
            << Image::state_to_str(img->get_state());
776

  
777
        error = oss.str();
778
        img->unlock();
779
        return -1;
780
    }
781

  
782
    img->set_state(Image::LOCKED);
783
    img->set_size(new_size);  
784

  
785
    ipool->update(img);
786

  
787
    drv_msg = format_message(img->to_xml(img_tmpl), ds_data);
788

  
789
    imd->resize(img->get_oid(), *drv_msg);
790

  
791
    oss << "Resizing image " << img->get_path()
792
        <<" to " << img->get_size()
793
        << "Mb (type: " <<  img->get_fstype() << ")";
794

  
795
    NebulaLog::log("ImM", Log::INFO, oss);
796

  
797
    img->unlock();
798

  
799
    delete drv_msg;
800

  
801
    return 0;
802
}
740 803

  
741 804
/* -------------------------------------------------------------------------- */
742 805
/* -------------------------------------------------------------------------- */
opennebula-3.8.1.resize/src/image/ImageManagerDriver.cc 2013-01-14 12:52:25.000000000 -0500
83 83
}
84 84

  
85 85
/* -------------------------------------------------------------------------- */
86

  
87
void ImageManagerDriver::resize(int oid, const string& drv_msg) const
88
{
89
    ostringstream os;
90

  
91
    os << "RESIZE " << oid << " " << drv_msg << endl;
92

  
93
    write(os);
94
}
95

  
96
/* -------------------------------------------------------------------------- */
86 97
/* -------------------------------------------------------------------------- */
87 98

  
88 99
/* ************************************************************************** */
......
522 533
}
523 534

  
524 535
/* -------------------------------------------------------------------------- */
536

  
537
static void resize_action(istringstream& is, 
538
                      ImagePool*     ipool, 
539
                      int            id, 
540
                      const string&  result)
541
{
542
    string  info;
543
    Image * image;
544

  
545
    ostringstream oss;
546

  
547
    image = ipool->get(id, true);
548

  
549
    if ( image == 0 )
550
    {
551
        return;
552
    }
553

  
554
    if ( result == "FAILURE" )
555
    {
556
        goto error;
557
    }
558

  
559
    image->set_state(Image::READY);
560

  
561
    ipool->update(image);
562

  
563
    image->unlock();
564

  
565
    NebulaLog::log("ImM", Log::INFO, "Image successfully resized.");
566

  
567
    return;
568

  
569
error:
570
    oss << "Error resizing image";
571

  
572
    getline(is, info);
573

  
574
    if (!info.empty() && (info[0] != '-'))
575
    {
576
        oss << ": " << info;
577
    }
578

  
579
    NebulaLog::log("ImM", Log::ERROR, oss);
580

  
581
    image->set_template_error_message(oss.str());
582
    image->set_state(Image::ERROR);
583

  
584
    ipool->update(image);
585

  
586
    image->unlock();
587

  
588
    return;
589
}
590

  
591
/* -------------------------------------------------------------------------- */
525 592
/* -------------------------------------------------------------------------- */
526 593

  
527 594
void ImageManagerDriver::protocol(
......
591 658
    {
592 659
        rm_action(is, ipool, id, result);
593 660
    }
661
    else if ( action == "RESIZE" )
662
    {
663
        resize_action(is, ipool, id, result);
664
    }
594 665
    else if (action == "LOG")
595 666
    {
596 667
        getline(is,info);
opennebula-3.8.1.resize/src/rm/RequestManager.cc 2013-01-14 12:17:40.000000000 -0500
333 333
    xmlrpc_c::methodPtr image_enable(new ImageEnable());
334 334
    xmlrpc_c::methodPtr image_chtype(new ImageChangeType());
335 335
    xmlrpc_c::methodPtr image_clone(new ImageClone());
336
    xmlrpc_c::methodPtr image_resize(new ImageResize());
336 337

  
337 338
    // Chown Methods
338 339
    xmlrpc_c::methodPtr vm_chown(new VirtualMachineChown());
......
444 445
    /* Image related methods*/
445 446
    RequestManagerRegistry.addMethod("one.image.persistent", image_persistent);
446 447
    RequestManagerRegistry.addMethod("one.image.enable", image_enable);
447
    RequestManagerRegistry.addMethod("one.image.update", image_update);     
448
    RequestManagerRegistry.addMethod("one.image.update", image_update);
448 449
    RequestManagerRegistry.addMethod("one.image.allocate", image_allocate);
449 450
    RequestManagerRegistry.addMethod("one.image.delete", image_delete);
450 451
    RequestManagerRegistry.addMethod("one.image.info", image_info);
......
452 453
    RequestManagerRegistry.addMethod("one.image.chmod", image_chmod);
453 454
    RequestManagerRegistry.addMethod("one.image.chtype", image_chtype);
454 455
    RequestManagerRegistry.addMethod("one.image.clone", image_clone);
456
    RequestManagerRegistry.addMethod("one.image.resize", image_resize);
455 457

  
456 458
    RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);
457 459

  
opennebula-3.8.1.resize/src/rm/RequestManagerImage.cc 2013-01-14 18:05:33.000000000 -0500
303 303
    success_response(new_id, att);
304 304
}
305 305

  
306
/* ------------------------------------------------------------------------- */
307
/* ------------------------------------------------------------------------- */
308

  
309
void ImageResize::request_execute(xmlrpc_c::paramList const& paramList,
310
                                      RequestAttributes& att)
311
{
312
    int     id   = xmlrpc_c::value_int(paramList.getInt(1));
313
    int     new_size = xmlrpc_c::value_int(paramList.getInt(2));
314

  
315
    int     rc, ds_id, size, uid, gid;
316
    string  error_str, ds_data;
317

  
318
    Template        img_usage;
319
    Image *         img;
320
    Datastore *     ds;
321

  
322
    Nebula&         nd     = Nebula::instance();
323
    ImageManager *  imagem = nd.get_imagem();
324
    DatastorePool * dspool = nd.get_dspool();
325

  
326
    if ( basic_authorization(id, att) == false )
327
    {
328
        return;
329
    }
330

  
331
    // ------------------------- Get Image info -------------------------
332

  
333
    img = static_cast<Image *>(pool->get(id,true));
334

  
335
    if ( img == 0 )
336
    {
337
        failure_response(NO_EXISTS,
338
                get_error(object_name(auth_object),id),
339
                att);
340

  
341
        return;
342
    }
343

  
344
    ds_id   = img->get_ds_id();
345
    size    = img->get_size();
346
    uid     = img->get_uid();
347
    gid     = img->get_gid();
348

  
349
    img->unlock();
350

  
351
    // ------------------------- Get Datastore info ----------------------------
352

  
353
    ds = dspool->get(ds_id, true);
354

  
355
    if ( ds == 0 )
356
    {
357
        failure_response(NO_EXISTS,
358
                get_error(object_name(PoolObjectSQL::DATASTORE), ds_id),
359
                att);
360

  
361
        return;
362
    }
363

  
364
    ds->to_xml(ds_data);
365

  
366
    ds->unlock();
367

  
368
    // -------------------------- Check and Update Quotas  ----------------------------
369

  
370
    // Check quota for owner of the image, not the request caller
371
    RequestAttributes quota_att(uid, gid, att);
372

  
373
    img_usage.add("DATASTORE", ds_id);
374
    img_usage.add("IMAGES", 0);  // Don't update images count
375
    
376
    if ( new_size > size )
377
    {
378
        // Update quota usage to extended size
379
        img_usage.add("SIZE", new_size - size);
380

  
381
        if ( quota_authorization(&img_usage, Quotas::DATASTORE, quota_att) == false )
382
        {
383
             // Over quota
384
             return;
385
        }
386
    }
387

  
388
    rc = imagem->resize_image(id, new_size, ds_data, error_str);
389

  
390
    if( rc < 0 )
391
    {
392
        if ( new_size > size ) {
393
            // Rollback quota update
394
            quota_rollback(&img_usage, Quotas::DATASTORE, quota_att);
395
        }
396

  
397
        failure_response(INTERNAL, request_error(error_str,""), att);
398
        return;
399
    }
400

  
401
    // If disk is being shrinked, reduce quota usage
402
    if ( new_size < size ) 
403
    {
404
        img_usage.add("SIZE", size - new_size);
405

  
406
        quota_rollback(&img_usage, Quotas::DATASTORE, quota_att);
407
    }
408

  
409
    success_response(id, att);
410
}
306 411

  
opennebula-3.8.1.resize/src/um/QuotaDatastore.cc 2013-01-14 18:04:07.000000000 -0500
31 31
    map<string, float> ds_request;
32 32

  
33 33
    string ds_id;
34
    int    size;
34
    int    size, images;
35 35

  
36 36
    tmpl->get("DATASTORE", ds_id);
37 37

  
......
47 47
        return false;
48 48
    }
49 49

  
50
    ds_request.insert(make_pair("IMAGES",1));
51
    ds_request.insert(make_pair("SIZE",  size));
50
    if ( tmpl->get("IMAGES", images) == false )
51
    {
52
        // Increment image count by default
53
        images = 1;
54
    }
55

  
56
    ds_request.insert(make_pair("IMAGES", images));
57
    ds_request.insert(make_pair("SIZE",   size));
52 58
    
53 59
    return check_quota(ds_id, ds_request, error);
54 60
}
......
61 67
    map<string, float> ds_request;
62 68

  
63 69
    string ds_id;
64
    int    size;
70
    int    size, images;
65 71

  
66 72
    tmpl->get("DATASTORE", ds_id);
67 73

  
......
75 81
        return;
76 82
    }
77 83

  
78
    ds_request.insert(make_pair("IMAGES",1));
79
    ds_request.insert(make_pair("SIZE",  size));
84
    if ( tmpl->get("IMAGES", images) == false )
85
    {
86
        // Decrement image count by default
87
        images = 1;
88
    }
89

  
90
    ds_request.insert(make_pair("IMAGES", images));
91
    ds_request.insert(make_pair("SIZE",   size));
80 92

  
81 93
    del_quota(ds_id, ds_request);
82 94
}