def test_kernel_lt_vlan_splinters(self):
        cluster = self._create_cluster_for_vlan_splinters()
        cluster_id = cluster.id
        editable_attrs = cluster.attributes.editable.copy()

        #value of kernel-ml should end up with vlan_splinters = off

        editable_attrs['vlan_splinters'] = {'value': 'kernel_lt'}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs['vlan_splinters']['value'],
                          'kernel_lt')

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'off')
            self.assertNotIn('trunks', L2_attrs)
    def test_hard_vlan_splinters_in_vlan(self):
        cluster = self._create_cluster_for_vlan_splinters('vlan')
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'hard' and check results.
        editable_attrs['common'].setdefault(
            'vlan_splinters', {'value': 'hard'}
        )['value'] = 'hard'
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        vlan_set = set(
            [ng.vlan_start for ng in cluster.network_groups if ng.vlan_start]
        )
        private_vlan_range = cluster.neutron_config.L2["phys_nets"][
            "physnet2"]["vlan_range"]
        vlan_set.update(xrange(*private_vlan_range))
        vlan_set.add(private_vlan_range[1])

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'auto')
            self.assertIn('trunks', L2_attrs)
            self.assertIn(0, L2_attrs['trunks'])
            map(
                lambda n: vlan_set.remove(n) if n else None,
                L2_attrs['trunks']
            )
        self.assertEquals(len(vlan_set), 0)
    def test_hard_vlan_splinters_in_gre(self):
        cluster = self._create_cluster_for_vlan_splinters('gre')
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'hard' and check results.
        editable_attrs.setdefault(
            'vlan_splinters', {'value': 'hard'}
        )['value'] = 'hard'
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        vlan_set = set(
            [ng.vlan_start for ng in cluster.network_groups if ng.vlan_start]
        )
        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'auto')
            self.assertIn('trunks', L2_attrs)
            self.assertIn(0, L2_attrs['trunks'])
            map(
                lambda n: vlan_set.remove(n) if n else None,
                L2_attrs['trunks']
            )
        self.assertEquals(len(vlan_set), 0)
    def test_hard_vlan_splinters_in_vlan(self):
        cluster = self._create_cluster_for_vlan_splinters('vlan')
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'hard' and check results.
        editable_attrs['common'].setdefault(
            'vlan_splinters', {'value': 'hard'}
        )['value'] = 'hard'
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        vlan_set = set(
            [ng.vlan_start for ng in cluster.network_groups if ng.vlan_start]
        )
        private_vlan_range = cluster.neutron_config.L2["phys_nets"][
            "physnet2"]["vlan_range"]
        vlan_set.update(xrange(*private_vlan_range))
        vlan_set.add(private_vlan_range[1])

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'auto')
            self.assertIn('trunks', L2_attrs)
            self.assertIn(0, L2_attrs['trunks'])
            map(
                lambda n: vlan_set.remove(n) if n else None,
                L2_attrs['trunks']
            )
        self.assertEquals(len(vlan_set), 0)
    def test_hard_vlan_splinters_in_vlan(self):
        cluster = self._create_cluster_for_vlan_splinters("vlan")
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'hard' and check results.
        editable_attrs["common"].setdefault("vlan_splinters", {"value": "hard"})["value"] = "hard"
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        vlan_set = set([ng.vlan_start for ng in cluster.network_groups if ng.vlan_start])
        private_vlan_range = cluster.neutron_config.L2["phys_nets"]["physnet2"]["vlan_range"]
        vlan_set.update(xrange(*private_vlan_range))
        vlan_set.add(private_vlan_range[1])

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node["network_scheme"]["interfaces"]
        for iface_attrs in interfaces.itervalues():
            self.assertIn("L2", iface_attrs)
            L2_attrs = iface_attrs["L2"]
            self.assertIn("vlan_splinters", L2_attrs)
            self.assertEquals(L2_attrs["vlan_splinters"], "auto")
            self.assertIn("trunks", L2_attrs)
            self.assertIn(0, L2_attrs["trunks"])
            map(lambda n: vlan_set.remove(n) if n else None, L2_attrs["trunks"])
        self.assertEquals(len(vlan_set), 0)
    def test_kernel_lt_vlan_splinters(self):
        cluster = self._create_cluster_for_vlan_splinters()
        cluster_id = cluster.id
        editable_attrs = cluster.attributes.editable.copy()

        #value of kernel-ml should end up with vlan_splinters = off

        editable_attrs['common']['vlan_splinters'] = {'value': 'kernel_lt'}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs['common']['vlan_splinters']['value'],
                          'kernel_lt')

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'off')
            self.assertNotIn('trunks', L2_attrs)
    def test_soft_vlan_splinters_in_vlan(self):
        cluster = self._create_cluster_for_vlan_splinters("vlan")
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'soft' and check results.
        editable_attrs["common"].setdefault("vlan_splinters", {"value": "soft"})["value"] = "soft"
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node["network_scheme"]["interfaces"]
        for iface_attrs in interfaces.itervalues():
            self.assertIn("L2", iface_attrs)
            L2_attrs = iface_attrs["L2"]
            self.assertIn("vlan_splinters", L2_attrs)
            self.assertEquals(L2_attrs["vlan_splinters"], "auto")
            self.assertIn("trunks", L2_attrs)
            self.assertEquals(L2_attrs["trunks"], [0])
    def test_soft_vlan_splinters_in_vlan(self):
        cluster = self._create_cluster_for_vlan_splinters('vlan')
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'soft' and check results.
        editable_attrs['common'].setdefault(
            'vlan_splinters', {'value': 'soft'}
        )['value'] = 'soft'
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'auto')
            self.assertIn('trunks', L2_attrs)
            self.assertEquals(L2_attrs['trunks'], [0])
    def test_soft_vlan_splinters_in_vlan(self):
        cluster = self._create_cluster_for_vlan_splinters('vlan')
        editable_attrs = cluster.attributes.editable.copy()

        # Set 'vlan_splinters' to 'soft' and check results.
        editable_attrs['common'].setdefault(
            'vlan_splinters', {'value': 'soft'}
        )['value'] = 'soft'
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'auto')
            self.assertIn('trunks', L2_attrs)
            self.assertEquals(L2_attrs['trunks'], [0])
    def test_vlan_splinters_disabled(self):
        cluster = self._create_cluster_for_vlan_splinters()
        cluster_id = cluster.id
        editable_attrs = cluster.attributes.editable.copy()

        # Remove 'vlan_splinters' attribute and check results.

        editable_attrs['common'].pop('vlan_splinters', None)
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable.copy()
        self.assertNotIn('vlan_splinters', editable_attrs['common'])

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertNotIn('vlan_splinters', L2_attrs)
            self.assertNotIn('trunks', L2_attrs)

        # Set 'vlan_splinters' to 'some_text' and check results.

        editable_attrs['common']['vlan_splinters'] = {'value': 'some_text'}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs['common']['vlan_splinters']['value'],
                          'some_text')

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertNotIn('vlan_splinters', L2_attrs)
            self.assertNotIn('trunks', L2_attrs)

        # Set 'vlan_splinters' to 'disabled' and check results.

        editable_attrs['common']['vlan_splinters'] = {'value': 'disabled'}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs['common']['vlan_splinters']['value'],
                          'disabled')

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'off')
            self.assertNotIn('trunks', L2_attrs)
    def test_vlan_splinters_disabled(self):
        cluster = self._create_cluster_for_vlan_splinters()
        cluster_id = cluster.id
        editable_attrs = cluster.attributes.editable.copy()

        # Remove 'vlan_splinters' attribute and check results.

        editable_attrs['common'].pop('vlan_splinters', None)
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable.copy()
        self.assertNotIn('vlan_splinters', editable_attrs['common'])

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertNotIn('vlan_splinters', L2_attrs)
            self.assertNotIn('trunks', L2_attrs)

        # Set 'vlan_splinters' to 'some_text' and check results.

        editable_attrs['common']['vlan_splinters'] = {'value': 'some_text'}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs['common']['vlan_splinters']['value'],
                          'some_text')

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertNotIn('vlan_splinters', L2_attrs)
            self.assertNotIn('trunks', L2_attrs)

        # Set 'vlan_splinters' to 'disabled' and check results.

        editable_attrs['common']['vlan_splinters'] = {'value': 'disabled'}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs['common']['vlan_splinters']['value'],
                          'disabled')

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node['network_scheme']['interfaces']
        for iface_attrs in interfaces.itervalues():
            self.assertIn('L2', iface_attrs)
            L2_attrs = iface_attrs['L2']
            self.assertIn('vlan_splinters', L2_attrs)
            self.assertEquals(L2_attrs['vlan_splinters'], 'off')
            self.assertNotIn('trunks', L2_attrs)
