Foreman Discovery build host with multiple IPs

Foreman 1.21.3 Discovery plugin 14.0.1

I’m trying, via the REST API, to build a discovered host with 2 IPs assigned to it. One that comes from the normal FDI DHCP process, and one that’s obtained after the fact, hopefully assigned during the provision process.

The problem I’m running into is when I try to put the IP on the interface I want (lets say p3p1) I get an error 2019-08-29T22:11:08 [W|app|473028af] Not queueing Host::Managed: [“Identifier has already been taken”, “Interfaces some interfaces are invalid”]

If I leave the identifier off, I get the IP discovered from the DHCP server just fine, and the box builds, it just creates a new interface with the IP instead of assigning the IP to the interface I want.

Is it possible to, via the API, create a host and specify the non-primary IP on a specific interface? The payload I’m using is:

{
    "discovered_host": {
        "name": "SomeTestBox",
        "mac": "xx:xx:8f:75:ea:xx",
        "ip": "10.4.16.49",
        "hostgroup_id": 24,
        "subnet_id": 3,
        "build": 1,
        "managed": "1",
        "interfaces_attributes": {
            "0": {
                "managed": "1",
                "subnet_id": "10",
                "primary": "0",
                "virtual": "0",
                "_destroy": "0",
                "mac": "3c:fd:fe:db:83:f0",
                "identifier": "p3p1"
            }
        }
    }
}

It looks like the PUT to the api/v2/discovered_hosts endpoint ends up being much the same as the post to the api/v2/hosts endpoint. I’ve created a host in the UI and it really looks the same, the only difference is that all 5 IPs are identified in the interfaces_attributes (eth1, eth2, ipmi, p3p1, p3p2)

The interface doesn’t have an IP on discovery, because nothing on that network is listening for DHCP, so it was very handy that I can just request this by including the subnet id and having it managed, or using the freeip endpoint. I’ve tried both with and without the IP, with and without the mac (that just errors saying you have to have a mac)

also, it’s adorable that when you get a 500 on the build endpoints, it gives you the message: RuntimeError: resource have no errors

One difference I see from the logs when doing it via the UI is that all the entries in “interfaces_attributes” has an id value. But I don’t know this on initial provision via a discovered host, and it’s not a fact or value that comes out of the GET of the host.

Discovery plugin was designed in a simplistic way, basically to avoid putting MAC addresses into the form. It quickly became one of the most popular plugins, however many expected features are missing.

I am afraid I don’t understand. You all the REST API but which endpoint? What are your expectations?

Unfortunately the unused_ip call not not used at all when provisioning discovered hosts, thus the plugin is only usable in workflows where the node can keep the DHCP-assigned IP address. There is a patch to change that - it will call unused_ip for all managed NICs but it’s not happening for now.

It should be pretty much the same, yes. I don’t understand what is the difference you see tho.

I am afraid I don’t understand. You all the REST API but which endpoint? What are your expectations?

I am performing a PUT on https://myforeman/api/v2/discovered_hosts with the following payload:

{
    "discovered_host": {
        "name": "SomeTestBox",
        "mac": "xx:xx:8f:75:ea:xx",
        "ip": "10.4.16.49",
        "hostgroup_id": 24,
        "subnet_id": 3,
        "build": 1,
        "managed": "1",
        "interfaces_attributes": {
            "0": {
                "managed": "1",
                "subnet_id": "10",
                "primary": "0",
                "virtual": "0",
                "_destroy": "0",
                "mac": "xx:xx:xx:db:83:f0",
                "identifier": "p3p1"
            }
        }
    }
} 

Which returns a 500 error 2019-08-29T22:11:08 [W|app|473028af] Not queueing Host::Managed: [“Identifier has already been taken”, “Interfaces some interfaces are invalid”]

If I omit the interfaces_attributes, the build works fine. If I omit the identifier p3p1 it also builds fine, though it assigns the IP and mac to a new interface instead of p3p1.

What I’m trying to do is get a box, on discovery, to build with two IPs, one of which is assigned to a specific interface ,the other just coming from the normal foreman discovery process.

HTTP PUT is an edit action, I can hardly comment since I don’t know what you actually have in your database. From the error it looks like you are trying to append new NIC with the same identifier p3p1 which must be unique. If your goal is to edit existing interface then you need to figure out the call that does it.

Now discovery does not support (is not tested) for this, but let me tell you that discovery host is just a regular host and you can use the normal Interface API to edit its NICs. Therefore I recommend you to learn how “hammer interface edit” works (use -d to see JSON payload) and than you can perform the very same request via interface/123 API endpoint with the host ID of the discovered host - it should work.

I’m doing a PUT, as thats what the documentation for this plugin says in order to make a discovered host a provisioned host (and get it to reboot and run through the pxe installs) from this site: https://github.com/theforeman/foreman_discovery/blob/develop/README.api.md

After the host gets built, I can use the ID returned from the PUT on the discovery_hosts endpoint to get the host and it’s interface IDs. The problem is that doing a get on the discovery_hosts doesn’t have any IDs for the interfaces, only a bunch of facts in the facts_hash. So it doesn’t appear that a discovery host is the same as a regular host. Besides the Facts Hash it only has the IP, Mac, last_report, subnet_id, subnet_name, hardware_model_name, memory, disk_count, disks_size, cpus, organization_id, organization_name, location_id, location_name, name, and id.

That ID value also is not something the hosts endpoint recognizes as trying to do a GET on that, returns a 404, which is what I’d expect.

It sounds like the discovered_hosts endpoint has no way to add additional IP values to any interface, as it has no concept of interfaces or their ids. At least thats what I’m seeing here unless I’m missing something.

1 Like

After a host is built, don’t use discovery edit API but host edit API: API documentation

Discovery edit host endpoint is the very same (forwards data) to edit host with few changes, so you can use the very same documentation for the discovered host edit API call.

However, this API should not be used to edit interfaces! You can only use it to add new interfaces (that’s why IDs are missing), if you want to edit NICs you need to use completely different endpoint. This is how REST is done: API documentation

Does it make sense now?

Thats what I was afraid of. There is no way, on discovery, to provision a box with multiple IPs or interfaces, it sounds like this can only happen after the PUT to the discovery endpiont, by doing PUT to the host endpoint. I have this working, was just worried that the host could boot up and pull down the kickstart before the interface was edited with the new subnet id / IP, so that the rendered template was stale. I mean it’s not too likely, baremetal boxes tend to take their sweet time booting up, but wanted to make sure it wasn’t a possibility.

All the same thanks for all the help and at least confirming that I wasn’t holding it wrong.

1 Like

We know this is very limiting and we would love to put more resources into this. Discovery as today can only provision hosts without NIC changes, or you can manually take it to the Edit Host form and do the changes manually.

There is another thread when I have a proposal about how to solve this but it will take some time.

1 Like