[ostree] admin: Also delete unsed boot directories



commit c66148160cb4b3ec761dcfc0027a9b300506d2bf
Author: Colin Walters <walters verbum org>
Date:   Sun Jul 7 13:45:18 2013 -0400

    admin: Also delete unsed boot directories
    
    My VM filled up /boot.  Oops.

 Makefile-tests.am             |    1 +
 src/ostree/ot-admin-cleanup.c |  122 +++++++++++++++++++++++++++++++++++++++++
 tests/t0016-admin-deploy.sh   |   58 +++++++++++++++++++
 3 files changed, 181 insertions(+), 0 deletions(-)
---
diff --git a/Makefile-tests.am b/Makefile-tests.am
index b81866b..0b83ebe 100644
--- a/Makefile-tests.am
+++ b/Makefile-tests.am
@@ -29,6 +29,7 @@ testfiles = t0000-basic \
        t0006-libarchive \
        t0011-pull-archive-z \
        t0015-admin-deploy \
+       t0016-admin-deploy \
        $(NULL)
 insttest_SCRIPTS = $(addprefix tests/,$(testfiles:=.sh))
 
diff --git a/src/ostree/ot-admin-cleanup.c b/src/ostree/ot-admin-cleanup.c
index d647fa5..1ca242a 100644
--- a/src/ostree/ot-admin-cleanup.c
+++ b/src/ostree/ot-admin-cleanup.c
@@ -94,6 +94,7 @@ list_deployment_dirs_for_os (GFile               *osdir,
  out:
   return ret;
 }