Example #12
0
    def update(cls, instance, data):
        """Update Node instance with specified parameters in DB.

        This includes:

        * adding node to Cluster (if cluster_id is not None in data) \
        (see :func:`add_into_cluster`)
        * updating roles for Node if it belongs to Cluster \
        (see :func:`update_roles` and :func:`update_pending_roles`)
        * removing node from Cluster (if cluster_id is None in data) \
        (see :func:`remove_from_cluster`)
        * updating interfaces for Node in DB (see :func:`update_interfaces`)
        * creating default Node attributes (see :func:`create_attributes`)

        :param data: dictionary of key-value pairs as object fields
        :returns: Node instance
        """
        data.pop("id", None)
        data.pop("network_data", None)

        roles = data.pop("roles", None)
        pending_roles = data.pop("pending_roles", None)
        new_meta = data.pop("meta", None)

        update_by_agent = data.pop("is_agent", False)

        disks_changed = None
        if new_meta and "disks" in new_meta and "disks" in instance.meta:
            key = operator.itemgetter("name")

            new_disks = sorted(new_meta["disks"], key=key)
            old_disks = sorted(instance.meta["disks"], key=key)

            disks_changed = (new_disks != old_disks)

        # TODO(enchantner): fix this temporary hack in clients
        if "cluster_id" not in data and "cluster" in data:
            cluster_id = data.pop("cluster", None)
            data["cluster_id"] = cluster_id

        if new_meta:
            instance.update_meta(new_meta)
            # The call to update_interfaces will execute a select query for
            # the current instance. This appears to overwrite the object in the
            # current session and we lose the meta changes.
            db().flush()
            if cls.is_interfaces_configuration_locked(instance):
                logger.debug("Interfaces are locked for update on node %s",
                             instance.human_readable_name)
            else:
                instance.ip = data.pop("ip", None) or instance.ip
                instance.mac = data.pop("mac", None) or instance.mac
                db().flush()
                cls.update_interfaces(instance, update_by_agent)

        cluster_changed = False
        add_to_cluster = False
        if "cluster_id" in data:
            new_cluster_id = data.pop("cluster_id")
            if instance.cluster_id:
                if new_cluster_id is None:
                    # removing node from cluster
                    cluster_changed = True
                    cls.remove_from_cluster(instance)
                elif new_cluster_id != instance.cluster_id:
                    # changing node cluster to another
                    # (is currently not allowed)
                    raise errors.CannotUpdate(
                        u"Changing cluster on the fly is not allowed"
                    )
            else:
                if new_cluster_id is not None:
                    # assigning node to cluster
                    cluster_changed = True
                    add_to_cluster = True
                    instance.cluster_id = new_cluster_id

        if "group_id" in data:
            new_group_id = data.pop("group_id")
            if instance.group_id != new_group_id:
                nm = Cluster.get_network_manager(instance.cluster)
                nm.clear_assigned_networks(instance)
                nm.clear_bond_configuration(instance)
            instance.group_id = new_group_id
            add_to_cluster = True

        # calculating flags
        roles_changed = (
            roles is not None and set(roles) != set(instance.roles)
        )
        pending_roles_changed = (
            pending_roles is not None and
            set(pending_roles) != set(instance.pending_roles)
        )

        super(Node, cls).update(instance, data)

        # we need to update relationships, if fk's are changed
        db.refresh(instance)

        if roles_changed:
            cls.update_roles(instance, roles)
        if pending_roles_changed:
            cls.update_pending_roles(instance, pending_roles)

        if add_to_cluster:
            cls.add_into_cluster(instance, instance.cluster_id)

        if any((
            roles_changed,
            pending_roles_changed,
            cluster_changed,
            disks_changed,
        )) and instance.status not in (
            consts.NODE_STATUSES.provisioning,
            consts.NODE_STATUSES.deploying
        ):
            # TODO(eli): we somehow should move this
            # condition into extension, in order to do
            # that probably we will have to create separate
            # table to keep disks which were used to create
            # volumes mapping.
            # Should be solved as a part of blueprint
            # https://blueprints.launchpad.net/fuel/+spec
            #                                 /volume-manager-refactoring
            fire_callback_on_node_update(instance)

        return instance
