image-resize-4.2.patch

Rebase against 4.2 - Simon Boulet, 07/30/2013 06:01 AM

Download (15.4 KB)

View differences:

include/ImageManager.h
180 180
     *         occurred describing the error.
181 181
     *  @result 0 on success
182 182
     */
183
     int stat_image(Template* img_tmpl, const string& ds_tmpl, string& res);
183
    int stat_image(Template* img_tmpl, const string& ds_tmpl, string& res);
184

  
185
    /**
186
     *  Resizes the image
187
     *    @param iid id of image
188
     *    @param new_size new size of the image in MB
189
     *    @return 0 on success
190
     */
191
    int resize_image(int iid, int new_size, const string& ds_data, string& error);
184 192

  
185 193
     /**
186 194
      *  Trigger a monitor action for the datastore.
include/ImageManagerDriver.h
114 114
     *    @param drv_msg xml data for the mad operation.
115 115
     */
116 116
    void monitor(int oid, const string& drv_msg) const;
117

  
118
    /**
119
     *  Sends a resize request to the MAD: "RESIZE IMAGE_ID PATH"
120
     *    @param oid the image id.
121
     *    @param drv_msg xml data for the mad operation.
122
     */
123
    void resize(int oid, const string& drv_msg) const;
117 124
};
118 125

  
119 126
/* -------------------------------------------------------------------------- */
include/RequestManagerImage.h
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
src/datastore_mad/one_datastore.rb
50 50
        :log     => "LOG",
51 51
        :stat    => "STAT",
52 52
        :clone   => "CLONE",
53
        :monitor => "MONITOR"
53
        :monitor => "MONITOR",
54
        :resize => "RESIZE"
54 55
    }
55 56

  
56 57
    # Register default actions for the protocol
......
65 66
                ACTION[:rm]      => nil,
66 67
                ACTION[:mkfs]    => nil,
67 68
                ACTION[:clone]   => nil,
68
                ACTION[:monitor] => nil
69
                ACTION[:monitor] => nil,
70
                ACTION[:resize]  => nil
69 71
            }
70 72
        }.merge!(options)
71 73

  
......
87 89
        register_action(ACTION[:stat].to_sym, method("stat"))
88 90
        register_action(ACTION[:clone].to_sym, method("clone"))
89 91
        register_action(ACTION[:monitor].to_sym, method("monitor"))
92
        register_action(ACTION[:resize].to_sym,method("resize"))
90 93
    end
91 94

  
92 95
    ############################################################################
......
123 126
        do_image_action(id, ds, :monitor, "#{drv_message} #{id}", true)
124 127
    end
125 128

  
129
    def resize(id, drv_message)
130
        ds = get_ds_type(drv_message)
131
        do_image_action(id, ds, :resize, "#{drv_message} #{id}")
132
    end
133

  
126 134
    private
127 135

  
128 136
    def is_available?(ds, id, action)
src/image/ImageManagerActions.cc
826 826

  
827 827
    return rc;
828 828
}
829
/* -------------------------------------------------------------------------- */
830
/* -------------------------------------------------------------------------- */
831

  
832
int ImageManager::resize_image(int   iid,
833
                               int   new_size,
834
                               const string& ds_data,
835
                               string& error)
