From b7f6ea0dd458cee86da6060eda20062e8719c6b1 Mon Sep 17 00:00:00 2001 From: Dirk von Suchodoletz Date: Sun, 28 Feb 2010 12:30:13 +0100 Subject: Updating vmchooser, heavy cleanup in vmware plugin ... --- .../plugins/vmware/OpenSLX/OSPlugin/vmware.pm | 131 ++++++++++----------- os-plugins/plugins/vmware/XX_vmware.sh | 73 +++--------- os-plugins/plugins/vmware/files/run-virt.include | 6 +- .../init-hooks/20-nw-bridge-config/bridge.sh | 2 +- .../init-hooks/60-have-servconfig/vm-dhcpd.sh | 56 +++++++++ 5 files changed, 142 insertions(+), 126 deletions(-) create mode 100755 os-plugins/plugins/vmware/init-hooks/60-have-servconfig/vm-dhcpd.sh diff --git a/os-plugins/plugins/vmware/OpenSLX/OSPlugin/vmware.pm b/os-plugins/plugins/vmware/OpenSLX/OSPlugin/vmware.pm index 0be6fe74..72629a14 100644 --- a/os-plugins/plugins/vmware/OpenSLX/OSPlugin/vmware.pm +++ b/os-plugins/plugins/vmware/OpenSLX/OSPlugin/vmware.pm @@ -300,8 +300,7 @@ sub installationPhase if (-e "/usr/bin/vmware" && ! -e "/usr/bin/vmware.slx-bak") { rename("/usr/bin/vmware", "/usr/bin/vmware.slx-bak"); } - # write the runlevel script - $self->_writeRunlevelScript(); + } sub removalPhase @@ -327,9 +326,7 @@ sub checkStage3AttrValues my $vendorOSAttrs = shift; my @problems; - my $vm_kind = $stage3Attrs->{'vmware::kind'} || ''; - - + my $vm_kind = $stage3Attrs->{'vmware::kind'} || ''; my $vmimg = $stage3Attrs->{'vmware::imagesrc'} || ''; if ($vm_kind eq 'local' && ! -x "/usr/lib/vmware/bin/vmplayer") { @@ -345,6 +342,13 @@ sub checkStage3AttrValues ); } + if ($vm_kind eq 'vmpl1.0' && + ! -d "/opt/openslx/plugin-repo/vmware/vmpl1.0/vmroot") { + push @problems, _tr( + "No OpenSLX installation of VMware Player 1 found or installation failed. Using it as virtual machine wouldn't work!" + ); + } + if ($vm_kind eq 'vmpl2.0' && ! -d "/opt/openslx/plugin-repo/vmware/vmpl2.0/vmroot") { push @problems, _tr( @@ -359,10 +363,10 @@ sub checkStage3AttrValues ); } - if ($vm_kind eq 'vmpl1.0' && - ! -d "/opt/openslx/plugin-repo/vmware/vmpl1.0/vmroot") { + if ($vm_kind eq 'vmpl3.0' && + ! -d "/opt/openslx/plugin-repo/vmware/vmpl3.0/vmroot") { push @problems, _tr( - "No OpenSLX installation of VMware Player 1 found or installation failed. Using it as virtual machine wouldn't work!" + "No OpenSLX installation of VMware Player 3 found or installation failed. Using it as virtual machine wouldn't work!" ); } @@ -377,30 +381,28 @@ sub checkStage3AttrValues ####################################### # Write the runlevelscript +# usage: _writeRunlevelScript("$vmpath", "$kind") sub _writeRunlevelScript { my $self = shift; - my $kind = $self->{attrs}->{'vmware::kind'} || 'local'; + my $vmpath = shift; + my $kind = shift; my $initfile = newInitFile(); - my %versionhash = (vmversion => "", vmbuildversion => ""); - my $vmversion = ""; my $script = ""; - my $vmpath = ""; my $modpath = ""; my $modlist = ""; + # vmpath is to be redefined here ... if ($kind =~ /local*/) { - $vmpath = "/"; + $vmpath = ""; $modpath = "/lib/modules/\$(uname -r)/misc"; } elsif ($kind =~ /vmpl*/) { $vmpath = "/opt/openslx/plugin-repo/vmware/${kind}"; $modpath = "${vmpath}/vmroot/modules"; } - %versionhash = _getVersion("${vmpath}/usr/bin"); - $vmversion = $versionhash{vmversion}; $initfile->setName("vmware-slx"); - $initfile->setDesc("Setup environment for VMware Workstation or Player ($vmversion)."); + $initfile->setDesc("Setup environment for VMware Workstation or Player ($kind)."); # functions ... $modlist = "vmnet vmmon"; @@ -417,7 +419,7 @@ sub _writeRunlevelScript insmod ${modpath}/vmblock.ko || return 1 End-of-Here $modlist .= "vsock vmci vmblock"; - } elsif ($kind eq 'local20' || $kind eq 'vmpl2.0' || $kind eq 'vmpl2.5') { + } elsif ($kind eq 'local20' || $kind eq 'local25' || $kind eq 'vmpl2.0' || $kind eq 'vmpl2.5') { $script .= unshiftHereDoc(<<" End-of-Here"); # VMplayer 2.X specific stuff insmod ${modpath}/vmblock.ko @@ -435,21 +437,20 @@ sub _writeRunlevelScript # vmnet0,1,8 (bridge, nat, host-only) interface definition $script = unshiftHereDoc(<<" End-of-Here"); # let point the path directly to the directory where the binary lives - location=$vmpath + location="$vmpath/usr/bin" if [ -n "\$vmnet0" ] ; then # the path might be directly point to the plugin dir - End-of-Here - if ($kind eq 'vmpl2.5' || $kind eq 'vmpl3.0' || $kind eq 'local25' || $kind eq 'local30') { - $script .= " \$location/vmnet-bridge -d /var/run/vmnet-bridge-0.pid -n 0\n"; - } else { + End-of-Here + if ($kind eq 'vmpl1.0' || $kind eq 'vmpl2.0' || $kind eq 'local10' || $kind eq 'local20') { $script .= " \$location/vmnet-bridge -d /var/run/vmnet-bridge-0.pid /dev/vmnet0 eth0\n"; + } else { + $script .= " \$location/vmnet-bridge -d /var/run/vmnet-bridge-0.pid -n 0\n"; } - $script = unshiftHereDoc(<<" End-of-Here"); + $script .= unshiftHereDoc(<<" End-of-Here"); fi if [ -n "\$vmnet1" ] ; then - \$location/usr/bin/vmnet-netifup -d /var/run/vmnet-netifup-vmnet1.pid \\ + \$location/vmnet-netifup -d /var/run/vmnet-netifup-vmnet1.pid \\ /dev/vmnet1 vmnet1 - dhcpif="\$dhcpif vmnet1" ip addr add \$vmnet1 dev vmnet1 ip link set vmnet1 up if [ -n "\$vmnet1nat" ] ; then @@ -458,7 +459,7 @@ sub _writeRunlevelScript #iptables -A -s vmnet1 -d br0 fi /opt/openslx/uclib-rootfs/usr/sbin/udhcpd \\ - -S /etc/vmware/udhcpd-vmnet1.conf/udhcpd.conf + -S /etc/vmware/udhcpd/udhcpd-vmnet1.conf fi if [ -n "\$vmnet8" ] ; then \$location/vmnet-netifup -d /var/run/vmnet-netifup-vmnet8.pid \\ @@ -469,9 +470,8 @@ sub _writeRunlevelScript # \$location/vmnet-natd -d /var/run/vmnet-natd-8.pid \\ # -m /etc/vmware/vmnet-natd-8.mac -c /etc/vmware/nat.conf 2>/dev/null # or logfile /opt/openslx/uclib-rootfs/usr/sbin/udhcpd \\ - -S /etc/vmware/udhcpd-vmnet8.conf/udhcpd.conf - fi - } + -S /etc/vmware/udhcpd/udhcpd-vmnet8.conf + fi End-of-Here $initfile->addFunction( "vmnetif", @@ -504,12 +504,12 @@ sub _writeRunlevelScript "$script" ); $initfile->addToCase( - 'status', - 'vmstatus' + "status", + "vmstatus" ); $initfile->addToCase( - 'restart', - '$0 stop && $0 start' + "restart", + "\$0 stop && \$0 start" ); my $distro = (split('-',$self->{'os-plugin-engine'}->distroName()))[0]; @@ -651,12 +651,6 @@ sub _localInstallation my $vmversion = ""; my $vmbuildversion = ""; - my $pluginFilesPath - = "$self->{'openslxBasePath'}/lib/plugins/$self->{'name'}/files"; - my $installationPath = "$self->{'pluginRepositoryPath'}/$kind"; - - mkpath($installationPath); - # if vmware ws is installed, vmplayer is installed, too. # we will only use vmplayer if (-e "/usr/lib/vmware/bin/vmplayer") { @@ -666,37 +660,43 @@ sub _localInstallation $vmversion = $versionhash{vmversion}; $vmbuildversion = $versionhash{vmbuildversion}; - ## Copy needed files - my @files = qw(nvram); - foreach my $file (@files) { - copyFile("$pluginFilesPath/$file", "$installationPath"); + # set version information + # VMplayer 2.0 + if ($vmversion eq "2.0" || $vmversion eq "6.0") { + $kind="local20"; + # VMplayer 2.5 + } elsif ($vmversion eq "2.5" || $vmversion eq "6.5") { + $kind="local25"; + # VMplayer 3.0, Workstation 7.0 + } elsif ($vmversion eq "3.0" || $vmversion eq "7.0") { + $kind="local30"; } + # Create runlevel script depending on detected version + $self->_writeRunlevelScript("$vmpath", "$kind"); - # Create runlevel script -> to be fixed!! - my $runlevelScript = "$self->{'pluginRepositoryPath'}/$kind/vmware.init"; - if ($vmversion eq "2.5") { - $self->_writeRunlevelScript($vmbin, $runlevelScript, "local25"); - } elsif ($vmversion eq "3.0") { - $self->_writeRunlevelScript($vmbin, $runlevelScript, "local30"); - } else { - $self->_writeRunlevelScript($vmbin, $runlevelScript, $kind); + # Create wrapper scripts, kind of localNN is set to local + if ( $kind =~ /local*/ ) { $kind = "local"; } + if (-e "/usr/lib/vmware/bin/vmware") { + $self->_writeWrapperScript("$vmpath", "$kind", "ws"); + } + if (-e "/usr/lib/vmware/bin/vmplayer") { + $self->_writeWrapperScript("$vmpath", "$kind", "player"); } - # Create wrapper scripts - if (-e "/usr/bin/vmware") { - $self->_writeWrapperScript("$vmpath", "$kind", "ws") - } else { - $self->_writeWrapperScript("$vmpath", "$kind", "player") + # copy nvram file + my $pluginFilesPath + = "$self->{'openslxBasePath'}/lib/plugins/$self->{'name'}/files"; + my @files = qw(nvram); + foreach my $file (@files) { + copyFile("$pluginFilesPath/$file", "$self->{'pluginRepositoryPath'}/$kind"); } - } - # else { TODO: errorhandling } - - ## Creating needed config /etc/vmware/config + } # else { TODO: errorhandling if file or string doesn't exist } + + ## creating needed config /etc/vmware/config $self->_writeVmwareConfigs("$kind", "$vmpath"); } - sub _vmpl2Installation { my $self = shift; @@ -723,8 +723,7 @@ sub _vmpl2Installation { system("/bin/sh /opt/openslx/plugin-repo/$self->{'name'}/$kind/install-vmpl.sh $kind"); # Create runlevel script - my $runlevelScript = "$self->{'pluginRepositoryPath'}/$kind/vmware.init"; - $self->_writeRunlevelScript($vmbin, $runlevelScript, $kind); + $self->_writeRunlevelScript($vmpath, $kind); # Create wrapperscripts $self->_writeWrapperScript("$vmpath", "$kind", "player"); @@ -759,8 +758,7 @@ sub _vmpl25Installation { system("/bin/sh /opt/openslx/plugin-repo/$self->{'name'}/$kind/install-vmpl.sh $kind"); # Create runlevel script - my $runlevelScript = "$self->{'pluginRepositoryPath'}/$kind/vmware.init"; - $self->_writeRunlevelScript($vmbin, $runlevelScript, $kind); + $self->_writeRunlevelScript($vmpath, $kind); # Create wrapperscripts $self->_writeWrapperScript("$vmpath", "$kind", "player"); @@ -795,8 +793,7 @@ sub _vmpl1Installation { system("/bin/sh /opt/openslx/plugin-repo/$self->{'name'}/$kind/install-vmpl.sh $kind"); # Create runlevel script - my $runlevelScript = "$self->{'pluginRepositoryPath'}/$kind/vmware.init"; - $self->_writeRunlevelScript($vmbin, $runlevelScript, $kind); + $self->_writeRunlevelScript($vmpath, $kind); # create wrapper scripts $self->_writeWrapperScript("$vmpath", "$kind", "player"); diff --git a/os-plugins/plugins/vmware/XX_vmware.sh b/os-plugins/plugins/vmware/XX_vmware.sh index b31df648..cb8683f6 100644 --- a/os-plugins/plugins/vmware/XX_vmware.sh +++ b/os-plugins/plugins/vmware/XX_vmware.sh @@ -43,6 +43,7 @@ if [ -e /initramfs/plugin-conf/vmware.conf ]; then testmkd /dev/shm/vmware 1777 testmkd /mnt/var/run/vmware 1777 testmkd ${PLUGINCONFDIR} + testmkd /mnt/etc/vmware/udhcpd # write the ${PLUGINCONFDIR}/vmware.conf file # check for the several variables and write the several files: @@ -55,27 +56,9 @@ stage3 setup" > ${PLUGINCONFDIR}/vmware.conf if [ "$vmware_bridge" = 1 ] ; then echo "vmnet0=true" >> ${PLUGINCONFDIR}/vmware.conf fi - # write the common dhcpd.conf header for vmnet1,8 - if [ -n "$vmware_vmnet1" -o -n "$vmware_vmnet8" ] ; then - # use the dns servers known to the vmware host - local dnslist=$(echo "$domain_name_servers"|sed "s/ /,/g") - echo "# Common dhcpd.conf header written in stage3 ..." \ - > /mnt/etc/vmware/dhcpd-head.conf - echo "allow unknown-clients;" \ - >> /mnt/etc/vmware/dhcpd-head.conf - echo "default-lease-time 1800;" \ - >> /mnt/etc/vmware/dhcpd-head.conf - echo "max-lease-time 7200;" \ - >> /mnt/etc/vmware/dhcpd-head.conf - echo "option domain-name-servers $dnslist;" \ - >> /mnt/etc/vmware/dhcpd-head.conf - echo "option domain-name \"vm.local\";" \ - >> /mnt/etc/vmware/dhcpd-head.conf - fi # variable might contain ",NAT" which is to be taken off if [ -n "$vmware_vmnet1" ] ; then - cp /mnt/etc/vmware/dhcpd-head.conf /mnt/etc/vmware/dhcpd-vmnet1.conf local vmnet1=${vmware_vmnet1%,*} # x.x.x.x/yy,NAT => 'x.x.x.x/yy' local vmnat=${vmware_vmnet1#$vmnet1*} # x.x.x.x/yy,NAT => ',NAT' local vmip=${vmnet1%/*} # x.x.x.x/yy => 'x.x.x.x'"> @@ -83,26 +66,15 @@ stage3 setup" > ${PLUGINCONFDIR}/vmware.conf local vmsub=$(echo $vmip |sed 's,\(.*\)\..*,\1,') # x.x.x.x => x.x.x echo -e "vmnet1=$vmnet1" >> ${PLUGINCONFDIR}/vmware.conf [ -n "$vmnat" ] && echo "vmnet1nat=true" >> ${PLUGINCONFDIR}/vmware.conf - echo -e "\n# definition for virtual vmnet1 interface" \ - >> /mnt/etc/vmware/dhcpd-vmnet1.conf - echo -e "subnet $(ipcalc -n $vmnet1|sed s/.*=//) netmask \ -$(ipcalc -m $vmnet1|sed s/.*=//) {" \ - >> /mnt/etc/vmware/dhcpd-vmnet1.conf - echo -e "\trange ${vmsub}.10 ${vmsub}.20;" \ - >> /mnt/etc/vmware/dhcpd-vmnet1.conf - echo -e "\toption broadcast-address $(ipcalc -b $vmnet1|sed s/.*=//);" \ - >> /mnt/etc/vmware/dhcpd-vmnet1.conf - # Maybe a different ip is needed s. nat: vmnet="${vmsub}.2" - echo -e "\toption routers $vmip;" \ - >> /mnt/etc/vmware/dhcpd-vmnet1.conf - echo -e "}" \ - >> /mnt/etc/vmware/dhcpd-vmnet1.conf - mknod /dev/vmnet1 c 119 1 + # setting up the udhcpd configuration + sed -e "s,NWIF,vmnet1,;s,/misc/,/vmware/," \ + -e "s,CNETWORK,$vmsub,;s,PIDFILE,/var/run/vmware/udhcpd-vmnet1.pid," \ + -e "s,LEASEFILE,/var/run/vmware/udhcpd-vmnet1.leases," \ + /mnt/etc/opt/openslx/udhcpd.conf >/mnt/etc/vmware/udhcpd/udhcpd-vmnet1.conf fi # vmware nat interface configuration if [ -n "$vmware_vmnet8" ] ; then - cp /mnt/etc/vmware/dhcpd-head.conf /mnt/etc/vmware/dhcpd-vmnet8.conf local vmnet8ip=${vmware_vmnet8%/*} local vmpx=${vmware_vmnet8#*/} local vmsub=$(echo $vmnet8ip |sed 's,\(.*\)\..*,\1,') # x.x.x.x => x.x.x"> @@ -111,19 +83,12 @@ $(ipcalc -m $vmnet1|sed s/.*=//) {" \ local vmip="${vmsub}.1" local vmnet="${vmsub}.2" echo -e "vmnet8=$vmip/$vmpx" >>${PLUGINCONFDIR}/vmware.conf - echo -e "\n# definition for virtual vmnet8 interface" \ - >> /mnt/etc/vmware/dhcpd-vmnet8.conf - echo -e "subnet $(ipcalc -n $vmip/$vmpx|sed s/.*=//) netmask \ -$(ipcalc -m $vmip/$vmpx|sed s/.*=//) {" \ - >> /mnt/etc/vmware/dhcpd-vmnet8.conf - echo -e "\trange ${vmsub}.10 ${vmsub}.20;" \ - >> /mnt/etc/vmware/dhcpd-vmnet8.conf - echo -e "\toption broadcast-address $(ipcalc -b $vmip/$vmpx|sed s/.*=//);" \ - >> /mnt/etc/vmware/dhcpd-vmnet8.conf - echo -e "\toption routers $vmnet;" \ - >> /mnt/etc/vmware/dhcpd-vmnet8.conf - echo -e "}" \ - >> /mnt/etc/vmware/dhcpd-vmnet8.conf + # setting up the udhcpd configuration + sed -e "s,NWIF,vmnet8,;s,/misc/,/vmware/," \ + -e "s,CNETWORK,$vmsub,;s,PIDFILE,/var/run/vmware/udhcpd-vmnet8.pid," \ + -e "s,LEASEFILE,/var/run/vmware/udhcpd-vmnet8.leases," \ + /mnt/etc/opt/openslx/udhcpd.conf >/mnt/etc/vmware/udhcpd/udhcpd-vmnet8.conf + # might be not needed any more ... echo -e "# Linux NAT configuration file" \ > /mnt/etc/vmware/nat.conf echo -e "[host]" \ @@ -143,11 +108,9 @@ $(ipcalc -m $vmip/$vmpx|sed s/.*=//) {" \ echo -e "[incomingudp]" \ >> /mnt/etc/vmware/nat.conf echo "00:50:56:F1:30:50" > /mnt/etc/vmware/vmnet-natd-8.mac - mknod /dev/vmnet8 c 119 8 fi # copy the runlevel script to the proper place and activate it - sed "s/eth0/$nwif/g" ${PLUGINDIR}/${vmware_kind}/vmware.init \ - > /mnt/etc/init.d/vmware-env \ + sed "s/eth0/$nwif/g" ${PLUGINDIR}/vmware-slx > /mnt/etc/init.d/vmware-env \ || echo " * Error copying runlevel script. Shouldn't happen." chmod a+x /mnt/etc/init.d/vmware-env rllinker "vmware-env" 20 2 @@ -174,16 +137,16 @@ ${vmware_imagesrc}." nonfatal ############################################################################ # vmware stuff second part: setting up the environment - # make vmware dhcpd more silent - touch /mnt/var/run/vmware/dhcpd-vmnet1.leases \ - /mnt/var/run/vmware/dhcpd-vmnet8.leases + # make udhcpd more silent + touch /mnt/var/run/vmware/udhcpd-vmnet1.leases \ + /mnt/var/run/vmware/udhcpd-vmnet8.leases # create the needed devices which effects all vmware options # they are not created automatically via module load - for i in "/dev/vmnet0 c 119 0" "/dev/vmmon c 10 165"; do + for i in "/dev/vmnet0 c 119 0" "/dev/vmnet1 c 119 1" \ + "/dev/vmnet8 c 119 8" "/dev/vmmon c 10 165"; do mknod $i done - chmod 0700 /dev/vmnet* echo -e "usbfs\t\t/proc/bus/usb\tusbfs\t\tauto\t\t 0 0" >> /mnt/etc/fstab diff --git a/os-plugins/plugins/vmware/files/run-virt.include b/os-plugins/plugins/vmware/files/run-virt.include index 6641d491..0fb1d228 100644 --- a/os-plugins/plugins/vmware/files/run-virt.include +++ b/os-plugins/plugins/vmware/files/run-virt.include @@ -1,7 +1,7 @@ # run-virt.include # ----------------------------------------------------------------------------- # Copyright (c) 2009 - RZ Uni Freiburg -# Copyright (c) 2009 - OpenSLX GmbH +# Copyright (c) 2009..2010 - OpenSLX GmbH # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING @@ -443,6 +443,6 @@ writelog "" # finally set env for run-virt.sh ################################################################################ -VIRTCMD=vmplayer +# using the modified version of the wrapper script +VIRTCMD=/var/opt/openslx/bin/vmplayer VIRTCMDOPTS="${vmopt} ${conffile}" - diff --git a/os-plugins/plugins/vmware/init-hooks/20-nw-bridge-config/bridge.sh b/os-plugins/plugins/vmware/init-hooks/20-nw-bridge-config/bridge.sh index 6aabe8ad..07113867 100755 --- a/os-plugins/plugins/vmware/init-hooks/20-nw-bridge-config/bridge.sh +++ b/os-plugins/plugins/vmware/init-hooks/20-nw-bridge-config/bridge.sh @@ -1,5 +1,5 @@ #!/bin/ash -# Copyright (c) 2009 - OpenSLX GmbH +# Copyright (c) 2009..2010 - OpenSLX GmbH # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING diff --git a/os-plugins/plugins/vmware/init-hooks/60-have-servconfig/vm-dhcpd.sh b/os-plugins/plugins/vmware/init-hooks/60-have-servconfig/vm-dhcpd.sh new file mode 100755 index 00000000..6bdfb8f1 --- /dev/null +++ b/os-plugins/plugins/vmware/init-hooks/60-have-servconfig/vm-dhcpd.sh @@ -0,0 +1,56 @@ +#!/bin/ash +# Copyright (c) 2010 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your feedback to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org +# +# Init hook to create a bridge on the active network interface +# (should be kept identical to the files of virtualbox and qemukvm plugins) +############################################################################# + +# configuring dhcpd stub for virtual networks +testmkd /mnt/etc/opt/openslx +echo " +# general udhcpd configuration file for virtual machines written by +# $0 during OpenSLX stage3 configuration + +# start and end of the IP lease block +start CNETWORK.20 +end CNETWORK.100 + +# interface that udhcpd will use +interface NWIF + +# how long an offered address is reserved (leased) in seconds +offer_time 6000 + +# location of the leases file +lease_file LEASEFILE + +# location of the pid file +pidfile PIDFILE + +opt dns ${domain_name_servers} +option subnet 255.255.255.0 +opt router CNETWORK.254 +opt wins CNETWORK.10 +option domain virtual.site ${domain_name} + +# additional options known to udhcpd +#subnet #timezone +#router #timesvr +#namesvr #dns +#logsvr #cookiesvr +#lprsvr #bootsize +#domain #swapsvr +#rootpath #ipttl +#mtu #broadcast +#wins #lease +#ntpsrv #tftp +#bootfile +" >/mnt/etc/opt/openslx/udhcpd.conf -- cgit v1.2.3-55-g7522