Example #13
0
    def update(cls, instance, data):
        """Update Node instance with specified parameters in DB.

        This includes:

        * adding node to Cluster (if cluster_id is not None in data) \
        (see :func:`add_into_cluster`)
        * updating roles for Node if it belongs to Cluster \
        (see :func:`update_roles` and :func:`update_pending_roles`)
        * removing node from Cluster (if cluster_id is None in data) \
        (see :func:`remove_from_cluster`)
        * updating interfaces for Node in DB (see :func:`update_interfaces`)
        * creating default Node attributes (see :func:`create_attributes`)

        :param data: dictionary of key-value pairs as object fields
        :returns: Node instance
        """
        data.pop("id", None)
        data.pop("network_data", None)

        roles = data.pop("roles", None)
        pending_roles = data.pop("pending_roles", None)
        new_meta = data.pop("meta", None)

        update_by_agent = data.pop("is_agent", False)

        disks_changed = None
        if new_meta and "disks" in new_meta and "disks" in instance.meta:
            key = operator.itemgetter("name")

            new_disks = sorted(new_meta["disks"], key=key)
            old_disks = sorted(instance.meta["disks"], key=key)

            disks_changed = (new_disks != old_disks)

        # TODO(enchantner): fix this temporary hack in clients
        if "cluster_id" not in data and "cluster" in data:
            cluster_id = data.pop("cluster", None)
            data["cluster_id"] = cluster_id

        if new_meta:
            instance.update_meta(new_meta)
            # The call to update_interfaces will execute a select query for
            # the current instance. This appears to overwrite the object in the
            # current session and we lose the meta changes.
            db().flush()
            if cls.is_interfaces_configuration_locked(instance):
                logger.debug("Interfaces are locked for update on node %s",
                             instance.human_readable_name)
            else:
                instance.ip = data.pop("ip", None) or instance.ip
                instance.mac = data.pop("mac", None) or instance.mac
                db().flush()
                cls.update_interfaces(instance, update_by_agent)

        cluster_changed = False
        add_to_cluster = False
        if "cluster_id" in data:
            new_cluster_id = data.pop("cluster_id")
            if instance.cluster_id:
                if new_cluster_id is None:
                    # removing node from cluster
                    cluster_changed = True
                    cls.remove_from_cluster(instance)
                elif new_cluster_id != instance.cluster_id:
                    # changing node cluster to another
                    # (is currently not allowed)
                    raise errors.CannotUpdate(
                        u"Changing cluster on the fly is not allowed")
            else:
                if new_cluster_id is not None:
                    # assigning node to cluster
                    cluster_changed = True
                    add_to_cluster = True
                    instance.cluster_id = new_cluster_id

        if "group_id" in data:
            new_group_id = data.pop("group_id")
            if instance.group_id != new_group_id:
                nm = Cluster.get_network_manager(instance.cluster)
                nm.clear_assigned_networks(instance)
                nm.clear_bond_configuration(instance)
            instance.group_id = new_group_id
            add_to_cluster = True

        # calculating flags
        roles_changed = (roles is not None
                         and set(roles) != set(instance.roles))
        pending_roles_changed = (
            pending_roles is not None
            and set(pending_roles) != set(instance.pending_roles))

        super(Node, cls).update(instance, data)

        # we need to update relationships, if fk's are changed
        db.refresh(instance)

        if roles_changed:
            cls.update_roles(instance, roles)
        if pending_roles_changed:
            cls.update_pending_roles(instance, pending_roles)

        if add_to_cluster:
            cls.add_into_cluster(instance, instance.cluster_id)

        if any((
                roles_changed,
                pending_roles_changed,
                cluster_changed,
                disks_changed,
        )) and instance.status not in (consts.NODE_STATUSES.provisioning,
                                       consts.NODE_STATUSES.deploying):
            # TODO(eli): we somehow should move this
            # condition into extension, in order to do
            # that probably we will have to create separate
            # table to keep disks which were used to create
            # volumes mapping.
            # Should be solved as a part of blueprint
            # https://blueprints.launchpad.net/fuel/+spec
            #                                 /volume-manager-refactoring
            fire_callback_on_node_update(instance)

        return instance
    def test_vlan_splinters_disabled(self):
        cluster = self._create_cluster_for_vlan_splinters()
        cluster_id = cluster.id
        editable_attrs = cluster.attributes.editable.copy()

        # Remove 'vlan_splinters' attribute and check results.

        editable_attrs["common"].pop("vlan_splinters", None)
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable.copy()
        self.assertNotIn("vlan_splinters", editable_attrs["common"])

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node["network_scheme"]["interfaces"]
        for iface_attrs in interfaces.itervalues():
            self.assertIn("L2", iface_attrs)
            L2_attrs = iface_attrs["L2"]
            self.assertNotIn("vlan_splinters", L2_attrs)
            self.assertNotIn("trunks", L2_attrs)

        # Set 'vlan_splinters' to 'some_text' and check results.

        editable_attrs["common"]["vlan_splinters"] = {"value": "some_text"}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs["common"]["vlan_splinters"]["value"], "some_text")

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node["network_scheme"]["interfaces"]
        for iface_attrs in interfaces.itervalues():
            self.assertIn("L2", iface_attrs)
            L2_attrs = iface_attrs["L2"]
            self.assertNotIn("vlan_splinters", L2_attrs)
            self.assertNotIn("trunks", L2_attrs)

        # Set 'vlan_splinters' to 'disabled' and check results.

        editable_attrs["common"]["vlan_splinters"] = {"value": "disabled"}
        db.refresh(cluster.attributes)
        cluster.attributes.editable = editable_attrs
        self.db.commit()

        cluster = self.db.query(Cluster).get(cluster_id)
        editable_attrs = cluster.attributes.editable
        self.assertEquals(editable_attrs["common"]["vlan_splinters"]["value"], "disabled")

        node = self.serializer.serialize(cluster, cluster.nodes)[0]
        interfaces = node["network_scheme"]["interfaces"]
        for iface_attrs in interfaces.itervalues():
            self.assertIn("L2", iface_attrs)
            L2_attrs = iface_attrs["L2"]
            self.assertIn("vlan_splinters", L2_attrs)
            self.assertEquals(L2_attrs["vlan_splinters"], "off")
            self.assertNotIn("trunks", L2_attrs)