2 # Convert a live CD iso into iscsi root bootable format
3 # iSCSI lun must be accessible via this script
4 # Copyright 2009 Red Hat, Inc.
5 # Written by Joey boggs <jboggs@redhat.com>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; version 2 of the License.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Library General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 from optparse
import OptionParser
21 from tempfile
import mkdtemp
29 parser
= OptionParser()
30 parser
.add_option("--iso", dest
="iso", help="LiveCD iso filename")
31 parser
.add_option("--target", dest
="target", help="iSCSI target ip address")
32 parser
.add_option("--targetname", dest
="targetname", help="iSCSI target lun")
33 parser
.add_option("--targetport", dest
="targetport", default
="3260", help="iSCSI port number, defaults to 3260")
34 parser
.add_option("--user", dest
="user", help="Target username(optional)")
35 parser
.add_option("--password", dest
="password", help="Target password")
36 parser
.add_option("--reverse_user", dest
="reverse_user", help="Reverse CHAP username(optional)")
37 parser
.add_option("--reverse_password", dest
="reverse_password", help="Reverse CHAP password(optional)")
38 parser
.add_option("--disk", dest
="disk", help="iSCSI disk device name")
39 parser
.add_option("--disk-label", dest
="disk_label", default
="ovirt-node-root", help="file system label")
41 (options
, args
) = parser
.parse_args()
47 if os
.geteuid () != 0:
48 fail("You must run as root")
50 if options
.iso
is None:
51 fail("ERROR: iso file must be defined")
53 options
.iso
= os
.path
.abspath(options
.iso
)
55 if options
.target
is None:
56 fail("ERROR: iscsi target must be defined")
58 if options
.targetname
is None:
59 fail("ERROR: iscsi targetname must be defined")
61 if len(options
.disk_label
.strip()) > 15:
62 fail("ERROR: disk label must be 14 characters or less")
65 file = os
.mkdir("tftpboot")
67 tftp_remove
= raw_input("tftpboot directory exists, overwrite? (y/N)? ")
68 if tftp_remove
.lower() == "y":
69 shutil
.rmtree("tftpboot")
75 if options
.disk
is None:
76 print "Below are the detected disks, if the iscsi disk is not shown, please ensure you are logged into the correct target\n"
77 bus
= dbus
.SystemBus ()
78 hal_obj
= bus
.get_object ('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
79 hal
= dbus
.Interface (hal_obj
, 'org.freedesktop.Hal.Manager')
80 udis
= hal
.FindDeviceByCapability ('storage')
84 dev_obj
= bus
.get_object ('org.freedesktop.Hal', udi
)
85 dev
= dbus
.Interface (dev_obj
, 'org.freedesktop.Hal.Device')
86 dev_bus
=dev
.GetProperty ('storage.bus')
87 dev_name
=dev
.GetProperty ('block.device')
88 dev_size
=dev
.GetProperty ('storage.size')
89 dev_size
=(dev_size
/1024/1024)
90 basename
=os
.path
.basename(udi
)
92 print "%s. %s %sM %s \n" % (dev_count
,dev_name
,dev_size
,basename
)
93 dev_dict
[str(dev_count
)] = dev_name
94 dev_count
= dev_count
+ 1
95 print "Enter Q to Quit"
96 dev_choice
= raw_input("Which device? ")
97 while not dev_dict
.has_key(dev_choice
):
98 if dev_choice
.lower() == "q":
102 print "%s is an invalid choice" % dev_choice
103 dev_choice
= raw_input("Which device? ")
104 options
.disk
= dev_dict
[dev_choice
]
106 cont
= raw_input("Creating file system on %s, do you wish to continue (y/N) " % options
.disk
)
107 if cont
.lower() != "y":
112 isomount_ret
= subprocess
.call(["mount", "-o", "loop", options
.iso
, isomount
])
113 if isomount_ret
!= 0:
114 fail("Error mounting %s" % options
.iso
)
116 kernel
="%s/isolinux/vmlinuz0" % isomount
117 initrd
="%s/isolinux/initrd0.img" % isomount
118 squashfs
="%s/LiveOS/squashfs.img" % isomount
119 ext3fs
="tftpboot/squashfs-root/LiveOS/ext3fs.img"
120 shutil
.copy(kernel
,"tftpboot")
121 shutil
.copy(initrd
,"tftpboot")
123 unsquash
= subprocess
.call(["unsquashfs", squashfs
])
125 # workaround until bug is fixed with squashfs -d option
126 shutil
.move("squashfs-root","tftpboot/squashfs-root")
128 print "Placing embedded file system on %s" % options
.disk
129 dd_cmd
="dd if=%s of=%s" % (ext3fs
,options
.disk
)
130 copy_iscsi_ret
= subprocess
.call(dd_cmd
, shell
=True)
131 if copy_iscsi_ret
!= 0:
132 fail("Error copying to %s" % options
.disk
)
134 umount_ret
= subprocess
.call(["umount", isomount
])
136 fail("Error unmounting %s, continuing" % isomount
)
139 shutil
.rmtree("tftpboot/squashfs-root")
143 # pxelinux configuration.
147 LABEL ovirt-node-iscsi
149 APPEND initrd=/initrd0.img ro root=LABEL=%(disk_label)s netroot=iscsi:%(user)s%(password)s@%(target)s::%(target_port)s::%(target_name)s ip=eth0:dhcp
154 # insert empty values for unneeded variables in the pxe template
155 if not options
.user
is None:
156 options
.user
= options
.user
+ ":"
160 if not options
.password
is None:
161 options
.password
= options
.password
+ ":"
163 options
.password
= ""
165 if not options
.reverse_user
is None:
166 options
.reverse_user
= options
.reverse_user
+ ":"
168 options
.reverse_user
= ""
170 if not options
.reverse_password
is None:
171 options
.reverse_password
= options
.reverse_password
+ ":"
173 options
.reverse_password
= ""
175 os
.mkdir("tftpboot/pxelinux.cfg")
176 pxe_cfg
= pxe_template
% {
177 "disk_label": options
.disk_label
,
178 "target": options
.target
,
179 "target_port": options
.targetport
,
180 "target_name": options
.targetname
,
181 "user": options
.user
,
182 "password": options
.password
,
183 "reverse_user": options
.reverse_user
,
184 "reverse_password": options
.reverse_password
187 pxe_conf
= open("tftpboot/pxelinux.cfg/default", 'w')
188 pxe_conf
.write(pxe_cfg
)
191 if os
.path
.exists("/usr/share/syslinux/pxelinux.0"):
192 shutil
.copy("/usr/share/syslinux/pxelinux.0","tftpboot")
193 elif os
.path
.exists("/usr/lib/syslinux/pxelinux.0"):
194 shutil
.copy("/usr/lib/syslinux/pxelinux.0","tftpboot")
196 print "Warning: You need to add pxelinux.0 to tftpboot/ subdirectory"
198 print "Your iscsiroot has been setup on %s" % options
.disk
200 print "Copy the tftpboot/ subdirectory to your tftpserver root directory"
201 print "Set up your DHCP, TFTP and PXE server to serve /tftpboot/.../pxeboot.0"