コード例 #1
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _update_sea(self, sea_dev, virt_adpts_list):
        """
        This method does nothing for HMC because VEAs (TrunkAdapters) are
        implicitly attached to the SEA when they're created.
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        pass
コード例 #2
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _find_first_avail_slot(self, vios):
        """
        This is not needed on HMC because the HMC will pick a slot for us.
        Furthermore, if there are no available slots, the _create_vea_on_vios()
        will raise an exception, so we don't really need this method to do
        anything. Just return a valid value so the invoker proceeds.
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        return 10
コード例 #3
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _supports_dynamic_update(self, vios=None):
        """
        This method returns whether the VIOS supports dynamically updating VLAN
        ids on VEAs or not.  On HMC, this depends on the system's capabilities.

        :param vios: VioServer DOM object representing VIOS running against
        :returns boolean: True if dynamic updates supported, False otherwise
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        if self._supports_dynamic_vlans is None:
            # Older firmware cannot dynamically update a VEA with vlans (boo).
            # We cache the ManagedSystem K2Response because that shouldn't
            # ever change.
            ras.trace(LOG, __name__, ras.TRACE_DEBUG,
                      ras.msg('info', 'K2_GET_MS'))

            # Make the K2 call to get the ManagedSystem response
            ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG,
                                    'Getting ManagedSystem')
            k2entry_ms = self._topo._find_k2_managed_system()
            ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG,
                                    'Got ManagedSystem')

            # Now check to see if the system supports dynamic vlan additions
            caps = k2entry_ms.element.find('AssociatedSystem'
                                           'Capabilities')
            dynamic_lpar = caps.findtext('VirtualEthernetAdapterDynamic'
                                         'LogicalPartitionCapable')

            # Convert and return what we found as a boolean
            self._supports_dynamic_vlans = (dynamic_lpar == 'true')
        return self._supports_dynamic_vlans
コード例 #4
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _delete_vea_on_vios(self, vios, vea, sea, virt_adpts_list):
        """
        This method will remove the given VEA from the given SEA on the
        system and delete it.

        :param vios: VioServer DOM object representing VIOS this is being
                     removed from.
        :param vea: VirtualEthernetAdapter DOM object
        :param sea: SharedEthernetAdapter DOM object
        :param virt_adpts_list: List of virtual adapters that should remain
                                on the SEA.  Ignored for HMC
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        k2resp = self._find_k2_bridge(sea)
        k2_bridge = k2resp.entry
        k2_vswitch_id = self._find_vswitch_id(sea)
        k2_load_grp = self._find_load_grp(vea.pvid, sea.vio_server.lpar_id,
                                          k2_vswitch_id, k2_bridge)
        if k2_load_grp:
            k2_bridge.element.find('LoadGroups').remove(k2_load_grp)

        self._update_vnets_from_ld_grps(k2_bridge)

        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, 'Setting VIOS')
        self._k2op.update(data=k2_bridge.element,
                          etag=k2resp.headers['etag'],
                          rootType='ManagedSystem',
                          rootId=self._topo._find_managed_system(),
                          childType='NetworkBridge',
                          childId=k2_bridge.properties['id'],
                          timeout=hmc.K2_RMC_WRITE_SEC,
                          xag=[None])
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, 'Set VIOS')

        # Be sure to refresh the cached data.
        self._invalidate_k2_cache()
