[arch-projects] [netctl][PATCH] Support dynamically appearing interfaces
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem). Add a parameter "DynamicProfileStart=" which, if enabled, makes the profile unit wanted by its interface unit (and not multi-user.target). --- docs/netctl.profile.5.txt | 4 ++++ src/netctl | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/netctl.profile.5.txt b/docs/netctl.profile.5.txt index efd4fb4..73d99f9 100644 --- a/docs/netctl.profile.5.txt +++ b/docs/netctl.profile.5.txt @@ -85,6 +85,10 @@ GENERAL OPTIONS A command that is executed after a connection is brought down. Similar precautions should be taken as with 'ExecUpPost'. +'DynamicProfileStart=':: + If ``yes`', the profile unit file is wanted by its interface unit file + instead of *multi-user.target*. This is needed if the interface + may appear dynamically (e. g. cell phone modem). IP OPTIONS ---------- diff --git a/src/netctl b/src/netctl index 498b50d..787a621 100755 --- a/src/netctl +++ b/src/netctl @@ -97,8 +97,18 @@ unit_enable() { if [[ -n $After ]]; then printf 'After="netctl@%s.service"\n' "${After[@]//\"/\\\"}" >> "$unit" fi - echo "ln -s '$unit' '${unit/system\//system/multi-user.target.wants/}'" - ln -s "$unit" "${unit/system\//system/multi-user.target.wants/}" + + local trigger="multi-user.target" + if is_yes "${DynamicProfileStart:-no}"; then + trigger="sys-subsystem-net-devices-${Interface/-/\\x2d}.device" + fi + + trigger="${unit/system\//system/$trigger.wants/}" + + echo "mkdir -p '$(dirname "$trigger")'" + mkdir -p "$(dirname "$trigger")" + echo "ln -s '$unit' '$trigger'" + ln -s "$unit" "$trigger" systemctl daemon-reload } -- 1.8.1.3
On Tue, Feb 12, 2013 at 1:40 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem).
Does this work? Is there a reason not to make the device the default trigger?
Add a parameter "DynamicProfileStart=" which, if enabled, makes the profile unit wanted by its interface unit (and not multi-user.target). --- docs/netctl.profile.5.txt | 4 ++++ src/netctl | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/docs/netctl.profile.5.txt b/docs/netctl.profile.5.txt index efd4fb4..73d99f9 100644 --- a/docs/netctl.profile.5.txt +++ b/docs/netctl.profile.5.txt @@ -85,6 +85,10 @@ GENERAL OPTIONS A command that is executed after a connection is brought down. Similar precautions should be taken as with 'ExecUpPost'.
+'DynamicProfileStart=':: + If ``yes`', the profile unit file is wanted by its interface unit file + instead of *multi-user.target*. This is needed if the interface + may appear dynamically (e. g. cell phone modem).
IP OPTIONS ---------- diff --git a/src/netctl b/src/netctl index 498b50d..787a621 100755 --- a/src/netctl +++ b/src/netctl @@ -97,8 +97,18 @@ unit_enable() { if [[ -n $After ]]; then printf 'After="netctl@%s.service"\n' "${After[@]//\"/\\\"}" >> "$unit" fi - echo "ln -s '$unit' '${unit/system\//system/multi-user.target.wants/}'" - ln -s "$unit" "${unit/system\//system/multi-user.target.wants/}" + + local trigger="multi-user.target" + if is_yes "${DynamicProfileStart:-no}"; then + trigger="sys-subsystem-net-devices-${Interface/-/\\x2d}.device" + fi + + trigger="${unit/system\//system/$trigger.wants/}" + + echo "mkdir -p '$(dirname "$trigger")'" + mkdir -p "$(dirname "$trigger")" + echo "ln -s '$unit' '$trigger'" + ln -s "$unit" "$trigger" systemctl daemon-reload }
-- 1.8.1.3
Am 14.02.2013 21:45, schrieb Jouke Witteveen:
On Tue, Feb 12, 2013 at 1:40 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem).
Does this work? Is there a reason not to make the device the default trigger?
That's an interesting question. You can always add a profile as a dependency to /etc/systemd/system/sys-subsystem-net-devices-FOO.device.wants/ and add BindsTo=sys-subsystem-net-devices-FOO.device so it goes down when the devices vanishes. This is actually pretty nice if you think about it. But do we really want that? Some people may say that they only want their devices going up when they launch multi-user.target, but not when they launch rescue.target. It's a matter you should consider carefully.
On Fri, Feb 15, 2013 at 10:40 AM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 14.02.2013 21:45, schrieb Jouke Witteveen:
On Tue, Feb 12, 2013 at 1:40 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem).
Does this work? Is there a reason not to make the device the default trigger?
That's an interesting question. You can always add a profile as a dependency to /etc/systemd/system/sys-subsystem-net-devices-FOO.device.wants/ and add BindsTo=sys-subsystem-net-devices-FOO.device so it goes down when the devices vanishes. This is actually pretty nice if you think about it.
But do we really want that? Some people may say that they only want their devices going up when they launch multi-user.target, but not when they launch rescue.target. It's a matter you should consider carefully.
Another option is to add everything to network.target.wants. Although that might be a better place, it doesn't really solve the initial problem. On the other hand: what is precisely the problem: the unit just times out and is not supposed to block anything.
Am 15.02.2013 12:43, schrieb Jouke Witteveen:
Another option is to add everything to network.target.wants.
Nope. network.target is not started by default and is quite mysterious anyway.
Although that might be a better place, it doesn't really solve the initial problem. On the other hand: what is precisely the problem: the unit just times out and is not supposed to block anything.
How is that related to the topic?
On Fri, Feb 15, 2013 at 1:08 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 12:43, schrieb Jouke Witteveen:
Another option is to add everything to network.target.wants.
Nope. network.target is not started by default and is quite mysterious anyway.
It is perhaps more understandable if network.target just wants all activated network configurations and multi-user.target wants network.target.
Although that might be a better place, it doesn't really solve the initial problem. On the other hand: what is precisely the problem: the unit just times out and is not supposed to block anything.
How is that related to the topic?
Part of the problem of Ivan Shapovalov I do not understand. If a profile is enabled and the interface does not appear, this should not delay anything.
Am 15.02.2013 13:11, schrieb Jouke Witteveen:
On Fri, Feb 15, 2013 at 1:08 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 12:43, schrieb Jouke Witteveen:
Another option is to add everything to network.target.wants.
Nope. network.target is not started by default and is quite mysterious anyway.
It is perhaps more understandable if network.target just wants all activated network configurations and multi-user.target wants network.target.
This isn't the case. network.target is ONLY activated when any service has Wants=/After=network.target to synchronize itself after the network start. All network services ususally have Before=network.target, without Wants= or Requires=. In short, network.target is only used as a synchronization point for services that require the network to be up.
Although that might be a better place, it doesn't really solve the initial problem. On the other hand: what is precisely the problem: the unit just times out and is not supposed to block anything.
How is that related to the topic?
Part of the problem of Ivan Shapovalov I do not understand. If a profile is enabled and the interface does not appear, this should not delay anything.
If a network interface doesn't appear and a network profile using it is activated, the service will wait for it until a timeout. This blocks the completion of multi-user.target. This likely won't be visible, but is undesirable.
On Fri, Feb 15, 2013 at 1:26 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 13:11, schrieb Jouke Witteveen:
On Fri, Feb 15, 2013 at 1:08 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 12:43, schrieb Jouke Witteveen:
Another option is to add everything to network.target.wants.
Nope. network.target is not started by default and is quite mysterious anyway.
It is perhaps more understandable if network.target just wants all activated network configurations and multi-user.target wants network.target.
This isn't the case. network.target is ONLY activated when any service has Wants=/After=network.target to synchronize itself after the network start. All network services ususally have Before=network.target, without Wants= or Requires=. In short, network.target is only used as a synchronization point for services that require the network to be up.
This implies we should drop Wants=network.target from netctl@.service and netctl-auto@.service.
Although that might be a better place, it doesn't really solve the initial problem. On the other hand: what is precisely the problem: the unit just times out and is not supposed to block anything.
How is that related to the topic?
Part of the problem of Ivan Shapovalov I do not understand. If a profile is enabled and the interface does not appear, this should not delay anything.
If a network interface doesn't appear and a network profile using it is activated, the service will wait for it until a timeout. This blocks the completion of multi-user.target. This likely won't be visible, but is undesirable.
Is this a consequence of DefaultDependencies=true (by default)? Otherwise, the netctl units do not enforce an ordering with regard to multi-user.target.
Am 15.02.2013 13:31, schrieb Jouke Witteveen:
On Fri, Feb 15, 2013 at 1:26 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 13:11, schrieb Jouke Witteveen:
On Fri, Feb 15, 2013 at 1:08 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 12:43, schrieb Jouke Witteveen:
Another option is to add everything to network.target.wants.
Nope. network.target is not started by default and is quite mysterious anyway.
It is perhaps more understandable if network.target just wants all activated network configurations and multi-user.target wants network.target.
This isn't the case. network.target is ONLY activated when any service has Wants=/After=network.target to synchronize itself after the network start. All network services ususally have Before=network.target, without Wants= or Requires=. In short, network.target is only used as a synchronization point for services that require the network to be up.
This implies we should drop Wants=network.target from netctl@.service and netctl-auto@.service.
Indeed, it's unnecessary.
If a network interface doesn't appear and a network profile using it is activated, the service will wait for it until a timeout. This blocks the completion of multi-user.target. This likely won't be visible, but is undesirable.
Is this a consequence of DefaultDependencies=true (by default)? Otherwise, the netctl units do not enforce an ordering with regard to multi-user.target.
Ordering on targets is implied by DefaultDependencies, yes. IMO, we should not override this. Loading a profile on an interface that doesn't exist is incorrect behaviour, we should not encourage it.
On 15 February 2013 13:26:39 Thomas Bächler wrote:
Am 15.02.2013 13:11, schrieb Jouke Witteveen:
On Fri, Feb 15, 2013 at 1:08 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 15.02.2013 12:43, schrieb Jouke Witteveen:
Another option is to add everything to network.target.wants.
Nope. network.target is not started by default and is quite mysterious anyway.
It is perhaps more understandable if network.target just wants all activated network configurations and multi-user.target wants network.target.
This isn't the case. network.target is ONLY activated when any service has Wants=/After=network.target to synchronize itself after the network start. All network services ususally have Before=network.target, without Wants= or Requires=. In short, network.target is only used as a synchronization point for services that require the network to be up.
Although that might be a better place, it doesn't really solve the initial problem. On the other hand: what is precisely the problem: the unit just times out and is not supposed to block anything.
How is that related to the topic?
Part of the problem of Ivan Shapovalov I do not understand. If a profile is enabled and the interface does not appear, this should not delay anything.
If a network interface doesn't appear and a network profile using it is activated, the service will wait for it until a timeout. This blocks the completion of multi-user.target. This likely won't be visible, but is undesirable.
The problem is that netctl units are Before=network.target, so anything that is After=network.target (e. g. samba and many other services) are delayed until the device and profile time out. So it is visible.
On 15 February 2013 10:40:52 Thomas Bächler wrote:
Am 14.02.2013 21:45, schrieb Jouke Witteveen:
On Tue, Feb 12, 2013 at 1:40 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem).
Does this work? Is there a reason not to make the device the default trigger? That's an interesting question. You can always add a profile as a dependency to /etc/systemd/system/sys-subsystem-net-devices-FOO.device.wants/ and add BindsTo=sys-subsystem-net-devices-FOO.device so it goes down when the devices vanishes. This is actually pretty nice if you think about it.
But do we really want that? Some people may say that they only want their devices going up when they launch multi-user.target, but not when they launch rescue.target. It's a matter you should consider carefully.
Yes, I also thought about that. Maybe adding RequisiteOverridable=multi- user.target will suffice?
On Fri, Feb 15, 2013 at 4:31 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
On 15 February 2013 10:40:52 Thomas Bächler wrote:
Am 14.02.2013 21:45, schrieb Jouke Witteveen:
On Tue, Feb 12, 2013 at 1:40 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem).
Does this work? Is there a reason not to make the device the default trigger? That's an interesting question. You can always add a profile as a dependency to /etc/systemd/system/sys-subsystem-net-devices-FOO.device.wants/ and add BindsTo=sys-subsystem-net-devices-FOO.device so it goes down when the devices vanishes. This is actually pretty nice if you think about it.
But do we really want that? Some people may say that they only want their devices going up when they launch multi-user.target, but not when they launch rescue.target. It's a matter you should consider carefully.
Yes, I also thought about that. Maybe adding RequisiteOverridable=multi- user.target will suffice?
Perhaps a really good solution would also take care of ifplugd, which has to go some day. Until such a solution comes around, I think this entire problem is best left for advanced users to tackle themselves. It is not trivial to get this right in netctl and it is easy for a knowledgeable user to fix things for this particular use-case. All that is needed is to move the symlink from multi-user.target.wants/ to some other directory, issue `systemctl daemon-reload` and everything should work as wanted. - Jouke
On 14 February 2013 21:45:52 Jouke Witteveen wrote:
On Tue, Feb 12, 2013 at 1:40 PM, Ivan Shapovalov <intelfx100@gmail.com> wrote:
If a profile is WantedBy=multi-user.target, it breaks init sequence if its interface is not immediately available at runtime (e. g. a cell-phone or USB modem).
Does this work? Is there a reason not to make the device the default trigger?
If you are asking about the patch, then it works. And what do you mean by "making the device the default trigger"?
Add a parameter "DynamicProfileStart=" which, if enabled, makes the profile unit wanted by its interface unit (and not multi-user.target). ---
docs/netctl.profile.5.txt | 4 ++++ src/netctl | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
Am 12.02.2013 13:40, schrieb Ivan Shapovalov:
diff --git a/docs/netctl.profile.5.txt b/docs/netctl.profile.5.txt index efd4fb4..73d99f9 100644 --- a/docs/netctl.profile.5.txt +++ b/docs/netctl.profile.5.txt @@ -85,6 +85,10 @@ GENERAL OPTIONS A command that is executed after a connection is brought down. Similar precautions should be taken as with 'ExecUpPost'.
+'DynamicProfileStart=':: + If ``yes`', the profile unit file is wanted by its interface unit file + instead of *multi-user.target*. This is needed if the interface + may appear dynamically (e. g. cell phone modem).
I'd name this differently. For example WantedBy=multi-user.target WantedBy=DEVICE WantedBy=foobar.target and make it default to multi-user.target. The special keyword DEVICE would make it start dynamically.
diff --git a/src/netctl b/src/netctl index 498b50d..787a621 100755 --- a/src/netctl +++ b/src/netctl @@ -97,8 +97,18 @@ unit_enable() { if [[ -n $After ]]; then printf 'After="netctl@%s.service"\n' "${After[@]//\"/\\\"}" >> "$unit" fi - echo "ln -s '$unit' '${unit/system\//system/multi-user.target.wants/}'" - ln -s "$unit" "${unit/system\//system/multi-user.target.wants/}" + + local trigger="multi-user.target" + if is_yes "${DynamicProfileStart:-no}"; then + trigger="sys-subsystem-net-devices-${Interface/-/\\x2d}.device" + fi
'Interface' is incorrect, if I remember right, this should be derived from BindsToInterfaces - but I am unsure whether that is a good idea, because BindsToInterfaces could have more than one value. It might still be worth doing it, for example: Try to bring up a bridge once one of the interfaces appears. But then, one should rather implement a system where the bridge is brought up and interfaces are dynamically added and removed as they appear.
+ + trigger="${unit/system\//system/$trigger.wants/}" + + echo "mkdir -p '$(dirname "$trigger")'" + mkdir -p "$(dirname "$trigger")" + echo "ln -s '$unit' '$trigger'" + ln -s "$unit" "$trigger" systemctl daemon-reload }
participants (3)
-
Ivan Shapovalov
-
Jouke Witteveen
-
Thomas Bächler