I have a need to setup a virtual network on a VM-host server. Usually, I just use the virt-manager gui application to create this task. However, I’d like to do this via command line this time. Why? Well, why not? It’s always fun to learn new thing. :)

libvirt keeps network configuration in XML files under /etc/libvirt/qemu/networks/. Here is what I have on one of my machines:

# ls -1 /etc/libvirt/qemu/networks/*xml

We can use also list all the available libvirt-related virtual networks using virsh command:

# virsh net-list --all
 Name           State      Autostart   Persistent
 classroom      active     yes         yes
 default        active     yes         yes
 kubernetes     inactive   no          yes
 minikube-net   inactive   no          yes
 other          inactive   no          yes
 storage        active     yes         yes
 student        active     yes         yes

Okay, let’s get into creating a new virtual network called netpriv. I have this XML file with the following content.

  <forward mode='nat'/>
  <bridge name='virbr1' stp='on' delay='0' />
  <ip address='' netmask=''>
      <range start='' end='' />

To create a new virtual network, we’ll use virsh net-create --file FILENAME.xml. (Note the name of FILENAME.xml doesn’t have to match with the name of the virtual network you want to create.)

# virsh net-create --file ./netpriv.xml
Network netpriv created from ./netpriv.xml

# virsh net-list
 Name      State    Autostart   Persistent
 default   active   yes         yes
 netpriv   active   no          no

We can verify our newly created network.

# virsh net-dumpxml netpriv
  <forward mode='nat'>
      <port start='1024' end='65535'/>
  <bridge name='virbr1' stp='on' delay='0'/>
  <mac address='52:54:00:c7:ee:34'/>
  <ip address='' netmask=''>
      <range start='' end=''/>

And one time, verify that a new virtual network interface has been created.

# ip a show virbr1
11: virbr1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:c7:ee:34 brd ff:ff:ff:ff:ff:ff
    inet brd scope global virbr1
       valid_lft forever preferred_lft forever

Update (2021-03-23):

I notice that the new virtual network is not started by default. Here’s how to make it autostart on the server’s reboot.

# virsh net-autostart netpriv
error: failed to mark network netpriv as autostarted
error: Requested operation is not valid: cannot set autostart for transient network

Great. What now?

According to this question on StackExchange, we can trick libvirt to convert the network configuration from transient to persistent with the following steps:

  1. Edit the network name
  2. Stop the network
  3. Start the network
  4. Finally, set the network to auto start

Let’s try it out. Remember the name of my virtual network is netpriv. Run virsh net-edit network_name. Add an empty line so that libvirt thinks there was a change in the file and will restart the network.

# virsh net-edit netpriv
Network netpriv XML configuration edited. 

Next, stop the network by running virsh net-destroy network_name. (Now, don’t let the name fool you. net-destroy does not destroy your network. It only stops the network.)

# virsh net-destroy netpriv
Network netpriv destroyed 

Then I start the network again.

# virsh net-start netpriv
Network netpriv started 

Let’s try to enable autostart.

# virsh net-autostart netpriv
Network netpriv marked as autostarted 

Finally we can verify the result.

# virsh net-list
 Name      State    Autostart Persistent
 default   active   yes         yes
 netpriv   active   yes         yes