Commit ffc2696b authored by Antoine Millet's avatar Antoine Millet
Browse files

Fixed vlan tags to handle simultaneous tagged and untagged VLANs

parent 5335f5f4
Loading
Loading
Loading
Loading
+34 −18
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import socket
import weakref
from StringIO import StringIO
from xml.etree import cElementTree as et
from collections import namedtuple
from itertools import izip, count
from functools import partial

@@ -42,7 +41,22 @@ REGEX_TAG_VALUE = '.+'
REGEX_TAG_IN_DESCRIPTION = '^@(' + REGEX_TAG_NAME + ')[ ]*?=[ ]*?(' + REGEX_TAG_VALUE + ')$'
REGEX_TAG_REPLACE = '^@%s[ ]*?=[ ]*?(' + REGEX_TAG_VALUE + ')$'

NetworkInterface = namedtuple('NetworkInterface', ('source', 'mac', 'model', 'vlans', 'mode'))

class NetworkInterface(object):

    def __init__(self, source=None, mac=None, model=None, untagged_vlan=None, tagged_vlans=None):
        self.source = source
        self.mac = mac
        self.model = model
        self.untagged_vlan = untagged_vlan
        self.tagged_vlans = set() if tagged_vlans is None else set(tagged_vlans)

    @property
    def vlans(self):
        if self.untagged_vlan is not None:
            yield self.untagged_vlan
        for vlan in self.tagged_vlans:
            yield vlan


class VirtualMachine(object):
@@ -88,8 +102,9 @@ class VirtualMachine(object):
                Tag('nic%s_mac' % i, nic.mac),
                Tag('nic%s_source' % i, nic.source),
                Tag('nic%s_model' % i, nic.model),
                Tag('nic%s_vlans' % i, ' '.join(nic.vlans)),
                Tag('nic%s_mode' % i, nic.mode),
                Tag('nic%s_untagged_vlan' % i, nic.untagged_vlan),
                Tag('nic%s_tagged_vlans' % i, ' '.join(str(x) for x in nic.tagged_vlans)),
                Tag('nic%s_vlans' % i, ' '.join(str(x) for x in nic.vlans)),
            ):
                self.tag_db.add_tag(t)

@@ -316,26 +331,27 @@ class VirtualMachine(object):
                except AttributeError:
                    source = None

                vlans = set()
                vlan_list = nic.find('vlan')
                if vlan_list is not None:
                    for tag in vlan_list.findall('tag'):
                        tid = tag.get('id')
                        if tid is not None:
                            vlans.add(tid)
                    mode = {'yes': 'tagged', 'no': 'untagged'}[vlan_list.get('trunk', 'yes' if len(vlans) > 1 else 'no')]
                elif source is not None:
                    mode = 'untagged'
                    vlans.add(source[2:])
                untagged_vlan = None
                tagged_vlans = set()
                vlan = nic.find('vlan')
                if vlan is None:
                    untagged_vlan = source[2:]
                else:
                    tags = vlan.findall('tag')
                    trunk = vlan.get('trunk') == 'yes' or len(tags) > 1
                    default_mode = 'tagged' if trunk else 'untagged'
                    for tag in tags:
                        if tag.get('nativeMode', default_mode) == 'untagged':
                            untagged_vlan = int(tag.get('id'))
                        else:
                    mode = 'unknown'
                            tagged_vlans.add(int(tag.get('id')))

                yield NetworkInterface(
                    mac=mac,
                    source=source,
                    model=model,
                    vlans=vlans,
                    mode=mode,
                    untagged_vlan=untagged_vlan,
                    tagged_vlans=tagged_vlans,
                )

    def open_console(self):