Floppy patch

  • Thread starter Thread starter Romain_Orange
  • Start date Start date
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 :

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'),