Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/iperf: Init the module #44134

Merged
merged 1 commit into from Sep 6, 2018
Merged

nixos/iperf: Init the module #44134

merged 1 commit into from Sep 6, 2018

Conversation

dasJ
Copy link
Member

@dasJ dasJ commented Jul 26, 2018

Motivation for this change

I'd like to have a NixOS module for iperf3, because it's supposed to run on my router as a daemon.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Fits CONTRIBUTING.md.

@teto
Copy link
Member

teto commented Jul 27, 2018

it might be best to name it iperf3 to remove the confusion on version number. There should be an option to pass arbitrary flags too.

@dasJ
Copy link
Member Author

dasJ commented Jul 27, 2018

@teto Rebased and fixed

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat! I've wanted an iperf module for a while :)

description = "Path to the configuration file containing authorized users credentials to run iperf tests";
};
extraFlags = mkOption {
type = types.listOf types.string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use types.str instead of types.string in all of the options.

};

script = ''
exec ${pkgs.iperf3}/bin/iperf \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can put a multiline command invocation into serviceConfig.ExecStart, so no need to use script + exec here

after = [ "network.target" ];

serviceConfig = {
Type = "simple";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"simple" is the default

script = ''
exec ${pkgs.iperf3}/bin/iperf \
--server \
--pidfile /run/iperf3/iperf.pid \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is preferred to not use PID files if not necessary, which is probably the case here, because iperf runs in the foreground by default, which is good.

RuntimeDirectory = "iperf3";
PIDFile = "/run/iperf3/iperf.pid";
PrivateDevices = true;
CapabilityBoundingSet = "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does an empty string do here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From systemd.exec(5):

If this option is not used, the capability bounding set is not modified on process execution, hence no limits on the capabilities of the process are enforced.

and:

If the empty string is assigned to this option, the bounding set is reset to the empty capability set, and all prior settings have no effect.

extraFlags = mkOption {
type = types.listOf types.string;
default = [ ];
description = "Extra flags to pass to iperf3(1)";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the descriptions should end with a colon.

description = "Emit debugging output";
};
rsaPrivateKey = mkOption {
type = types.nullOr types.string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can make the type types.path here, which forces it to be an absolute one (starting with "/"). Same for authorizedUsersFile

affinity = mkOption {
type = types.nullOr types.string;
default = null;
description = "CPU affinity for the process";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add an example = "4,5"; here and explain the syntax in short in the description.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The n,m syntax is only valid for the client, so I guess this wouldn't make too much sense.

${optionalString cfg.verbose "--verbose"} \
${optionalString cfg.debug "--debug"} \
${optionalString cfg.forceFlush "--forceflush"} \
${toString cfg.extraFlags}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use lib.escapeShellArgs cfg.extraFlags here, which handles escaping correctly.

api = {
enable = mkEnableOption "iperf3 network throughput testing server";
port = mkOption {
type = types.int;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use the newish types.ints.u16 to prevent people trying to assign a port outside of the valid range (have seen people do this)

@dasJ
Copy link
Member Author

dasJ commented Jul 30, 2018

@infinisil Fixed and rebased

description = "Emit debugging output.";
};
rsaPrivateKey = mkOption {
type = types.nullOr types.str;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types.str -> types.path

description = "Server port to listen on for iperf3 client requsts.";
};
affinity = mkOption {
type = types.nullOr types.str;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so yeah the n/m syntax doesn't make sense for the server, so only the n syntax does, which means the only valid values are integers, so I think this option should be adjusted to reflect that (and make the correct conversion with toString in the exec script).

description = "Path to the configuration file containing authorized users credentials to run iperf tests.";
};
extraFlags = mkOption {
type = types.listOf types.path;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types.path -> types.str

};
in {
options.services.iperf3 = api;
config = lib.mkIf cfg.enable imp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lib.mkIf -> mkIf

@dasJ
Copy link
Member Author

dasJ commented Aug 19, 2018

@infinisil Fixed and rebased

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@infinisil
Copy link
Member

infinisil commented Aug 19, 2018

Although, one thing I'm not so sure about: Is it really a good idea have this under the services.iperf3 instead of services.iperf?

Because the default iperf version is 3 already. I'm not sure about @teto's reasoning, but I'd be in favor of using services.iperf.

@dasJ
Copy link
Member Author

dasJ commented Aug 26, 2018

I personally prefer services.iperf as well, because it's the default version. Similar to grub 2 which is the default everywhere

@dasJ
Copy link
Member Author

dasJ commented Sep 6, 2018

So what's the matter with the name @teto @infinisil ?

@teto
Copy link
Member

teto commented Sep 6, 2018

I get bitten by the "man iperf" that doesn't work after a nix-shell -p iperf (it is man iperf3). Also with iperf you don't know which one you are running (flags are similar) while the codebases are completely different. And it seems iperf2 development resumed. As I work with both I tend to appreciate an accurate naming but don't mind me. The PR has been there long enough. In worst case, I can alias it ;)

@dasJ
Copy link
Member Author

dasJ commented Sep 6, 2018

@teto I rebased the PR to master again. Also, I changed the filename to iperf3.nix in case anyone will implement a iperf2 module as well.

@infinisil infinisil merged commit aed92ec into NixOS:master Sep 6, 2018
@dasJ
Copy link
Member Author

dasJ commented Sep 6, 2018

Aahh, Thank you!

@dasJ dasJ deleted the iperf branch September 6, 2018 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants