TurnKey Linux Virtual Appliance Library

Installing an appliance from a USB drive

My laptop doesn't have a CD/DVD drive. Is there a way to install Turnkey MediaWiki from a thumbdrive?

I tried copying all the files from the CD (after burning the iso file I downloaded here) on the thumbdrive and changing the boot order of the laptop, but I got the following messages:

No operative system found, and

Remove your accessories and press any key to reboot.

Evidently I'm doing something wrong. Any help please? 

Liraz Siri's picture

A couple of programs claim to do what you want

We don't yet officially support running our software appliances from USB just yet, but it is on our todo list.

Meanwhile, you may want to try a couple of tools I found that claim to do what you want - installing a Live CD ISO image as a Live USB:

I haven't had a chance to try these out yet myself so I will be very interested in the results you get (or don't get). Especially if it works!

Note that converting a Live CD ISO image to a Live USB image is technically possible but it is a bit more complicated than what you tried.

If the GUI tools above don't work for you, you might have better luck with a Python script Alon wrote that installs an extracted ISO filesystem to a USB device:

#!/usr/bin/python
# Copyright (c) 2008 Alon Swartz alon@turnkeylinux.org
"""
Put cdroot onto usb device

Example usage:
    # cdroot2usb.py extracted_iso /dev/sdb

"""
import os
import sys
import getopt
import shutil

from os.path import *

import executil
import temp

#todo:
#  check, and reset mbr?

def usage(s=None):
    if s is not None:
        print "error: " + str(s)

    print "Syntax: %s cdroot usbdev" % sys.argv[0]
    print __doc__.strip()

    sys.exit(1)

class Error(Exception):
    pass

class Cdroot:
    def __init__(self, path, dirs):
        self.path = realpath(path)

        for dir in dirs:
            if not exists(join(path, dir)):
                 raise Error('does not exist: %s' % join(path, dir))

class Partition:
    def __init__(self, s):
        fields = s.split(None, 7)
        if not len(fields) == 8:
            raise Error('unexpected structure')

        self.path = fields[0]

        self.is_bootable = False
        if fields[1] == '*':
            self.is_bootable = True
            fields.pop(1)  # remove bootable field, not present if not bootable

        self.start = fields[1]
        self.end = fields[2]
        self.blocks = fields[3]
        self.id = fields[4]
        self.fs = fields[5]

class UsbDev:
    def __init__(self, path, filesystem_ids):
        self.path = self._get_blockdev_path(path)
        if self.is_mounted():
            raise Error('usbdev is mounted')

        self.bootpart = self._get_bootable_partition()
        if self.bootpart is None:
            raise Error('no bootable partition found on device')

        if self.bootpart.id not in filesystem_ids:
            raise Error('bootable partition type not allowed',
                        filesystem_ids,
                        self.bootpart.id)

    @staticmethod
    def _get_blockdev_path(path):
        p = executil.getoutput("udevinfo -q path -n %s" % path).lstrip('/')
        for path in ( join('/sys', p , 'device'),
                      join('/sys/block', basename(p)),
                      join('/dev', basename(p)) ):
            if not exists(path):
                raise Error('usbdev path error: %s' % path)

        return join('/dev', basename(p))

    @staticmethod
    def _read_partition_table(path):
        partitions = []
        for line in executil.getoutput("fdisk -l %s" % path).splitlines():
            if line.startswith(path):
                partitions.append(Partition(line))

        return partitions

    def _get_bootable_partition(self):
        for partition in self._read_partition_table(self.path):
            if partition.is_bootable:
                return partition

        return None

    def is_mounted(self):
        mounts = file("/proc/mounts").read()
        if mounts.find(self.path) != -1:
            return True

        return False

    def install_bootloader(self):
        if self.is_mounted():
            raise Error('unmount usbdev to install boot loader')

        print "* installing bootloader"
        executil.system('syslinux', self.bootpart.path)

class Cdroot2Usbdev:
    def __init__(self, cdroot, usbdev):
        self.cdroot = cdroot
        self.usbdev = usbdev

        self.mountdir = temp.TempDir(dir='/media')
        self._mount()

    def copy(self):
        print "* copying cdroot"
        executil.system('cp -r %s/* %s' % (self.cdroot.path,
                                           self.mountdir.path))

    def isolinux2syslinux(self):
        print "* making isolinux configuration compatible for syslinux"
        path = self.mountdir.path
        executil.system('mv %s/isolinux/* %s' % (path, path))
        executil.system('mv %s/isolinux.cfg %s/syslinux.cfg' % (path, path))
        executil.system('rmdir %s/isolinux' % path)
        executil.system('rm %s/isolinux.bin' % path)

    def _mount(self):
        print "* mounting %s %s" % (self.usbdev.bootpart.path,
                                    self.mountdir.path)
        executil.system("mount", self.usbdev.bootpart.path, self.mountdir.path)

    def _umount(self):
        if self.usbdev.is_mounted():
            print "* umounting %s" % self.usbdev.bootpart.path
            executil.system("umount", self.usbdev.bootpart.path)

    def __del__(self):
        self._umount()

def main():
    try:
        opts, args = getopt.gnu_getopt(sys.argv[1:], "", [])
    except getopt.GetoptError, e:
        usage(e)

    if not args:
        usage()

    if len(args) != 2:
        usage("bad number of arguments")

    cdroot = Cdroot(path=args[0], dirs=('casper', 'isolinux'))
    usbdev = UsbDev(path=args[1], filesystem_ids=('16')) # Hidden FAT16

    c2u = Cdroot2Usbdev(cdroot, usbdev)
    c2u.copy()
    c2u.isolinux2syslinux()
    del c2u  # we want to make sure __del__ is called

    usbdev.install_bootloader()

if __name__ == "__main__":
    main()

Alon Swartz's picture

cdroot2usb python module dependencies

I just replied to a mail from Herson regarding the python modules cdroot2usb depends on, so I thought it would be a good idea to post a comment about it here.

My reply on the turnkey-discuss mailing list.
Liraz Siri's picture

Virtual Machine an alternative to bare metal installation

Note that it just occured to me that you may be trying to solve the wrong problem.

Instead of trying to install an appliance on the laptop's bare metal you'll find it is probably much easier to install it into a Virtual Machine (e.g., VirtualBox or VMWare) which can load the ISO into its "virtual" CD drive.

BTW, that's how we do most of our testing. Only rarely do we actually burn physical CDs.

Thank you liraz, I followed

Thank you liraz, I followed your advice and installed MediaWiki through the Virtual Machine solution. I am sorry I can´t give you any feedback on the other proposed solution (running the scripts to use the USB thumbdrive in live mode). Now I have one followup question, but I don´t know if it belongs here or on the MediaWiki forums: now that the wiki is up and running within the virtual machine (i use VirtualBox), how do i access it? The IP address that MediaWiki provides on startup is the one of the hosting machine, and I don´t seem to be able to access it. Any help?

Ok, it seems it has already

I can confirm unetbooting

And it's got the advantage of working also in windows (for those who are like myself, stuck dealing with it at work).

 

It works like a charm on the test unit I have here (An HP T5300 thin client. So potentially I could in theory recycle a thin client and make it into a domain controller. Not a bad idea, but meh.)

 

Now, to see if I can slap that baby on a CF flash card...

 

 

Post new comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account, used to display your avatar.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <p> <span> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <tr> <td> <em> <b> <u> <i> <strong> <font> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <strike> <caption>

More information about formatting options

Leave this field empty. It's part of a security mechanism.
(Dear spammers: moderators are notified of all new posts. Spam is deleted immediately)