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

NetworkUpdate: Operation not supported: can't update 'ip' section of network 'default' #87

Closed
a2geek opened this issue Jul 14, 2019 · 5 comments · Fixed by #148
Closed

Comments

@a2geek
Copy link

a2geek commented Jul 14, 2019

I'm not entirely certain if this is a bug in my code or something is up with the NetworkUpdate call from this library.

I'm writing some code that will ultimately be installed into a VM in order to manage multiple VM's. The base OS layer does not have any libvirt dependencies, and this is the best solution for my needs. (So thanks for that!)

When I do a NetworkUpdate to add an IP>DHCP>Host entry, an error is generated: Operation not supported: can't update 'ip' section of network 'default'.

What I've done:

  • verified the project is on the latest code.
  • extracted the specific code, and it fails.
  • used TLS connections (thinking there may be a different socket file to utilize)
  • implemented with the libvirt/libvirt-go library, and it works.
  • verified this also works from the virsh command-line.

Therefore, I think I've got a valid setup but haven't been able to identify what may be wrong (in either code base).

Running on Ubuntu 18.04.2.

$ virsh version
Compiled against library: libvirt 4.0.0
Using library: libvirt 4.0.0
Using API: QEMU 4.0.0
Running hypervisor: QEMU 2.11.1

Using this library (and it fails):

const networkDhcpXML = "<host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>"
const networkName = "default"
const socket = "/var/run/libvirt/libvirt-sock"

func main() {
	conn, err := net.DialTimeout("unix", socket, 2*time.Second)
	defer conn.Close()
	if err != nil {
		panic(err)
	}
	fmt.Printf("Connected to '%s'\n", socket)

	client := libvirt.New(conn)
	err = client.Connect()
	if err != nil {
		panic(err)
	}
	fmt.Printf("Connected to libvirt\n")

	net, err := client.NetworkLookupByName(networkName)
	if err != nil {
		panic(err)
	}
	fmt.Printf("net = %v\n", net)

	xmlDesc, err := client.NetworkGetXMLDesc(net, 0)
	if err != nil {
		panic(err)
	}
	fmt.Printf("networkXMLDesc=%s\n", xmlDesc)

	cmd := uint32(libvirt.NetworkUpdateCommandAddLast)
	section := uint32(libvirt.NetworkSectionIPDhcpHost)
	//netflags := libvirt.NetworkUpdateAffectLive | libvirt.NetworkUpdateAffectConfig
	fmt.Printf("NetworkUpdate(%v, %d, %d, -1, %s, %d)\n", net, cmd, section, networkDhcpXML, 0)
	err = client.NetworkUpdate(net, cmd, section, -1, networkDhcpXML, 0)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Setup network DHCP\n")
}

Using the libvirt/libvirt-go library (and it works):

const networkDhcpXML = "<host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>"
const networkName = "default"

func main() {
	conn, err := libvirt.NewConnect("qemu:///system")
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	net, err := conn.LookupNetworkByName(networkName)
	defer net.Free()
	if err != nil {
		panic(err)
	}
	fmt.Printf("net = %v\n", net)

	xmlDesc, err := net.GetXMLDesc(0)
	if err != nil {
		panic(err)
	}
	fmt.Printf("networkXMLDesc=%s\n", xmlDesc)

	cmd := libvirt.NETWORK_UPDATE_COMMAND_ADD_LAST
	section := libvirt.NETWORK_SECTION_IP_DHCP_HOST
	//netflags := libvirt.NetworkUpdateAffectLive | libvirt.NetworkUpdateAffectConfig
	fmt.Printf("NetworkUpdate(%v, %d, %d, -1, %s, %d)\n", net, cmd, section, networkDhcpXML, 0)
	err = net.Update(cmd, section, -1, networkDhcpXML, 0)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Setup network DHCP\n")
}

Using virsh:

$ virsh net-update default add --section ip-dhcp-host --xml "<host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>"
Updated network default live state

If it's useful, the specific usage is in the libvirtManager here. It's been rejiggered into the samples to work out whatever issue is occurring.

Thanks for any information you may provide!

@trapgate
Copy link
Member

