R
Romain_Orange
Guest
Bonjour,
For my business, i have made a floppy patch on Proxmox 2.1.
With this patch, you can add "flp" directory, download "flp" files into and, in the same way of cdrom devices, you can create floppy devices and put flp into.
The code is a little bit dirty but, it works fine.
You can find the patch below.
QemuServer.diff :
Storage.diff :
Config.diff
Content.diff :
Status.diff
pvemanagerlib.diff
For my business, i have made a floppy patch on Proxmox 2.1.
With this patch, you can add "flp" directory, download "flp" files into and, in the same way of cdrom devices, you can create floppy devices and put flp into.
The code is a little bit dirty but, it works fine.
You can find the patch below.
QemuServer.diff :
Code:
--- QemuServer.pm.OLD 2012-08-22 17:38:46.000000000 +0200
+++ QemuServer.pm 2012-08-17 09:53:06.000000000 +0200
@@ -401,6 +401,7 @@
my $MAX_HOSTPCI_DEVICES = 2;
my $MAX_SERIAL_PORTS = 4;
my $MAX_PARALLEL_PORTS = 3;
+my $MAX_FLOPPY_DEVICES = 2;
my $nic_model_list = ['rtl8139', 'ne2k_pci', 'e1000', 'pcnet', 'virtio',
'ne2k_isa', 'i82551', 'i82557b', 'i82559er'];
@@ -536,6 +537,18 @@
EODESCR
};
+my $floppydesc= {
+ optional => 1,
+ type => 'string', format => 'pve-qm-drive',
+ typetext => '[volume=]volume,] [,media=cdrom|disk] [,cyls=c,heads=h,secs=s[,trans=t]] [,snapshot=on|off] [,cache=none|writethrough|writeback|unsafe] [,format=f] [,backup=yes|no] [,rerror=ignore|report|stop] [,werror=enospc|ignore|report|stop] [,aio=native|threads]',
+ description => <<EODESCR,
+
+ Note : OB floppy plugin
+
+EODESCR
+};
+PVE::JSONSchema::register_standard_option("pve-qm-floppy", $floppydesc);
+
for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
$confdesc->{"parallel$i"} = $paralleldesc;
}
@@ -571,6 +584,10 @@
for (my $i = 0; $i < $MAX_USB_DEVICES; $i++) {
$confdesc->{"usb$i"} = $usbdesc;
}
+for (my $i = 0; $i < $MAX_FLOPPY_DEVICES; $i++) {
+ $drivename_hash->{"floppy$i"} = 1;
+ $confdesc->{"floppy$i"} = $floppydesc;
+}
my $unuseddesc = {
optional => 1,
@@ -625,6 +642,7 @@
return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
(map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
(map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))),
+ (map { "floppy$_" } (0 .. ($MAX_FLOPPY_DEVICES - 1))),
(map { "sata$_" } (0 .. ($MAX_SATA_DISKS - 1))));
}
@@ -987,7 +1005,9 @@
} elsif ($drive->{interface} eq 'usb') {
die "implement me";
# -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
- } else {
+ } elsif ($drive->{interface} eq 'floppy') {
+
+ }else {
die "unsupported interface type";
}
@@ -1025,6 +1045,10 @@
my $pathinfo = $path ? "file=$path," : '';
+ if($drive->{interface} eq 'floppy'){
+ return "${pathinfo}index=$drive->{index},if=floppy";
+ }
+
return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
}
@@ -2256,7 +2280,9 @@
}
push @$cmd, '-drive',print_drive_full($storecfg, $vmid, $drive);
- push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
+ if($drive->{interface} ne 'floppy'){
+ push @$cmd, '-device',print_drivedevice_full($storecfg,$vmid, $drive);
+ }
});
push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
Storage.diff :
Code:
--- Storage.pm.OLD 2012-08-22 17:38:58.000000000 +0200
+++ Storage.pm 2012-08-23 13:55:31.000000000 +0200
@@ -143,7 +143,7 @@
shared => 0,
disable => 0,
maxfiles => 0,
- content => [ { images => 1, rootdir => 1, vztmpl => 1, iso => 1, backup => 1, none => 1 },
+ content => [ { images => 1, rootdir => 1, vztmpl => 1, iso => 1, backup => 1, flp => 1,none => 1 },
{ images => 1, rootdir => 1 }],
format => [ { raw => 1, qcow2 => 1, vmdk => 1 } , 'raw' ],
},
@@ -723,6 +723,15 @@
return $isodir;
}
+sub get_flp_dir {
+ my ($cfg, $storeid) = @_;
+
+ my $isodir = $cfg->{ids}->{$storeid}->{path};
+ $isodir .= '/template/flp';
+
+ return $isodir;
+}
+
sub get_vztmpl_dir {
my ($cfg, $storeid) = @_;
@@ -964,7 +973,9 @@
return ('image', $name, $vmid);
} elsif ($volname =~ m!^iso/([^/]+\.[Ii][Ss][Oo])$!) {
return ('iso', $1);
- } elsif ($volname =~ m!^vztmpl/([^/]+\.tar\.gz)$!) {
+ } elsif ($volname =~ m!^flp/([^/]+\.[Ff][Ll][Pp])$!) {
+ return ('flp', $1);
+ }elsif ($volname =~ m!^vztmpl/([^/]+\.tar\.gz)$!) {
return ('vztmpl', $1);
} elsif ($volname =~ m!^rootdir/(\d+)$!) {
return ('rootdir', $1, $1);
@@ -1073,6 +1084,7 @@
my $imagedir = get_image_dir($cfg, $storeid, $vmid);
my $isodir = get_iso_dir($cfg, $storeid);
+ my $flpdir = get_flp_dir($cfg, $storeid);
my $tmpldir = get_vztmpl_dir($cfg, $storeid);
my $backupdir = get_backup_dir($cfg, $storeid);
my $privatedir = get_private_dir($cfg, $storeid);
@@ -1081,6 +1093,8 @@
$path = "$imagedir/$name";
} elsif ($vtype eq 'iso') {
$path = "$isodir/$name";
+ } elsif ($vtype eq 'flp'){
+ $path = "$flpdir/$name";
} elsif ($vtype eq 'vztmpl') {
$path = "$tmpldir/$name";
} elsif ($vtype eq 'rootdir') {
@@ -1512,7 +1526,7 @@
sub template_list {
my ($cfg, $storeid, $tt) = @_;
- die "unknown template type '$tt'\n" if !($tt eq 'iso' || $tt eq 'vztmpl' || $tt eq 'backup');
+ die "unknown template type '$tt'\n" if !($tt eq 'iso' || $tt eq 'vztmpl' || $tt eq 'backup' || $tt eq 'flp');
my $ids = $cfg->{ids};
@@ -1533,6 +1547,7 @@
next if $tt eq 'iso' && !$scfg->{content}->{iso};
next if $tt eq 'vztmpl' && !$scfg->{content}->{vztmpl};
next if $tt eq 'backup' && !$scfg->{content}->{backup};
+ next if $tt eq 'flp' && !$scfg->{content}->{flp};
activate_storage ($cfg, $sid);
@@ -1541,7 +1556,9 @@
my $path;
if ($tt eq 'iso') {
$path = get_iso_dir($cfg, $sid);
- } elsif ($tt eq 'vztmpl') {
+ } elsif ($tt eq 'flp') {
+ $path = get_flp_dir($cfg, $sid);
+ }elsif ($tt eq 'vztmpl') {
$path = get_vztmpl_dir($cfg, $sid);
} elsif ($tt eq 'backup') {
$path = get_backup_dir($cfg, $sid);
@@ -1558,6 +1575,11 @@
$info = { volid => "$sid:iso/$1", format => 'iso' };
+ }if ($tt eq 'flp') {
+ next if $fn !~ m!/([^/]+\.[Ff][Ll][Pp])$!;
+
+ $info = { volid => "$sid:flp/$1", format => 'flp' };
+
} elsif ($tt eq 'vztmpl') {
next if $fn !~ m!/([^/]+\.tar\.gz)$!;
Config.diff
Code:
--- Config.pm.sav 2012-08-23 16:33:19.000000000 +0200
+++ Config.pm 2012-08-23 13:14:24.000000000 +0200
@@ -15,7 +15,7 @@
use base qw(PVE::RESTHandler);
-my @ctypes = qw(images vztmpl iso backup);
+my @ctypes = qw(images vztmpl iso backup flp);
my $storage_type_enum = ['dir', 'nfs', 'lvm', 'iscsi'];
Content.diff :
Code:
--- Content.pm.sav 2012-08-23 16:33:07.000000000 +0200
+++ Content.pm 2012-08-23 14:28:13.000000000 +0200
@@ -73,7 +73,9 @@
$data = PVE::Storage::vdisk_list ($cfg, $storeid, $param->{vmid});
} elsif ($ct eq 'iso') {
$data = PVE::Storage::template_list ($cfg, $storeid, 'iso');
- } elsif ($ct eq 'vztmpl') {
+ } elsif ($ct eq 'flp') {
+ $data = PVE::Storage::template_list ($cfg, $storeid, 'flp');
+ }elsif ($ct eq 'vztmpl') {
$data = PVE::Storage::template_list ($cfg, $storeid, 'vztmpl');
} elsif ($ct eq 'backup') {
$data = PVE::Storage::template_list ($cfg, $storeid, 'backup');
Status.diff
Code:
--- Status.pm.sav 2012-08-23 16:32:59.000000000 +0200
+++ Status.pm 2012-08-23 14:36:24.000000000 +0200
@@ -319,6 +319,13 @@
raise_param_exc({ filename => "missing '.iso' extension" });
}
$path = PVE::Storage::get_iso_dir($cfg, $param->{storage});
+
+ } elsif ($content eq 'flp') {
+ if ($filename !~ m![^/]+\.[Ff][Ll][Pp]$!) {
+ raise_param_exc({ filename => "missing '.flp' extension" });
+ }
+ $path = PVE::Storage::get_flp_dir($cfg, $param->{storage});
+
} elsif ($content eq 'vztmpl') {
if ($filename !~ m![^/]+\.tar\.gz$!) {
raise_param_exc({ filename => "missing '.tar.gz' extension" });
pvemanagerlib.diff
Code:
--- pvemanagerlib.js.OLD 2012-08-22 17:39:32.000000000 +0200
+++ pvemanagerlib.js 2012-08-27 09:35:10.000000000 +0200
@@ -641,6 +641,8 @@
cta.push('Templates');
} else if (ct === 'iso') {
cta.push('ISO');
+ }else if (ct === 'flp') {
+ cta.push('FLP');
} else if (ct === 'rootdir') {
cta.push('Containers');
}
@@ -3844,6 +3846,7 @@
me.callParent();
}
});
+
Ext.define('PVE.form.ControllerSelector', {
extend: 'Ext.form.FieldContainer',
alias: ['widget.PVE.form.ControllerSelector'],
@@ -3953,7 +3956,100 @@
me.callParent();
}
-}); Ext.define('PVE.form.RealmComboBox', {
+});
+
+Ext.define('PVE.form.FloppySelector', {
+ extend: 'Ext.form.FieldContainer',
+ alias: ['widget.PVE.form.FloppySelector'],
+
+ statics: {
+ maxIds: {
+ floppy: 2
+ }
+ },
+
+ vmconfig: {}, // used to check for existing devices
+
+ setVMConfig: function(vmconfig, autoSelect) {
+ var me = this;
+
+ me.vmconfig = Ext.apply({}, vmconfig);
+ if (autoSelect) {
+ var clist = ['floppy'];
+
+ Ext.Array.each(clist, function(controller) {
+ var confid, i;
+
+ me.down('field[name=controller]').setValue(controller);
+ for (i = 0; i <= PVE.form.ControllerSelector.maxIds[controller]; i++) {
+ confid = controller + i.toString();
+ if (!Ext.isDefined(me.vmconfig[confid])) {
+ me.down('field[name=deviceid]').setValue(i);
+ return false; // break
+ }
+ }
+ });
+ }
+ me.down('field[name=deviceid]').validate();
+ },
+
+ initComponent: function() {
+ var me = this;
+
+ Ext.apply(me, {
+ fieldLabel: 'Bus/Device',
+ layout: 'hbox',
+ height: 22, // hack: set to same height as other fields
+ defaults: {
+ flex: 1,
+ hideLabel: true
+ },
+ items: [
+ {
+ xtype: 'PVE.form.BusTypeSelector',
+ name: 'controller',
+ value: 'floppy',
+ allowBlank: false,
+ listeners: {
+ change: function(t, value) {
+ if (!me.rendered || !value) {
+ return;
+ }
+ var field = me.down('field[name=deviceid]');
+ field.setMaxValue(PVE.form.ControllerSelector.maxIds[value]);
+ field.validate();
+ }
+ }
+ },
+ {
+ xtype: 'numberfield',
+ name: 'deviceid',
+ minValue: 0,
+ maxValue: PVE.form.ControllerSelector.maxIds.floppy,
+ value: '0',
+ validator: function(value) {
+ /*jslint confusion: true */
+ if (!me.rendered) {
+ return;
+ }
+ var field = me.down('field[name=controller]');
+ var controller = field.getValue();
+ var confid = controller + value;
+ if (Ext.isDefined(me.vmconfig[confid])) {
+ return "This device is already in use.";
+ }
+ return true;
+ }
+ }
+ ]
+ });
+
+ me.callParent();
+ }
+});
+
+
+ Ext.define('PVE.form.RealmComboBox', {
extend: 'Ext.form.field.ComboBox',
alias: ['widget.pveRealmComboBox'],
@@ -4527,7 +4623,7 @@
me.data = [];
- var cts = ['images', 'iso', 'vztmpl', 'backup', 'rootdir'];
+ var cts = ['images', 'iso', 'vztmpl', 'backup', 'rootdir', 'flp'];
Ext.Array.each(cts, function(ct) {
me.data.push([ct, PVE.Utils.format_content_types(ct)]);
});
@@ -10146,6 +10242,142 @@
}
});
+Ext.define('PVE.qemu.FloppyInputPanel', {
+ extend: 'PVE.panel.InputPanel',
+ alias: 'widget.PVE.qemu.FloppyInputPanel',
+
+ insideWizard: false,
+
+ onGetValues: function(values) {
+ var me = this;
+
+ var confid = me.confid || (values.controller + values.deviceid);
+
+ me.drive.media = 'disk';
+ if (values.mediaType === 'flp') {
+ me.drive.file = values.cdimage;
+ }else {
+ me.drive.file = 'none';
+ }
+
+ var params = {};
+
+ params[confid] = PVE.Parser.printQemuDrive(me.drive);
+
+ return params;
+ },
+
+ setVMConfig: function(vmconfig) {
+ var me = this;
+
+ if (me.bussel) {
+ me.bussel.setVMConfig(vmconfig, true);
+ }
+ },
+
+ setDrive: function(drive) {
+ var me = this;
+
+ var values = {};
+ if (drive.file === 'flp') {
+ values.mediaType = 'flp';
+ } else if (drive.file === 'none') {
+ values.mediaType = 'none';
+ } else {
+ values.mediaType = 'flp';
+ var match = drive.file.match(/^([^:]+):/);
+ if (match) {
+ values.cdstorage = match[1];
+ values.cdimage = drive.file;
+ }
+ }
+
+ me.drive = drive;
+
+ me.setValues(values);
+ },
+
+ setNodename: function(nodename) {
+ var me = this;
+
+ me.cdstoragesel.setNodename(nodename);
+ me.cdfilesel.setStorage(undefined, nodename);
+ },
+
+ initComponent : function() {
+ var me = this;
+
+ me.drive = {};
+
+ var items = [];
+
+ if (!me.confid) {
+ me.bussel = Ext.createWidget('PVE.form.FloppySelector');
+ items.push(me.bussel);
+ }
+
+ items.push({
+ xtype: 'radiofield',
+ name: 'mediaType',
+ inputValue: 'flp',
+ boxLabel: 'Use Floppy flp image file',
+ checked: true,
+ listeners: {
+ change: function(f, value) {
+ if (!me.rendered) {
+ return;
+ }
+ me.down('field[name=cdstorage]').setDisabled(!value);
+ me.down('field[name=cdimage]').setDisabled(!value);
+ me.down('field[name=cdimage]').validate();
+ }
+ }
+ });
+
+ me.cdfilesel = Ext.create('PVE.form.FileSelector', {
+ name: 'cdimage',
+ nodename: me.nodename,
+ storageContent: 'flp',
+ fieldLabel: 'Flp Image',
+ labelAlign: 'right',
+ allowBlank: false
+ });
+
+ me.cdstoragesel = Ext.create('PVE.form.StorageSelector', {
+ name: 'cdstorage',
+ nodename: me.nodename,
+ fieldLabel: gettext('Storage'),
+ labelAlign: 'right',
+ storageContent: 'flp',
+ allowBlank: false,
+ autoSelect: me.insideWizard,
+ listeners: {
+ change: function(f, value) {
+ me.cdfilesel.setStorage(value);
+ }
+ }
+ });
+
+ items.push(me.cdstoragesel);
+ items.push(me.cdfilesel);
+
+ items.push({
+ xtype: 'radiofield',
+ name: 'mediaType',
+ inputValue: 'none',
+ boxLabel: 'Do not use any media'
+ });
+
+ if (me.insideWizard) {
+ me.column1 = items;
+ } else {
+ me.items = items;
+ }
+
+ me.callParent();
+ }
+});
+
Ext.define('PVE.qemu.CDEdit', {
extend: 'PVE.window.Edit',
@@ -10188,6 +10420,51 @@
});
}
});
+
+Ext.define('PVE.qemu.FloppyEdit', {
+ extend: 'PVE.window.Edit',
+
+ initComponent : function() {
+ var me = this;
+
+ var nodename = me.pveSelNode.data.node;
+ if (!nodename) {
+ throw "no node name specified";
+ }
+
+ me.create = me.confid ? false : true;
+
+ var ipanel = Ext.create('PVE.qemu.FloppyInputPanel', {
+ confid: me.confid,
+ nodename: nodename
+ });
+
+ Ext.applyIf(me, {
+ subject: 'Floppy Drive',
+ items: [ ipanel ]
+ });
+
+ me.callParent();
+
+ me.load({
+ success: function(response, options) {
+ ipanel.setVMConfig(response.result.data);
+ if (me.confid) {
+ var value = response.result.data[me.confid];
+ var drive = PVE.Parser.parseQemuDrive(me.confid, value);
+ if (!drive) {
+ Ext.Msg.alert('Error', 'Unable to parse drive options');
+ me.close();
+ return;
+ }
+ ipanel.setDrive(drive);
+ }
+ }
+ });
+ }
+});
+
+
// fixme: howto avoid jslint type confusion?
/*jslint confusion: true */
Ext.define('PVE.qemu.HDInputPanel', {
@@ -10621,6 +10898,16 @@
cdheader: gettext('CD/DVD Drive') + ' (' + confid +')'
};
}
+ for (i = 0; i < 2; i++) {
+ confid = "floppy" + i;
+ rows[confid] = {
+ group: 1,
+ tdCls: 'pve-itype-icon-storage',
+ editor: 'PVE.qemu.FloppyEdit',
+ header: gettext('Floppy Drive') + ' (' + confid +')',
+ cdheader: gettext('Floppy Drive') + ' (' + confid +')'
+ };
+ }
for (i = 0; i < 16; i++) {
confid = "virtio" + i;
rows[confid] = {
@@ -10786,6 +11073,19 @@
win.show();
}
},
+ {
+ text: gettext('Floppy Drive'),
+ iconCls: 'pve-itype-icon-storage',
+ //disabled: !caps.vms['VM.Config.Floppy'],
+ handler: function() {
+ var win = Ext.create('PVE.qemu.FloppyEdit', {
+ url: '/api2/extjs/' + baseurl,
+ pveSelNode: me.pveSelNode
+ });
+ win.on('destroy', reload);
+ win.show();
+ }
+ },
{
text: gettext('Network Device'),
iconCls: 'pve-itype-icon-network',
@@ -13613,6 +13913,7 @@
data: [
['iso', 'ISO image'],
['backup', 'VZDump backup file'],
+ ['flp', 'FLP image'],
['vztmpl', 'OpenVZ template']
],
fieldLabel: gettext('Content'),