836
{
837
    const ImageManagerDriver* imd = get();
838

  
839
    ostringstream oss;
840
    Image *       img;
841

  
842
    string   img_tmpl;
843
    string * drv_msg;
844

  
845
    if ( imd == 0 )
846
    {
847
        error = "Could not get datastore driver";
848

  
849
        NebulaLog::log("ImM",Log::ERROR, error);
850
        return -1;
851
    }
852

  
853
    img = ipool->get(iid, true);
854

  
855
    if (img == 0)
856
    {
857
        error = "Cannot resize image, it does not exist";
858
        return -1;
859
    }
860

  
861
    if ( img->get_state() != Image::READY &&
862
         img->get_state() != Image::USED &&
863
         img->get_state() != Image::USED_PERS )
864
    {
865
        oss << "Cannot resize image in state: "
866
            << Image::state_to_str(img->get_state());
867

  
868
        error = oss.str();
869
        img->unlock();
870
        return -1;
871
    }
872

  
873
    img->set_state(Image::LOCKED);
874
    img->set_size(new_size);  
875

  
876
    ipool->update(img);
877

  
878
    drv_msg = format_message(img->to_xml(img_tmpl), ds_data);
879

  
880
    imd->resize(img->get_oid(), *drv_msg);
881

  
882
    oss << "Resizing image " << img->get_path()
883
        <<" to " << img->get_size()
884
        << "Mb (type: " <<  img->get_fstype() << ")";
885

  
886
    NebulaLog::log("ImM", Log::INFO, oss);
887

  
888
    img->unlock();
889

  
890
    delete drv_msg;
891

  
892
    return 0;
893
}
829 894

  
830 895
/* -------------------------------------------------------------------------- */
831 896
/* -------------------------------------------------------------------------- */
src/image/ImageManagerDriver.cc
94 94
}
95 95

  
96 96
/* -------------------------------------------------------------------------- */
97

  
98
void ImageManagerDriver::resize(int oid, const string& drv_msg) const
99
{
100
    ostringstream os;
101

  
102
    os << "RESIZE " << oid << " " << drv_msg << endl;
103

  
104
    write(os);
105
}
106

  
107
/* -------------------------------------------------------------------------- */
97 108
/* -------------------------------------------------------------------------- */
98 109

  
99 110
/* ************************************************************************** */
......
666 677
}
667 678

  
668 679
/* -------------------------------------------------------------------------- */
680

  
681
static void resize_action(istringstream& is, 
682
                      ImagePool*     ipool, 
683
                      int            id, 
684
                      const string&  result)
685
{
686
    string  info;
687
    Image * image;
688

  
689
    ostringstream oss;
690

  
691
    image = ipool->get(id, true);
692

  
693
    if ( image == 0 )
694
    {
695
        return;
696
    }
697

  
698
    if ( result == "FAILURE" )
699
    {
700
        goto error;
701
    }
702

  
703
    if ( image->get_running() == 0 ) {
704
        image->set_state(Image::READY);
705
    } else if ( image->isPersistent() ) {
706
        image->set_state(Image::USED_PERS);
707
    } else {
708
        image->set_state(Image::USED);
709
    }
710

  
711
    ipool->update(image);
712

  
713
    image->unlock();
714

  
715
    NebulaLog::log("ImM", Log::INFO, "Image successfully resized.");
716

  
717
    return;
718

  
719
error:
720
    oss << "Error resizing image";
721

  
722
    getline(is, info);
723

  
724
    if (!info.empty() && (info[0] != '-'))
725
    {
726
        oss << ": " << info;
727
    }
728

  
729
    NebulaLog::log("ImM", Log::ERROR, oss);
730

  
731
    image->set_template_error_message(oss.str());
732
    image->set_state(Image::ERROR);
733

  
734
    ipool->update(image);
735

  
736
    image->unlock();
737

  
738
    return;
739
}
740

  
741
/* -------------------------------------------------------------------------- */
669 742
/* -------------------------------------------------------------------------- */
670 743

  
671 744
void ImageManagerDriver::protocol(const string& message) const
......
740 813
    {
741 814
        monitor_action(is, dspool, id, result);
742 815
    }
816
    else if ( action == "RESIZE" )
817
    {
818
        resize_action(is, ipool, id, result);
819
    }
743 820
    else if (action == "LOG")
744 821
    {
745 822
        getline(is,info);
src/rm/RequestManager.cc
343 343
    xmlrpc_c::methodPtr image_enable(new ImageEnable());
344 344
    xmlrpc_c::methodPtr image_chtype(new ImageChangeType());
345 345
    xmlrpc_c::methodPtr image_clone(new ImageClone());
346
    xmlrpc_c::methodPtr image_resize(new ImageResize());
346 347

  
347 348
    // Chown Methods
348 349
    xmlrpc_c::methodPtr vm_chown(new VirtualMachineChown());
......
494 495
    RequestManagerRegistry.addMethod("one.image.chtype", image_chtype);
495 496
    RequestManagerRegistry.addMethod("one.image.clone", image_clone);
496 497
    RequestManagerRegistry.addMethod("one.image.rename", image_rename);
498
    RequestManagerRegistry.addMethod("one.image.resize", image_resize);
497 499

  
498 500
    RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);
499 501

  
src/rm/RequestManagerImage.cc
423 423
    success_response(new_id, att);
