[gnome-ostree] qa: Extract out guestfish helper code, various fixes to deploy/grub config
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-ostree] qa: Extract out guestfish helper code, various fixes to deploy/grub config
- Date: Thu, 10 Jan 2013 01:19:15 +0000 (UTC)
commit a660ce929196bd42c6c665b1d4960cbb5d8c1d79
Author: Colin Walters <walters verbum org>
Date: Wed Jan 9 18:57:36 2013 -0500
qa: Extract out guestfish helper code, various fixes to deploy/grub config
Makefile-ostbuild.am | 1 +
src/ostbuild/js/builtins/qa_make_disk.js | 12 ++--
src/ostbuild/js/builtins/qa_pull_deploy.js | 79 ++++++++++++++++------------
src/ostbuild/js/guestfish.js | 62 ++++++++++++++++++++++
4 files changed, 114 insertions(+), 40 deletions(-)
---
diff --git a/Makefile-ostbuild.am b/Makefile-ostbuild.am
index 9740386..90f9979 100644
--- a/Makefile-ostbuild.am
+++ b/Makefile-ostbuild.am
@@ -45,6 +45,7 @@ jsostbuild_DATA= \
src/ostbuild/js/jsondb.js \
src/ostbuild/js/jsonutil.js \
src/ostbuild/js/main.js \
+ src/ostbuild/js/guestfish.js \
src/ostbuild/js/params.js \
src/ostbuild/js/procutil.js \
src/ostbuild/js/snapshot.js \
diff --git a/src/ostbuild/js/builtins/qa_make_disk.js b/src/ostbuild/js/builtins/qa_make_disk.js
index f6ca0fc..b125505 100644
--- a/src/ostbuild/js/builtins/qa_make_disk.js
+++ b/src/ostbuild/js/builtins/qa_make_disk.js
@@ -25,6 +25,7 @@ const GSystem = imports.gi.GSystem;
const ArgParse = imports.argparse;
const ProcUtil = imports.procutil;
+const GuestFish = imports.guestfish;
const loop = GLib.MainLoop.new(null, true);
@@ -51,13 +52,12 @@ const QaMakeDisk = new Lang.Class({
let guestfishProcess;
ProcUtil.runSync(['qemu-img', 'create', tmppath.get_path(), '' + sizeMb + 'M'], cancellable);
- let lines = ProcUtil.runProcWithInputSyncGetLines(['guestfish', '-a', tmppath.get_path()],
- cancellable,
- 'launch\n\
+ let makeDiskCmd = 'launch\n\
part-init /dev/vda mbr\n\
blockdev-getsize64 /dev/vda\n\
-blockdev-getss /dev/vda\n');
-
+blockdev-getss /dev/vda\n';
+ let gf = new GuestFish.GuestFish(tmppath, true);
+ let lines = gf.run(makeDiskCmd, cancellable, {partitionOpts: [], readWrite: true});
if (lines.length != 2)
throw new Error("guestfish returned unexpected output lines (" + lines.length + ", expected 2");
let diskBytesize = parseInt(lines[0]);
@@ -86,7 +86,7 @@ mkdir /boot\n\
swapOffset, rootOffset - 1,
rootOffset, endOffset - 1]);
print("partition config: ", partconfig);
- lines = ProcUtil.runProcWithInputSyncGetLines(['guestfish', '-a', tmppath.get_path()], cancellable, partconfig);
+ lines = gf.run(partconfig, cancellable, {partitionOpts: [], readWrite: true});
GSystem.file_rename(tmppath, path, cancellable);
print("Created: " + path.get_path());
}
diff --git a/src/ostbuild/js/builtins/qa_pull_deploy.js b/src/ostbuild/js/builtins/qa_pull_deploy.js
index 9bf872f..353ae7d 100644
--- a/src/ostbuild/js/builtins/qa_pull_deploy.js
+++ b/src/ostbuild/js/builtins/qa_pull_deploy.js
@@ -25,6 +25,7 @@ const GSystem = imports.gi.GSystem;
const ArgParse = imports.argparse;
const ProcUtil = imports.procutil;
+const GuestFish = imports.guestfish;
const loop = GLib.MainLoop.new(null, true);
@@ -35,14 +36,17 @@ const QaPullDeploy = new Lang.Class({
let deployBootdir = mntdir.resolve_relative_path('ostree/deploy/' + osname + '/current/boot');
let d = deployBootdir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, cancellable);
let finfo;
- while ((finfo = d.next_file(cancellable)) != null) {
- let child = deployBootdir.get_child(finfo.get_name());
- if (child.get_basename().indexOf('vmlinuz-') == 0) {
- return child;
+ try {
+ while ((finfo = d.next_file(cancellable)) != null) {
+ let child = deployBootdir.get_child(finfo.get_name());
+ if (child.get_basename().indexOf('vmlinuz-') == 0) {
+ return child;
+ }
}
+ throw new Error("Couldn't find vmlinuz- in " + deployBootdir.get_path());
+ } finally {
+ d.close(null);
}
- d.close(cancellable);
- throw new Error("Couldn't find vmlinuz- in " + deployBootdir.get_path());
},
_parseKernelRelease: function(kernelPath) {
@@ -62,17 +66,6 @@ const QaPullDeploy = new Lang.Class({
return path;
},
- // https://bugzilla.redhat.com/show_bug.cgi?id=892834
- // Also; we have to recreate it as a directory, then
- // delete that again to avoid further fuse/guestfs bugs.
- _workaroundGuestfsFuseBug: function(symlinkPath, cancellable) {
- GSystem.shutil_rm_rf(symlinkPath, cancellable);
- GSystem.file_ensure_directory(symlinkPath, true, cancellable);
- let dummyFile = symlinkPath.get_child('dummy');
- dummyFile.replace_contents('hello world', null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, cancellable);
- GSystem.shutil_rm_rf(symlinkPath, cancellable);
- },
-
execute: function(argv) {
let cancellable = null;
let parser = new ArgParse.ArgumentParser("Generate a disk image");
@@ -120,19 +113,24 @@ const QaPullDeploy = new Lang.Class({
ProcUtil.runSync(adminCmd.concat(['init-fs', mntdir.get_path()]), cancellable,
{logInitiation: true, env: adminEnv});
}
- ProcUtil.runSync(adminCmd.concat(['os-init', args.osname]), cancellable,
- {logInitiation: true, env: adminEnv});
+
+ // *** NOTE ***
+ // Here we blow away any current deployment. This is pretty lame, but it
+ // avoids us triggering a variety of guestfs/FUSE bugs =(
+ // See: https://bugzilla.redhat.com/show_bug.cgi?id=892834
+ //
+ // But regardless, it's probably useful if every
+ // deployment starts clean, and callers can use libguestfs
+ // to crack the FS open afterwards and modify config files
+ // or the like.
+ GSystem.shutil_rm_rf(ostree_osdir, cancellable);
+
ProcUtil.runSync(adminCmd.concat(['os-init', args.osname]), cancellable,
{logInitiation: true, env: adminEnv});
ProcUtil.runSync(['ostree', '--repo=' + ostreedir.get_child('repo').get_path(),
'pull-local', args.srcrepo, args.target], cancellable,
{logInitiation: true, env: adminEnv});
- let currentDeployLink = ostree_osdir.get_child('current');
- let currentEtcDeployLink = ostree_osdir.get_child('current-etc');
- this._workaroundGuestfsFuseBug(currentDeployLink, cancellable);
- this._workaroundGuestfsFuseBug(currentEtcDeployLink, cancellable);
-
ProcUtil.runSync(adminCmd.concat(['deploy', '--no-kernel', args.osname, args.target]), cancellable,
{logInitiation: true, env: adminEnv});
ProcUtil.runSync(adminCmd.concat(['update-kernel', '--no-bootloader', args.osname]), cancellable,
@@ -162,10 +160,10 @@ LABEL=gnostree-swap swap swap defaults 0 0\n';
let grubConfPath = grubDir.get_child('grub.conf');
let grubConf = Format.vprintf('default=0\n\
timeout=5\n\
-title GNOME-OSTree\n\
+title %s\n\
root (hd0,0)\n\
- kernel /%s root=LABEL=gnostree-root\n\
- initrd /%s\n', [bootRelativeKernelPath, bootRelativeInitramfsPath]);
+ kernel /%s root=LABEL=gnostree-root ostree=%s/current\n\
+ initrd /%s\n', [args.osname, bootRelativeKernelPath, args.osname, bootRelativeInitramfsPath]);
grubConfPath.replace_contents(grubConf, null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, cancellable);
} finally {
if (guestmountPidFile.query_exists(null)) {
@@ -181,8 +179,23 @@ title GNOME-OSTree\n\
} catch (e) {
if (!(e.origError && e.origError.domain == GLib.spawn_exit_error_quark()))
throw e;
- else
+ else {
+ let proc = GSystem.Subprocess.new_simple_argv(['fuser', '-m', mntdir.get_path()],
+ GSystem.SubprocessStreamDisposition.INHERIT,
+ GSystem.SubprocessStreamDisposition.INHERIT,
+ cancellable);
+ proc.init(cancellable);
+ proc.wait_sync(cancellable);
+ let creds = new Gio.Credentials();
+ proc = GSystem.Subprocess.new_simple_argv(['ls', '-al', '/proc/' + creds.get_unix_pid() + '/fd'],
+ GSystem.SubprocessStreamDisposition.INHERIT,
+ GSystem.SubprocessStreamDisposition.INHERIT,
+ cancellable);
+ proc.init(cancellable);
+ proc.wait_sync(cancellable);
+
GLib.usleep(GLib.USEC_PER_SEC);
+ }
}
}
let pid = parseInt(pidStr);
@@ -205,12 +218,10 @@ title GNOME-OSTree\n\
}
}
- let grubInstallCmds = 'grub-install / /dev/vda\n';
- let lines = ProcUtil.runProcWithInputSyncGetLines(['guestfish', '-a', args.diskpath,
- '-m', '/dev/sda3',
- '-m', '/dev/sda1:/boot'],
- cancellable, grubInstallCmds);
-
+ let gf = new GuestFish.GuestFish(diskpath, true);
+ gf.run('grub-install / /dev/vda\n', cancellable,
+ {partitionOpts: ['-m', '/dev/sda3', '-m', '/dev/sda1:/boot'],
+ readWrite: true});
print("Complete!");
}
});
diff --git a/src/ostbuild/js/guestfish.js b/src/ostbuild/js/guestfish.js
new file mode 100644
index 0000000..bd3a29e
--- /dev/null
+++ b/src/ostbuild/js/guestfish.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2012,2013 Colin Walters <walters verbum org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+
+const GSystem = imports.gi.GSystem;
+const Params = imports.params;
+const ProcUtil = imports.procutil;
+
+const GuestFish = new Lang.Class({
+ Name: 'GuestFish',
+
+ _init: function(diskpath, useLockFile) {
+ this._diskpath = diskpath;
+ if (useLockFile) {
+ let lockfilePath = diskpath.get_parent().get_child(diskpath.get_basename() + '.guestfish-lock');
+ this._lockfilePath = lockfilePath;
+ } else {
+ this._lockfilePath = null;
+ }
+ },
+
+ run: function(input, cancellable, params) {
+ params = Params.parse(params, {partitionOpts: ['-i'],
+ readWrite: false});
+
+ try {
+ let guestfishArgv = ['guestfish', '-a', this._diskpath.get_path()];
+ if (params.readWrite)
+ guestfishArgv.push('--rw');
+ else
+ guestfishArgv.push('--ro');
+ guestfishArgv.push.apply(guestfishArgv, params.partitionOpts);
+
+ let stream = this._lockfilePath.create(Gio.FileCreateFlags.NONE, cancellable);
+ stream.close(cancellable);
+
+ return ProcUtil.runProcWithInputSyncGetLines(guestfishArgv, cancellable, input);
+ } finally {
+ if (this._lockfilePath != null) {
+ GSystem.file_unlink(this._lockfilePath, cancellable);
+ }
+ }
+ }
+});
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]