Skip to content

Commit

Permalink
daemon: Add new ModifyYumRepo DBus API
Browse files Browse the repository at this point in the history
This allows clients such as gnome-software to enable and disable
yum repositories.

The API is generic, but for now we only allow changing the 'enabled'
key. If needed, it's easy to allow changing other settings in the
future. See the discussion in the PR for the reasoning.

Closes: #1771

Closes: #1780
Approved by: cgwalters
  • Loading branch information
kalev authored and rh-atomic-bot committed Mar 21, 2019
1 parent b324ee4 commit 891f5b7
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/daemon/org.projectatomic.rpmostree1.policy
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@
</defaults>
</action>

<action id="org.projectatomic.rpmostree1.repo-modify">
<description>Modify repository settings</description>
<message>Authentication is required to modify repository settings</message>
<icon_name>package-x-generic</icon_name>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>

<action id="org.projectatomic.rpmostree1.client-management">
<description>Register and unregister as a sysroot client</description>
<message>Authentication is required to register as a sysroot client</message>
Expand Down
7 changes: 7 additions & 0 deletions src/daemon/org.projectatomic.rpmostree1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@
<arg type="s" name="transaction_address" direction="out"/>
</method>

<!-- Set options in yum .repo files -->
<method name="ModifyYumRepo">
<arg type="s" name="repo_id" direction="in"/>
<arg type="a{ss}" name="settings" direction="in"/>
<arg type="s" name="transaction_address" direction="out"/>
</method>

