core: add "real" NMDevice property
authorDan Williams <dcbw@redhat.com>
Fri, 5 Sep 2014 13:50:02 +0000 (08:50 -0500)
committerThomas Haller <thaller@redhat.com>
Fri, 4 Dec 2015 11:15:12 +0000 (12:15 +0100)
This property is TRUE for devices that exist either as a kernel device
or are backed by some other resource (eg, ModemManager object, Bluez
device, etc).  It will eventually be FALSE for software devices that
are not yet instantiated.

introspection/nm-device.xml
src/devices/nm-device.c
src/devices/nm-device.h
src/settings/nm-settings.c

index fd377a0..cf04ac8 100644 (file)
         LLDP TLV names to variant boxed values.
       </tp:docstring>
     </property>
+    <property name="Real" type="b" access="read">
+      <tp:docstring>
+        True if the device exists, or False for placeholder devices that
+        do not yet exist but could be automatically created by NetworkManager
+        if one of their AvailableConnections was activated.
+      </tp:docstring>
+    </property>
 
     <method name="Disconnect">
       <tp:docstring>
index 54b0253..d55493f 100644 (file)
@@ -129,6 +129,7 @@ enum {
        PROP_HAS_PENDING_ACTION,
        PROP_METERED,
        PROP_LLDP_NEIGHBORS,
+       PROP_REAL,
        LAST_PROP
 };
 
@@ -207,6 +208,7 @@ typedef struct {
        char *        udi;
        char *        iface;   /* may change, could be renamed by user */
        int           ifindex;
+       gboolean      real;
        char *        ip_iface;
        int           ip_ifindex;
        NMDeviceType  type;
@@ -559,12 +561,33 @@ nm_device_get_ifindex (NMDevice *self)
        return NM_DEVICE_GET_PRIVATE (self)->ifindex;
 }
 
+/**
+ * nm_device_is_software:
+ * @self: the #NMDevice
+ *
+ * Indicates if the device is a software-based virtual device without
+ * backing hardware, which can be added and removed programmatically.
+ *
+ * Returns: %TRUE if the device is a software-based device
+ */
 gboolean
 nm_device_is_software (NMDevice *self)
 {
        return NM_FLAGS_HAS (NM_DEVICE_GET_PRIVATE (self)->capabilities, NM_DEVICE_CAP_IS_SOFTWARE);
 }
 
+/**
+ * nm_device_is_real:
+ * @self: the #NMDevice
+ *
+ * Returns: %TRUE if the device exists, %FALSE if the device is a placeholder
+ */
+gboolean
+nm_device_is_real (NMDevice *self)
+{
+       return NM_DEVICE_GET_PRIVATE (self)->real;
+}
+
 const char *
 nm_device_get_ip_iface (NMDevice *self)
 {
@@ -1829,6 +1852,9 @@ setup (NMDevice *self, NMPlatformLink *plink)
                        device_set_master (self, master);
        }
 
+       priv->real = TRUE;
+       g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
+
        g_object_thaw_notify (G_OBJECT (self));
 }
 
@@ -2445,7 +2471,7 @@ device_has_config (NMDevice *self)
                return TRUE;
 
        /* The existence of a software device is good enough. */
-       if (nm_device_is_software (self))
+       if (nm_device_is_software (self) && nm_device_is_real (self))
                return TRUE;
 
        /* Slaves are also configured by definition */
@@ -6489,7 +6515,7 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex)
                return;
        if (priv->queued_act_request)
                return;
-       if (!nm_device_is_software (self))
+       if (!nm_device_is_software (self) || !nm_device_is_real (self))
                return;
        if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED)
                return;