424 424
}
425 425

  
426
/* ------------------------------------------------------------------------- */
427
/* ------------------------------------------------------------------------- */
428

  
429
void ImageResize::request_execute(xmlrpc_c::paramList const& paramList,
430
                                      RequestAttributes& att)
431
{
432
    int     id   = xmlrpc_c::value_int(paramList.getInt(1));
433
    int     new_size = xmlrpc_c::value_int(paramList.getInt(2));
434

  
435
    int     rc, ds_id, size, uid, gid;
436
    string  error_str, ds_data;
437

  
438
    Template        img_usage;
439
    Image *         img;
440
    Datastore *     ds;
441

  
442
    Nebula&         nd     = Nebula::instance();
443
    ImageManager *  imagem = nd.get_imagem();
444
    DatastorePool * dspool = nd.get_dspool();
445

  
446
    if ( basic_authorization(id, att) == false )
447
    {
448
        return;
449
    }
450

  
451
    // ------------------------- Get Image info -------------------------
452

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

  
455
    if ( img == 0 )
456
    {
457
        failure_response(NO_EXISTS,
458
                get_error(object_name(auth_object),id),
459
                att);
460

  
461
        return;
462
    }
463

  
464
    ds_id   = img->get_ds_id();
465
    size    = img->get_size();
466
    uid     = img->get_uid();
467
    gid     = img->get_gid();
468

  
469
    img->unlock();
470

  
471
    // ------------------------- Get Datastore info ----------------------------
472

  
473
    ds = dspool->get(ds_id, true);
474

  
475
    if ( ds == 0 )
476
    {
477
        failure_response(NO_EXISTS,
478
                get_error(object_name(PoolObjectSQL::DATASTORE), ds_id),
479
                att);
480

  
481
        return;
482
    }
483

  
484
    ds->to_xml(ds_data);
485

  
486
    ds->unlock();
487

  
488
    // -------------------------- Check and Update Quotas  ----------------------------
489

  
490
    // Check quota for owner of the image, not the request caller
491
    RequestAttributes quota_att(uid, gid, att);
492

  
493
    img_usage.add("DATASTORE", ds_id);
494
    img_usage.add("IMAGES", 0);  // Don't update images count
495
    
496
    if ( new_size > size )
497
    {
498
        // Update quota usage to extended size
499
        img_usage.add("SIZE", new_size - size);
500

  
501
        if ( quota_authorization(&img_usage, Quotas::DATASTORE, quota_att) == false )
502
        {
503
             // Over quota
504
             return;
505
        }
506
    }
507

  
508
    rc = imagem->resize_image(id, new_size, ds_data, error_str);
509

  
510
    if( rc < 0 )
511
    {
512
        if ( new_size > size ) {
513
            // Rollback quota update
514
            quota_rollback(&img_usage, Quotas::DATASTORE, quota_att);
515
        }
516

  
517
        failure_response(INTERNAL, request_error(error_str,""), att);
518
        return;
519
    }
520

  
521
    // If disk is being shrinked, reduce quota usage
522
    if ( new_size < size ) 
523
    {
524
        img_usage.add("SIZE", size - new_size);
525

  
526
        quota_rollback(&img_usage, Quotas::DATASTORE, quota_att);
527
    }
528

  
529
    success_response(id, att);
530
}
426 531

  
src/um/QuotaDatastore.cc
32 32
    map<string, float> ds_request;
33 33

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

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

  
......
48 48
        return false;
49 49
    }
50 50

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

  
57
    ds_request.insert(make_pair("IMAGES", images));
58
    ds_request.insert(make_pair("SIZE",   size));
53 59

  
54 60
    return check_quota(ds_id, ds_request, default_quotas, error);
55 61
}
......
62 68
    map<string, float> ds_request;
63 69

  
64 70
    string ds_id;
65
    int    size;
71
    int    size, images;
66 72

  
67 73
    tmpl->get("DATASTORE", ds_id);
68 74

  
......
76 82
        return;
77 83
    }
78 84

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

  
91
    ds_request.insert(make_pair("IMAGES", images));
92
    ds_request.insert(make_pair("SIZE",   size));
81 93

  
82 94
    del_quota(ds_id, ds_request);
83 95
}
84
-