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)
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)