The error you're getting seems to be coming from virNetworkDefUpdateIP in the libvirt sources. But that's not the right routine - you're trying to update the DHCP host settings, which is section "ip/dhcp/host", and is handled by virNetworkDefUpdateIPDHCPHost. You'd get this error if the section parameter passed into the NetworkUpdate call were wrong (3 instead of 4), but libvirt.NetworkSectionIpDhcpHost and NETWORK_SECTION_IP_DHCP_HOST are both 4, in the sources I'm looking at. (libvirt 4.0.0). It might be interesting to try some other values for the section parameter, and see if you get back sensible errors.

@a2geek
Copy link
Author

a2geek commented Jul 16, 2019

I get the same response regardless of values (tried 1, 2, 3, 4, 5, and 500):

NetworkUpdate(3, 500, -1, <host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>, 0)
panic: Operation not supported: can't update 'ip' section of network 'default'

I am using Go 1.12 and modules. go.mod is:

$ cat go.mod
module ip-dhcp-host

go 1.12

require github.com/digitalocean/go-libvirt v0.0.0-20190715144809-7b622097a793

Just in case there's a specific version or something.

@a2geek
Copy link
Author

a2geek commented Jul 16, 2019

Hmm. Going with your suggestion, I "widened" the net... I tried setting command, section, and flags to 4. Flags wouldn't allow it (actually gave me a flags related error).

But...

	cmd := uint32(4)
	section := uint32(4)
	fmt.Printf("NetworkUpdate(%d, %d, -1, %s, %d)\n", cmd, section, networkDhcpXML, 0)
	err = client.NetworkUpdate(net, cmd, section, -1, networkDhcpXML, 0)

Gave me:

NetworkUpdate(4, 4, -1, <host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>, 0)
Setup network DHCP

... and as proof:

$ virsh net-dumpxml default
<network>
  <name>default</name>
  <uuid>bcb85dc8-ad27-4861-9f85-692167fd79fa</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:82:d1:6e'/>
  <ip address='192.168.123.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.123.2' end='192.168.123.254'/>
      <host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>
      <host name='totally-fake-vm' ip='192.168.123.6'/>
    </dhcp>
  </ip>
</network>

... and running it again errors out (as expected):

NetworkUpdate(4, 4, -1, <host name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>, 0)
panic: Requested operation is not valid: there is an existing dhcp host entry in network 'default' that matches "<host mac='unknown' name='vm-8029d8c8-ee6c-45b9-6476-3ba7381c3cb5' ip='192.168.123.7'/>"

Is something cross-wired somewhere? Even in my code? Sadly, I'm not spotting anything. (But also admitting I'm a Go rookie, haven't touched C in 30 years, and utter neophyte with Libvirt! LOL)

a2geek added a commit to a2geek/libvirt-bosh-cpi that referenced this issue Jul 20, 2019
@karlskewes
Copy link

Thank you so much for posting this issue. We've just run into it with the terraform libvirt provider.

Seems there has been work going on upstream to improve a situation where command and section argument ordering is swapped around.

See:

karlskewes added a commit to dmacvicar/terraform-provider-libvirt that referenced this issue May 28, 2021
At some point we will need to swap the params back once a change has
made it's way through the system.

digitalocean/go-libvirt#87

`command` and `section` params are reversed now and will need to be put back in order when fix flows through
history: https://listman.redhat.com/archives/libvir-list/2021-March/msg00054.html
merged fix: https://listman.redhat.com/archives/libvir-list/2021-March/msg00758.html
dmacvicar pushed a commit to dmacvicar/terraform-provider-libvirt that referenced this issue Jun 28, 2021
At some point we will need to swap the params back once a change has
made it's way through the system.

digitalocean/go-libvirt#87

`command` and `section` params are reversed now and will need to be put back in order when fix flows through
history: https://listman.redhat.com/archives/libvir-list/2021-March/msg00054.html
merged fix: https://listman.redhat.com/archives/libvir-list/2021-March/msg00758.html
@cfergeau
Copy link
Contributor

My take on this is cfergeau@8108763

cfergeau added a commit to cfergeau/go-libvirt that referenced this issue May 12, 2022
NetworkUpdateFixed is a wrapper over NetworkUpdate which swaps `Command`
and `Section` when needed.
This function must be used instead of NetworkUpdate to be sure that the
NetworkUpdate call works both with older and newer libvirtd connections.

