Multiple machines on the same ip address

Hello,

I’m a little confused how I should specify the list of hosts (inventory) when all my machines are accessible via a single IP address with different ports (it’s a private cloud with multiple VMs).
Something like:

[webservers]
private.cloud.ip.address:8000
private.cloud.ip.address:8001

private.cloud.ip.address:8002

doesn’t seem to work.

Any ideas?

SSH forwarded and such? Yeah, right now, I’m pretty sure that won’t work. If those are all SSH forwarded, you could run ansible from private.cloud.ip.address in the interim, if possible.

Presently, you can specify the port, but can’t alias the machines. The proposal has been to extend the YAML inventory format for this purpose to be able to represent extra variables
like the host alias, default user, etc. This is actually the next big development item on my list, and I’m probably going to tackle this today.

Here’s the YAML format:

http://ansible.github.com/patterns.html#advanced-inventory-file-format
(the main feature of this format being it supports group variables and may support includes and groups of groups in the future)

but really, I’d like to be able to use this in the simple format myself too.

I think we could easily expess most everything in the non-YAML inventory format too, like this:

[webservers]
private.cloud.ip.address:8000
private.cloud.ip.address:8001
private.cloud.ip.address:8002
private.cloud.ip.address:8003 alias=clyde user=pacman sudo=True

I think for most people needing a host in only one group, that would be sufficient.

Stay tuned on this, should have something fairly soon.

–Michael

We allow expression of all needed variables like so:

[webservers]
host1
host1:8002 with alias=clydge user=pacman sudo=True somevar=asdf

We allow group wide variables to be applied a simple format, and try to parse the line values as JSON to support very basic lists and hashes

