]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - release/tools/vmimage.subr
MFV ntp-4.2.8p3 (r284990).
[FreeBSD/FreeBSD.git] / release / tools / vmimage.subr
1 #!/bin/sh
2 #
3 # $FreeBSD$
4 #
5 #
6 # Common functions for virtual machine image build scripts.
7 #
8
9 export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
10 trap "cleanup" INT QUIT TRAP ABRT TERM
11
12 write_partition_layout() {
13         if [ -z "${NOSWAP}" ]; then
14                 SWAPOPT="-p freebsd-swap/swapfs::1G"
15         fi
16
17         _OBJDIR="$(make -C ${WORLDDIR} -V .OBJDIR)"
18         if [ -d "${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}" ]; then
19                 BOOTFILES="/${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}/usr/src/sys/boot"
20         else
21                 BOOTFILES="/${_OBJDIR}/sys/boot"
22         fi
23
24         case "${TARGET}:${TARGET_ARCH}" in
25                 amd64:amd64 | i386:i386)
26                         mkimg -s gpt -f ${VMFORMAT} \
27                                 -b ${BOOTFILES}/i386/pmbr/pmbr \
28                                 -p freebsd-boot/bootfs:=${BOOTFILES}/i386/gptboot/gptboot \
29                                 ${SWAPOPT} \
30                                 -p freebsd-ufs/rootfs:=${VMBASE} \
31                                 -o ${VMIMAGE}
32                         ;;
33                 arm64:aarch64)
34                         mkimg -s mbr -f ${VMFORMAT} \
35                                 -p efi:=${BOOTFILES}/efi/boot1/boot1.efifat \
36                                 -p freebsd:=${VMBASE} \
37                                 -o ${VMIMAGE}
38                         ;;
39                 powerpc:powerpc*)
40                         mkimg -s apm -f ${VMFORMAT} \
41                                 -p apple-boot/bootfs:=${BOOTFILES}/powerpc/boot1.chrp/boot1.hfs \
42                                 ${SWAPOPT} \
43                                 -p freebsd-ufs/rootfs:=${VMBASE} \
44                                 -o ${VMIMAGE}
45                         ;;
46                 *)
47                         # ENOTSUPP
48                         return 1
49                         ;;
50         esac
51
52         return 0
53 }
54
55 err() {
56         printf "${@}\n"
57         cleanup
58         return 1
59 }
60
61 cleanup() {
62         if [ -c "${DESTDIR}/dev/null" ]; then
63                 umount_loop ${DESTDIR}/dev 2>/dev/null
64         fi
65         umount_loop ${DESTDIR}
66         if [ ! -z "${mddev}" ]; then
67                 mdconfig -d -u ${mddev}
68         fi
69
70         return 0
71 }
72
73 vm_create_base() {
74         # Creates the UFS root filesystem for the virtual machine disk,
75         # written to the formatted disk image with mkimg(1).
76
77         mkdir -p ${DESTDIR}
78         truncate -s ${VMSIZE} ${VMBASE}
79         mddev=$(mdconfig -f ${VMBASE})
80         newfs -L rootfs /dev/${mddev}
81         mount /dev/${mddev} ${DESTDIR}
82
83         return 0
84 }
85
86 vm_copy_base() {
87         # Creates a new UFS root filesystem and copies the contents of the
88         # current root filesystem into it.  This produces a "clean" disk
89         # image without any remnants of files which were created temporarily
90         # during image-creation and have since been deleted (e.g., downloaded
91         # package archives).
92
93         mkdir -p ${DESTDIR}/old
94         mdold=$(mdconfig -f ${VMBASE})
95         mount /dev/${mdold} ${DESTDIR}/old
96
97         truncate -s ${VMSIZE} ${VMBASE}.tmp
98         mkdir -p ${DESTDIR}/new
99         mdnew=$(mdconfig -f ${VMBASE}.tmp)
100         newfs -L rootfs /dev/${mdnew}
101         mount /dev/${mdnew} ${DESTDIR}/new
102
103         tar -cf- -C ${DESTDIR}/old . | tar -xUf- -C ${DESTDIR}/new
104
105         umount_loop /dev/${mdold}
106         rmdir ${DESTDIR}/old
107         mdconfig -d -u ${mdold}
108
109         umount_loop /dev/${mdnew}
110         rmdir ${DESTDIR}/new
111         tunefs -j enable /dev/${mdnew}
112         mdconfig -d -u ${mdnew}
113         mv ${VMBASE}.tmp ${VMBASE}
114 }
115
116 vm_install_base() {
117         # Installs the FreeBSD userland/kernel to the virtual machine disk.
118
119         cd ${WORLDDIR} && \
120                 make DESTDIR=${DESTDIR} \
121                 installworld installkernel distribution || \
122                 err "\n\nCannot install the base system to ${DESTDIR}."
123
124         echo '# Custom /etc/fstab for FreeBSD VM images' \
125                 > ${DESTDIR}/etc/fstab
126         echo "/dev/${ROOTLABEL}/rootfs   /       ufs     rw      1       1" \
127                 >> ${DESTDIR}/etc/fstab
128         if [ -z "${NOSWAP}" ]; then
129                 echo '/dev/gpt/swapfs  none    swap    sw      0       0' \
130                         >> ${DESTDIR}/etc/fstab
131         fi
132
133         mkdir -p ${DESTDIR}/dev
134         mount -t devfs devfs ${DESTDIR}/dev
135         chroot ${DESTDIR} /usr/bin/newaliases
136         chroot ${DESTDIR} /etc/rc.d/ldconfig forcestart
137         umount_loop ${DESTDIR}/dev
138
139         cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf
140
141         return 0
142 }
143
144 vm_extra_install_base() {
145         # Prototype.  When overridden, runs extra post-installworld commands
146         # as needed, based on the target virtual machine image or cloud
147         # provider image target.
148
149         return 0
150 }
151
152 vm_extra_enable_services() {
153         if [ ! -z "${VM_RC_LIST}" ]; then
154                 for _rcvar in ${VM_RC_LIST}; do
155                         echo ${_rcvar}_enable="YES" >> ${DESTDIR}/etc/rc.conf
156                 done
157         fi
158
159         return 0
160 }
161
162 vm_extra_install_packages() {
163         if [ -z "${VM_EXTRA_PACKAGES}" ]; then
164                 return 0
165         fi
166         mkdir -p ${DESTDIR}/dev
167         mount -t devfs devfs ${DESTDIR}/dev
168         chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \
169                 /usr/sbin/pkg bootstrap -y
170         chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \
171                 /usr/sbin/pkg install -y ${VM_EXTRA_PACKAGES}
172         umount_loop ${DESTDIR}/dev
173
174         return 0
175 }
176
177 vm_extra_install_ports() {
178         # Prototype.  When overridden, installs additional ports within the
179         # virtual machine environment.
180
181         return 0
182 }
183
184 vm_extra_pre_umount() {
185         # Prototype.  When overridden, performs additional tasks within the
186         # virtual machine environment prior to unmounting the filesystem.
187         # Note: When overriding this function, removing resolv.conf in the
188         # disk image must be included.
189
190         rm -f ${DESTDIR}/etc/resolv.conf
191         return 0
192 }
193
194 vm_extra_pkg_rmcache() {
195         if [ -e ${DESTDIR}/usr/local/sbin/pkg ]; then
196                 chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \
197                         /usr/local/sbin/pkg clean -y -a
198         fi
199
200         return 0
201 }
202
203 umount_loop() {
204         DIR=$1
205         i=0
206         sync
207         while ! umount ${DIR}; do
208                 i=$(( $i + 1 ))
209                 if [ $i -ge 10 ]; then
210                         # This should never happen.  But, it has happened.
211                         echo "Cannot umount(8) ${DIR}"
212                         echo "Something has gone horribly wrong."
213                         return 1
214                 fi
215                 sleep 1
216         done
217
218         return 0
219 }
220
221 vm_create_disk() {
222         echo "Creating image...  Please wait."
223         echo
224
225         write_partition_layout || return 1
226
227         return 0
228 }
229
230 vm_extra_create_disk() {
231
232         return 0
233 }
234