コード例 #5
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _find_vlan_users(self, vios, vlanid, vswitch=None):
        """
        This method will search for the given vlanid on the system and return
        two things.  First, the pvid of the SEA on the VIOS containing the
        vlanid.  Second, the number of users of that vlanid total (ie, client
        LPARs in addition to VIOS).

        :param vios: VIOS dom object we're operating on
        :param vlanid: VLANID to search for
        :param vswitch: vswitch name to associate with this vlanid
        :returns pvid: port vlanid of the SEA on the VIOS containing the
                       vlanid.  Will be 0 if not found.
        :returns num_users: Total number of adapters found with this vlanid.
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        pvid = 0
        num_users = 0

        # Find the VIOS's VEA (if any) that has this vlanid configured on it.
        # Note that this is coming from the database, not the live system.
        # We assume the database is up to date and if we had a race condition
        # where two processes were unplugging the same vlanid (and this is
        # protected by a lock, so only one runs at a time) and the first guy
        # totally removed the vlanid from the system, the database would
        # have been updated and the second unplug will see no evidence of that
        # vlanid on the VIOS reflected in the database at this point.
        for vea in vios.get_all_virtual_ethernet_adapters():
            if vea.is_vlan_configured(vlanid, vswitch):
                # Found a user of the vlanid
                num_users += 1
                # Remember pvid of adapter containing vlanid
                pvid = vea.pvid
                break

        # Now, get all client lpar adapters to see if any of them have the
        # vlanid configured.  This will be an actual K2 call to the HMC...
        # which means if there are a lot of LPARs, this will be SLOOOOWWW....
        # Apparently this will be coming from the database at some point, so
        # we got that going for us.  Note, we don't cache the LogicalPartition
        # K2Response because client LPARs come and go.
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG,
                                'Getting LPARs')
        k2response = self._k2op.read(
            rootType='ManagedSystem',
            rootId=self._topo._find_managed_system(),
            childType='LogicalPartition',
            timeout=hmc.K2_READ_SEC,
            xag=[None])
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, 'Got LPARs')

        # If we found no client LPARs, just return
        if not k2response.feed or not k2response.feed.entries:
            ras.trace(LOG, __name__, ras.TRACE_INFO,
                      ras.msg('info', 'NO_CLIENT_LPAR') % self._topo.host_name)
            return pvid, num_users

        # For each LPAR
        for lpar in k2response.feed.entries:
            # Build a link to all the ClientNetworkAdapters.
            cna_links = lpar.element.findall('./ClientNetworkAdapters/link')

            # If there were some ClientNetworkAdapters
            if cna_links:
                # Get the link for the next K2 call.  Just use the first
                # CNA link found because we're going to strip the UUID to get
                # all adapters in one K2 call anyways.
                href = cna_links[0].getattrib()['href']

                # Strip the UUID
                href = href[0:href.rfind('/')] + '?group=None'

                # Get the adapters
                ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG,
                                        'Getting client adapters')
                k2_adapter_response = self._k2op.readbyhref(
                    href=href,
                    timeout=hmc.K2_READ_SEC)
                ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG,
                                        'Got client adapters')

                # Be sure we found some client adapters
                if not k2_adapter_response.feed or \
                        not k2_adapter_response.feed.entries:
                    ras.trace(LOG, __name__, ras.TRACE_INFO,
                              ras.msg('info', 'NO_CLIENT_ADAPTERS') %
                              {'lpar': lpar.element.findtext('PartitionName'),
                               'lparid': lpar.element.findtext('PartitionID')})
                    # Move on to the next client lpar
                    continue

                # Loop through all adapters and look for our vlanid
                for adapter in k2_adapter_response.feed.entries:
                    # Get the client adapter's PVID
                    client_pvid = adapter.element.findtext('PortVLANID')
                    # If we found a pvid and it matches our vlanid
                    if client_pvid and int(client_pvid) == vlanid:
                        # Bump the users count
                        num_users += 1

                    # I don't think we have additional vlans to worry about,
                    # but just in case...
                    addl_vlans = adapter.element.findtext('TaggedVLANIDs')
                    # If we found some additional vlans
                    if addl_vlans:
                        # Make a string list
                        addl_vlans = addl_vlans.split(',')
                        # Now search for our vlanid.  Our vlanid is an int,
                        # so we use list comprehension to convert the list of
                        # strings to a list of ints
                        if vlanid in [str(x) for x in addl_vlans]:
                            num_users += 1

        return pvid, num_users
コード例 #6
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _dynamic_update_vea(self, vios, sea, vea):
        """
        This method will only work if _supports_dynamic_update returns True.

        Will dyanmically update VLANs on an existing VEA.

        :param vios: VioServer DOM object representing VIOS this is being
                     created on.
        :param sea: SharedEthernetAdapter DOM object that owns the VEA
        :param vea: VirtualEthernetAdapter DOM object that represents the
                    element on the system to update.  Should have the updated
                    information about the VLANs on it already.
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        k2_virt_nets = self._k2op.read(
            rootType='ManagedSystem',
            rootId=self._topo._find_managed_system(),
            childType='VirtualNetwork',
            timeout=hmc.K2_READ_SEC,
            xag=[None])
        k2_vswitch_id = self._find_vswitch_id(sea)

        # Build all of the desired K2 Virtual Networks
        desired_k2_vnets = []
        pvid_k2_net = self._find_or_build_k2_vnet(k2_virt_nets,
                                                  vea.pvid,
                                                  k2_vswitch_id,
                                                  False, False)
        desired_k2_vnets.append(pvid_k2_net.properties.get('link'))

        for addl_vlan_id in vea.addl_vlan_ids:
            net = self._find_or_build_k2_vnet(k2_virt_nets, addl_vlan_id,
                                              k2_vswitch_id, True, False)
            desired_k2_vnets.append(net.properties.get('link'))

        k2_vnet_elems = []
        for desired_k2_vnet in desired_k2_vnets:
            attributes = {'href': desired_k2_vnet, 'rel': 'related'}
            k2_vnet_elems.append(k2.K2Element('link', attrib=attributes))

        k2resp = self._find_k2_bridge(sea)
        k2_bridge = k2resp.entry
        k2_load_grp = self._find_load_grp(vea.pvid, sea.vio_server.lpar_id,
                                          k2_vswitch_id, k2_bridge)

        # If the load group is None here, we find that this happens when an
        # SEA is set up for failover, but the failover SEA isn't sync'd
        # properly.
        if k2_load_grp is None:
            raise exception.IBMPowerVMIncorrectLoadGroup()

        # Update the K2 Load Group with your new Virtual Networks children
        replaced_grps = k2_load_grp.find('VirtualNetworks')
        if replaced_grps:
            k2_load_grp.remove(replaced_grps)
        k2_load_grp.append(k2.K2Element('VirtualNetworks',
                                        children=k2_vnet_elems))

        self._update_vnets_from_ld_grps(k2_bridge)

        k2resp = self._k2op.update(data=k2_bridge.element,
                                   etag=k2resp.headers['etag'],
                                   rootType='ManagedSystem',
                                   rootId=self._topo._find_managed_system(),
                                   childType='NetworkBridge',
                                   childId=k2_bridge.properties['id'],
                                   timeout=hmc.K2_RMC_WRITE_SEC,
                                   xag=[None])

        # Be sure to refresh the cached data.
        self._invalidate_k2_cache()
