Search in sources :

Example 1 with ZFSException

use of org.jvnet.solaris.libzfs.ZFSException in project hudson-2.x by hudson.

the class ZFSInstaller method migrate.

/**
     * Migrates $HUDSON_HOME to a new ZFS file system.
     *
     * TODO: do this in a separate JVM to elevate the privilege.
     *
     * @param listener
     *      Log of migration goes here.
     * @param target
     *      Dataset to move the data to.
     * @return
     *      false if a migration failed.
     */
private static boolean migrate(TaskListener listener, String target) throws IOException, InterruptedException {
    PrintStream out = listener.getLogger();
    File home = Hudson.getInstance().getRootDir();
    // do the migration
    LibZFS zfs = new LibZFS();
    ZFSFileSystem existing = zfs.getFileSystemByMountPoint(home);
    if (existing != null) {
        out.println(home + " is already on ZFS. Doing nothing");
        return true;
    }
    File tmpDir = Util.createTempDir();
    // mount a new file system to a temporary location
    out.println("Opening " + target);
    ZFSFileSystem hudson = zfs.open(target, ZFSFileSystem.class);
    hudson.setMountPoint(tmpDir);
    // mark this file system as "managed by Hudson"
    hudson.setProperty("hudson:managed-by", "hudson");
    hudson.mount();
    // copy all the files
    out.println("Copying all existing data files");
    if (system(home, listener, "/usr/bin/cp", "-pR", ".", tmpDir.getAbsolutePath()) != 0) {
        out.println("Failed to copy " + home + " to " + tmpDir);
        return false;
    }
    // unmount
    out.println("Unmounting " + target);
    hudson.unmount(MountFlags.MS_FORCE);
    // move the original directory to the side
    File backup = new File(home.getPath() + ".backup");
    out.println("Moving " + home + " to " + backup);
    if (backup.exists())
        Util.deleteRecursive(backup);
    if (!home.renameTo(backup)) {
        out.println("Failed to move your current data " + home + " out of the way");
    }
    // update the mount point
    out.println("Creating a new mount point at " + home);
    if (!home.mkdir())
        throw new IOException("Failed to create mount point " + home);
    out.println("Mounting " + target);
    hudson.setMountPoint(home);
    hudson.mount();
    out.println("Sharing " + target);
    try {
        hudson.setProperty("sharesmb", "on");
        hudson.setProperty("sharenfs", "on");
        hudson.share();
    } catch (ZFSException e) {
        listener.error("Failed to share the file systems: " + e.getCode());
    }
    // delete back up
    out.println("Deleting " + backup);
    if (system(new File("/"), listener, "/usr/bin/rm", "-rf", backup.getAbsolutePath()) != 0) {
        out.println("Failed to delete " + backup.getAbsolutePath());
        return false;
    }
    out.println("Migration completed");
    return true;
}
Also used : PrintStream(java.io.PrintStream) ZFSException(org.jvnet.solaris.libzfs.ZFSException) LibZFS(org.jvnet.solaris.libzfs.LibZFS) ZFSFileSystem(org.jvnet.solaris.libzfs.ZFSFileSystem) IOException(java.io.IOException) File(java.io.File)

Example 2 with ZFSException

use of org.jvnet.solaris.libzfs.ZFSException in project hudson-2.x by hudson.

the class ZFSInstaller method createZfsFileSystem.

/**
     * Creates a ZFS file system to migrate the data to.
     *
     * <p>
     * This has to be done while we still have an interactive access with the user, since it involves the password.
     *
     * <p>
     * An exception will be thrown if the operation fails. A normal completion means a success.
     *
     * @return
     *      The ZFS dataset name to migrate the data to.
     */
private String createZfsFileSystem(final TaskListener listener, String rootUsername, String rootPassword) throws IOException, InterruptedException, ZFSException {
    // capture the UID that Hudson runs under
    // so that we can allow this user to do everything on this new partition
    final int uid = LIBC.geteuid();
    final int gid = LIBC.getegid();
    passwd pwd = LIBC.getpwuid(uid);
    if (pwd == null)
        throw new IOException("Failed to obtain the current user information for " + uid);
    final String userName = pwd.pw_name;
    final File home = Hudson.getInstance().getRootDir();
    // return true indicating a success
    return SU.execute(listener, rootUsername, rootPassword, new Callable<String, IOException>() {

        public String call() throws IOException {
            PrintStream out = listener.getLogger();
            LibZFS zfs = new LibZFS();
            ZFSFileSystem existing = zfs.getFileSystemByMountPoint(home);
            if (existing != null) {
                // no need for migration
                out.println(home + " is already on ZFS. Doing nothing");
                return existing.getName();
            }
            String name = computeHudsonFileSystemName(zfs, zfs.roots().get(0));
            out.println("Creating " + name);
            ZFSFileSystem hudson = zfs.create(name, ZFSFileSystem.class);
            // mount temporarily to set the owner right
            File dir = Util.createTempDir();
            hudson.setMountPoint(dir);
            hudson.mount();
            if (LIBC.chown(dir.getPath(), uid, gid) != 0)
                throw new IOException("Failed to chown " + dir);
            hudson.unmount();
            try {
                // mark this file system as "managed by Hudson"
                hudson.setProperty("hudson:managed-by", "hudson");
                ACLBuilder acl = new ACLBuilder();
                acl.user(userName).withEverything();
                hudson.allow(acl);
            } catch (ZFSException e) {
                // revert the file system creation
                try {
                    hudson.destory();
                } catch (Exception _) {
                // but ignore the error and let the original error thrown
                }
                throw e;
            }
            return hudson.getName();
        }
    });
}
Also used : PrintStream(java.io.PrintStream) CLibrary.passwd(org.jvnet.libpam.impl.CLibrary.passwd) ACLBuilder(org.jvnet.solaris.libzfs.ACLBuilder) ZFSException(org.jvnet.solaris.libzfs.ZFSException) LibZFS(org.jvnet.solaris.libzfs.LibZFS) ZFSFileSystem(org.jvnet.solaris.libzfs.ZFSFileSystem) IOException(java.io.IOException) File(java.io.File) ServletException(javax.servlet.ServletException) ZFSException(org.jvnet.solaris.libzfs.ZFSException) IOException(java.io.IOException)

