Пример #1
0
def _cascade_save(db_vios, context, db_session):
    """
    The save semantics throw errors (until Issue 3749 is resolved) that causes
    the objects to require a specific order when saved.  This method handles
    the saving of the objects.
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_SAVE_START') %
           {'host': db_vios.get_host_name(),
            'vios': db_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Loop through the VEAs...
    for vea in db_vios.get_all_virtual_ethernet_adapters():
        db_session.add(vea)

    # Loop through the SEAs
    for sea in db_vios.get_shared_ethernet_adapters():
        db_session.add(sea)
        sea.primary_vea  # If not called...may set pvea to None?
        sea.control_channel
        sea.additional_veas

    # Save the VioServer
    # Removing 'add': 5278 fix causes InvalidRequestError--SEA already deleted
    #db_session.add(db_vios)
    db_session.flush()

    msg = (ras.vif_get_msg('info', 'RECONCILE_SAVE_END') %
           {'host': db_vios.get_host_name(),
            'vios': db_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #2
0
def _remove_sea(db_sea, db_vio_server, context, db_session):
    """
    Will remove a SharedEthernetAdapter from the database.

    :param db_sea: The DOM object that represents the SharedEthernetAdapter
                   to remove from the database.
    :param db_vio_server: The VioServer that represents the corresponding
                          VioServer for this object.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_SEA_DEL_START') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': db_sea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    db_sea.delete(context, db_session)
    db_vio_server.remove_adapter(db_sea)

    msg = (ras.vif_get_msg('info', 'RECONCILE_SEA_DEL_END') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': db_sea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #3
0
    def _delete_vea_on_vios(self, vios, vea_dev, sea_dev, 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_dev: VirtualEthernetAdapter DOM object
        :param sea_dev: SharedEthernetAdapter DOM object
        :param virt_adpts_list: List of VEA devnames that should remain on the
                                SEA
        """
        # Run the first two commands in a loop in case the rmdev fails.
        # Running the first command repeatedly isn't a problem because
        # it's setting the SEA to what we want, and that doesn't change.
        # If this fails, it'll be on the rmdev.
        for x in range(RMDEV_ATTEMPTS):
            try:
                cmds = \
                    (utils.change_sea_virt_adapters_cmd(seaname=sea_dev.name,
                                                        pveaname=sea_dev.
                                                        get_primary_vea().name,
                                                        virt_list=
                                                        virt_adpts_list)
                        + ' && ' +
                        utils.remove_virtual_device(vea_dev.name)
                        + ' && ' +
                        utils.remove_virtual_slot_cmd(lpar_id=vea_dev.
                                                      vio_server.lpar_id,
                                                      slot_num=vea_dev.slot))
                self._pvmops.run_vios_command(cmds)

                # If we got here, all is well
                break
            except Exception as e:
                ras.trace(LOG, __name__, ras.TRACE_ERROR,
                          ras.msg('error', 'VETH_FAILTOREMOVE') %
                          {'slotnum': vea_dev.slot} + '(' + _('%s') % e + ')')

                # Sleep before we try again
                if x < (RMDEV_ATTEMPTS - 1):
                    time.sleep(1)
                else:
                    # This was our last attempt.  Re-raise the exception.
                    raise
Пример #4
0
    def _find_all_host_names(self, context):
        """
        This returns a list of compute nodes after querying the Nova DB

        :param context: A context object that is used to authorize the DB
                        access.
        :returns: A set of compute nodes.
        """
        compute_nodes = db.compute_node_get_all(context)
        return_nodes = []
        for compute in compute_nodes:
            if not compute['service']:
                ras.trace(LOG, __name__, ras.TRACE_WARNING,
                          _('No service for compute ID %s' % compute['id']))
                continue
            host_to_send = compute['service']['host']
            return_nodes.append(host_to_send)
        return return_nodes
Пример #5
0
def _reconcile_sea(db_sea, server_sea, db_vio_server, context, db_session):
    """
    Will reconcile the database SharedEthernetAdapter to match that of the
    Server side SharedEthernetAdapter.

    :param db_sea: The DOM object that represents the SharedEthernetAdapter to
                   update.
    :param server_sea: The DOM object that represents the master data for the
                       database.
    :param db_vio_server: The VioServer that represents the corresponding
                          VioServer for this object.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_SEA_START') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': db_sea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    db_sea.name = server_sea.name
    db_sea.vio_server = db_vio_server
    db_sea.slot = server_sea.slot
    db_sea.state = server_sea.state

    current_db_veas = db_vio_server.get_all_virtual_ethernet_adapters()

    db_sea.primary_vea = _find_adapter(current_db_veas,
                                       server_sea.primary_vea.name)

    if server_sea.control_channel:
        db_sea.control_channel = _find_adapter(current_db_veas,
                                               server_sea.control_channel.name)
    else:
        db_sea.control_channel = None

    db_sea.additional_veas = _find_adapter_list(current_db_veas,
                                                server_sea.additional_veas)

    msg = (ras.vif_get_msg('info', 'RECONCILE_SEA_END') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': db_sea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #6
0
def _add_sea(server_sea, db_vio_server, context, db_session, dom_factory):
    """
    Adds the SharedEthernetAdapter object to the database.

    :param server_sea: The server side SharedEthernetAdapter object to merge
                       into the database.
    :param db_vio_server: The VioServer that represents the corresponding
                          VioServer for this object.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    :param dom_factory: The factory to use to convert the DOM objects.
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_SEA_ADD_START') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': server_sea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Swap in the Server (non-DB backed) VEAs with the real DB backed VEAs
    db_veas = db_vio_server.get_all_virtual_ethernet_adapters()
    db_pvea = _find_adapter(db_veas, server_sea.primary_vea.name)
    db_ctl = None
    if server_sea.control_channel:
        db_ctl = _find_adapter(db_veas, server_sea.control_channel.name)

    db_addl_veas = []
    if server_sea.additional_veas:
        db_addl_veas = _find_adapter_list(db_veas,
                                          server_sea.additional_veas)

    dom_factory.create_sea(server_sea.name,
                           db_vio_server,
                           server_sea.slot,
                           server_sea.state,
                           db_pvea,
                           db_ctl,
                           db_addl_veas)

    msg = (ras.vif_get_msg('info', 'RECONCILE_SEA_ADD_END') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': server_sea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #7
0
def _add_vios(server_vios, host, context, db_session, dom_factory):
    """
    Adds the VioServer object to the database.

    :param server_vios: The server side VioServer object to merge into the
                        database.
    :param host: The host for the VioServer
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    :param dom_factory: The factory to use to convert the DOM objects.
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_VIOS_ADD_START') %
           {'host': server_vios.get_host_name(),
            'vios': server_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Copy into a database backed DOM, because the DOM doesn't yet support
    # a single object to represent both DB and non-DB backed elements.
    db_vio = dom_factory.create_vios(lpar_name=server_vios.lpar_name,
                                     lpar_id=server_vios.lpar_id,
                                     host_name=server_vios.get_host_name(),
                                     state=server_vios.state,
                                     rmc_state=server_vios.rmc_state)

    # The VioServer passed in is a no-DB VioServer object.  First must convert
    # that over to the proper DB backed object and save it.
    db_vio.save(context, db_session)
    host.vio_servers.append(db_vio)

    # Cascade down into the adapters.
    for vea in server_vios.get_all_virtual_ethernet_adapters():
        _add_vea(vea, db_vio, context, db_session, dom_factory)
    for sea in server_vios.get_shared_ethernet_adapters():
        _add_sea(sea, db_vio, context, db_session, dom_factory)

    _cascade_save(db_vio, context, db_session)

    msg = (ras.vif_get_msg('info', 'RECONCILE_VIOS_ADD_END') %
           {'host': server_vios.get_host_name(),
            'vios': server_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #8
0
    def _find_peer_network_sea(self, context, host_name, vlanid, session):
        """
        This method finds whether a given vlanid exists for a host network or
        not. If it finds that this VLAN is part of an existing network, it
        returns the corresponding SEA.

        :param context: The context used to call the dom API
        :param host_id: The host_id of the host for which the network
                        associations are fetched.
        :param vlanid: The vlan id for which the match is needed.
        :param session: The database session object.
        :returns: either an SEA or None
        """
        # The VLAN ID may be none here, indicating a pull for all SEAs.
        if vlanid is None:
            return None

        network_associations = dom_api.\
            network_association_find_all(context, host_name, session)
        # net_map should always be of size 1
        for network_association in network_associations:
            if network_association:
                try:
                    net_api = self._build_network_api()
                    neutron_net = net_api.get(context,
                                              network_association.
                                              neutron_net_id)
                except Exception as e:
                    # Will throw an exception if the neutron client could
                    # not be found
                    ras.trace(LOG, __name__, ras.TRACE_WARNING,
                              _('Neutron client not found for net_id %s' %
                                network_association.neutron_net_id))
            if 'neutron_net' in locals() and neutron_net:
                if neutron_net.get("provider:segmentation_id") == vlanid:
                    # There should be only one SEA per VLAN so we return
                    # as soon as we find one.
                    return network_association.sea
                if neutron_net.get("vlan") == vlanid:
                    return network_association.sea
        return None
Пример #9
0
def _remove_vios(db_vios, host, context, db_session):
    """
    Will remove a VioServer from the database.

    :param db_vios: The DOM object that represents the VioServer to remove from
                    the database.
    :param host: The host for the VioServer
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_VIOS_DEL_START') %
           {'host': db_vios.get_host_name(),
            'vios': db_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    db_vios.delete(context, db_session)
    host.vio_servers.remove(db_vios)

    msg = (ras.vif_get_msg('info', 'RECONCILE_VIOS_DEL_END') %
           {'host': db_vios.get_host_name(),
            'vios': db_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #10
0
def _remove_vea(db_vea, db_vio_server, context, db_session):
    """
    Will remove a VirtualEthernetAdapter from the database.

    :param db_vea: The DOM object that represents the VirtualEthernetAdapter
                   to remove from the database.
    :param db_vio_server: The VioServer that represents the corresponding
                          VioServer for this object.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_VEA_DEL_START') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': db_vea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Need to remove the VEA from the parent SEA.
    owning_sea = db_vio_server.get_sea_for_vea(db_vea)
    if owning_sea is not None:
        # If it is the primary VEA...just ignore...that means the SEA is also
        # being deleted...
        if owning_sea.primary_vea == db_vea:
            pass
        elif owning_sea.control_channel == db_vea:
            owning_sea.control_channel = None
        elif db_vea in owning_sea.additional_veas:
            owning_sea.additional_veas.remove(db_vea)

    db_vea.delete(context, db_session)
    db_vio_server.remove_adapter(db_vea)

    msg = (ras.vif_get_msg('info', 'RECONCILE_VEA_DEL_END') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': db_vea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #11
0
def _add_vea(server_vea, db_vio_server, context, db_session, dom_factory):
    """
    Adds the VirtualEthernetAdapter object to the database.

    :param server_vea: The server side VirtualEthernetAdapter object to merge
                       into the database.
    :param db_vio_server: The VioServer that represents the corresponding
                          VioServer for this object.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    :param dom_factory: The factory to use to convert the DOM objects.
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_VEA_ADD_START') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': server_vea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Copy into a database backed DOM, because the DOM doesn't yet support
    # a single object to represent both DB and non-DB backed elements.
    vea = dom_factory.create_vea(server_vea.name,
                                 db_vio_server,
                                 server_vea.slot,
                                 server_vea.pvid,
                                 server_vea.is_trunk,
                                 server_vea.trunk_pri,
                                 server_vea.state,
                                 server_vea.ieee_eth,
                                 server_vea.vswitch_name,
                                 server_vea.addl_vlan_ids)
    vea.save(context, db_session)

    msg = (ras.vif_get_msg('info', 'RECONCILE_VEA_ADD_END') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': server_vea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #12
0
def _reconcile_vea(db_vea, server_vea, db_vio_server, context, db_session):
    """
    Will reconcile the database VirtualEthernetAdapter to match that of the
    Server side VirtualEthernetAdapter.

    :param db_vea: The DOM object that represents the VirtualEthernetAdapter to
                   update.
    :param server_vea: The DOM object that represents the master data for the
                       database.
    :param db_vio_server: The VioServer that represents the corresponding
                          VioServer for this object.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    """
    msg = (ras.vif_get_msg('info', 'RECONCILE_VEA_START') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': server_vea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    db_vea.name = server_vea.name
    db_vea.pvid = server_vea.pvid
    db_vea.vio_server = db_vio_server
    db_vea.slot = server_vea.slot
    db_vea.is_trunk = server_vea.is_trunk
    db_vea.state = server_vea.state
    db_vea.trunk_pri = server_vea.trunk_pri
    db_vea.ieee_eth = server_vea.ieee_eth
    db_vea.vswitch_name = server_vea.vswitch_name
    db_vea.addl_vlan_ids = server_vea.addl_vlan_ids

    msg = (ras.vif_get_msg('info', 'RECONCILE_VEA_END') %
           {'host': db_vio_server.get_host_name(),
            'vios': db_vio_server.lpar_id,
            'adpt': server_vea.name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #13
0
    def _get_sea_from_ivm(self, vios, sea_devname, virt_eths, dom_factory=model.No_DB_DOM_Factory()):
        """
        Connect to an IVM endpoint and retrieve all of the configuration for a
        SEA and the VEAs associated with it.

        :param vios: The VioServer DOM object that represents this IVM
        :param sea_devname: The device name for the SEA to query
        :param virt_eths: Dictionary of physical adapter info from IVM
        :param dom_factory: Factory used to create the DOM objects, optional.
        :returns SharedEthernetAdapter: An SEA DOM object
        """
        # Got the SEA logical device name on VIOS.
        # Need to find out its pvid_adapter and virt_adapters and pvid
        cmd = utils.get_sea_attribute_cmd(sea_devname)

        output = self._pvmops.run_vios_command(cmd)

        # Output example:
        # ['value', '', '100', 'ent4', 'ent4,ent13,ent14',
        #  'ent24            Available     Shared Ethernet Adapter']
        if len(output) == 0 or output[0] != "value":
            ras.trace(LOG, __name__, ras.TRACE_ERROR, ras.vif_get_msg("error", "VIOS_CMDFAIL") % {"cmd": cmd})
            return None

        # Get rid of 'value','' from the list
        output[0:2] = []

        # Find out pvid adapter and all the virt_adapters for
        # the give SEA and create SeaDevices object based
        # on the information retrieved from HMC/IVM.
        sea_pvid = int(output[0].strip())

        sea_pvid_adpt = output[1].strip()
        sea_virt_adpts = output[2].strip().split(",")
        sea_state = output[3].split()[1]

        # virt_adpts has at least pvid_adpt
        if sea_pvid_adpt not in sea_virt_adpts:
            msg = ras.vif_get_msg("error", "SEA_INVALIDSTATE")
            ras.function_tracepoint(LOG, __name__, ras.TRACE_ERROR, msg)
            return None

        # Get the full virt_adapters list without the pvid_adapter
        sea_virt_adpts.remove(sea_pvid_adpt)

        # Get the slot number for this adapter
        vea_slot_num = utils.parse_slot_num(virt_eths, sea_pvid_adpt)

        # Create the VEA and SEA dom objects
        vea_dev = self._get_vea_for_slot(vios, sea_pvid_adpt, vea_slot_num, sea_pvid, dom_factory)
        sea_dev = dom_factory.create_sea(
            name=sea_devname,
            vio_server=vios,
            slot=vea_slot_num,
            state=sea_state,
            primary_vea=vea_dev,
            control_channel=None,
            additional_veas=None,
        )

        ras.trace(LOG, __name__, ras.TRACE_DEBUG, ("SEA %(devname)s is discovered" % {"devname": sea_devname}))

        # Find all the virt_adapters if there are any in sea_virt_adpts
        # list
        for devname in sea_virt_adpts:

            # Get the slot number for this adapter
            vea_slot_num = utils.parse_slot_num(virt_eths, devname)

            vea_dev = self._get_vea_for_slot(vios, devname, vea_slot_num, sea_pvid, dom_factory)

            try:
                sea_dev.add_vea_to_sea(vea_dev)
            except excp.IBMPowerVMInvalidSEAConfig:
                msg = ras.vif_get_msg("error", "SEA_FAILTOADDVEA") % {"veaname": vea_dev.name, "seaname": sea_dev.name}
                ras.trace(LOG, __name__, ras.TRACE_EXCEPTION, msg)
                return None
        # End of for loop to discovery all the virtual adapters
        # for the SEA. It is the end of the inner for loop
        return sea_dev
Пример #14
0
    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: SEA that owns the VEA.  Not needed on IVM as the VEA is
                    attached to the SEA in a separate step.
        :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: Always returns None
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        try:
            cmd = utils.create_8021Q_vea_cmd(lpar_id=vios.lpar_id,
                                             slotnum=slotnum,
                                             port_vlan_id=port_vlan_id,
                                             addl_vlan_ids=addl_vlan_ids)
            self._pvmops.run_vios_command(cmd)

            # find out the new slot's devname. Even though DR slot add
            # operation will call cfgmgr on the VIOS, just invoke cfgdev
            # again on vio0 to make sure the device is discovered by VIOS.
            cmd = utils.get_newly_added_slot_name_cmd(lpar_id=vios.lpar_id,
                                                      mts=self._get_mts(),
                                                      slotnum=slotnum)

            vea_devname = self._pvmops.run_vios_command(cmd)[0]
            msg = (ras.vif_get_msg('info', 'VEA_DEV_NAME') %
                   {'vea_dev': vea_devname, 'cmd': cmd})
        except Exception as e:  # catch the hmc/vios command exception
            ras.trace(LOG, __name__, ras.TRACE_EXCEPTION,
                      ras.msg('error', 'VETH_NOTCFG') % {'slotnum': slotnum} +
                      "(" + (_('%s') % e) + ")")
            raise

        if not vea_devname:
            # failed to find the newly created veth slot on VIOS. clean it up.
            ras.trace(LOG, __name__, ras.TRACE_ERROR,
                      ras.msg('error', 'VETH_NOTCFG') % {'slotnum': slotnum})
            try:
                cmds = utils.remove_virtual_slot_cmd(lpar_id=vios.lpar_id,
                                                     slot_num=slotnum)
                self._pvmops.run_vios_command(cmds)

                ras.trace(LOG, __name__, ras.TRACE_DEBUG,
                          'Clean up: slot %(slotnum)d has been removed' %
                          {'slotnum': slotnum})

            except Exception:
                ras.trace(LOG, __name__, ras.TRACE_EXCEPTION,
                          ras.msg('error', 'VETH_FAILTOREMOVE') %
                          {'slotnum': slotnum} + "(" + _('%s') % e + ")")

            raise excp.IBMPowerVMFailToAddDataVlan(data_vlan_id=addl_vlan_ids)

        # If we got here, we succeeded!
        return vea_devname, None
Пример #15
0
def _reconcile_host(context, host_data, dom_factory=dom.DOM_Factory(),
                    db_session=None):
    """
    Performs the actual reconciliation at the host level

    :param context: The database context.
    :param host_data: A dictionary of data that represents the latest inventory
                      information on the server.  The data should be in the
                      network DOM format.
    :param dom_factory: Optional factory used to create the DOM objects.  Not
                        required to be set.
    :param db_session: The database session.  Should be started and finalized
                       outside this class.
    """
    if not db_session:
        db_session = session.get_session()

    # Parse the inventory data into a DOM object.  Use the no_db DOM factory
    # as we want to parse into non-DB backed elements to start...
    non_db_fact = dom.No_DB_DOM_Factory()
    server_dom = dom.parse_to_host(host_data, non_db_fact)

    msg = (ras.vif_get_msg('info', 'RECONCILE_HOST_START') %
           {'host': server_dom.host_name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Get the inventory data from the database.
    db_vio_servers = db.vio_server_find_all(context, server_dom.host_name,
                                            db_session)

    # If there are no VIO Servers, the system may be turned off.  It is very
    # unlikely that they are actually removed (all of them at least).
    # Therefore, we flip the SEAs in each VioServer to a state of unavailable
    # and they do not show up in the UI...but are not deleted.
    if len(server_dom.vio_servers) == 0:
        LOG.info(_("Flipping host %s to unavailable due to lack of VioServers"
                   % server_dom.host_name))
        _make_system_unavailable(db_vio_servers, context, db_session)
        return

    # The first step is to find VIO Servers do add/remove/modify.  Those are
    # the three passes that need to be made.
    #
    # We start with the idea that all of the data base items should be removed.
    # From there, we parse down which are still on the system (therefore need
    # to be modified) and then the new adds.
    db_vios_to_del = dom.shallow_copy_as_ordinary_list(db_vio_servers)
    srv_vios_to_add = []
    srv_vios_to_modify = []

    for vio_server in server_dom.vio_servers:
        db_vios = _find_vios(db_vio_servers, vio_server.lpar_id)
        if db_vios:
            srv_vios_to_modify.append(vio_server)
            db_vios_to_del.remove(db_vios)
        else:
            srv_vios_to_add.append(vio_server)

    # Now that we know what to modify/create/delete...loop through each and
    # execute the commands to reconcile
    db_host_dom = dom.Host(server_dom.host_name, db_vio_servers)

    # Save off the network associations first so we can recreate any that
    # need to be later on.
    net_assns = _build_net_assn_dict(
        db.network_association_find_all(context,
                                        db_host_dom.host_name,
                                        db_session))

    for db_vios in db_vios_to_del:
        _remove_vios(db_vios, db_host_dom, context, db_session)
    for server_vios in srv_vios_to_modify:
        _reconcile_vios(_find_vios(db_vio_servers, server_vios.lpar_id),
                        server_vios, context, db_session, dom_factory)
    for server_vios in srv_vios_to_add:
        _add_vios(server_vios, db_host_dom, context, db_session, dom_factory)

    msg = (ras.vif_get_msg('info', 'RECONCILE_HOST_END') %
           {'host': server_dom.host_name})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    # Cleanup NetworkAssociations in case any VIOSes went away or came back.
    _cleanup_network_associations(db_host_dom, net_assns, context, db_session)
Пример #16
0
def _reconcile_vios(db_vios, server_vios, context, db_session, dom_factory):
    """
    Will reconcile the database VioServer object to match that of the Server
    VioServer object.

    :param db_vios: The VioServer object in the database.
    :param server_vios: The VioServer object that represents the current state
                        on the server system.
    :param context: The context for the operations
    :param db_session: The database session to use for this transaction
    :param dom_factory: The factory to use to convert the DOM objects.
    """

    msg = (ras.vif_get_msg('info', 'RECONCILE_VIOS_START') %
           {'host': server_vios.get_host_name(),
            'vios': server_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)

    db_veas = db_vios.get_all_virtual_ethernet_adapters()
    db_seas = db_vios.get_shared_ethernet_adapters()

    srv_veas = server_vios.get_all_virtual_ethernet_adapters()
    srv_seas = server_vios.get_shared_ethernet_adapters()

    # Have to 'load' these objects due to an issue found in 3749.  By calling
    # these, the attributes are loaded into memory.  If we don't do this
    # then when the VEAs change, they may remove themselves from the SEA.
    for db_sea in db_seas:
        db_sea.primary_vea
        db_sea.control_channel
        db_sea.additional_veas

    # Save the rmc_state of the vios.  This may or may not be different than
    # what's already in the db.
    db_vios.rmc_state = server_vios.rmc_state
    ras.trace(LOG, __name__, ras.TRACE_DEBUG,
              'RMC state for lpar %d (%s): %s, ' % (server_vios.lpar_id,
                                                    server_vios.lpar_name,
                                                    server_vios.rmc_state))

    # If the RMC connection is down, then we'll just update the VIOS's
    # rmc_state in the db, no other reconciliation will occur.  Since rmc_state
    # is taken into account when checking whether an adapter is available, we
    # don't need to update all the adapters.
    if server_vios.rmc_state.lower() == 'active':
        # RMC is up, proceed as normal.

        # The first step to reconciliation is the VEAs, as they are input into
        # the SEAs.
        #
        # We start with the idea that all of the VEAs on the VIOS should be
        # removed.  Then the code will parse out from that delete list and
        # create lists of adapters to add and merge.
        db_veas_to_del = dom.shallow_copy_as_ordinary_list(db_veas)
        srv_veas_to_add = []
        srv_veas_to_modify = []

        for srv_vea in srv_veas:
            db_vea = _find_adapter(db_veas, srv_vea.name)
            if db_vea:
                srv_veas_to_modify.append(srv_vea)
                db_veas_to_del.remove(db_vea)
            else:
                srv_veas_to_add.append(srv_vea)

        # We have sorted how each object should be handled.  Handle these
        # before moving on to the SEAs.
        for db_vea in db_veas_to_del:
            _remove_vea(db_vea, db_vios, context, db_session)
        for server_vea in srv_veas_to_modify:
            _reconcile_vea(_find_adapter(db_veas, server_vea.name),
                           server_vea, db_vios, context, db_session)
        for server_vea in srv_veas_to_add:
            _add_vea(server_vea, db_vios, context, db_session, dom_factory)

        # At this point, we have reconciled the VirtualEthernetAdapters.  Next
        # up is the SharedEthernetAdapters, that contain the
        # VirtualEthernetAdapters.
        db_seas_to_del = dom.shallow_copy_as_ordinary_list(db_seas)
        srv_seas_to_add = []
        srv_seas_to_modify = []

        for srv_sea in srv_seas:
            db_sea = _find_adapter(db_seas, srv_sea.name)
            if db_sea:
                srv_seas_to_modify.append(srv_sea)
                db_seas_to_del.remove(db_sea)
            else:
                srv_seas_to_add.append(srv_sea)

        # Now that we have sorted how each object should be handle (Create,
        # Update, or Delete), execute those actions...
        for db_sea in db_seas_to_del:
            _remove_sea(db_sea, db_vios, context, db_session)
        for server_sea in srv_seas_to_modify:
            _reconcile_sea(_find_adapter(db_seas, server_sea.name),
                           server_sea, db_vios, context, db_session)
        for server_sea in srv_seas_to_add:
            _add_sea(server_sea, db_vios, context, db_session, dom_factory)
    else:
        ras.trace(LOG, __name__, ras.TRACE_WARNING,
                  _('RMC state for lpar %(lpar)d (%(lpar_name)s): %(state)s' %
                    {'lpar': server_vios.lpar_id,
                     'lpar_name': server_vios.lpar_name,
                     'state': server_vios.rmc_state}))

    # Whether reconciled or just set rmc_state, we need to save back to the DB.
    _cascade_save(db_vios, context, db_session)

    msg = (ras.vif_get_msg('info', 'RECONCILE_VIOS_END') %
           {'host': server_vios.get_host_name(),
            'vios': server_vios.lpar_id})
    ras.trace(LOG, __name__, ras.TRACE_DEBUG, msg)
Пример #17
0
    def _populate_adapters_into_vios(self, vios, dom_factory=model.No_DB_DOM_Factory()):
        """
        Overridden method from
        powervc_nova.virt.ibmpowervm.vif.topo.IBMPowerVMNetworkTopo

        This method returns all the adapters, both SEA and VEA, for the VIOS
        this IVM runs on.  Each VEA will be attached to it's owning SEA, if it
        has one.

        :param vios: VioServer to fetch adapters from
        :param dom_factory: Factory used to create the DOM objects, optional.
        :returns boolean: True if at least one adapter was found, False
                          otherwise.
        """
        ras.function_tracepoint(LOG, __name__, ras.TRACE_DEBUG, "Enter")

        try:
            # If the VIOS RMC state is down, we can't use adapters on it.
            if vios.rmc_state.lower() != "active":
                ras.trace(LOG, __name__, ras.TRACE_INFO, _("RMC state is not active on VIOS lpar %s") % vios.lpar_name)
                return False

            # Find all of the adapters on the VIOS
            cmd = utils.get_all_sea_with_physloc_cmd()
            output = self._pvmops.run_vios_command(cmd)
            virt_eths = utils.parse_physloc_adapter_output(output)

            # Find all of the SEAs on this IVM
            seas_found = {}
            for vea in virt_eths:
                if virt_eths[vea][0].strip() != "Shared Ethernet Adapter":
                    # this is not a SEA device.
                    continue
                seas_found[vea] = virt_eths[vea]

            # Go through the SEAs and get their current configuration from IVM
            veas_attached_to_seas = []
            for sea_devname in seas_found:

                # Connect to the IVM endpoint and collect the SEA info
                sea_dev = self._get_sea_from_ivm(vios, sea_devname, virt_eths, dom_factory)

                # Keep track of which VEAs are owned by an SEA so we can later
                # detect orphan VEAs
                veas_attached_to_seas.append(sea_dev.primary_vea.name)
                for vea in sea_dev.additional_veas:
                    veas_attached_to_seas.append(vea.name)

            # Any VEA not on an SEA is considered an orphan
            self._find_orphaned_veas(vios, virt_eths, veas_attached_to_seas, dom_factory)

            # Return True if adapters were found
            if len(seas_found.values()) > 0:
                ras.trace(LOG, __name__, ras.TRACE_DEBUG, "SEA discover finished successfully.")
                return True

            ras.trace(LOG, __name__, ras.TRACE_ERROR, ras.vif_get_msg("error", "VIOS_NOSEA"))
            raise excp.IBMPowerVMValidSEANotFound()

        except pvmexcp.IBMPowerVMCommandFailed:
            ras.trace(LOG, __name__, ras.TRACE_EXCEPTION, ras.vif_get_msg("error", "VIOS_CMDFAIL") % {"cmd": cmd})
            return False
        except Exception as e:
            ras.trace(
                LOG, __name__, ras.TRACE_EXCEPTION, ras.vif_get_msg("error", "VIOS_UNKNOWN") + " (" + _("%s") % e + ")"
            )
            return False