@@ -6602,10 +6628,10 @@ impl_device_delete (NMDevice *self, GDBusMethodInvocation *context)
 {
        GError *error = NULL;
 
-       if (!nm_device_is_software (self)) {
+       if (!nm_device_is_software (self) || !nm_device_is_real (self)) {
                error = g_error_new_literal (NM_DEVICE_ERROR,
                                             NM_DEVICE_ERROR_NOT_SOFTWARE,
-                                            "This device is not a software device");
+                                            "This device is not a software device or is not realized");
                g_dbus_method_invocation_take_error (context, error);
                return;
        }
@@ -10149,6 +10175,9 @@ get_property (GObject *object, guint prop_id,
                        g_value_take_variant (value, g_variant_builder_end (&array_builder));
                }
                break;
+       case PROP_REAL:
+               g_value_set_boolean (value, priv->real);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -10439,6 +10468,13 @@ nm_device_class_init (NMDeviceClass *klass)
                                       G_PARAM_READABLE |
                                       G_PARAM_STATIC_STRINGS));
 
+       g_object_class_install_property
+               (object_class, PROP_REAL,
+                g_param_spec_boolean (NM_DEVICE_REAL, "", "",
+                                      FALSE,
+                                      G_PARAM_READABLE |
+                                      G_PARAM_STATIC_STRINGS));
+
        /* Signals */
        signals[STATE_CHANGED] =
                g_signal_new ("state-changed",
index 704ef6e..8931b85 100644 (file)
@@ -59,6 +59,7 @@
 #define NM_DEVICE_HW_ADDRESS       "hw-address"
 #define NM_DEVICE_METERED          "metered"
 #define NM_DEVICE_LLDP_NEIGHBORS  "lldp-neighbors"
+#define NM_DEVICE_REAL             "real"
 
 #define NM_DEVICE_TYPE_DESC        "type-desc"      /* Internal only */
 #define NM_DEVICE_RFKILL_TYPE      "rfkill-type"    /* Internal only */
@@ -326,6 +327,7 @@ const char *        nm_device_get_udi               (NMDevice *dev);
 const char *   nm_device_get_iface             (NMDevice *dev);
 int             nm_device_get_ifindex  (NMDevice *dev);
 gboolean        nm_device_is_software   (NMDevice *dev);
+gboolean        nm_device_is_real       (NMDevice *dev);
 const char *   nm_device_get_ip_iface  (NMDevice *dev);
 int             nm_device_get_ip_ifindex(NMDevice *dev);
 const char *   nm_device_get_driver    (NMDevice *dev);
index d742333..3ba5b5d 100644 (file)
@@ -1854,13 +1854,20 @@ default_wired_clear_tag (NMSettings *self,
                nm_config_set_no_auto_default_for_device (NM_SETTINGS_GET_PRIVATE (self)->config, device);
 }
 
-void
-nm_settings_device_added (NMSettings *self, NMDevice *device)
+static void
+device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
 {
        NMConnection *connection;
        NMSettingsConnection *added;
        GError *error = NULL;
 
+       if (!nm_device_is_real (device))
+               return;
+
+       g_signal_handlers_disconnect_by_func (device,
+                                             G_CALLBACK (device_realized),
+                                             self);
+
        /* If the device isn't managed or it already has a default wired connection,
         * ignore it.
         */
@@ -1898,11 +1905,27 @@ nm_settings_device_added (NMSettings *self, NMDevice *device)
                     nm_settings_connection_get_id (added));
 }
 
+void
+nm_settings_device_added (NMSettings *self, NMDevice *device)
+{
+       if (nm_device_is_real (device))
+               device_realized (device, NULL, self);
+       else {
+               g_signal_connect_after (device, "notify::" NM_DEVICE_REAL,
+                                       G_CALLBACK (device_realized),
+                                       self);
+       }
+}
+
 void
 nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting)
 {
        NMSettingsConnection *connection;
 
+       g_signal_handlers_disconnect_by_func (device,
+                                             G_CALLBACK (device_realized),
+                                             self);
+
        connection = g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG);
        if (connection) {
                default_wired_clear_tag (self, device, connection, FALSE);