+
 static gboolean
 list_all_deployment_directories (GFile               *sysroot,
                                  GPtrArray          **out_deployments,
@@ -154,6 +155,100 @@ list_all_deployment_directories (GFile               *sysroot,
 }
 
 static gboolean
+parse_bootdir_name (const char *name,
+                    char      **out_osname,
+                    char      **out_csum)
+{
+  const char *lastdash;
+  
+  if (out_osname)
+    *out_osname = NULL;
+  if (out_csum)
+    *out_csum = NULL;
+
+  lastdash = strrchr (name, '-');
+
+  if (!lastdash)
+    return FALSE;
+      
+  if (!ostree_validate_checksum_string (lastdash + 1, NULL))
+    return FALSE;
+
+  if (out_osname)
+    *out_osname = g_strndup (name, lastdash - name);
+  if (out_csum)
+    *out_csum = g_strdup (lastdash + 1);
+
+  return TRUE;
+}
+
+static gboolean
+list_all_boot_directories (GFile               *sysroot,
+                           GPtrArray          **out_bootdirs,
+                           GCancellable        *cancellable,
+                           GError             **error)
+{
+  gboolean ret = FALSE;
+  gs_unref_object GFileEnumerator *dir_enum = NULL;
+  gs_unref_object GFile *boot_ostree = NULL;
+  gs_unref_object GFile *osdir = NULL;
+  gs_unref_ptrarray GPtrArray *ret_bootdirs = NULL;
+  GError *temp_error = NULL;
+
+  boot_ostree = g_file_resolve_relative_path (sysroot, "boot/ostree");
+
+  ret_bootdirs = g_ptr_array_new_with_free_func (g_object_unref);
+
+  dir_enum = g_file_enumerate_children (boot_ostree, OSTREE_GIO_FAST_QUERYINFO,
+                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                        cancellable, &temp_error);
+  if (!dir_enum)
+    {
+      if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+        {
+          g_clear_error (&temp_error);
+          goto done;
+        } 
+      else
+        {
+          g_propagate_error (error, temp_error);
+          goto out;
+        }
+    }
+
+  while (TRUE)
+    {
+      GFileInfo *file_info = NULL;
+      GFile *child = NULL;
+      const char *name;
+
+      if (!gs_file_enumerator_iterate (dir_enum, &file_info, &child,
+                                       NULL, error))
+        goto out;
+      if (file_info == NULL)
+        break;
+
+      if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
+        continue;
+
+      /* Only look at directories ending in -CHECKSUM; nothing else
+       * should be in here, but let's be conservative.
+       */
+      name = g_file_info_get_name (file_info);
+      if (!parse_bootdir_name (name, NULL, NULL))
+        continue;
+      
+      g_ptr_array_add (ret_bootdirs, g_object_ref (child));
+    }
+  
+ done:
+  ret = TRUE;
+  ot_transfer_out_value (out_bootdirs, &ret_bootdirs);
+ out:
+  return ret;
+}
+
+static gboolean
 cleanup_other_bootversions (GFile               *sysroot,
                             int                  bootversion,
                             int                  subbootversion,
@@ -212,20 +307,25 @@ cleanup_old_deployments (GFile               *sysroot,
   guint i;
   gs_unref_object GFile *active_root = g_file_new_for_path ("/");
   gs_unref_hashtable GHashTable *active_deployment_dirs = NULL;
+  gs_unref_hashtable GHashTable *active_boot_checksums = NULL;
   gs_unref_ptrarray GPtrArray *all_deployment_dirs = NULL;
+  gs_unref_ptrarray GPtrArray *all_boot_dirs = NULL;
 
   if (!ot_admin_util_get_devino (active_root, &root_device, &root_inode,
                                  cancellable, error))
     goto out;
 
   active_deployment_dirs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, 
g_object_unref);
+  active_boot_checksums = g_hash_table_new_full (g_str_hash, (GEqualFunc)g_str_equal, g_free, NULL);
 
   for (i = 0; i < deployments->len; i++)
     {
       OtDeployment *deployment = deployments->pdata[i];
       GFile *deployment_path = ot_admin_get_deployment_directory (sysroot, deployment);
+      char *bootcsum = g_strdup (ot_deployment_get_bootcsum (deployment));
       /* Transfer ownership */
       g_hash_table_insert (active_deployment_dirs, deployment_path, deployment_path);
+      g_hash_table_insert (active_boot_checksums, bootcsum, bootcsum);
     }
 
   if (!list_all_deployment_directories (sysroot, &all_deployment_dirs,
@@ -260,6 +360,28 @@ cleanup_old_deployments (GFile               *sysroot,
         }
     }
 
+  if (!list_all_boot_directories (sysroot, &all_boot_dirs,
+                                  cancellable, error))
+    goto out;
+  
+  for (i = 0; i < all_boot_dirs->len; i++)
+    {
+      GFile *bootdir = all_boot_dirs->pdata[i];
+      gs_free char *osname = NULL;
+      gs_free char *bootcsum = NULL;
+
+      if (!parse_bootdir_name (gs_file_get_basename_cached (bootdir),
+                               &osname, &bootcsum))
+        g_assert_not_reached ();
+
+      if (g_hash_table_lookup (active_boot_checksums, bootcsum))
+        continue;
+
+      g_print ("ostadmin: Deleting bootdir %s\n", gs_file_get_path_cached (bootdir));
+      if (!gs_shutil_rm_rf (bootdir, cancellable, error))
+        goto out;
+    }
+
   ret = TRUE;
  out:
   return ret;
diff --git a/tests/t0016-admin-deploy.sh b/tests/t0016-admin-deploy.sh
new file mode 100755
index 0000000..ab0bb9a
--- /dev/null
+++ b/tests/t0016-admin-deploy.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+#
+# Copyright (C) 2011,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.
+
+set -e
+
+. $(dirname $0)/libtest.sh
+
+echo "1..1"
+
+setup_os_repository "archive-z2"
+
+echo "ok setup"
+
+echo "1..2"
+
+ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
+rev=$(ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
+export rev
+# This initial deployment gets kicked off with some kernel arguments 
+ostree admin --sysroot=sysroot deploy --karg=root=LABEL=MOO --karg=quiet --os=testos 
testos:testos/buildmaster/x86_64-runtime
+assert_has_dir sysroot/boot/ostree/testos-${bootcsum}
+
+echo "ok deploy command"
+
+# Commit + upgrade twice, so that we'll rotate out the original deployment
+orig_bootcsum=${bootcsum}
+os_repository_new_commit
+ostree --repo=sysroot/ostree/repo remote add testos file://$(pwd)/testos-repo 
testos/buildmaster/x86_64-runtime
+ostree admin --sysroot=sysroot upgrade --os=testos
+os_repository_new_commit
+ostree --repo=sysroot/ostree/repo remote add testos file://$(pwd)/testos-repo 
testos/buildmaster/x86_64-runtime
+ostree admin --sysroot=sysroot upgrade --os=testos
+
+rev=${newrev}
+newrev=$(ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
+assert_not_streq ${rev} ${newrev}
+assert_not_streq ${orig_bootcsum} ${bootcsum}
+assert_not_has_dir sysroot/boot/ostree/testos-${orig_bootcsum}
+assert_has_dir sysroot/boot/ostree/testos-${bootcsum}
+assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/os-release 'NAME=TestOS'
+
+echo "ok deploy and GC /boot"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]