122 lines
3.7 KiB
Markdown
122 lines
3.7 KiB
Markdown
title: How to build an OpenStack alternative: Step 3, Generating Mac Addresses
|
|
---
|
|
pub_date: 2020-01-13
|
|
---
|
|
author: ungleich virtualisation team
|
|
---
|
|
twitter_handle: ungleich
|
|
---
|
|
_hidden: no
|
|
---
|
|
_discoverable: yes
|
|
---
|
|
abstract:
|
|
First step to automation
|
|
---
|
|
body:
|
|
|
|
This time we describe how to begin automation in uncloud,
|
|
our OpenStack alternative.
|
|
|
|
The previous time we described
|
|
[how to secure the network](../how-to-build-an-openstack-alternative-step-2-secure-the-network/).
|
|
|
|
## Mac Addresses
|
|
|
|
Mac addresses are identifiers for network cards. Like a street number
|
|
is for a house. A virtual machine can have one or more network
|
|
interfaces. Each of these interfaces need a unique number, the mac
|
|
address.
|
|
|
|
## Choosing the prefix
|
|
|
|
We checked how [OpenNebula](https://opennebula.org/) is doing it.
|
|
They basically use the **02:00** prefix and generate mac addresses after
|
|
that. The
|
|
[QEMU mac address
|
|
prefix](https://gist.github.com/ashee/9241ab6281e6f4d1ef9b)
|
|
seems to be 52:54:00.
|
|
According to [Michael
|
|
Stapelberg](https://michael.stapelberg.ch/posts/2012-11-21-kvm_best_practices_2012/)
|
|
the **f6** prefix can be used due to the second lowest bit set to 1.
|
|
|
|
Checking with [wikipedia](https://en.wikipedia.org/wiki/MAC_address),
|
|
this bit indeed specifies whether or not a mac address is locally or
|
|
universally administrated.
|
|
|
|
For that reason we will use **42** as our prefix, which is **1000010**
|
|
in binary and thus has the second least significant bit set to 1.
|
|
|
|
## Generating Mac addresses
|
|
|
|
Mac addresses are basically just numbers and so we treat them as
|
|
such. We need to store the index of which is the current mac address
|
|
and for the next time we create a VM, use the next mac address.
|
|
|
|
The python code to generate a new mac address looks as follows:
|
|
|
|
```
|
|
@staticmethod
|
|
def int_to_mac(number):
|
|
b = number.to_bytes(6, byteorder="big")
|
|
return ':'.join(format(s, '02x') for s in b)
|
|
|
|
def getnext(self):
|
|
if self.last:
|
|
last_number = int(self.last[0], 16)
|
|
|
|
if last_number == int('0xffffff', 16):
|
|
raise Error("Exhausted all possible mac addresses - try to free some")
|
|
|
|
next_number = last_number + 1
|
|
else:
|
|
next_number = 0
|
|
|
|
next_number_string = "{:012x}".format(next_number)
|
|
|
|
next_mac_number = self.prefix + next_number
|
|
next_mac = self.int_to_mac(next_mac_number)
|
|
```
|
|
|
|
It basically says:
|
|
|
|
* If there has been a mac address used add 1 to it and use the next
|
|
one
|
|
* Produce an error, if the whole prefix has been used
|
|
* If no mac address has been used, use the first one
|
|
* Convert the number to the standard format (aa:bb:cc:dd:ee:ff)
|
|
|
|
There is some additional logic on saving the MAC address to which we
|
|
will come back in one of the next posts.
|
|
|
|
## Using the MAC address generator
|
|
|
|
From our prototype, we modify the original `vm.sh` script to include a
|
|
call to the mac address generator as follows:
|
|
|
|
```
|
|
...
|
|
mac=$(./mac-gen.py)
|
|
...
|
|
$qemu -name "uncloud-${uuid}" \
|
|
-machine pc,accel=${accel} \
|
|
-m ${memory} \
|
|
-smp ${cores} \
|
|
-uuid ${uuid} \
|
|
-drive file=alpine-virt-3.11.2-x86_64.iso,media=cdrom \
|
|
-netdev tap,id=netmain,script=./ifup.sh,downscript=./ifdown.sh \
|
|
-device virtio-net-pci,netdev=netmain,id=net0,mac=${mac}
|
|
```
|
|
|
|
In good UNIX manner, the generator simply outputs the MAC address on
|
|
stdout to be used by any software.
|
|
|
|
## Status
|
|
|
|
While being a small and very specific tool, the mac address generator
|
|
is actually a key element of creating a virtualisation
|
|
framework. Without it, it is practically impossible to spawn a dynamic
|
|
amount of virtual machines.
|
|
|
|
With our prototype, a secured network and the mac address generator we
|
|
are not far from being able to migrate some test VMs to uncloud.
|