[pve-devel] [PATCH manager] WIP: upload disk image

Timo Grodzinski t.grodzinski at profihost.ag
Fri Jan 29 18:38:15 CET 2016


Signed-off-by: Timo Grodzinski <t.grodzinski at profihost.ag>
---
 PVE/REST.pm                      |   2 +-
 www/manager/qemu/HardwareView.js | 189 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/PVE/REST.pm b/PVE/REST.pm
index bf7ce15..f66d28e 100644
--- a/PVE/REST.pm
+++ b/PVE/REST.pm
@@ -98,7 +98,7 @@ sub auth_handler {
 
 	$rpcenv->set_user($username);
 
-	if ($method eq 'POST' && $rel_uri =~ m|^/nodes/([^/]+)/storage/([^/]+)/upload$|) {
+	if ($method eq 'POST' && $rel_uri =~ m|^/nodes/([^/]+)/storage/([^/]+)/upload(?:_image)?$|) {
 	    my ($node, $storeid) = ($1, $2);
 	    # we disable CSRF checks if $isUpload is set,
 	    # to improve security we check user upload permission here
diff --git a/www/manager/qemu/HardwareView.js b/www/manager/qemu/HardwareView.js
index 89f2f4e..34a5dcc 100644
--- a/www/manager/qemu/HardwareView.js
+++ b/www/manager/qemu/HardwareView.js
@@ -298,6 +298,16 @@ Ext.define('PVE.qemu.HardwareView', {
 	    win.on('destroy', reload);
 	};
 
+        var run_upload = function() {
+	    var win = Ext.create('PVE.storage.UploadImage', {
+	        nodename: nodename,
+                vmid: vmid,
+	        storage: "local" // XXX
+	    });
+	    win.show();
+	    win.on('destroy', reload);
+	};
+
 	var run_cpuoptions = function() {
 	    var sockets = me.getObjectValue('sockets', 1);
 	    var cores = me.getObjectValue('cores', 1);
@@ -344,6 +354,10 @@ Ext.define('PVE.qemu.HardwareView', {
 	    disabled: true,
 	    handler: run_resize
 	});
+        var upload_btn = new PVE.button.Button({
+            text: gettext('Upload disk'),
+            handler: run_upload
+        });
 
 	var move_btn = new PVE.button.Button({
 	    text: gettext('Move disk'),
@@ -510,6 +524,7 @@ Ext.define('PVE.qemu.HardwareView', {
 		}, 
 		remove_btn,
 		edit_btn,
+		upload_btn,
 		resize_btn,
 		move_btn,
 		diskthrottle_btn,
@@ -535,3 +550,177 @@ Ext.define('PVE.qemu.HardwareView', {
 	});
     }
 });
+
+// XXX move to pve-manager/www/manager/qemu/HardwareView.js
+// XXX borrowed from /home/tgrodzinski/devel/proxmox2/pve-manager/www/manager/storage/ContentView.js
+// XXX 'PVE.storage.Upload'
+Ext.define('PVE.storage.UploadImage', {
+    extend: 'Ext.window.Window',
+    alias: ['widget.pveStorageUploadImage'],
+
+    resizable: false,
+
+    modal: true,
+
+    initComponent : function() {
+	/*jslint confusion: true */
+        var me = this;
+
+	var xhr;
+
+	if (!me.nodename) {
+	    throw "no node name specified";
+	}
+
+        if (!me.vmid) {
+	    throw "no vm ID specified";
+	}
+
+
+	if (!me.storage) {
+	    throw "no storage ID specified";
+	}
+
+	var baseurl = "/nodes/" + me.nodename + "/storage/" + me.storage + "/upload_image";
+
+	var pbar = Ext.create('Ext.ProgressBar', {
+            text: 'Ready',
+	    hidden: true
+	});
+
+	me.formPanel = Ext.create('Ext.form.Panel', {
+	    method: 'POST',
+	    waitMsgTarget: true,
+	    bodyPadding: 10,
+	    border: false,
+	    width: 300,
+	    fieldDefaults: {
+		labelWidth: 100,
+		anchor: '100%'
+            },
+	    items: [
+		{ // XXX erlaubte dateiendungen angeben
+		    xtype: 'filefield',
+		    name: 'filename',
+		    buttonText: gettext('Select File...'),
+		    allowBlank: false
+		},
+		pbar
+	    ]
+	});
+
+	var form = me.formPanel.getForm();
+
+	var doStandardSubmit = function() {
+	    form.submit({
+		url: "/api2/htmljs" + baseurl,
+		waitMsg: gettext('Uploading file...'),
+		success: function(f, action) {
+		    me.close();
+		},
+		failure: function(f, action) {
+		    var msg = PVE.Utils.extractFormActionError(action);
+                    Ext.Msg.alert(gettext('Error'), msg);
+		}
+	    });
+	};
+
+	var updateProgress = function(per, bytes) {
+	    var text = (per * 100).toFixed(2) + '%';
+	    if (bytes) {
+		text += " (" + PVE.Utils.format_size(bytes) + ')';
+	    }
+	    pbar.updateProgress(per, text);
+	};
+ 
+	var abortBtn = Ext.create('Ext.Button', {
+	    text: gettext('Abort'),
+	    disabled: true,
+	    handler: function() {
+		me.close();
+	    }
+	});
+
+	var submitBtn = Ext.create('Ext.Button', {
+	    text: gettext('Upload'),
+	    disabled: true,
+	    handler: function(button) {
+		var fd;
+		try {
+		    fd = new FormData();
+		} catch (err) {
+		    doStandardSubmit();
+		    return;
+		}
+
+		button.setDisabled(true);
+		abortBtn.setDisabled(false);
+                
+		fd.append('content', 'images'); // XXX hard coded, see /PVE/API2/Storage/Status.pm
+                fd.append('vmid', me.vmid);
+                fd.append('format', 'qcow2'); // XXX hard coded
+
+		field = form.findField('filename');
+		var file = field.fileInputEl.dom;
+		fd.append("filename", file.files[0]);
+		field.setDisabled(true);
+
+		pbar.setVisible(true);
+		updateProgress(0);
+
+		xhr = new XMLHttpRequest();
+
+		xhr.addEventListener("load", function(e) {   
+		    if (xhr.status == 200) {
+			me.close();
+		    } else {  
+			var msg = gettext('Error') + " " + xhr.status.toString() + ": " + Ext.htmlEncode(xhr.statusText);
+			var result = Ext.decode(xhr.responseText);
+			result.message = msg;
+			var htmlStatus = PVE.Utils.extractRequestError(result, true);
+			Ext.Msg.alert(gettext('Error'), htmlStatus, function(btn) {
+			    me.close();
+			});
+
+		    }  
+		}, false);
+
+		xhr.addEventListener("error", function(e) {
+		    var msg = "Error " + e.target.status.toString() + " occurred while receiving the document.";
+		    Ext.Msg.alert(gettext('Error'), msg, function(btn) {
+			me.close();
+		    });
+		});
+ 
+		xhr.upload.addEventListener("progress", function(evt) {
+		    if (evt.lengthComputable) {  
+			var percentComplete = evt.loaded / evt.total;  
+			updateProgress(percentComplete, evt.loaded);
+		    } 
+		}, false);
+
+		xhr.open("POST", "/api2/json" + baseurl, true);
+		xhr.send(fd);		
+	    }
+	});
+
+	form.on('validitychange', function(f, valid) {
+	    submitBtn.setDisabled(!valid);
+	});
+
+        Ext.applyIf(me, {
+            title: gettext('Upload'),
+	    items: me.formPanel,
+	    buttons: [ abortBtn, submitBtn ],
+	    listeners: {
+		close: function() {
+		    if (xhr) {
+			xhr.abort();
+		    }
+		}
+	    }
+	});
+
+        me.callParent();
+    }
+});
-- 
2.1.4




More information about the pve-devel mailing list