예제 #1
0
    def test_find_wrapper(self):
        wrap1 = mock.MagicMock()
        wrap1.uuid = 'a'
        wrap2 = mock.MagicMock()
        wrap2.uuid = 'b'
        wraps = [wrap1, wrap2]

        self.assertEqual(wrap1, util.find_wrapper(wraps, 'a'))
        self.assertEqual(wrap2, util.find_wrapper(wraps, 'b'))
        self.assertIsNone(util.find_wrapper(wraps, 'c'))
예제 #2
0
    def test_find_wrapper(self):
        wrap1 = mock.MagicMock()
        wrap1.uuid = 'a'
        wrap2 = mock.MagicMock()
        wrap2.uuid = 'b'
        wraps = [wrap1, wrap2]

        self.assertEqual(wrap1, util.find_wrapper(wraps, 'a'))
        self.assertEqual(wrap2, util.find_wrapper(wraps, 'b'))
        self.assertIsNone(util.find_wrapper(wraps, 'c'))
예제 #3
0
    def _remove_vlan_from_nb_synch(self,
                                   nb_uuid,
                                   vlan_id,
                                   fail_if_pvid=False,
                                   existing_nbs=None):
        # Ensure we're working with an integer
        vlan_id = int(vlan_id)

        if existing_nbs is not None:
            nb_wraps = existing_nbs
        else:
            # Get the updated feed of NetworkBridges
            nb_wraps = pvm_net.NetBridge.get(self.adapter,
                                             parent_type=pvm_ms.System,
                                             parent_uuid=self.host_uuid)

        # Find our Network Bridge
        req_nb = pvm_util.find_wrapper(nb_wraps, nb_uuid)

        # Determine if we're trying to remove an arbitrary PVID off of the
        # network bridge.  If so, we need to get a new, available arbitrary
        # PVID and swap that in.
        if vlan_id in req_nb.arbitrary_pvids:
            # Need to find the peers on this vSwitch.  Arbitrary PVIDs can
            # only be used once per vSwitch
            all_nbs_on_vs = self._find_peer_nbs(nb_wraps,
                                                req_nb,
                                                include_self=True)

            # Find a new arbitrary VLAN ID and swap it to a new, available
            # value.  Need to get the orphans so that we do not assign to an
            # existing orphan VLAN.
            other_vlans = [vlan_id] + self._get_orphan_vlans(req_nb.vswitch_id)
            new_a_vid = self._find_new_arbitrary_vid(all_nbs_on_vs,
                                                     others=other_vlans)
            self._reassign_arbitrary_vid(vlan_id, new_a_vid, req_nb)
            return

        # If the VLAN is not on the bridge, no action
        if not req_nb.supports_vlan(vlan_id):
            return

        # Fail if we're the PVID.
        if fail_if_pvid and req_nb.load_grps[0].pvid == vlan_id:
            raise pvm_exc.PvidOfNetworkBridgeError(vlan_id=vlan_id)

        # If this is on the first load group/trunk adapter, we leave it.
        if (req_nb.load_grps[0].pvid == vlan_id
                or vlan_id in req_nb.load_grps[0].tagged_vlans
                or len(req_nb.load_grps) == 1):
            return

        # Rip the VLAN out of the wrapper element.
        self._remove_vlan_from_nb(req_nb, vlan_id)

        # Now update the network bridge.
        req_nb.update()