[webservers:vars]
backup=backup.example.com
alist=[‘a,’,b’,‘c’,'d]

While it’s not beautiful, if you need to support nested vars, you actually DON’T need to do it in this file, because you could do this in a playbook (note: need a solution for multiple groups):

vars_files:

  • /some/file/group_vars/{{ $group_name[0] }}

And in /some/file/group_vars/group_name:

  • somevar:
    a=2
    b:
    one:foo
    two:bar

etc

And of course we could also have groups of groups

[webservers]
group=webservers-phx
group=webservers-rdu

In this case, the YAML inventory format technically wouldn’t need to exist. I’m not saying we should get rid of it, but…
It seems best to have one way to do things, and YAML is fiddly. (Does having two formats feel weird to anyone?)

We allow expression of all needed variables like so:

[webservers]
host1
host1:8002 with alias=clydge user=pacman sudo=True somevar=asdf

We allow group wide variables to be applied a simple format, and try to parse the line values as JSON to support very basic lists and hashes

[webservers:vars]
backup=backup.example.com
alist=[‘a,’,b’,‘c’,'d]

While it’s not beautiful, if you need to support nested vars, you actually DON’T need to do it in this file, because you could do this in a playbook (note: need a solution for multiple groups):

vars_files:

  • /some/file/group_vars/{{ $group_name[0] }}

And in /some/file/group_vars/group_name:

  • somevar:
    a=2
    b:
    one:foo
    two:bar

etc

And of course we could also have groups of groups

[webservers]
group=webservers-phx
group=webservers-rdu

In this case, the YAML inventory format technically wouldn’t need to exist. I’m not saying we should get rid of it, but…
It seems best to have one way to do things, and YAML is fiddly. (Does having two formats feel weird to anyone?)

I also think that only one format should exist, but, while I’m not a fan of YAML myself, since everything else is written in that format maybe for this case YAML should also be used? (for consistency’s sake)

===

To put it all together, this might be a real world inventory config:

groups

[webservers-phx]
host1:8008 somevar=1234 othervar=5678
host2
host3
host4

[webservers-rdu]
host5
host6
host7
host9

groups of groups (could be defined, first, won’t matter)

[us:children]
rdu
phx

[rdu:children]
webservers-rdu
dbservers-rdu

[phx:children]
webservers-phx
dbservers-phx

[webservers:children]
webservers-phx
webservers-rdu

begin group variables

[rdu:vars]
backup=backup.rdu.example.com
ntp=ntp.rdu.example.com

[phx:vars]
backup=backup.phx.example.com
ntp=ntp.phx.exaple.com

[webservers:vars]
http_port=80

[all:vars]
sudo=True
ansible_ssh_port: 5150

I’m going to take a stab at this, probably using config parser, it certainly is 100% backwards compat with the old inventory format.

–Michael

As long as I can have the same hostname/ip with different ports and be treated like different machines, it’s ok for my use case:

[webservers]
private.cloud.ip.address:8000 <— this is VM1
private.cloud.ip.address:8001 <— this is VM2

I also think that only one format should exist, but, while I’m not a fan of YAML myself, since everything else is written in that format maybe for this case YAML should also be used? (for consistency’s sake)

Yeah, I think it presents a too high barrier for entry.

I can think ok in YAML when I’m doing play books (there is a small level of hierarchy), but I want to write as little of it as possible. Debugging long YAML files is difficult.

As long as I can have the same hostname/ip with different ports and be treated like different machines, it’s ok for my use case:

[webservers]
private.cloud.ip.address:8000 <— this is VM1
private.cloud.ip.address:8001 <— this is VM2

This is what the alias=foo was intended to be on each line. Yes.

It's weird. If anything, I'd be in favor of getting rid of the old
ad-hoc format. To use ansible for more than a one-off job, you need to
learn YAML anyway. I wrote the inventory for two reasons: to use per
host defined vars in a straightforward way and because of the
uniformity with the rest of ansible. Plus it's pretty syntax
highlighted. The simplest form is also simple:

It's weird. If anything, I'd be in favor of getting rid of the old
ad-hoc format. To use ansible for more than a one-off job, you need to
learn YAML anyway. I wrote the inventory for two reasons: to use per
host defined vars in a straightforward way and because of the
uniformity with the rest of ansible. Plus it's pretty syntax
highlighted. The simplest form is also simple:

While the simplest form of the YAML format is simple. I think the way of representing group and host vars doesn't quite work with my brain. Long ago I swore I wasn't going to force YAML configuration files on people again, and I'm kind of doing it. I strongly dislike that, presently, the YAML mode is the only way to do complex things with the configuration, and we're on the edge of adding more to it. YAML is a format where it is easy to make errors which render your configuration not working. I am accepting of that when doing playbooks, because there is a minor level of nesting, but this nesting should not be necessary to express inventory.

Either way, changing topics, making changes in the inventory code is becoming difficult, so I'm going to be working on another rev of the inventory code to make it a bit more OO, while still keeping the interface that is exposed to ansible and ansible-playbooks compatible.

We need a Inventory() class that just represents Inventory, in terms of Group objects and Host objects. These need
methods on each class, with variables on each host, and variables on each group.

You should be able to call a method on each host and get variables, etc. It shouldn't be using low level data structures.

Then we have another file that contains the parser, and produces an Inventory object that can be asked Host and Group questions.

The Inventory object should support a serialize method that dumps the configuration back out too -- so if I wanted to shoot other code in the head, and make it possible to implement cobbler integration in terms of a cron tab on a cobbler trigger, we could do that. The result is a vast simplification of having 3 ways to do something into one, and not requiring people to suffer learning two different YAML dialects.

---
- myhost1
- myhost2

No potential user will be scared of that, especially when you play the
reuse card while explaining it.

That's a straw-man though compared to the fully fleshed out version. To be fair, it offers a ton of great capabilities, and that was a very impressive feature… that being said, about half the folks out find it a bit confusing, and I don't want to keep adding to it.

We already have a 'custom language' in playbooks. Do we want a
completely different second one?

Essentially that's what the YAML playbook format actually is -- a second language, complete with indentation rules.

However, INI files (we may have to iterate on the syntax some) are pretty basic. And this is forward compatible with what we have now, since the sections are arbitrary.

Since the type of the YAML inventory file is presently a list, it is difficult to do things like top level variables, or express global settings.

Essentially the inventory file is more or less becoming settings, and … yeah … I have to go with my gut feel here that YAML as a configuration file is a source of problems. Especially when converting from simple hosts to groups of hosts, with group vars and host vars is non-intuitive.

Ok, so as an initial compromise, I'll implement the new groups parser
as I've described, say inventory_parser.py. There can be another
inventory_parser_yaml.py as well, but may disappear from devel branch
for a few days until that happens.

External API scripts may also briefly "blink out" on the devel branch
too, until we can find out how to reimplement them.

I think it's important to maintain existing support for people, I was
mostly just frustrated at the level of parser/data mixing. We can
address that seperately. I think the YAML format does get labelled
"alternate format", though, and we can see what people are using over
time and make a decision about that later. It would be easy to write
a migration tool if need be.

Has this feature been added for 0.4 by any chance?

Yes, and is documented on ansible.github.com now as well:

http://ansible.github.com/patterns.html

(There are some important doc formatting errors that will be resolved
when I rebuild the docs. Doing that shortly.)

I’m trying to figure this out for my use case but either I’m braindead or something is not working out.
I’m testing with the devel branch (HEAD at commit 5ab77b8239f8cc532eb0ea0002a1d5d3fdab1731) and as I mentioned before I have multiple hosts accessible via the same IP address but with different ports (the ports are forwarded to the corresponding virtual machines).

$ cat try1

$ cat try1
---
- group: all
hosts:
- host: 10.120.137.188
vars:
- ansible_ssh_port: 23000
- host: 10.120.137.188
vars:
- ansible_ssh_port: 23001
$ ansible all -i ./try1 -m shell -a uptime
10.120.137.188 | success | rc=0 >>
09:07:20 up 23:29, 1 user, load average: 0.00, 0.01, 0.05

$ cat try2
[all]
10.120.137.188:23000
10.120.137.188:23001

This is because the same host is in their twice with two different variables.

Try just naming the host "10.120.137.188:23000" like you did in the other.

It should work. If it doesn't, it needs to :slight_smile:

Well, it kinda doesn’t…

$ cat try4

Ok, that should be fixed.

File a bug or a pull request please?

Ok, that should be fixed.

File a bug or a pull request please?

Submitted issue: https://github.com/ansible/ansible/issues/399