<!-- Available modifiers:
"set-refspec" (type 's')
"set-revision" (type 's')
Expand Down
59 changes: 59 additions & 0 deletions src/daemon/rpmostreed-os.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ os_authorize_method (GDBusInterfaceSkeleton *interface,
{
g_ptr_array_add (actions, "org.projectatomic.rpmostree1.repo-refresh");
}
else if (g_strcmp0 (method_name, "ModifyYumRepo") == 0)
{
g_ptr_array_add (actions, "org.projectatomic.rpmostree1.repo-modify");
}
else if (g_strcmp0 (method_name, "Deploy") == 0)
{
g_ptr_array_add (actions, "org.projectatomic.rpmostree1.deploy");
Expand Down Expand Up @@ -916,6 +920,60 @@ os_handle_refresh_md (RPMOSTreeOS *interface,
return TRUE;
}

static gboolean
os_handle_modify_yum_repo (RPMOSTreeOS *interface,
GDBusMethodInvocation *invocation,
const char *arg_repo_id,
GVariant *arg_settings)
{
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
const char *osname;
GError *local_error = NULL;

/* try to merge with an existing transaction, otherwise start a new one */
glnx_unref_object RpmostreedTransaction *transaction = NULL;
RpmostreedSysroot *rsysroot = rpmostreed_sysroot_get ();
if (!rpmostreed_sysroot_prep_for_txn (rsysroot, invocation, &transaction, &local_error))
goto out;
if (transaction)
goto out;

if (!rpmostreed_sysroot_load_state (rpmostreed_sysroot_get (),
cancellable,
&ot_sysroot,
NULL,
&local_error))
goto out;

osname = rpmostree_os_get_name (interface);

transaction = rpmostreed_transaction_new_modify_yum_repo (invocation,
ot_sysroot,
osname,
arg_repo_id,
arg_settings,
cancellable,
&local_error);
if (transaction == NULL)
goto out;

rpmostreed_sysroot_set_txn (rsysroot, transaction);

out:
if (local_error != NULL)
{
g_dbus_method_invocation_take_error (invocation, local_error);
}
else
{
const char *client_address = rpmostreed_transaction_get_client_address (transaction);
rpmostree_os_complete_modify_yum_repo (interface, invocation, client_address);
}

return TRUE;
}

/* This is an older variant of Cleanup, kept for backcompat */
static gboolean
os_handle_clear_rollback_target (RPMOSTreeOS *interface,
Expand Down Expand Up @@ -1668,6 +1726,7 @@ rpmostreed_os_iface_init (RPMOSTreeOSIface *iface)
iface->handle_get_deployment_boot_config = os_handle_get_deployment_boot_config;
iface->handle_kernel_args = os_handle_kernel_args;
iface->handle_refresh_md = os_handle_refresh_md;
iface->handle_modify_yum_repo = os_handle_modify_yum_repo;
iface->handle_rollback = os_handle_rollback;
iface->handle_set_initramfs_state = os_handle_set_initramfs_state;
iface->handle_update_deployment = os_handle_update_deployment;
Expand Down
149 changes: 149 additions & 0 deletions src/daemon/rpmostreed-transaction-types.c
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,155 @@ rpmostreed_transaction_new_refresh_md (GDBusMethodInvocation *invocation,

}

/* ================================ ModifyYumRepo ================================ */

typedef struct {
RpmostreedTransaction parent;
char *osname;
char *repo_id;
GVariant *settings;
} ModifyYumRepoTransaction;

typedef RpmostreedTransactionClass ModifyYumRepoTransactionClass;

GType modify_yum_repo_transaction_get_type (void);

G_DEFINE_TYPE (ModifyYumRepoTransaction,
modify_yum_repo_transaction,
RPMOSTREED_TYPE_TRANSACTION)

static void
modify_yum_repo_transaction_finalize (GObject *object)
{
ModifyYumRepoTransaction *self;

self = (ModifyYumRepoTransaction *) object;
g_free (self->osname);
g_free (self->repo_id);
g_variant_unref (self->settings);

G_OBJECT_CLASS (modify_yum_repo_transaction_parent_class)->finalize (object);
}

static DnfRepo *
get_dnf_repo_by_id (RpmOstreeContext *ctx, const char *repo_id)
{
DnfContext *dnfctx = rpmostree_context_get_dnf (ctx);

GPtrArray *repos = dnf_context_get_repos (dnfctx);
for (guint i = 0; i < repos->len; i++)
{
DnfRepo *repo = repos->pdata[i];
if (g_strcmp0 (dnf_repo_get_id (repo), repo_id) == 0)
return repo;
}

return NULL;
}

static gboolean
modify_yum_repo_transaction_execute (RpmostreedTransaction *transaction,
GCancellable *cancellable,
GError **error)
{
ModifyYumRepoTransaction *self = (ModifyYumRepoTransaction *) transaction;
OstreeSysroot *sysroot = rpmostreed_transaction_get_sysroot (transaction);

rpmostree_transaction_set_title ((RPMOSTreeTransaction*)self, "modify-yum-repo");

g_autoptr(OstreeDeployment) cfg_merge_deployment =
ostree_sysroot_get_merge_deployment (sysroot, self->osname);

OstreeRepo *ot_repo = ostree_sysroot_repo (sysroot);
g_autoptr(RpmOstreeContext) ctx = rpmostree_context_new_system (ot_repo, cancellable, error);

/* We could bypass rpmostree_context_setup() here and call dnf_context_setup() ourselves
* since we're not actually going to perform any installation. Though it does provide us
* with the right semantics for install/source_root. */
if (!rpmostree_context_setup (ctx, NULL, NULL, NULL, cancellable, error))
return FALSE;

/* point libdnf to our repos dir */
rpmostree_context_configure_from_deployment (ctx, sysroot, cfg_merge_deployment);

DnfRepo *repo = get_dnf_repo_by_id (ctx, self->repo_id);
if (repo == NULL)
return glnx_throw (error, "Yum repo '%s' not found", self->repo_id);

GVariantIter iter;
GVariant *child;
g_variant_iter_init (&iter, self->settings);
while ((child = g_variant_iter_next_value (&iter)) != NULL)
{
const char *parameter = NULL;
const char *value = NULL;
g_variant_get_child (child, 0, "&s", &parameter);
g_variant_get_child (child, 1, "&s", &value);

/* Only allow changing 'enabled' for now. See the discussion about changing arbitrary
* .repo settings in https://github.com/projectatomic/rpm-ostree/pull/1780 */
if (g_strcmp0 (parameter, "enabled") != 0)
return glnx_throw (error, "Changing '%s' not allowed in yum .repo files", parameter);

if (g_strcmp0 (value, "0") != 0 &&
g_strcmp0 (value, "1") != 0)
return glnx_throw (error, "Only '0' and '1' are allowed for the '%s' key", parameter);

if (!dnf_repo_set_data (repo, parameter, value, error))
return FALSE;
}

if (!dnf_repo_commit (repo, error))
return FALSE;

return TRUE;
}

static void
modify_yum_repo_transaction_class_init (CleanupTransactionClass *class)
{
GObjectClass *object_class;

object_class = G_OBJECT_CLASS (class);
object_class->finalize = modify_yum_repo_transaction_finalize;

class->execute = modify_yum_repo_transaction_execute;
}

static void
modify_yum_repo_transaction_init (ModifyYumRepoTransaction *self)
{
}

RpmostreedTransaction *
rpmostreed_transaction_new_modify_yum_repo (GDBusMethodInvocation *invocation,
OstreeSysroot *sysroot,
const char *osname,
const char *repo_id,
GVariant *settings,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL);

ModifyYumRepoTransaction *self =
g_initable_new (modify_yum_repo_transaction_get_type (),
cancellable, error,
"invocation", invocation,
"sysroot-path", gs_file_get_path_cached (ostree_sysroot_get_path (sysroot)),
NULL);

if (self != NULL)
{
self->osname = g_strdup (osname);
self->repo_id = g_strdup (repo_id);
self->settings = g_variant_ref (settings);
}

return (RpmostreedTransaction *) self;
}

/* ================================KernelArg================================ */

typedef struct {
Expand Down
10 changes: 10 additions & 0 deletions src/daemon/rpmostreed-transaction-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,16 @@ rpmostreed_transaction_new_refresh_md (GDBusMethodInvocation *invocation,
const char *osname,
GCancellable *cancellable,
GError **error);

RpmostreedTransaction *
rpmostreed_transaction_new_modify_yum_repo (GDBusMethodInvocation *invocation,
OstreeSysroot *sysroot,
const char *osname,
const char *repo_id,
GVariant *settings,
GCancellable *cancellable,
GError **error);

typedef enum {
RPMOSTREE_TRANSACTION_KERNEL_ARG_FLAG_REBOOT = (1 << 0),
} RpmOstreeTransactionKernelArgFlags;
Expand Down

0 comments on commit 891f5b7

Please sign in to comment.