libnm-core: add nm_connection_is_virtual()

Add a method to determine if a connection applies to a virtual device.

Perhaps eventually the logic should be spread across the NMSetting
classes, but for now it's better off having it in NMConnection than
once in NMManager and once in nmcli.
This commit is contained in:
Dan Winship 2014-08-04 16:27:43 -04:00
parent ab26964c56
commit ee3467e531
5 changed files with 79 additions and 88 deletions

View file

@ -1861,30 +1861,6 @@ activate_connection_cb (NMClient *client, NMActiveConnection *active, GError *er
g_free (info);
}
/* We were using nm_connection_get_virtual_iface_name() to determine whether the
* connection is virtual or not. But it did't work for VLANs without
* vlan.interface-name. nm_connection_get_virtual_iface_name() returns NULL for those.
* So we need to use our own implementation for now.
*/
static gboolean
is_connection_virtual (NMConnection *connection)
{
if ( nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
|| nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
|| nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)
|| nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
return TRUE;
if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
NMSettingInfiniband *s_infi = nm_connection_get_setting_infiniband (connection);
int p_key = nm_setting_infiniband_get_p_key (s_infi);
const char *parent = nm_setting_infiniband_get_parent (s_infi);
if (p_key != -1 && parent)
return TRUE;
}
return FALSE;
}
static gboolean
nmc_activate_connection (NmCli *nmc,
NMConnection *connection,
@ -1907,7 +1883,7 @@ nmc_activate_connection (NmCli *nmc,
device_found = find_device_for_connection (nmc, connection, ifname, ap, nsp, &device, &spec_object, &local);
/* Virtual connection may not have their interfaces created yet */
if (!device_found && !is_connection_virtual (connection)) {
if (!device_found && !nm_connection_is_virtual (connection)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_CON_ACTIVATION,
"%s", local && local->message ? local->message : _("unknown error"));
g_clear_error (&local);

View file

@ -1473,6 +1473,40 @@ nm_connection_get_connection_type (NMConnection *connection)
return nm_setting_connection_get_connection_type (s_con);
}
/**
* nm_connection_is_virtual:
* @connection: an #NMConnection
*
* Checks if @connection refers to a virtual device (and thus can potentially be
* activated even if the device it refers to doesn't exist).
*
* Returns: whether @connection refers to a virtual device
*/
gboolean
nm_connection_is_virtual (NMConnection *connection)
{
const char *type;
type = nm_connection_get_connection_type (connection);
g_return_val_if_fail (type != NULL, FALSE);
if ( !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
|| !strcmp (type, NM_SETTING_TEAM_SETTING_NAME)
|| !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)
|| !strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
return TRUE;
if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
NMSettingInfiniband *s_ib;
s_ib = nm_connection_get_setting_infiniband (connection);
g_return_val_if_fail (s_ib != NULL, FALSE);
return nm_setting_infiniband_get_virtual_interface_name (s_ib) != NULL;
}
return FALSE;
}
/**
* nm_connection_get_virtual_device_description:
* @connection: an #NMConnection for a virtual device type

View file

@ -217,6 +217,7 @@ const char * nm_connection_get_uuid (NMConnection *connection);
const char * nm_connection_get_id (NMConnection *connection);
const char * nm_connection_get_connection_type (NMConnection *connection);
gboolean nm_connection_is_virtual (NMConnection *connection);
char * nm_connection_get_virtual_device_description (NMConnection *connection);
NMSetting8021x * nm_connection_get_setting_802_1x (NMConnection *connection);

View file

@ -118,6 +118,7 @@ global:
nm_connection_get_uuid;
nm_connection_get_virtual_device_description;
nm_connection_is_type;
nm_connection_is_virtual;
nm_connection_need_secrets;
nm_connection_normalize;
nm_connection_remove_setting;

View file

@ -961,89 +961,68 @@ get_virtual_iface_name (NMManager *self,
NMDevice **out_parent)
{
NMDevice *parent = NULL;
const char *ifname;
if (out_parent)
*out_parent = NULL;
if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
return g_strdup (nm_connection_get_interface_name (connection));
if (!nm_connection_is_virtual (connection))
return NULL;
if (nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME))
return g_strdup (nm_connection_get_interface_name (connection));
if (nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
return g_strdup (nm_connection_get_interface_name (connection));
ifname = nm_connection_get_interface_name (connection);
if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) {
NMSettingVlan *s_vlan;
const char *ifname;
char *vname;
s_vlan = nm_connection_get_setting_vlan (connection);
g_return_val_if_fail (s_vlan != NULL, NULL);
parent = find_vlan_parent (self, connection);
if (parent) {
ifname = nm_connection_get_interface_name (connection);
if (!parent)
return NULL;
if (!nm_device_supports_vlans (parent)) {
nm_log_warn (LOGD_DEVICE, "(%s): No support for VLANs on interface %s of type %s",
ifname ? ifname : nm_connection_get_id (connection),
nm_device_get_ip_iface (parent),
nm_device_get_type_desc (parent));
return NULL;
}
/* If the connection doesn't specify the interface name for the VLAN
* device, we create one for it using the VLAN ID and the parent
* interface's name.
*/
if (ifname)
vname = g_strdup (ifname);
else {
vname = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent),
nm_setting_vlan_get_id (s_vlan));
}
if (out_parent)
*out_parent = parent;
return vname;
if (!nm_device_supports_vlans (parent)) {
nm_log_warn (LOGD_DEVICE, "(%s): No support for VLANs on interface %s of type %s",
ifname ? ifname : nm_connection_get_id (connection),
nm_device_get_ip_iface (parent),
nm_device_get_type_desc (parent));
return NULL;
}
}
if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
parent = find_infiniband_parent (self, connection);
if (parent) {
NMSettingInfiniband *s_infiniband;
s_infiniband = nm_connection_get_setting_infiniband (connection);
if (out_parent)
*out_parent = parent;
return g_strdup (nm_setting_infiniband_get_virtual_interface_name (s_infiniband));
/* If the connection doesn't specify the interface name for the VLAN
* device, we create one for it using the VLAN ID and the parent
* interface's name.
*/
if (ifname)
vname = g_strdup (ifname);
else {
vname = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent),
nm_setting_vlan_get_id (s_vlan));
}
if (out_parent)
*out_parent = parent;
return vname;
}
return NULL;
}
static gboolean
connection_needs_virtual_device (NMConnection *connection)
{
if ( nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
|| nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
|| nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)
|| nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME))
return TRUE;
if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) {
NMSettingInfiniband *s_infiniband;
parent = find_infiniband_parent (self, connection);
if (!parent)
return NULL;
s_infiniband = nm_connection_get_setting_infiniband (connection);
g_return_val_if_fail (s_infiniband != NULL, FALSE);
if (nm_setting_infiniband_get_p_key (s_infiniband) != -1)
return TRUE;
if (out_parent)
*out_parent = parent;
return g_strdup (nm_setting_infiniband_get_virtual_interface_name (s_infiniband));
}
return FALSE;
/* For any other virtual connection, NMSettingConnection:interface-name is
* the virtual device name.
*/
g_return_val_if_fail (ifname != NULL, NULL);
return g_strdup (ifname);
}
/***************************/
@ -1149,7 +1128,7 @@ system_create_virtual_devices (NMManager *self)
NMConnection *connection = iter->data;
/* We only create a virtual interface if the connection can autoconnect */
if ( connection_needs_virtual_device (connection)
if ( nm_connection_is_virtual (connection)
&& nm_settings_connection_can_autoconnect (NM_SETTINGS_CONNECTION (connection)))
system_create_virtual_device (self, connection);
}
@ -1163,7 +1142,7 @@ connection_added (NMSettings *settings,
{
NMConnection *connection = NM_CONNECTION (settings_connection);
if (connection_needs_virtual_device (connection)) {
if (nm_connection_is_virtual (connection)) {
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
@ -2439,7 +2418,7 @@ find_master (NMManager *self,
NMConnection *candidate = iter->data;
char *vname;
if (connection_needs_virtual_device (candidate)) {
if (nm_connection_is_virtual (candidate)) {
vname = get_virtual_iface_name (self, candidate, NULL);
if ( g_strcmp0 (master, vname) == 0
&& is_compatible_with_slave (candidate, connection))
@ -2620,7 +2599,7 @@ ensure_master_active_connection (NMManager *self,
/* Device described by master_connection may be a virtual one that's
* not created yet.
*/
if (!found_device && connection_needs_virtual_device (master_connection)) {
if (!found_device && nm_connection_is_virtual (master_connection)) {
master_ac = nm_manager_activate_connection (self,
master_connection,
NULL,
@ -2679,7 +2658,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
device = nm_active_connection_get_device (active);
if (!device) {
if (!connection_needs_virtual_device (connection)) {
if (!nm_connection_is_virtual (connection)) {
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
@ -3109,7 +3088,7 @@ validate_activation_request (NMManager *self,
goto error;
}
} else {
gboolean is_software = connection_needs_virtual_device (connection);
gboolean is_software = nm_connection_is_virtual (connection);
/* VPN and software-device connections don't need a device yet */
if (!vpn && !is_software) {