Example 3 with ZFSException

use of org.jvnet.solaris.libzfs.ZFSException in project hudson-2.x by hudson.

the class ZFSInstaller method doStart.

/**
     * Called from the confirmation screen to actually initiate the migration.
     */
public void doStart(StaplerRequest req, StaplerResponse rsp, @QueryParameter String username, @QueryParameter String password) throws ServletException, IOException {
    requirePOST();
    Hudson hudson = Hudson.getInstance();
    hudson.checkPermission(Hudson.ADMINISTER);
    final String datasetName;
    ByteArrayOutputStream log = new ByteArrayOutputStream();
    StreamTaskListener listener = new StreamTaskListener(log);
    try {
        datasetName = createZfsFileSystem(listener, username, password);
    } catch (Exception e) {
        e.printStackTrace(listener.error(e.getMessage()));
        if (e instanceof ZFSException) {
            ZFSException ze = (ZFSException) e;
            if (ze.getCode() == ErrorCode.EZFS_PERM) {
                // permission problem. ask the user to give us the root password
                req.setAttribute("message", log.toString());
                rsp.forward(this, "askRootPassword", req);
                return;
            }
        }
        // for other kinds of problems, report and bail out
        req.setAttribute("pre", true);
        sendError(log.toString(), req, rsp);
        return;
    }
    // file system creation successful, so restart
    WebAppController.get().install(new HudsonIsRestarting());
    // redirect the user to the manage page
    rsp.sendRedirect2(req.getContextPath() + "/manage");
    // asynchronously restart, so that we can give a bit of time to the browser to load "restarting..." screen.
    new Thread("restart thread") {

        @Override
        public void run() {
            try {
                Thread.sleep(5000);
                // close all descriptors on exec except stdin,out,err
                int sz = LIBC.getdtablesize();
                for (int i = 3; i < sz; i++) {
                    int flags = LIBC.fcntl(i, F_GETFD);
                    if (flags < 0)
                        continue;
                    LIBC.fcntl(i, F_SETFD, flags | FD_CLOEXEC);
                }
                // re-exec with the system property to indicate where to migrate the data to.
                // the 2nd phase is implemented in the migrate method.
                JavaVMArguments args = JavaVMArguments.current();
                args.setSystemProperty(ZFSInstaller.class.getName() + ".migrate", datasetName);
                Daemon.selfExec(args);
            } catch (InterruptedException e) {
                LOGGER.log(Level.SEVERE, "Restart failed", e);
            } catch (IOException e) {
                LOGGER.log(Level.SEVERE, "Restart failed", e);
            }
        }
    }.start();
}
Also used : StreamTaskListener(hudson.util.StreamTaskListener) ZFSException(org.jvnet.solaris.libzfs.ZFSException) Hudson(hudson.model.Hudson) JavaVMArguments(com.sun.akuma.JavaVMArguments) ByteArrayOutputStream(org.apache.commons.io.output.ByteArrayOutputStream) IOException(java.io.IOException) HudsonIsRestarting(hudson.util.HudsonIsRestarting) ServletException(javax.servlet.ServletException) ZFSException(org.jvnet.solaris.libzfs.ZFSException) IOException(java.io.IOException)

Aggregations

IOException (java.io.IOException)3 ZFSException (org.jvnet.solaris.libzfs.ZFSException)3 File (java.io.File)2 PrintStream (java.io.PrintStream)2 ServletException (javax.servlet.ServletException)2 LibZFS (org.jvnet.solaris.libzfs.LibZFS)2 ZFSFileSystem (org.jvnet.solaris.libzfs.ZFSFileSystem)2 JavaVMArguments (com.sun.akuma.JavaVMArguments)1 Hudson (hudson.model.Hudson)1 HudsonIsRestarting (hudson.util.HudsonIsRestarting)1 StreamTaskListener (hudson.util.StreamTaskListener)1 ByteArrayOutputStream (org.apache.commons.io.output.ByteArrayOutputStream)1 CLibrary.passwd (org.jvnet.libpam.impl.CLibrary.passwd)1 ACLBuilder (org.jvnet.solaris.libzfs.ACLBuilder)1