コード例 #7
0
ファイル: driver_hmc.py プロジェクト: windskyer/k_nova
    def _create_vea_on_vios(self, vios, sea, slotnum, port_vlan_id,
                            addl_vlan_ids):
        """
        This method will create the 802.1Q VirtualEthernetAdapter on the
        VIOS and return the device name of the newly created adapter.  A
        IBMPowerVMFailToAddDataVlan should be raised if unable to create the
        new VEA.

        :param vios: VioServer DOM object representing VIOS this is being
                     created on.
        :param sea: SharedEthernetAdapter DOM object that owns the new VEA
        :param slotnum: Virtual slot number to create the new VEA in.
        :param port_vlan_id: pvid to set on the new VEA
        :param addl_vlan_ids: Additional vlan ids to set on the new VEA
        :returns vea_devname: Device name of the newly created VEA
        :returns slot_number: Slot number the VEA was created in.
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        k2_virt_nets = self._k2op.read(
            rootType='ManagedSystem',
            rootId=self._topo._find_managed_system(),
            childType='VirtualNetwork',
            timeout=hmc.K2_READ_SEC,
            xag=[None])
        k2_vswitch_id = self._find_vswitch_id(sea)

        # Build all of the desired K2 Virtual Networks
        desired_k2_vnets = []
        pvid_k2_net = self._find_or_build_k2_vnet(k2_virt_nets, port_vlan_id,
                                                  k2_vswitch_id, False, False)
        desired_k2_vnets.append(pvid_k2_net.properties.get('link'))

        for addl_vlan_id in addl_vlan_ids:
            net = self._find_or_build_k2_vnet(k2_virt_nets, addl_vlan_id,
                                              k2_vswitch_id, True, True)
            desired_k2_vnets.append(net.properties.get('link'))

        k2_vnet_elems = []
        for desired_k2_vnet in desired_k2_vnets:
            attributes = {'href': desired_k2_vnet, 'rel': 'related'}
            k2_vnet_elems.append(k2.K2Element('link', attrib=attributes))

        # At this point, we have all the VirtualNetworks we want added.
        # Need to make a new LoadGroup to represent it.
        attrs = []
        attrs.append(k2.K2Element('PortVLANID', text=str(port_vlan_id)))
        attrs.append(k2.K2Element('VirtualNetworks',
                                  children=k2_vnet_elems))

        new_load_grp = k2.K2Element('LoadGroup',
                                    attrib={'schemaVersion': 'V1_0'},
                                    children=attrs)

        k2resp = self._find_k2_bridge(sea)
        k2_bridge = k2resp.entry
        k2_bridge.element.find('LoadGroups').append(new_load_grp)

        self._update_vnets_from_ld_grps(k2_bridge)

        k2resp = self._k2op.update(data=k2_bridge.element,
                                   etag=k2resp.headers['etag'],
                                   rootType='ManagedSystem',
                                   rootId=self._topo._find_managed_system(),
                                   childType='NetworkBridge',
                                   childId=k2_bridge.properties['id'],
                                   timeout=hmc.K2_RMC_WRITE_SEC,
                                   xag=[None])

        # Be sure to refresh the cached data.
        self._invalidate_k2_cache()

        # Workaround for K2 bug (SW225510)!
        # TODO: Remove when fixed.
        k2resp = self._k2op.read(rootType='ManagedSystem',
                                 rootId=self._topo._find_managed_system(),
                                 childType='NetworkBridge',
                                 childId=k2_bridge.properties['id'],
                                 timeout=hmc.K2_RMC_READ_SEC,
                                 xag=[None])

        trunk_adpt = self._find_trunk_adapter(port_vlan_id,
                                              sea.vio_server.lpar_id,
                                              k2_vswitch_id, k2resp.entry)

        # TODO if trunk_adpt is None, throw an error
        # Get the appropriate data to pass back
        dev_name = trunk_adpt.findtext('DeviceName')
        # TODO: Remove once everyone's at 1340A HMC
        if dev_name is None:
            dev_name = trunk_adpt.findtext('InterfaceName')
        slot_num = int(trunk_adpt.findtext('VirtualSlotNumber'))
        return dev_name, slot_num
コード例 #8
0
ファイル: topo_hmc.py プロジェクト: windskyer/k_nova
    def _get_all_vios(self, dom_factory=model.No_DB_DOM_Factory()):
        """
        This method will return all VIOSes available on the current host (as
        identified in the operator).

        :param dom_factory: Factory used to create the DOM objects, optional.
        :returns vioses: A list of VioServer objects
        """
        # Get the system we are managing
        managed_system_uuid = self._find_managed_system()

        # Clear out the data
        self.vio_server_map = {}
        self._repopulate_vswitch_data()

        # Move on to VIOS info.  Start with an empty list
        vios_list = []

        # Get all the VIOSes on the HMC.  The response will contain all the
        # info we need for adapters, so save it off so we don't have to
        # make unnecessary K2 calls later on.
        ras.function_tracepoint(LOG, __name__,
                                ras.TRACE_DEBUG, 'Getting VIOS')
        self.k2_vios_resp = self.operator.read(rootType='ManagedSystem',
                                               rootId=managed_system_uuid,
                                               childType='VirtualIOServer',
                                               timeout=hmc.K2_RMC_READ_SEC,
                                               xag=[k2const.VIOS_NET_EXT_PROP],
                                               age=self.read_age)
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, 'Got VIOS')

        # Get the network bridges
        ras.function_tracepoint(LOG, __name__,
                                ras.TRACE_DEBUG,
                                'Getting Network Bridges')
        self.k2_net_bridge_resp = self.operator.read(
            rootType='ManagedSystem',
            rootId=managed_system_uuid,
            childType='NetworkBridge',
            timeout=hmc.K2_RMC_READ_SEC,
            age=self.read_age)
        ras.function_tracepoint(LOG, __name__,
                                ras.TRACE_DEBUG,
                                'Got Network Bridges')

        # If we find no VIOS, just return
        if not self.k2_vios_resp.feed or not self.k2_vios_resp.feed.entries:
            ras.trace(LOG, __name__, ras.TRACE_DEBUG,
                      ras.vif_get_msg('error', 'VIOS_NONE') % self.host_name)
            return vios_list

        # Loop through all VIOSes found
        for entry in self.k2_vios_resp.feed.entries:

            # Grab the necessary attributes
            lpar_id = int(entry.element.findtext('PartitionID'))
            lpar_name = entry.element.findtext('PartitionName')
            state = entry.element.findtext('PartitionState')
            rmc_state = entry.element.findtext('ResourceMonitoring'
                                               'ControlState')

            # If RMC is down, we want to log why.  Could be helpful down the
            # road...
            if rmc_state is None or rmc_state.lower() != 'active':
                LOG.warn(_('K2 RMC state for lpar %(lpid)d (%(lname)s): '
                           '%(state)s') % {'lpid': lpar_id, 'lname': lpar_name,
                                           'state': rmc_state})
                data = self.k2_vios_resp.body
                LOG.warn(_('K2Response: %(resp)s') % {'resp': data})

            # Add the data to the map
            self.vio_server_map[lpar_id] = entry.properties['link']

            # Create a VIOS DOM object
            vios = dom_factory.create_vios(lpar_name=lpar_name,
                                           lpar_id=lpar_id,
                                           host_name=self.host_name,
                                           state=state,
                                           rmc_state=rmc_state)
            vios_list.append(vios)

            ras.trace(LOG, __name__, ras.TRACE_DEBUG,
                      ras.vif_get_msg('info', 'FOUND_VIOS') %
                      {'lpar_id': lpar_id, 'lpar_name': lpar_name})

        return vios_list