diff -r d8f88998215a virt-convert
--- a/virt-convert	Wed Sep 16 11:42:53 2009 -0400
+++ b/virt-convert	Tue Sep 22 17:04:41 2009 -0400
@@ -247,12 +247,12 @@
             if not dformat:
                 dformat = "raw"
 
-            if d.path and dformat != "none":
-                verbose(options, _("Converting disk '%(path)s' to type "
-                                   "%(format)s...") % {"path": d.path,
-                                                       "format": dformat})
-
-            d.convert(options.input_dir, options.output_dir, dformat)
+            if not options.output_format == "ec2":
+                if d.path and format != "none":
+                    verbose(options, _("Converting disk '%(path)s' to type "
+                                       "%(format)s...") % {"path": d.path,
+                                                       "format": format})
+                d.convert(options.input_dir, options.output_dir, format)
 
     except OSError, e:
         cleanup(_("Couldn't convert disks: %s") % e.strerror,
diff -r d8f88998215a virtconv/ec2config.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/virtconv/ec2config.py	Tue Sep 22 17:04:41 2009 -0400
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+#
+# ec2config.py: Convert a virtual appliance image in an EC2 AMI
+#
+# Copyright 2008, Red Hat  Inc.
+# Joseph Boggs <jboggs@redhat.com>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import os
+import sys
+import logging
+import random
+import shutil
+from virtinst.cli import fail
+from virtconv import _gettext as _
+import virtconv.rpmcheck as rpmcheck
+import virtconv.ec2fs as ec2fs
+import subprocess    
+
+class EC2Config():
+ 
+    def makedev(self,tmpdir):
+        devs=["console","null","zero"]
+        devnull = file('/dev/null', 'w')
+        for dev in devs:  
+            makedev_cmd="/sbin/MAKEDEV -d %s/dev -x %s" % (tmpdir,dev)
+            makedev_ret = subprocess.call(makedev_cmd, shell=True,stdout=devnull, stderr=devnull)
+
+    def fstab(self,tmpdir):
+        logging.info("* - Updating /etc/fstab")
+        fstab_path = tmpdir + "/etc/fstab"
+        os.system("touch " + fstab_path)
+        fstab = open(fstab_path, "w")
+        ec2_fstab =  "/dev/sda1  /         ext3    defaults        1 1\n"
+        ec2_fstab += "/dev/sda2  /mnt      ext3    defaults        1 2\n"
+        ec2_fstab += "/dev/sda3  swap      swap    defaults        0 0\n"
+        ec2_fstab += "none       /dev/pts  devpts  gid=5,mode=620  0 0\n"
+        ec2_fstab += "none       /dev/shm  tmpfs   defaults        0 0\n"
+        ec2_fstab += "none       /proc     proc    defaults        0 0\n"
+        ec2_fstab += "none       /sys      sysfs   defaults        0 0\n"
+        fstab.writelines(ec2_fstab)
+        fstab.close()
+
+
+    def rclocal_config(self,tmpdir):
+        rclocal_path = tmpdir + "/etc/rc.local"
+        rclocal = open(rclocal_path, "w")
+        logging.info("* - Creating rc.local configuration\n")
+        ec2_rclocal = "if [ ! -d /root/.ssh ] ; then\n"
+        ec2_rclocal += "mkdir -p /root/.ssh\n"
+        ec2_rclocal += "chmod 700 /root/.ssh\n"
+        ec2_rclocal += "fi\n\n"
+        ec2_rclocal += " # Fetch public key using HTTP\n"
+        ec2_rclocal += "curl -f http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /tmp/my-key\n"
+        ec2_rclocal += "if [ $? -eq 0 ] ; then\n"
+        ec2_rclocal += "cat /tmp/my-key >> /root/.ssh/authorized_keys\n"
+        ec2_rclocal += "chmod 600 /root/.ssh/authorized_keys\n"
+        ec2_rclocal += "rm /tmp/my-key\n"
+        ec2_rclocal += "fi\n\n"
+        ec2_rclocal += "# or fetch public key using the file in the ephemeral store:\n"
+        ec2_rclocal += "if [ -e /mnt/openssh_id.pub ] ; then\n"
+        ec2_rclocal += "cat /mnt/openssh_id.pub >> /root/.ssh/authorized_keys\n"
+        ec2_rclocal += "chmod 600 /root/.ssh/authorized_keys\n"
+        ec2_rclocal += "fi\n\n"
+        ec2_rclocal += "# Update the EC2 AMI creation tools\n"
+        ec2_rclocal += "echo Updating ec2-ami-tools\n"
+        ec2_rclocal += "curl -o /tmp/ec2-ami-tools.noarch.rpm http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm && \n"
+        ec2_rclocal += "rpm -Uvh /tmp/ec2-ami-tools.noarch.rpm && \n"
+        ec2_rclocal += "echo \" + Updated ec2-ami-tools\"\n"
+        rclocal.writelines(ec2_rclocal)
+        rclocal.close()    
+        return True
+
+    def ssh_config(self,tmpdir):
+        try: 
+            sshdconfig_path = tmpdir + "/etc/ssh/sshd_config"
+            sshdconfig = open(sshdconfig_path,"w")
+        except IOError, (errno, strerror):
+            logging.error( "%s, %s" % (strerror,sshdconfig_path))
+            fail(_("The openssh_server package must be installed to convert and function properly on EC2"))
+        else:
+            logging.info("* - Creating ssh configuration")
+            ec2_sshdconfig = "UseDNS  no\n"
+            ec2_sshdconfig +="PermitRootLogin without-password\n"
+            sshdconfig.writelines(ec2_sshdconfig)
+            sshdconfig.close()  
+        return True
+
+    def eth0_config(self,tmpdir):
+        try: 
+            logging.info("* - Creating eth0 configuration")
+            eth0_path = tmpdir + "/etc/sysconfig/network-scripts/ifcfg-eth0"
+            os.system("touch %s" % eth0_path)
+            eth0 = open(eth0_path, "w")
+        except IOError, (errno, strerror):
+            fail(_("%s, %s" % (strerror,eth0_path)))
+        else:
+            ec2_eth0  = "ONBOOT=yes\n"
+            ec2_eth0 += "DEVICE=eth0\n"
+            ec2_eth0 += "BOOTPROTO=dhcp\n"
+            eth0.writelines(ec2_eth0)
+            eth0.close()
+            os.system("chroot %s /sbin/chkconfig network on" % tmpdir)
+        
+        logging.info("* - Prevent nosegneg errors")
+        os.system("echo \"hwcap 0 nosegneg\" > %s/etc/ld.so.conf.d/nosegneg.conf" % tmpdir)    
+    
+    def ami_tools(self,tmpdir):
+        logging.info("Adding EC2 Tools")
+        
+        if not os.path.isdir(tmpdir + "/home/ec2"): 
+            os.mkdir(tmpdir + "/home/ec2")
+            
+        ec2td = os.system("curl -o /tmp/ec2-api-tools-1.2-9739.zip http://s3.amazonaws.com/ec2-downloads/ec2-api-tools-1.2-9739.zip")
+        if ec2td == 0:
+            os.system("unzip -qo /tmp/ec2-api-tools-1.2-9739.zip -d /home/ec2")
+        else:
+            fail(_("EC2 tools download error!"))
+    
+    def kernel_modules(self,tmpdir):    
+        logging.info("Configure image for accepting the EC2 kernel")
+        # note this is the most current Fedora kernel available in EC2 as of 10/2009
+        kd = os.system("curl -o /tmp/kernel-xen-2.6.21.7-2.fc8.i686.rpm http://kojipkgs.fedoraproject.org/packages/kernel-xen-2.6/2.6.21.7/2.fc8/i686/kernel-xen-2.6.21.7-2.fc8.i686.rpm")
+        if kd == 0:
+            os.system("rpm -ivh --nodeps /tmp/kernel-xen-2.6.21.7-2.fc8.i686.rpm --root=%s" % tmpdir)
+        else:
+            fail(_("Kernel download error!"))
diff -r d8f88998215a virtconv/ec2fs.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/virtconv/ec2fs.py	Tue Sep 22 17:04:41 2009 -0400
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+#
+# ec2fs.py: Convert a virtual appliance image in an EC2 AMI
+#
+# Copyright 2008, Red Hat  Inc.
+# Joseph Boggs <jboggs@redhat.com>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import os
+import subprocess
+import logging
+import shutil
+from virtinst.cli import fail
+ 
+class LoopBackDiskImage(): 
+
+    def setup_fs(self,imagefile,tmpdir):
+            loop_devices = [] 
+            loop_partition_dict = {} 
+            tmproot = tmpdir + "-tmproot"
+            tmpimage = tmpdir + "-tmpimage"            
+            
+            logging.debug("TMPDIR: " + tmpdir)
+            free_loop_dev = os.popen("/sbin/losetup -f")
+            loop_device = free_loop_dev.read().strip()
+
+            if not loop_device:
+                fail(_("Unable to find a free loop device"))
+     
+            os.system("/sbin/losetup %s %s" % (loop_device,imagefile))
+            os.system("/sbin/kpartx -a %s" % loop_device)
+            loop_partitions = os.popen("/sbin/kpartx -lv %s|awk {'print $1'}" % loop_device)
+
+            for dev in loop_partitions:
+                dev = dev.strip()
+                label = os.popen("e2label /dev/mapper/%s 2>&1" % dev)
+                label = label.read().strip()
+                if label.startswith("e2label"):
+                    fail(_("Unable to detect partition label on %s, continuing anyways, if %s is a swap partition, no action is needed" % (dev,dev)))
+                else: 
+                    loop_partition_dict[dev] = label  
+                    logging.debug( dev + " : " + label)
+
+            dev = loop_partition_dict.values()
+            dev.sort()
+            os.mkdir(tmproot) 
+
+            for value in dev:
+                for key in loop_partition_dict.keys():
+                    if (value == loop_partition_dict[key]):
+                        ld = os.popen("/sbin/losetup -f")
+                        loop_partition_device = ld.read().strip()
+                        if not loop_device:
+                            fail(_("Please review your loopback device settings and remove unneeded ones"))
+                        os.system("mount -o loop /dev/mapper/%s %s%s" % (key,tmproot,value))
+            
+            tmp_disk_space = os.popen("du -s %s|awk {'print $1'}" % tmproot)
+            tmp_disk_space= int(tmp_disk_space.read()) / 1024
+            new_disk_space = int(tmp_disk_space + ((tmp_disk_space * 0.30)))
+
+            print "\nCreating a new disk image: %sM total" % str(new_disk_space)
+            create_disk = os.system("dd if=/dev/zero of=%s/ec2-diskimage.img bs=1M count=%s" % (tmpimage,new_disk_space))
+            os.system("mke2fs -Fj %s/ec2-diskimage.img" % tmpimage)
+            if not loop_device:
+                fail(_("Please review your loopback devices and remove unneeded ones"))
+            os.system("mount -o loop %s/ec2-diskimage.img %s" % (tmpimage,tmpdir))
+            
+            print "Performing rsync on all partitions to new root"
+            os.system("rsync -u -r -a  %s/* %s" % (tmproot,tmpdir))
+
+            dev.sort(reverse=True)
+
+            for value in dev:
+                logging.info("Unmounting %s%s" % (tmpdir,value))
+                os.system("umount %s%s" % (tmproot,value))
+
+            logging.info("Freeing loopdevices")
+            os.system("kpartx -d %s" % loop_device)
+            os.system("losetup -d %s" % loop_device)
+            return
+        
+    def unmount(self,tmpdir):
+        logging.debug("Unmounting directory %s" % tmpdir)
+        os.system("/bin/umount %s" % tmpdir)
+        return
+    
+    def cleanup(self,tmpdir):
+        os.system("rm -rf %s/*" % tmpdir)
+        return
diff -r d8f88998215a virtconv/parsers/ec2.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/virtconv/parsers/ec2.py	Tue Sep 22 17:04:41 2009 -0400
@@ -0,0 +1,105 @@
+#!/usr/bin/python
+#
+# Copyright 2009  Red Hat, Inc.
+# Joey Boggs <jboggs@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA.
+
+from virtconv import _gettext as _
+from virtconv.cli import fail
+from tempfile import mkdtemp
+import virtconv.formats as formats
+import virtconv.vmcfg as vmcfg
+import virtconv.diskcfg as diskcfg
+import virtconv.netdevcfg as netdevcfg
+import virtconv.ec2config as ec2config
+import virtconv.ec2fs as ec2fs
+import sys
+import os
+import logging
+import shutil
+
+class ec2_parser(formats.parser):
+    """
+    Support for VMWare .vmx files.  Note that documentation is
+    particularly sparse on this format, with pretty much the best
+    resource being http://sanbarrow.com/vmx.html
+    """
+
+    name = "ec2"
+    suffix = ".ec2"
+    can_import = False
+    can_export = True
+    can_identify = True
+
+    @staticmethod
+    def identify_file(input_file):
+        """
+        Return True if the given file is of this format.
+        """
+        return False
+
+    @staticmethod
+    def import_file(input_file):
+        """
+        Import a configuration file.  Raises if the file couldn't be
+        opened, or parsing otherwise failed.
+        """
+
+    @staticmethod
+    def export(vm,output_file):
+        """
+        Export a configuration file as a string.
+        @vm vm configuration instance
+
+        Raises ValueError if configuration is not suitable.
+        """
+        tmpdir = mkdtemp()
+        tmpimage = tmpdir + "-tmpimage"
+        os.mkdir(tmpimage)
+        newimage = tmpimage + "/ec2-diskimage.img"
+
+        fsutil = ec2fs.LoopBackDiskImage()
+
+        if len(vm.disks) > 1:
+            fail(_("EC2 conversion only supports 1 disk currently"))
+        for devid, disk in sorted(vm.disks.items()):
+            fsutil.setup_fs(disk.path,tmpdir)
+
+        config = ec2config.EC2Config()
+        config.makedev(tmpdir)
+        config.fstab(tmpdir)
+        config.rclocal_config(tmpdir)
+        config.eth0_config(tmpdir)
+        config.ami_tools(tmpdir)
+        config.kernel_modules(tmpdir)
+        fsutil.unmount(tmpdir)
+        shutil.move(newimage,output_file)
+        fsutil.cleanup(tmpdir)
+
+    @staticmethod
+    def export_file(vm, output_file):
+        """
+        Export a configuration file.
+        @vm vm configuration instance
+        @output_file Output file
+
+        Raises ValueError if configuration is not suitable, or another
+        exception on failure to write the output file.
+        """
+        output = ec2_parser.export(vm,output_file)
+
+formats.register_parser(ec2_parser)
