Skip to content
This repository has been archived by the owner on Jun 25, 2023. It is now read-only.

Make IP determination platform-agnostic and a bit more flexible #114

Closed
Werelds opened this issue May 19, 2015 · 7 comments
Closed

Make IP determination platform-agnostic and a bit more flexible #114

Werelds opened this issue May 19, 2015 · 7 comments

Comments

@Werelds
Copy link

Werelds commented May 19, 2015

I’ve been using Landrush for a Vagrant setup for a while now, works pretty well. Today I had a case where I needed Landrush to use a specific interface’s IP..which is set to DHCP so I can’t specify the IP in the configuration.

After some digging, I found out that the IP is currently determined by picking the last IP address returned by hostname -I. Not only is that not entirely portable, it's also a bit rigid. Given that there is no 100% portable manner of doing this, I started to look at some options.

It didn't take long until I had a working prototype written in about 50 lines of Go (see here). No cgo involved, so it can be cross-compiled to all platforms without issues. Without any arguments it does the exact same thing hostname -I does - list out interface's addresses in order. Give it an argument and it'll only return the given NIC's address. On any error it returns a non-zero exit code just like hostname. This would also allow us to have an option to specify the interface to use; something like vagrant.landrush.nic = 'eth1'.

I'm not sure what the best way to distribute the binaries would be (they range from 1.9 to 2.5 megabytes depending on the target platform), download them on demand would be most efficient obviously.

I think this method would help to make things a bit more flexible; obviously this is a very minimal example too, as I kept the code to a minimum, but it could easily be expanded. Wildcard matching on either NIC name or address could easily be added for example.

@njam
Copy link
Contributor

njam commented May 19, 2015

Using a custom tool sounds good because programs like hostname, ip addr or ifconfig behave quite differently across linux distributions.

But I can't think of a good way how to distribute such a binary onto the VM. Probably @phinze knows more.

Here's a similar project: https://pypi.python.org/pypi/netifaces/

Maybe there's also a way using shell scripting? That would require some research on how the above programs behave on different platforms.

@Werelds
Copy link
Author

Werelds commented May 19, 2015

Yeah, my main question is whether it's possible to download a file onto the VM via the Vagrant library without having to rely on curl or wget being present.

It can be done with the shell too, but you never know which one is actually present; just like neither curl nor wget might be present, you'd have to test whether to use ip or ifconfig (or even ipconfig for a Windows guest for example). And parsing their input, as you rightfully pointed out, is a lot trickier because the format differs between versions (aside from it being more verbose than necessary for this specific use). That's what lead me to trying to do it via Go, because it is easy to cross compile and the stdlib has got a lot of this stuff already built in.

The most complicated part of this route would be determining which binary to use. Go supports them all but obviously a binary compiled for linux/i386 won't work on darwin/amd64.

I've done a little digging and I think the shell provisioner actually does roughly the same (please do correct me if I'm wrong, I know some Ruby but I'm far from an expert). Downloading the file to the host can be done via Vagrant::Util::Downloader, after which the file can be uploaded via Vagrant::Plugin::V2::Communicator.upload (so that's via machine.communicate.tap).

@njam
Copy link
Contributor

njam commented May 20, 2015

Ok, that sounds like a plan! Let's see if @phinze thinks it's a reasonable scenario.

@ahpook
Copy link

ahpook commented May 20, 2015

As someone who maintains a project that is responsible for finding tidbits of information about different operating systems, let me advise some caution -- this is one of those problems that seems really trivial when you start out and then balloons in complexity really quickly.

I'd suggest using ohai either as a library or vendored CLI tool rather than re-inventing this wheel, since it's a pure-ruby implementation that has a deep history of OS knowledge.

As far as getting info back into landrush... I need to read up on that a bit. There are mechanisms inside the Vagrant 'provisioner' classes to mount shares and run programs inside the VM as it's being brought up so that would be a pretty handy thing to use, but I don't know if those happen too early/too late in the bootstrapping process to help us.

@Werelds
Copy link
Author

Werelds commented May 25, 2015

I'm well aware of that, but that's one of the reasons I looked at Go. Doing this in C/CPP would've been an option too, but as you said you quickly run into the endless variations and differences between systems. That's exactly what Go deals with in most of its stdlib though. If you look at the source (http://golang.org/src/net/ - it's the interface_* files we're interested in) you'll see that there's abstractions for most platforms. I think what I'm suggesting is not that far fetched, especially since we're not attempting to resolve anything. We only need to enumerate IP addresses, not resolve a hostname or determine the "primary" IP.

You've got the abstractions in Facter too, but you take it a step further by attempting to reliably determine the primary NIC amongst others.

Ohai could be an option, but I think the fact that it depends on Ruby goes against portability a lot.

@phinze
Copy link
Contributor

phinze commented May 26, 2015

FWIW I think it's worth giving this a shot w/ Go.

Your cautions are well heard, @ahpook - this is the sort of area where a lot of existing hard work has been done. I think we should keep something like ohai in our back pocket in case this gets hairy.

But I think because we're focused on answering a single question here rather than a generalized set of questions, that the relatively lightweight / single-binary simplicity of a Go solution is worth seeing if we can achieve.

@Werelds
Copy link
Author

Werelds commented Aug 15, 2015

@phinze @njam I've opened a preliminary pull request - will comment in a minute with other potential features we can consider (it's very bare bones at the moment and I'm 99% sure that my approach to Ruby has flaws :P).

hferentschik pushed a commit to hferentschik/landrush that referenced this issue May 13, 2016
…ntroducing landrush-ip

- Adding an 'interface' setting to config
hferentschik added a commit to hferentschik/landrush that referenced this issue May 13, 2016
@hferentschik hferentschik added this to the v.1.1.0 milestone May 17, 2016
hferentschik pushed a commit that referenced this issue Jun 22, 2016
… on landrush-ip

- Adding Cucumber tests for the landrush-ip integration
hferentschik added a commit to hferentschik/landrush that referenced this issue Jun 30, 2016
hferentschik added a commit to hferentschik/landrush that referenced this issue Jun 30, 2016
hferentschik added a commit to hferentschik/landrush that referenced this issue Jun 30, 2016
hferentschik added a commit to hferentschik/landrush that referenced this issue Jun 30, 2016
hferentschik added a commit to hferentschik/landrush that referenced this issue Jul 1, 2016
hferentschik added a commit to hferentschik/landrush that referenced this issue Jul 1, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants