Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
These tools are used for creating an initial seed zone as a baseline, based on files from a smartos-live build. This seed zone can then be built upon for more general purpose images.
- Loading branch information
Jonathan Perkin
committed
Aug 9, 2013
1 parent
295a3d2
commit eaaa56a
Showing
10 changed files
with
677 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
output/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,57 @@ | ||
imagetools | ||
========== | ||
|
||
Tools for creating SmartOS images | ||
Tools for creating SmartOS images. | ||
|
||
### Creating seed images | ||
|
||
Seed images are the absolute baseline of a SmartOS image. They are created | ||
from files produced by a smartos-live build, containing the original `/etc`, | ||
`/var` and SMF manifest database. | ||
|
||
First, you need to perform a smartos-live build, as described in the wiki | ||
page: | ||
|
||
http://wiki.smartos.org/display/DOC/Building+SmartOS+on+SmartOS | ||
|
||
Then from the global zone: | ||
|
||
$ ./create-seed /path/to/smartos-live seed-image | ||
|
||
This will create a `zones/seed-image` file system containing the seed files. | ||
|
||
To create a SNGL seed, you will then need to extract a bootstrap tarball over | ||
the top to populate enough of `/usr` for the zone to boot. I tend to use our | ||
pbulk pkgsrc bootstrap for this, for example: | ||
|
||
$ ./create-seed /path/to/smartos-live seed-sngl | ||
$ gtar -zxf /path/to/bootstrap-2013Q2-sngl.tar.gz -C /zones/seed-sngl/root/ | ||
|
||
Once you have a seed file system ready, use `create-image` to turn it into a | ||
provisionable image and manifest. | ||
|
||
$ ./create-image seed-1.0 seed-image | ||
Enter your username: jperkin | ||
Enter your user UUID (leave empty to create one): d9d9dd4b-3011-4a45-bffe-ddc9ba4be2d2 | ||
Enter description: Seed Image | ||
|
||
This will use `/zones/seed-image`, snapshot it, and create a file system image | ||
along with a manifest file ready for importing with `imgadm`. Give it your | ||
user credentials (or just make some up) and a useful description when | ||
prompted. | ||
|
||
Once complete it will output an `imgadm` command you can use, e.g. | ||
|
||
Done. Now run this to install the image: | ||
|
||
imgadm install -m ./output/seed-1.0.json -f ./output/seed-1.0.zfs.gz | ||
|
||
You can then use the UUID as input for the next phase. | ||
|
||
### Creating base images | ||
|
||
Base images are comprised of a baseline seed image, plus an applied `basesh` | ||
image. This overlays the basic set of pkgsrc packages, standard users, and | ||
some config customisation applicable to each base image. | ||
|
||
TODO.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#!/bin/bash | ||
# | ||
# Create an image and manifest out of a shut down zone. The zone | ||
# should have been prepared with sm-prepare-image. | ||
# | ||
|
||
if [ $# -ne 2 ]; then | ||
echo "usage: $0 <name> <zone>" >&2 | ||
exit 2 | ||
else | ||
name=$1; shift | ||
zone=$1; shift | ||
fi | ||
|
||
set -e | ||
|
||
read -p 'Enter your username: ' creator_name | ||
read -p 'Enter your user UUID (leave empty to create one): ' creator_uuid | ||
|
||
if [ -z "${creator_uuid}" ]; then | ||
creator_uuid=$(uuid) | ||
fi | ||
|
||
read -p 'Enter description: ' description | ||
|
||
if [ -z "${description}" ]; then | ||
echo "WARNING: No description entered. Edit ${outdir}/${name}.json" | ||
echo "when this script finishes." | ||
fi | ||
|
||
outdir="$(dirname $0)/output" | ||
echo "Taking snapshot ..." | ||
zfs snapshot zones/${zone}@snap$$ | ||
echo "Sending snapshot to ${outdir}/${name}.zfs.gz ..." | ||
zfs send zones/${zone}@snap$$ | gzip -9 >${outdir}/${name}.zfs.gz | ||
zfs destroy zones/${zone}@snap$$ | ||
|
||
echo "Creating ${outdir}/${name}.json ..." | ||
sha1=$(digest -a sha1 ${outdir}/${name}.zfs.gz) | ||
size=$(ls -l ${outdir}/${name}.zfs.gz | awk '{print $5}') | ||
uuid=$(uuid) | ||
datestamp=$(date '+%FT%RZ') | ||
|
||
cat $(dirname $0)/imgjson.in \ | ||
| sed -e "s/@NAME@/${name%-*}/g" \ | ||
-e "s/@VERSION@/${name##*-}/g" \ | ||
-e "s/@CREATOR_NAME@/${creator_name}/g" \ | ||
-e "s/@CREATOR_UUID@/${creator_uuid}/g" \ | ||
-e "s/@DATESTAMP@/${datestamp}/g" \ | ||
-e "s/@DESCRIPTION@/${description}/g" \ | ||
-e "s/@SHA1@/${sha1}/g" \ | ||
-e "s/@SIZE@/${size}/g" \ | ||
-e "s/@UUID@/${uuid}/g" \ | ||
>${outdir}/${name}.json | ||
|
||
echo "Done. Now run this to install the image:" | ||
echo "" | ||
echo " imgadm install -m ${outdir}/${name}.json -f ${outdir}/${name}.zfs.gz" | ||
echo "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#!/bin/bash | ||
# | ||
# This is a script to create an initial 'seed' image based on pristine | ||
# sources. User images will be built on top of this one. | ||
# | ||
# Two arguments are required: | ||
# | ||
# * a path to a built smartos-live repository | ||
# * the name of the seed image to create | ||
# | ||
|
||
|
||
if [ $# -ne 2 ]; then | ||
echo "usage: $0 <smartos-live> <seedname>" >&2 | ||
exit 2 | ||
else | ||
smartoslive=$1; shift | ||
protoname=$1; shift | ||
fi | ||
|
||
imagetoolsdir="$(dirname $0)" | ||
|
||
set -ex | ||
|
||
zfs destroy zones/${protoname} || true | ||
zfs create zones/${protoname} | ||
|
||
# | ||
# Requisite directories and symlinks | ||
# | ||
for dir in /home /root /var/ssh | ||
do | ||
mkdir -p /zones/${protoname}/root${dir} | ||
done | ||
mkdir -p -m 1777 /zones/${protoname}/root/tmp | ||
ln -s ./usr/bin /zones/${protoname}/root/bin | ||
|
||
# | ||
# Copy in proto directories | ||
# | ||
for dir in etc var | ||
do | ||
rsync -av ${smartoslive}/proto/${dir} /zones/${protoname}/root/ | ||
done | ||
|
||
# | ||
# Apply overlays | ||
# | ||
rsync -av ${smartoslive}/overlay/generic/etc/ /zones/${protoname}/root/etc/ | ||
|
||
# | ||
# Apply manual changes. | ||
# | ||
# - remove legacy rc2.d scripts | ||
# - remove users which may clash with pkgsrc, and sort. | ||
# | ||
rm -f /zones/${protoname}/root/etc/rc2.d/S* | ||
ed /zones/${protoname}/root/etc/passwd <<EOF | ||
/^lp/d | ||
/^gdm/d | ||
/^mysql/d | ||
/^openldap/d | ||
/^webservd/d | ||
/^postgres/d | ||
w | ||
q | ||
EOF | ||
ed /zones/${protoname}/root/etc/shadow <<EOF | ||
/^lp/d | ||
/^gdm/d | ||
/^mysql/d | ||
/^openldap/d | ||
/^webservd/d | ||
/^postgres/d | ||
w | ||
q | ||
EOF | ||
ed /zones/${protoname}/root/etc/group <<EOF | ||
/^lp/d | ||
/^gdm/d | ||
/^mysql/d | ||
/^openldap/d | ||
/^webservd/d | ||
/^postgres/d | ||
w | ||
q | ||
EOF | ||
for file in group passwd | ||
do | ||
sort -t: -k3,3n /zones/${protoname}/root/etc/${file} >/tmp/${file} \ | ||
&& mv /tmp/${file} /zones/${protoname}/root/etc/${file} | ||
done | ||
ed /zones/${protoname}/root/etc/user_attr >/dev/null <<EOF | ||
/^lp/d | ||
/^admin/d | ||
w | ||
q | ||
EOF | ||
|
||
# | ||
# Generate SVC repository. Some manifests are missing, apply them manually. | ||
# | ||
${imagetoolsdir}/create-smf-repo ${smartoslive} ${imagetoolsdir}/include/manifests /tmp/repository.db | ||
#svcdir="${smartoslive}/projects/illumos/usr/src/cmd/svc" | ||
#for mf in ${smartoslive}/proto/lib/svc/manifest/system/boot-archive.xml \ | ||
# ${smartoslive}/overlay/generic/lib/svc/manifest/system/sysidtool.xml \ | ||
#for mf in ${imagetoolsdir}/include/mdata.xml | ||
#do | ||
# env SVCCFG_REPOSITORY=/tmp/repository.db \ | ||
# SVCCFG_CONFIGD_PATH=${svcdir}/configd/svc.configd-native \ | ||
# ${svcdir}/svccfg/svccfg-native import ${mf} | ||
#done | ||
# | ||
# Import our fake mdata.xml to satisfy SDC 6.5 and 7.0 | ||
# | ||
#env SVCCFG_REPOSITORY=/tmp/repository.db \ | ||
# SVCCFG_CONFIGD_PATH=${smartoslive}/projects/illumos/usr/src/cmd/svc/configd/svc.configd-native \ | ||
# ${smartoslive}/projects/illumos/usr/src/cmd/svc/svccfg/svccfg-native import ${imagetoolsdir}/include/mdata.xml | ||
cp /tmp/repository.db /zones/${protoname}/root/etc/svc/repository.db | ||
|
||
# | ||
# Do just enough zoneinit stuff to get a zone to boot, this will be overwritten | ||
# later when we do a proper smtools install. | ||
# | ||
mkdir -p /zones/${protoname}/root/var/zoneinit | ||
cp ${imagetoolsdir}/include/zoneinit.json /zones/${protoname}/root/var/zoneinit | ||
cp ${imagetoolsdir}/include/S99final /zones/${protoname}/root/etc/rc2.d/S99final | ||
chmod 0755 /zones/${protoname}/root/etc/rc2.d/S99final |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#!/bin/bash | ||
# | ||
# CDDL HEADER START | ||
# | ||
# The contents of this file are subject to the terms of the | ||
# Common Development and Distribution License (the "License"). | ||
# You may not use this file except in compliance with the License. | ||
# | ||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | ||
# or http://www.opensolaris.org/os/licensing. | ||
# See the License for the specific language governing permissions | ||
# and limitations under the License. | ||
# | ||
# When distributing Covered Code, include this CDDL HEADER in each | ||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE. | ||
# If applicable, add the following below this CDDL HEADER, with the | ||
# fields enclosed by brackets "[]" replaced with your own identifying | ||
# information: Portions Copyright [yyyy] [name of copyright owner] | ||
# | ||
# CDDL HEADER END | ||
# | ||
# Copyright (c) 2012 Joyent, Inc. All rights reserved. | ||
# | ||
|
||
# | ||
# This tool builds a small SMF seed repository for a given brand based on its | ||
# manifests file which is used by our zones service. | ||
# | ||
|
||
# | ||
# Changes for this 'imagetools' version: | ||
# | ||
# * Use a configurable location to the 'smartos-live' build area | ||
# * Copy in manifests from multiple locations, and show where they came from. | ||
# | ||
|
||
if [ $# -ne 3 ]; then | ||
echo "usage: $0 <smartoslive> <manifests> <output>" >&2 | ||
exit 2 | ||
else | ||
SMARTOS_LIVE=$1; shift | ||
MANIFEST_LIST=$1; shift | ||
OUTPUT=$1; shift | ||
fi | ||
|
||
SVCCFG="${SMARTOS_LIVE}/projects/illumos/usr/src/cmd/svc/svccfg/svccfg-native" | ||
CONFIGD="${SMARTOS_LIVE}/projects/illumos/usr/src/cmd/svc/configd/svc.configd-native" | ||
#MANIFEST_LIST="${SMARTOS_LIVE}/overlay/generic/usr/lib/brand/joyent/manifests" | ||
MANIFESTS_LOCAL="$(dirname $0)/manifest" | ||
MANIFESTS_GENERIC="${SMARTOS_LIVE}/overlay/generic/lib/svc/manifest" | ||
MANIFESTS_PROTO="${SMARTOS_LIVE}/proto/lib/svc/manifest" | ||
MANIFESTS_SMARTOS="${SMARTOS_LIVE}/overlay/smartos/lib/svc/manifest" | ||
TMPFILE="/tmp/$(basename $0).$$" | ||
|
||
function fail | ||
{ | ||
local msg="$*" | ||
[[ -z "$msg" ]] && msg="failed" | ||
echo "$msg" >&2 | ||
exit 1 | ||
} | ||
|
||
# | ||
# XXX We really want to control this in a different way. We'd really rather not | ||
# have to hardcode machinations on the XML format of a manifest, because really, | ||
# that's just bad. On the flip side, we can't use libscf, but we can change the | ||
# file format that we use, which is probably what makes sense in the long run. | ||
# e.g. because a manifest can deliver more than one instance, we'd need to | ||
# explicitly call out which instances delivered by the manifest we'd like to | ||
# enable and disable. | ||
# | ||
function import_manifest | ||
{ | ||
local svc | ||
|
||
if [ -f "$MANIFESTS_LOCAL/$1" ]; then | ||
svc="$MANIFESTS_LOCAL/$1" | ||
echo -n "local: " | ||
elif [ -f "$MANIFESTS_GENERIC/$1" ]; then | ||
svc="$MANIFESTS_GENERIC/$1" | ||
echo -n "generic: " | ||
elif [ -f "$MANIFESTS_PROTO/$1" ]; then | ||
svc="$MANIFESTS_PROTO/$1" | ||
echo -n "proto: " | ||
elif [ -f "$MANIFESTS_SMARTOS/$1" ]; then | ||
svc="$MANIFESTS_SMARTOS/$1" | ||
echo -n "smartos: " | ||
else | ||
fail "cannot find $1" | ||
fi | ||
on="" | ||
[[ ! -f "$svc" ]] && fail "cannot find $svc" | ||
nawk -v status=$2 < $svc > $TMPFILE '{ | ||
if (($1 == "<instance" && | ||
$2 == "name=\047default\047") || | ||
$1 == "<create_default_instance") { | ||
if (status == "enabled") | ||
n=sub("\047false\047", "\047true\047") | ||
else | ||
n=sub("\047true\047", "\047false\047") | ||
} | ||
print $0 | ||
}' | ||
[[ $? -eq 0 ]] || fail "failed to nawk manifest" | ||
$SVCCFG import $TMPFILE || fail "failed to import $svc" | ||
rm -f $TMPFILE | ||
} | ||
|
||
function build_database | ||
{ | ||
local input output | ||
input=$1 | ||
output=$2 | ||
export SVCCFG_REPOSITORY=$output | ||
export SVCCFG_CONFIGD_PATH=$CONFIGD | ||
rm -f $SVCCFG_REPOSITORY | ||
|
||
[[ -f $input ]] || fail "can't read manifest input file: $input" | ||
while read service enabled import; do | ||
[[ -z "$service" ]] && continue | ||
[[ "$service" =~ ^\# ]] && continue | ||
[[ "$import" == "noimport" ]] && continue | ||
import_manifest $service $enabled | ||
|
||
echo $service $enabled | ||
done < $input | ||
} | ||
|
||
# | ||
# We need to walk through a few different sources of brands and work through it. | ||
# For now we only care about doing this for the Joyent minimal zone. Some day we | ||
# can extend this to everything. | ||
# | ||
build_database ${MANIFEST_LIST} ${OUTPUT} | ||
chmod 444 ${OUTPUT} | ||
chown root:root ${OUTPUT} | ||
echo "Generated ${OUTPUT}" |
Oops, something went wrong.