def bind_port(self, port_context): """Set binding for a valid segment """ host_name = port_context.host elements = list() try: # Append to empty list to add as much elements as possible # in the case it raises an exception elements.extend(self._fetch_elements_by_host(host_name)) except Exception: LOG.exception( _LE('Error fetching elements for host %(host_name)r.'), {'host_name': host_name}, exc_info=1) if not elements: # In case it wasn't able to find any network topology element # for given host then it uses the legacy OVS one keeping the old # behaviour LOG.warning( _LW('Using legacy OVS network topology element for port ' 'binding for host: %(host_name)r.'), {'host_name': host_name}) # Imported here to avoid cyclic module dependencies from networking_odl.ml2 import ovsdb_topology elements = [ovsdb_topology.OvsdbNetworkTopologyElement()] # TODO(Federico Ressi): in the case there are more candidate virtual # switches instances for the same host it choses one for binding # port. As there isn't any know way to perform this selection it # selects a VIF type that is valid for all switches that have # been found and a VIF type valid for all them. This has to be improved for vif_type in self.valid_vif_types: vif_type_is_valid_for_all = True for element in elements: if vif_type not in element.valid_vif_types: # it is invalid for at least one element: discard it vif_type_is_valid_for_all = False break if vif_type_is_valid_for_all: # This is the best VIF type valid for all elements LOG.debug( "Found VIF type %(vif_type)r valid for all network " "topology elements for host %(host_name)r.", { 'vif_type': vif_type, 'host_name': host_name }) for element in elements: # It assumes that any element could be good for given host # In most of the cases I expect exactely one element for # every compute host try: return element.bind_port(port_context, vif_type, self._vif_details) except Exception: LOG.exception( _LE('Network topology element has failed binding ' 'port:\n%(element)s'), {'element': element.to_json()}) LOG.error( _LE('Unable to bind port element for given host and valid VIF ' 'types:\n' '\thostname: %(host_name)s\n' '\tvalid VIF types: %(valid_vif_types)s'), { 'host_name': host_name, 'valid_vif_types': ', '.join(self.valid_vif_types) })
def fetch_all(self, keys, timeout): # this mean now in numbers current_clock = time.clock() # this is the moment in the future in which new entries will expires new_entries_timeout = current_clock + timeout # entries to be fetched because missing or expired new_entries = collections.OrderedDict() # all entries missing or expired missing = collections.OrderedDict() # captured error for the case a problem has to be reported cause_exc_info = None for key in keys: entry = self._entries.get(key) if entry is None or entry.is_expired(current_clock) or entry.error: # this entry has to be fetched new_entries[key] = missing[key] =\ self.create_new_entry(new_entries_timeout) elif entry.values: # Yield existing entry for value in entry.values: yield key, value else: # This entry is not expired and there were no error where it # has been fetch. Therefore we accept that there are no values # for given key until it expires. This is going to produce a # KeyError if it is still missing at the end of this function. missing[key] = entry if missing: if new_entries: # Fetch some entries and update the cache try: new_entry_keys = tuple(new_entries) for key, value in self._fetch_all(new_entry_keys): entry = new_entries.get(key) if entry: # Add fresh new value entry.add_value(value) else: # This key was not asked, but we take it in any # way. "Noli equi dentes inspicere donati." new_entries[key] = entry = self.create_new_entry( new_entries_timeout, value) # pylint: disable=broad-except except Exception: # Something has gone wrong: update and yield what got until # now before raising any error cause_exc_info = sys.exc_info() LOG.warning( _LW('Error fetching values for keys: %r'), ', '.join(repr(k) for k in new_entry_keys), exc_info=cause_exc_info) # update the cache with new fresh entries self._entries.update(new_entries) missing_keys = [] for key, entry in six.iteritems(missing): if entry.values: # yield entries that was missing before for value in entry.values: # Yield just fetched entry yield key, value else: if cause_exc_info: # mark this entry as failed entry.error = cause_exc_info # after all this entry is still without any value missing_keys.append(key) if missing_keys: # After all some entry is still missing, probably because the # key was invalid. It's time to raise an error. missing_keys = tuple(missing_keys) if not cause_exc_info: # Search for the error cause in missing entries for key in missing_keys: error = self._entries[key].error if error: # A cached entry for which fetch method produced an # error will produce the same error if fetch method # fails to fetch it again without giving any error # Is this what we want? break else: # If the cause of the problem is not knwow then # probably keys were wrong message = 'Invalid keys: {!r}'.format( ', '.join(missing_keys)) error = KeyError(message) try: raise error except KeyError: cause_exc_info = sys.exc_info() raise CacheFetchError( missing_keys=missing_keys, cause_exc_info=cause_exc_info)
def bind_port(self, port_context): """Set binding for a valid segment """ host_name = port_context.host elements = list() try: # Append to empty list to add as much elements as possible # in the case it raises an exception elements.extend(self._fetch_elements_by_host(host_name)) except Exception: LOG.exception( _LE('Error fetching elements for host %(host_name)r.'), {'host_name': host_name}, exc_info=1) if not elements: # In case it wasn't able to find any network topology element # for given host then it uses the legacy OVS one keeping the old # behaviour LOG.warning( _LW('Using legacy OVS network topology element for port ' 'binding for host: %(host_name)r.'), {'host_name': host_name}) # Imported here to avoid cyclic module dependencies from networking_odl.ml2 import ovsdb_topology elements = [ovsdb_topology.OvsdbNetworkTopologyElement()] # TODO(Federico Ressi): in the case there are more candidate virtual # switches instances for the same host it choses one for binding # port. As there isn't any know way to perform this selection it # selects a VIF type that is valid for all switches that have # been found and a VIF type valid for all them. This has to be improved for vif_type in self.valid_vif_types: vif_type_is_valid_for_all = True for element in elements: if vif_type not in element.valid_vif_types: # it is invalid for at least one element: discard it vif_type_is_valid_for_all = False break if vif_type_is_valid_for_all: # This is the best VIF type valid for all elements LOG.debug( "Found VIF type %(vif_type)r valid for all network " "topology elements for host %(host_name)r.", {'vif_type': vif_type, 'host_name': host_name}) for element in elements: # It assumes that any element could be good for given host # In most of the cases I expect exactely one element for # every compute host try: return element.bind_port( port_context, vif_type, self._vif_details) except Exception: LOG.exception( _LE('Network topology element has failed binding ' 'port:\n%(element)s'), {'element': element.to_json()}) LOG.error( _LE('Unable to bind port element for given host and valid VIF ' 'types:\n' '\thostname: %(host_name)s\n' '\tvalid VIF types: %(valid_vif_types)s'), {'host_name': host_name, 'valid_vif_types': ', '.join(self.valid_vif_types)})
def fetch_all(self, keys, timeout): # this mean now in numbers current_clock = time.clock() # this is the moment in the future in which new entries will expires new_entries_timeout = current_clock + timeout # entries to be fetched because missing or expired new_entries = collections.OrderedDict() # all entries missing or expired missing = collections.OrderedDict() # captured error for the case a problem has to be reported cause_exc_info = None for key in keys: entry = self._entries.get(key) if entry is None or entry.is_expired(current_clock) or entry.error: # this entry has to be fetched new_entries[key] = missing[key] =\ self.create_new_entry(new_entries_timeout) elif entry.values: # Yield existing entry for value in entry.values: yield key, value else: # This entry is not expired and there were no error where it # has been fetch. Therefore we accept that there are no values # for given key until it expires. This is going to produce a # KeyError if it is still missing at the end of this function. missing[key] = entry if missing: if new_entries: # Fetch some entries and update the cache try: new_entry_keys = tuple(new_entries) for key, value in self._fetch_all(new_entry_keys): entry = new_entries.get(key) if entry: # Add fresh new value entry.add_value(value) else: # This key was not asked, but we take it in any # way. "Noli equi dentes inspicere donati." new_entries[key] = entry = self.create_new_entry( new_entries_timeout, value) # pylint: disable=broad-except except Exception: # Something has gone wrong: update and yield what got until # now before raising any error cause_exc_info = sys.exc_info() LOG.warning(_LW('Error fetching values for keys: %r'), ', '.join(repr(k) for k in new_entry_keys), exc_info=cause_exc_info) # update the cache with new fresh entries self._entries.update(new_entries) missing_keys = [] for key, entry in six.iteritems(missing): if entry.values: # yield entries that was missing before for value in entry.values: # Yield just fetched entry yield key, value else: if cause_exc_info: # mark this entry as failed entry.error = cause_exc_info # after all this entry is still without any value missing_keys.append(key) if missing_keys: # After all some entry is still missing, probably because the # key was invalid. It's time to raise an error. missing_keys = tuple(missing_keys) if not cause_exc_info: # Search for the error cause in missing entries for key in missing_keys: error = self._entries[key].error if error: # A cached entry for which fetch method produced an # error will produce the same error if fetch method # fails to fetch it again without giving any error # Is this what we want? break else: # If the cause of the problem is not knwow then # probably keys were wrong message = 'Invalid keys: {!r}'.format( ', '.join(missing_keys)) error = KeyError(message) try: raise error except KeyError: cause_exc_info = sys.exc_info() raise CacheFetchError(missing_keys=missing_keys, cause_exc_info=cause_exc_info)