++blog uncloud 3

This commit is contained in:
Nico Schottelius 2020-01-13 11:34:29 +01:00
parent 7519f26ebb
commit c6ba63e69b
2 changed files with 125 additions and 3 deletions

View file

@ -0,0 +1,122 @@
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.!

View file

@ -1,8 +1,6 @@
- how to secure the network - metadata!
- rate limiting
- automating - automating
- trigger / postgres / etcd - trigger / postgres / etcd
- metadata!
- building vm images! - building vm images!
- generate tap names matching vm??? problem, because inteerfaces are - generate tap names matching vm??? problem, because inteerfaces are
limited in length! limited in length!
@ -63,3 +61,5 @@ table bridge filter {
can generate new full chain, change only the jump can generate new full chain, change only the jump
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Much later:
- rate limiting