libvirt on-wire protocol had a bug for a long time where Command and Section
were reversed. It's been fixed in newer libvirt versions, and backported to
some older versions. This helper detects what argument order libvirtd expects
and makes the correct NetworkUpdate call.

Ideally 'NetworkUpdate' in internal/constants/remote_protocol.gen.go
could be renamed to 'networkUpdate' or such, and the new helper would be
'NetworkUpdate', but I don't know if it's possible to do this with the
code generator.

See https://listman.redhat.com/archives/libvir-list/2021-March/msg00054.html
https://gitlab.com/libvirt/libvirt/-/commit/94741bc53e9b9a405fae8f2e96b780c2891b2ff0
https://gitlab.com/libvirt/libvirt/-/commit/b0f78d626a18bcecae3a4d165540ab88bfbfc9ee

This fixes digitalocean#87
cfergeau added a commit to cfergeau/go-libvirt that referenced this issue May 16, 2022
NetworkUpdateCompat is a wrapper over NetworkUpdate which swaps `Command`
and `Section` when needed.
This function must be used instead of NetworkUpdate to be sure that the
NetworkUpdate call works both with older and newer libvirtd connections.

libvirt on-wire protocol had a bug for a long time where Command and Section
were reversed. It's been fixed in newer libvirt versions, and backported to
some older versions. This helper detects what argument order libvirtd expects
and makes the correct NetworkUpdate call.

Ideally 'NetworkUpdate' in internal/constants/remote_protocol.gen.go
could be renamed to 'networkUpdate' or such, and the new helper would be
'NetworkUpdate', but I don't know if it's possible to do this with the
code generator.

See https://listman.redhat.com/archives/libvir-list/2021-March/msg00054.html
https://gitlab.com/libvirt/libvirt/-/commit/94741bc53e9b9a405fae8f2e96b780c2891b2ff0
https://gitlab.com/libvirt/libvirt/-/commit/b0f78d626a18bcecae3a4d165540ab88bfbfc9ee

This fixes digitalocean#87
cfergeau added a commit to cfergeau/go-libvirt that referenced this issue Jun 9, 2022
NetworkUpdateCompat is a wrapper over NetworkUpdate which swaps `Command`
and `Section` when needed.
This function must be used instead of NetworkUpdate to be sure that the
NetworkUpdate call works both with older and newer libvirtd connections.

libvirt on-wire protocol had a bug for a long time where Command and Section
were reversed. It's been fixed in newer libvirt versions, and backported to
some older versions. This helper detects what argument order libvirtd expects
and makes the correct NetworkUpdate call.

Ideally 'NetworkUpdate' in internal/constants/remote_protocol.gen.go
could be renamed to 'networkUpdate' or such, and the new helper would be
'NetworkUpdate', but I don't know if it's possible to do this with the
code generator.

See https://listman.redhat.com/archives/libvir-list/2021-March/msg00054.html
https://gitlab.com/libvirt/libvirt/-/commit/94741bc53e9b9a405fae8f2e96b780c2891b2ff0
https://gitlab.com/libvirt/libvirt/-/commit/b0f78d626a18bcecae3a4d165540ab88bfbfc9ee

This fixes digitalocean#87
connorkuehl pushed a commit that referenced this issue Jun 16, 2022
NetworkUpdateCompat is a wrapper over NetworkUpdate which swaps `Command`
and `Section` when needed.
This function must be used instead of NetworkUpdate to be sure that the
NetworkUpdate call works both with older and newer libvirtd connections.

libvirt on-wire protocol had a bug for a long time where Command and Section
were reversed. It's been fixed in newer libvirt versions, and backported to
some older versions. This helper detects what argument order libvirtd expects
and makes the correct NetworkUpdate call.

Ideally 'NetworkUpdate' in internal/constants/remote_protocol.gen.go
could be renamed to 'networkUpdate' or such, and the new helper would be
'NetworkUpdate', but I don't know if it's possible to do this with the
code generator.

See https://listman.redhat.com/archives/libvir-list/2021-March/msg00054.html
https://gitlab.com/libvirt/libvirt/-/commit/94741bc53e9b9a405fae8f2e96b780c2891b2ff0
https://gitlab.com/libvirt/libvirt/-/commit/b0f78d626a18bcecae3a4d165540ab88bfbfc9ee

This fixes #87
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants