예제 #1
0
static gboolean
cleanup_logical_volume_walker (GDBusObjectManager *objman,
                               LvmLogicalVolume *logical_volume,
                               gpointer user_data,
                               GError **error)
{
  StorageProvider *provider = user_data;
  UDisksBlock *block = lvm_util_peek_block_for_logical_volume (storage_provider_get_lvm_object_manager (provider),
                                                               storage_provider_get_udisks_client (provider),
                                                               logical_volume);
  if (block)
    {
      /* The logical volume is active, let's clean it up by walking
         the tree of block devices hanging off of it.
       */
      return cleanup_block (provider, block, error);
    }
  else
    {
      /* The logical volume is inactive, let's clean it up by removing
         the remembered configs from its children.
      */
      LvmObject *object = LVM_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (logical_volume)));
      GList *remembered_configs = storage_provider_get_and_forget_remembered_configs
        (provider, g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
      for (GList *l = remembered_configs; l; l = l->next)
        {
          GVariant *config = l->data;
          storage_remove_config (provider, NULL, config);
        }
      g_list_free_full (remembered_configs, (GDestroyNotify)g_variant_unref);
      return TRUE;
    }
}
예제 #2
0
static gboolean
walk_block_parents (UDisksClient *client,
                    GDBusObjectManager  *objman,
                    UDisksBlock *block,
                    ObjectWalker *walker,
                    gpointer user_data,
                    GError **error)
{
  /* Parents are
     - of a block that is a logical volume, the logical volume object
     - of a clear text device, the encrypted device.

     XXX - support the whole tree.
  */

  while (block)
    {
      const gchar *path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (block));
      LvmLogicalVolumeBlock *lvm_block =
        LVM_LOGICAL_VOLUME_BLOCK (g_dbus_object_manager_get_interface (objman, path,
                                                                       "com.redhat.lvm2.LogicalVolumeBlock"));

      const gchar *logical_volume_path =
        (lvm_block ? lvm_logical_volume_block_get_logical_volume (lvm_block) : "/");
      const gchar *crypto_path = udisks_block_get_crypto_backing_device (block);

      if (g_strcmp0 (logical_volume_path, "/") != 0)
        {
          gs_unref_object LvmObject *logical_volume_object =
            LVM_OBJECT (g_dbus_object_manager_get_object (objman, logical_volume_path));

          if (logical_volume_object)
            {
              if (!walker (client, G_DBUS_OBJECT (logical_volume_object), user_data, error))
                return FALSE;
            }
          block = NULL;
        }
      else if (g_strcmp0 (crypto_path, "/") != 0)
        {
          UDisksObject *crypto_object = udisks_client_peek_object (client, crypto_path);
          if (crypto_object)
            {
              if (!walker (client, G_DBUS_OBJECT (crypto_object), user_data, error))
                return FALSE;
            }
          block = udisks_object_peek_block (crypto_object);
        }
      else
        block = NULL;
    }

  return TRUE;
}
예제 #3
0
const gchar *
storage_provider_translate_path (StorageProvider *provider,
                                 const gchar *udisks_or_lvm_path)
{
  StorageObject *object = NULL;

  if (udisks_or_lvm_path == NULL)
    udisks_or_lvm_path = "/";

  gs_unref_object UDisksObject *udisks_object = udisks_client_get_object (provider->udisks_client,
                                                                          udisks_or_lvm_path);
  if (udisks_object != NULL)
    {

      UDisksDrive *udisks_drive = udisks_object_peek_drive (udisks_object);
      if (udisks_drive != NULL)
        object = storage_provider_lookup_for_udisks_drive (provider, udisks_drive);

      UDisksBlock *udisks_block = udisks_object_peek_block (udisks_object);
      if (udisks_block != NULL)
        object = storage_provider_lookup_for_udisks_block (provider, udisks_block);

      UDisksMDRaid *udisks_raid = udisks_object_peek_mdraid (udisks_object);
      if (udisks_raid != NULL)
        object = storage_provider_lookup_for_udisks_mdraid (provider, udisks_raid);
    }

  gs_unref_object LvmObject *lvm_object = LVM_OBJECT (g_dbus_object_manager_get_object (provider->lvm_objman,
                                                                                        udisks_or_lvm_path));
  if (lvm_object)
    {
      LvmVolumeGroup *lvm_volume_group = lvm_object_peek_volume_group (lvm_object);
      if (lvm_volume_group != NULL)
        object = storage_provider_lookup_for_lvm_volume_group (provider, lvm_volume_group);

      LvmLogicalVolume *lvm_logical_volume = lvm_object_peek_logical_volume (lvm_object);
      if (lvm_logical_volume != NULL)
        object = storage_provider_lookup_for_lvm_logical_volume (provider, lvm_logical_volume);
    }

  if (object != NULL)
    {
      // g_debug ("%s -> %s", udisks_or_lvm_path, g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
      return g_dbus_object_get_object_path (G_DBUS_OBJECT (object));
    }
  else
    {
      // g_debug ("%s -> nothing", udisks_or_lvm_path);
      return "/";
    }
}
예제 #4
0
void
storage_block_update (StorageBlock *block)
{
  CockpitStorageBlock *iface = COCKPIT_STORAGE_BLOCK (block);
  StorageProvider *provider;
  UDisksClient *udisks_client;
  UDisksObject *udisks_object;
  UDisksBlock *udisks_block;
  UDisksPartition *udisks_partition = NULL;
  UDisksPartitionTable *udisks_partition_table = NULL;
  UDisksFilesystem *udisks_filesystem = NULL;

  provider = storage_object_get_provider (block->object);
  udisks_client = storage_provider_get_udisks_client (provider);
  udisks_block = block->udisks_block;
  udisks_object = (UDisksObject *)g_dbus_interface_get_object (G_DBUS_INTERFACE (udisks_block));
  if (udisks_object != NULL)
    {
      udisks_partition = udisks_object_peek_partition (udisks_object);
      udisks_partition_table = udisks_object_peek_partition_table (udisks_object);
      udisks_filesystem = udisks_object_peek_filesystem (udisks_object);
    }

  {
    gs_free gchar *d =
      g_filename_display_name (udisks_block_get_preferred_device (udisks_block));
    cockpit_storage_block_set_device (iface, d);
  }

  cockpit_storage_block_set_size       (iface, udisks_block_get_size (udisks_block));
  cockpit_storage_block_set_id_usage   (iface, udisks_block_get_id_usage   (udisks_block));
  cockpit_storage_block_set_id_type    (iface, udisks_block_get_id_type    (udisks_block));
  cockpit_storage_block_set_id_version (iface, udisks_block_get_id_version (udisks_block));
  cockpit_storage_block_set_id_label   (iface, udisks_block_get_id_label   (udisks_block));
  cockpit_storage_block_set_id_uuid    (iface, udisks_block_get_id_uuid    (udisks_block));

  cockpit_storage_block_set_hint_ignore (iface, udisks_block_get_hint_ignore (udisks_block));

  if (udisks_partition == NULL)
    {
      cockpit_storage_block_set_partition_number (iface, 0);
      cockpit_storage_block_set_partition_table (iface, "/");
    }
  else
    {
      UDisksPartitionTable *table_for_partition;
      const gchar *objpath = "/";
      GDBusObject *o;
      UDisksBlock *b;
      StorageObject *so;

      table_for_partition = udisks_client_get_partition_table (udisks_client, udisks_partition);
      if (table_for_partition != NULL)
        {
          o = g_dbus_interface_get_object (G_DBUS_INTERFACE (table_for_partition));
          if (o != NULL)
            {
              b = udisks_object_peek_block (UDISKS_OBJECT (o));
              if (b != NULL)
                {
                  so = storage_provider_lookup_for_udisks_block (provider, b);
                  if (so != NULL)
                    {
                      objpath = g_dbus_object_get_object_path (G_DBUS_OBJECT (so));
                    }
                }
            }
        }
      cockpit_storage_block_set_partition_table (iface, objpath);
      cockpit_storage_block_set_partition_number (iface, udisks_partition_get_number (udisks_partition));
    }

  GVariantBuilder partitions;
  g_variant_builder_init (&partitions, G_VARIANT_TYPE ("a(otts)"));

  if (udisks_partition_table != NULL)
    {
      GList *ps, *l;
      ps = udisks_client_get_partitions (udisks_client, udisks_partition_table);
      for (l = ps; l != NULL; l = l->next)
        {
          UDisksPartition *p = UDISKS_PARTITION (l->data);
          GDBusObject *o;
          UDisksBlock *b;
          StorageObject *so;

          o = g_dbus_interface_get_object (G_DBUS_INTERFACE (p));
          if (o != NULL)
            {
              b = udisks_object_peek_block (UDISKS_OBJECT (o));
              if (b != NULL)
                {
                  so = storage_provider_lookup_for_udisks_block (provider, b);
                  if (so != NULL)
                    {
                      const gchar *type = "p";
                      if (udisks_partition_get_is_container (p))
                        type = "x";
                      else if (udisks_partition_get_is_contained (p))
                        type = "l";
                      g_variant_builder_add (&partitions, "(otts)",
                                             g_dbus_object_get_object_path (G_DBUS_OBJECT (so)),
                                             udisks_partition_get_offset (p),
                                             udisks_partition_get_size (p),
                                             type);
                    }
                }
            }
        }
      g_list_free_full (ps, g_object_unref);
      const gchar *type = udisks_partition_table_get_type_ (udisks_partition_table);
      if (type == NULL || type[0] == '\0')
        type = "unknown";
      cockpit_storage_block_set_partition_table_type (iface, type);
    }
  else
    cockpit_storage_block_set_partition_table_type (iface, "");

  cockpit_storage_block_set_partitions (iface, g_variant_builder_end (&partitions));

  cockpit_storage_block_set_drive
    (iface, storage_provider_translate_path (provider, udisks_block_get_drive (udisks_block)));
  cockpit_storage_block_set_crypto_backing_device
    (iface, storage_provider_translate_path (provider, udisks_block_get_crypto_backing_device (udisks_block)));
  cockpit_storage_block_set_mdraid
    (iface, storage_provider_translate_path (provider, udisks_block_get_mdraid (udisks_block)));
  cockpit_storage_block_set_mdraid_member
    (iface, storage_provider_translate_path (provider, udisks_block_get_mdraid_member (udisks_block)));

  if (udisks_filesystem)
    {
      const gchar *const *p = udisks_filesystem_get_mount_points (udisks_filesystem);
      gchar *u[g_strv_length ((gchar **)p) + 1];
      int i;
      for (i = 0; p[i]; i++)
        u[i] = g_filename_display_name (p[i]);
      u[i] = NULL;
      cockpit_storage_block_set_mounted_at (iface, (const gchar *const *)u);
      for (i = 0; u[i]; i++)
        g_free (u[i]);
    }

  GVariantIter iter;
  g_variant_iter_init (&iter, udisks_block_get_configuration (udisks_block));
  const gchar *type;
  GVariant *details;
  gboolean got_fstab = FALSE, got_crypttab = FALSE;
  while (g_variant_iter_next (&iter, "(&s*)", &type, &details))
    {
      if (strcmp (type, "fstab") == 0 && !got_fstab)
        {
          got_fstab = TRUE;
          const gchar *dir = variant_lookup (details, "dir");
          if (dir)
            {
              gs_free gchar *dir_display = g_filename_display_name (dir);
              cockpit_storage_block_set_mount_point (iface, dir_display);
            }
          const gchar *opts = variant_lookup (details, "opts");
          if (opts)
            {
              gs_free gchar *opts_locale = g_locale_to_utf8 (opts, -1, NULL, NULL, NULL);
              if (opts_locale)
                cockpit_storage_block_set_mount_options (iface, opts_locale);
              else
                g_warning ("Can't convert fstab options into UTF8");
            }
        }
      else if (strcmp (type, "crypttab") == 0 && !got_crypttab)
        {
          got_crypttab = TRUE;
          const gchar *opts = variant_lookup (details, "options");
          if (opts)
            {
              gs_free gchar *opts_locale = g_locale_to_utf8 (opts, -1, NULL, NULL, NULL);
              if (opts_locale)
                cockpit_storage_block_set_crypto_options (iface, opts_locale);
              else
                g_warning ("Can't convert crypttab options into UTF8");
            }
        }
      g_variant_unref (details);
    }

  /* Now the com.redhat.lvm2 overlays.  The StorageProvider makes sure
     that we are called whenever something changes about them.
   */

  LvmLogicalVolumeBlock *lv = NULL;
  LvmPhysicalVolumeBlock *pv = NULL;

  GDBusObjectManager *objman = storage_provider_get_lvm_object_manager (provider);
  GDBusObject *lvm_object =
    g_dbus_object_manager_get_object (objman,
                                      g_dbus_object_get_object_path (G_DBUS_OBJECT (udisks_object)));
  if (lvm_object)
    {
      lv = lvm_object_peek_logical_volume_block (LVM_OBJECT (lvm_object));
      pv = lvm_object_peek_physical_volume_block (LVM_OBJECT (lvm_object));
    }

  if (lv)
    {
      cockpit_storage_block_set_logical_volume
        (iface,
         storage_provider_translate_path
         (provider,
          lvm_logical_volume_block_get_logical_volume (lv)));
    }
  else
    cockpit_storage_block_set_logical_volume (iface, "/");

  if (pv)
    {
      cockpit_storage_block_set_pv_group
        (iface,
         storage_provider_translate_path (provider,
                                          lvm_physical_volume_block_get_volume_group (pv)));
      cockpit_storage_block_set_pv_size (iface,
                                         lvm_physical_volume_block_get_size (pv));
      cockpit_storage_block_set_pv_free_size (iface,
                                              lvm_physical_volume_block_get_free_size (pv));
    }
  else
    {
      cockpit_storage_block_set_pv_group (iface, "/");
      cockpit_storage_block_set_pv_size (iface, 0);
      cockpit_storage_block_set_pv_free_size (iface, 0);
    }
}
예제 #5
0
static void
provider_update_objects (StorageProvider *provider)
{
  GDBusObjectManagerServer *object_manager;
  GList *udisks_objects;
  GList *lvm_objects;
  GList *wanted;
  GList *added, *removed;
  GList *l;

  object_manager = G_DBUS_OBJECT_MANAGER_SERVER (daemon_get_object_manager (provider->daemon));
  udisks_objects = g_dbus_object_manager_get_objects (udisks_client_get_object_manager (provider->udisks_client));
  lvm_objects = g_dbus_object_manager_get_objects (provider->lvm_objman);

  wanted = NULL;
  for (l = udisks_objects; l != NULL; l = l->next)
    {
      GDBusInterface *iface = get_udisk_iface (UDISKS_OBJECT (l->data));
      if (iface == NULL)
        continue;

      wanted = g_list_prepend (wanted, g_object_ref (iface));
    }
  for (l = lvm_objects; l != NULL; l = l->next)
    {
      if (!LVM_IS_OBJECT (l->data))
        continue;

      GDBusInterface *iface = get_lvm_iface (LVM_OBJECT (l->data));
      if (iface == NULL)
        continue;

      wanted = g_list_prepend (wanted, g_object_ref (iface));
    }

  wanted = g_list_sort (wanted, (GCompareFunc)udisks_iface_compare_func);
  provider->ifaces = g_list_sort (provider->ifaces, (GCompareFunc)udisks_iface_compare_func);
  diff_sorted_lists (provider->ifaces, wanted, (GCompareFunc)udisks_iface_compare_func,
                     &added, &removed, NULL);

  for (l = removed; l != NULL; l = l->next)
    {
      GDBusInterface *iface = G_DBUS_INTERFACE (l->data);
      StorageObject *object;

      object = g_hash_table_lookup (provider->hash_interface_to_storage_object, iface);
      g_warn_if_fail (object != NULL);
      if (object)
        {
          g_warn_if_fail (g_dbus_object_manager_server_unexport (object_manager,
                          g_dbus_object_get_object_path (G_DBUS_OBJECT (object))));
        }

      g_hash_table_remove (provider->hash_interface_to_storage_object, iface);
      provider->ifaces = g_list_remove (provider->ifaces, iface);
      g_object_unref (iface);
    }

  for (l = added; l != NULL; l = l->next)
    {
      GDBusInterface *iface = G_DBUS_INTERFACE (l->data);
      StorageObject *object = make_storage_object (provider, iface);

      g_warn_if_fail (g_hash_table_lookup (provider->hash_interface_to_storage_object, iface) == NULL);
      g_hash_table_insert (provider->hash_interface_to_storage_object,
                           g_object_ref (iface),
                           object);

      gs_free gchar *object_path = storage_object_make_object_path (object);
      g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path);
      g_dbus_object_manager_server_export_uniquely (object_manager, G_DBUS_OBJECT_SKELETON (object));

      provider->ifaces = g_list_prepend (provider->ifaces, g_object_ref (iface));
    }

  g_list_free (added);
  g_list_free (removed);
  g_list_free_full (udisks_objects, g_object_unref);
  g_list_free_full (lvm_objects, g_object_unref);
  g_list_free_full (wanted, g_object_unref);
}