예제 #4
0
    def remove_vlan_from_nb(self,
                            nb_uuid,
                            vlan_id,
                            fail_if_pvid=False,
                            existing_nbs=None):
        """Will remove the VLAN from a given Network Bridge.

        :param nb_uuid: The Network Bridge UUID.
        :param vlan_id: The VLAN identifier.
        :param fail_if_pvid: If set to true, will raise an exception if this is
                             the PVID on a Network Bridge.
        :param existing_nbs: Optional.  If set, should be the existing network
                             bridge wrappers.  If not provided, will gather
                             from the system directly.
        """
        # Ensure we're working with an integer
        vlan_id = int(vlan_id)

        if existing_nbs is not None:
            nb_wraps = existing_nbs
        else:
            # Get the updated feed of NetworkBridges
            nb_feed = self.adapter.read(
                pvm_ms.System.schema_type,
                root_id=self.host_uuid,
                child_type=pvm_net.NetBridge.schema_type)
            nb_wraps = pvm_net.NetBridge.wrap(nb_feed)

        # Find our Network Bridge
        req_nb = pvm_util.find_wrapper(nb_wraps, nb_uuid)

        # Determine if we're trying to remove an arbitrary PVID off of the
        # network bridge.  If so, we need to get a new, available arbitrary
        # PVID and swap that in.
        if vlan_id in req_nb.arbitrary_pvids:
            # Need to find the peers on this vSwitch.  Arbitrary PVIDs can
            # only be used once per vSwitch
            all_nbs_on_vs = self._find_peer_nbs(nb_wraps,
                                                req_nb,
                                                include_self=True)

            # Find a new arbitrary VLAN ID and swap it to a new, available
            # value.  Need to get the orphans so that we do not assign to an
            # existing orphan VLAN.
            other_vlans = [vlan_id] + self._get_orphan_vlans(req_nb.vswitch_id)
            new_a_vid = self._find_new_arbitrary_vid(all_nbs_on_vs,
                                                     others=other_vlans)
            self._reassign_arbitrary_vid(vlan_id, new_a_vid, req_nb)
            return

        # If the VLAN is not on the bridge, no action
        if not req_nb.supports_vlan(vlan_id):
            return

        # Fail if we're the PVID.
        if fail_if_pvid and req_nb.load_grps[0].pvid == vlan_id:
            raise pvm_exc.PvidOfNetworkBridgeError(vlan_id=vlan_id)

        # If this is on the first load group/trunk adapter, we leave it.
        if (req_nb.load_grps[0].pvid == vlan_id
                or vlan_id in req_nb.load_grps[0].tagged_vlans
                or len(req_nb.load_grps) == 1):
            return

        # Rip the VLAN out of the wrapper element.
        self._remove_vlan_from_nb(req_nb, vlan_id)

        # Now update the network bridge.
        req_nb.update()
예제 #5
0
    def ensure_vlans_on_nb(self, nb_uuid, vlan_ids):
        """Will make sure that the VLANs are assigned to the Network Bridge.

        This method will reorder the arbitrary VLAN IDs as needed (those which
        are the PVID of the TrunkAdapter, but not the primary TrunkAdapter).

        VLANs are always added to TrunkAdapters that are 'non-primary' (not the
        first TrunkAdapter).  However, if the VLAN is on the primary
        TrunkAdapter then it is left on the system. The only 'untagged' VLAN
        that is allowed is the primary TrunkAdapter's PVID.

        If the VLAN specified is on another Network Bridge's TrunkAdapter
        (which happens to be on the same virtual switch):
         - An error will be thrown if it is on the primary TrunkAdapter.
         - It will be removed off the Network Bridge if it is on the
           non-primary TrunkAdapter.

        This method will not remove VLAN IDs from the network bridge that
        aren't part of the vlan_ids list.  Instead, each VLAN is simply added
        to the Network Bridge's VLAN list.

        :param nb_uuid: The Network Bridge UUID.
        :param vlan_ids: The list of VLANs to ensure are on the Network Bridge.
        """
        # Ensure the VLANs are ints, not strings.
        vlan_ids = [int(x) for x in vlan_ids]

        # Get the updated feed of NetworkBridges
        nb_feed = self.adapter.read(pvm_ms.System.schema_type,
                                    root_id=self.host_uuid,
                                    child_type=pvm_net.NetBridge.schema_type)
        nb_wraps = pvm_net.NetBridge.wrap(nb_feed)

        # Find the appropriate Network Bridge
        req_nb = pvm_util.find_wrapper(nb_wraps, nb_uuid)

        # Call down to the ensure_vlan_on_nb method only for the additions.
        new_vlans = []
        peer_nbs = self._find_peer_nbs(nb_wraps, req_nb)
        all_nbs_on_vs = [req_nb]
        all_nbs_on_vs.extend(peer_nbs)

        # Need to evaluate the status of each VLAN.
        for vlan_id in vlan_ids:
            # No action required.  The VLAN is already part of the bridge.
            if req_nb.supports_vlan(vlan_id):
                continue

            # If its supported by a peer...
            for peer_nb in peer_nbs:
                if peer_nb.supports_vlan(vlan_id):
                    # Remove the VLAN.
                    self.remove_vlan_from_nb(peer_nb.uuid,
                                             vlan_id,
                                             fail_if_pvid=True,
                                             existing_nbs=nb_wraps)
                    break

            # If it is an arbitrary VLAN ID on our network.  This should be
            # very rare.  But if it does happen, we should re-order the VLANs
            # and then retry this whole method.
            if self._is_arbitrary_vid(vlan_id, all_nbs_on_vs):
                # Find a new arbitrary VLAN ID, and re-assign the original
                # value to this new one.
                other_vlans = (vlan_ids +
                               self._get_orphan_vlans(req_nb.vswitch_id))
                new_a_vid = self._find_new_arbitrary_vid(all_nbs_on_vs,
                                                         others=other_vlans)
                self._reassign_arbitrary_vid(vlan_id, new_a_vid, req_nb)
                return self.ensure_vlans_on_nb(nb_uuid, vlan_ids)

            # At this point, we've done all the easy checks.  Next up is to
            # detect if it is an orphan.
            self._validate_orphan_on_ensure(vlan_id, req_nb.vswitch_id)

            # Lastly, if we're here...it must be a completely new VLAN.
            new_vlans.append(vlan_id)

        # If there are no new VLANs, no need to continue.
        if len(new_vlans) == 0:
            return

        # At this point, all of the new VLANs that need to be added are in the
        # new_vlans list.  Now we need to put them on load groups.
        self._add_vlans_to_nb(req_nb, all_nbs_on_vs, new_vlans)

        # At this point, the network bridge should just need to be updated.
        # The Load Groups on the Network Bridge should be correct.
        req_nb.update()
