
On 06/09/2014 11:56 PM, ssdxiao wrote:
Upload ISO to the path /var/lib/kimchi/iso of the local disk
Signed-off-by: ssdxiao <ssdxiao@163.com> --- contrib/kimchi.spec.fedora.in | 1 + contrib/kimchi.spec.suse.in | 1 + po/en_US.po | 3 + po/pt_BR.po | 3 + po/zh_CN.po | 3 + src/kimchi/control/storagepools.py | 28 +- src/nginx.conf.in | 1 + ui/css/theme-default/upload.css | 43 ++ ui/js/resumable.js | 816 +++++++++++++++++++++++++++++++++ ui/js/src/kimchi.template_add_main.js | 27 ++ ui/pages/kimchi-ui.html.tmpl | 1 + ui/pages/template-add.html.tmpl | 13 + 12 files changed, 938 insertions(+), 2 deletions(-) create mode 100644 ui/css/theme-default/upload.css create mode 100644 ui/js/resumable.js
diff --git a/src/kimchi/control/storagepools.py b/src/kimchi/control/storagepools.py index b75bca0..72b9f78 100644 --- a/src/kimchi/control/storagepools.py +++ b/src/kimchi/control/storagepools.py @@ -18,8 +18,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import cherrypy - - +import os +import errno from kimchi.control.base import Collection, Resource from kimchi.control.storagevolumes import IsoVolumes, StorageVolumes from kimchi.control.utils import get_class_name, model_fn @@ -28,6 +28,9 @@ from kimchi.model.storagepools import ISO_POOL_NAME from kimchi.control.utils import UrlSubNode
+ISO_UPLOAD_DIR = "/var/lib/kimchi/iso/" + + @UrlSubNode("storagepools", True, ['POST', 'DELETE']) class StoragePools(Collection): def __init__(self, model): @@ -35,6 +38,11 @@ class StoragePools(Collection): self.resource = StoragePool isos = IsoPool(model) setattr(self, ISO_POOL_NAME, isos) + try: + os.makedirs(ISO_UPLOAD_DIR, mode=0755) + except OSError as e: + if e.errno == errno.EEXIST: + pass
def create(self, params, *args): try: @@ -57,6 +65,22 @@ class StoragePools(Collection):
return resp
+ @cherrypy.expose + def upload(self, *args, **kwargs): + method = cherrypy.request.method.upper() + if method != "POST": + raise cherrypy.HTTPError(405) + fileName = kwargs["resumableFilename"] + chunkSize = kwargs["resumableChunkSize"] + chunkNumber = kwargs["resumableChunkNumber"] + position = int(chunkSize) * (int(chunkNumber)-1) + + filePath = ISO_UPLOAD_DIR+fileName + fp = open(filePath, "a+") + fp.seek(position) + fp.write(kwargs["file"].fullvalue()) + fp.close() +
1) The upload action is related to a specific storage pool instance, so it must be in StoragePool(Resource) So the API will be: POST /storagepools/<pool-name>/upload {file: <filename>} The code should be like: # in StoragePool(Resource) self.upload = self.generate_action_handler('upload') 2) The upload logic is implemented in the models. The control only receive/parse the request and send the response it gets from model We have 2 models: src/model/ and src/mockmodel.py The first one is the real model (connects to libvirt and make all happen) and the second one is a fake model - only to make the tests easier to do # in src/kimchi/model/storagepools.py (StoragePoolModel(object)) def upload(self): # insert the upload code here # in src/mockmodel.py def storagepool_upload(self): # create a fake upload method 3) For new features (and this is the case), you need to add a new test case for it tests/test_rest.py tests/test_model.py tests/test_mockmodel.py 4) Make sure you code is ready for review by running "make check" and "make check-local"
def _get_resources(self, filter_params): try: res_list = super(StoragePools, self)._get_resources(filter_params) diff --git a/src/nginx.conf.in b/src/nginx.conf.in index 38e643d..9568476 100644 --- a/src/nginx.conf.in +++ b/src/nginx.conf.in @@ -37,6 +37,7 @@ http {
access_log /var/log/nginx/access.log main; sendfile on; + client_max_body_size 2m;
server { listen $proxy_ssl_port ssl;