예제 #6
0
    def _ensure_vlans_on_nb_synch(self, nb_uuid, vlan_ids):
        # Ensure the VLANs are ints, not strings.
        vlan_ids = [int(x) for x in vlan_ids]

        # Get the updated feed of NetworkBridges
        nb_wraps = pvm_net.NetBridge.get(self.adapter,
                                         parent_type=pvm_ms.System,
                                         parent_uuid=self.host_uuid)

        # Find the appropriate Network Bridge
        req_nb = pvm_util.find_wrapper(nb_wraps, nb_uuid)

        # Call down to the ensure_vlan_on_nb method only for the additions.
        new_vlans = []
        peer_nbs = self._find_peer_nbs(nb_wraps, req_nb)
        all_nbs_on_vs = [req_nb]
        all_nbs_on_vs.extend(peer_nbs)

        # Need to evaluate the status of each VLAN.
        for vlan_id in vlan_ids:
            # No action required.  The VLAN is already part of the bridge.
            if req_nb.supports_vlan(vlan_id):
                continue

            # If its supported by a peer...
            for peer_nb in peer_nbs:
                if peer_nb.supports_vlan(vlan_id):
                    # Remove the VLAN.
                    self._remove_vlan_from_nb_synch(peer_nb.uuid,
                                                    vlan_id,
                                                    fail_if_pvid=True,
                                                    existing_nbs=nb_wraps)
                    break

            # If it is an arbitrary VLAN ID on our network.  This should be
            # very rare.  But if it does happen, we should re-order the VLANs
            # and then retry this whole method.
            if self._is_arbitrary_vid(vlan_id, all_nbs_on_vs):
                # Find a new arbitrary VLAN ID, and re-assign the original
                # value to this new one.
                other_vlans = (vlan_ids +
                               self._get_orphan_vlans(req_nb.vswitch_id))
                new_a_vid = self._find_new_arbitrary_vid(all_nbs_on_vs,
                                                         others=other_vlans)
                self._reassign_arbitrary_vid(vlan_id, new_a_vid, req_nb)
                return self._ensure_vlans_on_nb_synch(nb_uuid, vlan_ids)

            # At this point, we've done all the easy checks.  Next up is to
            # detect if it is an orphan.
            self._validate_orphan_on_ensure(vlan_id, req_nb.vswitch_id)

            # Lastly, if we're here...it must be a completely new VLAN.
            new_vlans.append(vlan_id)

        # If there are no new VLANs, no need to continue.
        if len(new_vlans) == 0:
            return

        # At this point, all of the new VLANs that need to be added are in the
        # new_vlans list.  Now we need to put them on load groups.
        self._add_vlans_to_nb(req_nb, all_nbs_on_vs, new_vlans)

        # At this point, the network bridge should just need to be updated.
        # The Load Groups on the Network Bridge should be correct.
        req_nb.update()