def schedule_unscheduled_bgp_speakers(self, context, host): """Schedule unscheduled BgpSpeaker to a BgpDrAgent. """ LOG.debug('Started auto-scheduling on host %s', host) with context.session.begin(subtransactions=True): bgp_dragent = obj_reg.load_class('Agent').get_object( context, agent_type=bgp_consts.AGENT_TYPE_BGP_ROUTING, host=host, admin_state_up=True) if not bgp_dragent: LOG.debug('No enabled BgpDrAgent on host %s', host) return False if utils.is_agent_down( bgp_dragent.heartbeat_timestamp): LOG.warning(_LW('BgpDrAgent %s is down'), bgp_dragent.id) return False if self._is_bgp_speaker_hosted(context, bgp_dragent['id']): # One BgpDrAgent can only host one BGP speaker LOG.debug('BgpDrAgent already hosting a speaker on host %s. ' 'Cannot schedule an another one', host) return False unscheduled_speakers = self._get_unscheduled_bgp_speakers(context) if not unscheduled_speakers: LOG.debug('Nothing to auto-schedule on host %s', host) return False self.bind(context, [bgp_dragent], unscheduled_speakers[0]) return True
def auto_schedule_networks(self, plugin, context, host): """Schedule non-hosted networks to the DHCP agent on the specified host. """ agents_per_network = cfg.CONF.dhcp_agents_per_network # a list of (agent, net_ids) tuples bindings_to_add = [] with context.session.begin(subtransactions=True): fields = ['network_id', 'enable_dhcp', 'segment_id'] subnets = plugin.get_subnets(context, fields=fields) net_ids = {} net_segment_ids = collections.defaultdict(set) for s in subnets: if s['enable_dhcp']: net_segment_ids[s['network_id']].add(s.get('segment_id')) for network_id, segment_ids in net_segment_ids.items(): is_routed_network = any(segment_ids) net_ids[network_id] = is_routed_network if not net_ids: LOG.debug('No non-hosted networks') return False dhcp_agents = agent_obj.Agent.get_objects( context, agent_type=constants.AGENT_TYPE_DHCP, host=host, admin_state_up=True) segment_host_mapping = network.SegmentHostMapping.get_objects( context, host=host) segments_on_host = {s.segment_id for s in segment_host_mapping} for dhcp_agent in dhcp_agents: if agent_utils.is_agent_down( dhcp_agent.heartbeat_timestamp): LOG.warning('DHCP agent %s is not active', dhcp_agent.id) continue for net_id, is_routed_network in net_ids.items(): agents = plugin.get_dhcp_agents_hosting_networks( context, [net_id]) segments_on_network = net_segment_ids[net_id] if is_routed_network: if len(segments_on_network & segments_on_host) == 0: continue else: if len(agents) >= agents_per_network: continue if any(dhcp_agent.id == agent.id for agent in agents): continue net = plugin.get_network(context, net_id) az_hints = (net.get(az_def.AZ_HINTS) or cfg.CONF.default_availability_zones) if (az_hints and dhcp_agent['availability_zone'] not in az_hints): continue bindings_to_add.append((dhcp_agent, net_id)) # do it outside transaction so particular scheduling results don't # make other to fail for agent, net_id in bindings_to_add: self.resource_filter.bind(context, [agent], net_id) return True
def is_eligible_agent(active, agent): if active is None: # filtering by activeness is disabled, all agents are eligible return True else: # note(rpodolyaka): original behaviour is saved here: if active # filter is set, only agents which are 'up' # (i.e. have a recent heartbeat timestamp) # are eligible, even if active is False return not agent_utils.is_agent_down(agent["heartbeat_timestamp"])
def _make_agent_dict(self, agent, fields=None): attr = ext_agent.RESOURCE_ATTRIBUTE_MAP.get( ext_agent.RESOURCE_NAME + 's') res = dict((k, agent[k]) for k in attr if k not in ['alive', 'configurations']) res['alive'] = not utils.is_agent_down( res['heartbeat_timestamp'] ) res['configurations'] = self._get_dict(agent, 'configurations') res['resource_versions'] = self._get_dict(agent, 'resource_versions', ignore_missing=True) res['availability_zone'] = agent['availability_zone'] return db_utils.resource_fields(res, fields)
def get_enabled_agent_on_host(self, context, agent_type, host): """Return agent of agent_type for the specified host.""" query = context.session.query(agent_model.Agent) query = query.filter(agent_model.Agent.agent_type == agent_type, agent_model.Agent.host == host, agent_model.Agent.admin_state_up == sql.true()) try: agent = query.one() except exc.NoResultFound: LOG.debug('No enabled %(agent_type)s agent on host ' '%(host)s', {'agent_type': agent_type, 'host': host}) return if utils.is_agent_down(agent.heartbeat_timestamp): LOG.warning(_LW('%(agent_type)s agent %(agent_id)s is not active'), {'agent_type': agent_type, 'agent_id': agent.id}) return agent
def get_enabled_agent_on_host(self, context, agent_type, host): """Return agent of agent_type for the specified host.""" agent = agent_obj.Agent.get_object(context, agent_type=agent_type, host=host, admin_state_up=True) if not agent: LOG.debug('No enabled %(agent_type)s agent on host ' '%(host)s', {'agent_type': agent_type, 'host': host}) return if utils.is_agent_down(agent.heartbeat_timestamp): LOG.warning('%(agent_type)s agent %(agent_id)s is not active', {'agent_type': agent_type, 'agent_id': agent.id}) return agent
def is_eligible_agent(active, agent): if active is None: # filtering by activeness is disabled, all agents are eligible return True else: # note(rpodolyaka): original behaviour is saved here: if active # filter is set, only agents which are 'up' # (i.e. have a recent heartbeat timestamp) # are eligible, even if active is False if agent_utils.is_agent_down(agent['heartbeat_timestamp']): LOG.warning( 'Agent %(agent)s is down. Type: %(type)s, host: ' '%(host)s, heartbeat: %(heartbeat)s', { 'agent': agent['id'], 'type': agent['agent_type'], 'host': agent['host'], 'heartbeat': agent['heartbeat_timestamp'] }) return False return True
def get_l3_agents_hosting_routers(self, context, router_ids, admin_state_up=None, active=None): if not router_ids: return [] query = context.session.query(rb_model.RouterL3AgentBinding) query = query.options(orm.contains_eager( rb_model.RouterL3AgentBinding.l3_agent)) query = query.join(rb_model.RouterL3AgentBinding.l3_agent) query = query.filter( rb_model.RouterL3AgentBinding.router_id.in_(router_ids)) if admin_state_up is not None: query = (query.filter(agent_model.Agent.admin_state_up == admin_state_up)) l3_agents = [binding.l3_agent for binding in query] if active is not None: l3_agents = [l3_agent for l3_agent in l3_agents if not agent_utils.is_agent_down( l3_agent['heartbeat_timestamp'])] return l3_agents
def get_l3_agents_hosting_routers(self, context, router_ids, admin_state_up=None, active=None): if not router_ids: return [] record_objs = rb_obj.RouterL3AgentBinding.get_objects( context, router_id=router_ids) if admin_state_up is not None: l3_agents = ag_obj.Agent.get_objects(context, id=[obj.l3_agent_id for obj in record_objs], admin_state_up=admin_state_up) else: l3_agents = [ ag_obj.Agent.get_object(context, id=obj.l3_agent_id) for obj in record_objs ] if active is not None: l3_agents = [l3_agent for l3_agent in l3_agents if not agent_utils.is_agent_down( l3_agent['heartbeat_timestamp'])] return l3_agents
def get_enabled_agent_on_host(self, context, agent_type, host): """Return agent of agent_type for the specified host.""" agent = agent_obj.Agent.get_object(context, agent_type=agent_type, host=host, admin_state_up=True) if not agent: LOG.debug('No enabled %(agent_type)s agent on host ' '%(host)s', { 'agent_type': agent_type, 'host': host }) return if utils.is_agent_down(agent.heartbeat_timestamp): LOG.warning('%(agent_type)s agent %(agent_id)s is not active', { 'agent_type': agent_type, 'agent_id': agent.id }) return agent
def get_enabled_agent_on_host(self, context, agent_type, host): """Return agent of agent_type for the specified host.""" query = context.session.query(agent_model.Agent) query = query.filter(agent_model.Agent.agent_type == agent_type, agent_model.Agent.host == host, agent_model.Agent.admin_state_up == sql.true()) try: agent = query.one() except exc.NoResultFound: LOG.debug('No enabled %(agent_type)s agent on host ' '%(host)s', { 'agent_type': agent_type, 'host': host }) return if utils.is_agent_down(agent.heartbeat_timestamp): LOG.warning('%(agent_type)s agent %(agent_id)s is not active', { 'agent_type': agent_type, 'agent_id': agent.id }) return agent
def monitor_agent_state(self): """Represents L2gateway agent scheduler thread. Maintains list of active and inactive agents based on the heartbeat recorded. """ context = neutron_context.get_admin_context() try: all_agents = self.plugin.get_agents( context, filters={'agent_type': [srv_const.AGENT_TYPE_L2GATEWAY]}) except Exception: LOG.exception("Unable to get the agent list. Continuing...") return # Reset the agents that will be processed for selecting the # Monitor agent agents_to_process = [] for agent in all_agents: if not utils.is_agent_down(agent['heartbeat_timestamp']): agents_to_process.append(agent) if agents_to_process: self._select_agent_type(context, agents_to_process) return
def auto_schedule_networks(self, plugin, context, host): """Schedule non-hosted networks to the DHCP agent on the specified host. """ agents_per_network = cfg.CONF.dhcp_agents_per_network # a list of (agent, net_ids) tuples bindings_to_add = [] # NOTE(ralonsoh) use writer manager to call get_network. See # https://review.opendev.org/#/c/483518/. Must be changed to READER. with db_api.CONTEXT_WRITER.using(context): fields = ['network_id', 'enable_dhcp', 'segment_id'] subnets = plugin.get_subnets(context, fields=fields) net_ids = {} net_segment_ids = collections.defaultdict(set) for s in subnets: if s['enable_dhcp']: net_segment_ids[s['network_id']].add(s.get('segment_id')) for network_id, segment_ids in net_segment_ids.items(): is_routed_network = any(segment_ids) net_ids[network_id] = is_routed_network if not net_ids: LOG.debug('No non-hosted networks') return False dhcp_agents = agent_obj.Agent.get_objects( context, agent_type=constants.AGENT_TYPE_DHCP, host=host, admin_state_up=True) segment_host_mapping = network.SegmentHostMapping.get_objects( context, host=host) segments_on_host = {s.segment_id for s in segment_host_mapping} for dhcp_agent in dhcp_agents: if agent_utils.is_agent_down(dhcp_agent.heartbeat_timestamp): LOG.warning('DHCP agent %s is not active', dhcp_agent.id) continue for net_id, is_routed_network in net_ids.items(): agents = plugin.get_dhcp_agents_hosting_networks( context, [net_id]) segments_on_network = net_segment_ids[net_id] if is_routed_network: if len(segments_on_network & segments_on_host) == 0: continue else: if len(agents) >= agents_per_network: continue if any(dhcp_agent.id == agent.id for agent in agents): continue net = plugin.get_network(context, net_id) az_hints = (net.get(az_def.AZ_HINTS) or cfg.CONF.default_availability_zones) if (az_hints and dhcp_agent['availability_zone'] not in az_hints): continue bindings_to_add.append( (dhcp_agent, net_id, is_routed_network)) # do it outside transaction so particular scheduling results don't # make other to fail debug_data = [] for agent, net_id, is_routed_network in bindings_to_add: self.resource_filter.bind(context, [agent], net_id, force_scheduling=is_routed_network) debug_data.append('(%s, %s, %s)' % (agent['agent_type'], agent['host'], net_id)) LOG.debug('Resources bound (agent type, host, resource id): %s', ', '.join(debug_data)) return True
def is_agent_down(heart_beat_time): return utils.is_agent_down(heart_beat_time)
def is_active(self): return not utils.is_agent_down(self.heartbeat_timestamp)
def auto_schedule_networks(self, plugin, context, host): """Schedule non-hosted networks to the DHCP agent on the specified host. """ agents_per_network = cfg.CONF.dhcp_agents_per_network # a list of (agent, net_ids) tuples bindings_to_add = [] with context.session.begin(subtransactions=True): fields = ['network_id', 'enable_dhcp', 'segment_id'] subnets = plugin.get_subnets(context, fields=fields) net_ids = {} net_segment_ids = collections.defaultdict(set) for s in subnets: if s['enable_dhcp']: net_segment_ids[s['network_id']].add(s.get('segment_id')) for network_id, segment_ids in net_segment_ids.items(): is_routed_network = any(segment_ids) net_ids[network_id] = is_routed_network if not net_ids: LOG.debug('No non-hosted networks') return False query = context.session.query(agent_model.Agent) query = query.filter( agent_model.Agent.agent_type == constants.AGENT_TYPE_DHCP, agent_model.Agent.host == host, agent_model.Agent.admin_state_up == sql.true()) dhcp_agents = query.all() segment_host_mapping = network.SegmentHostMapping.get_objects( context, host=host) segments_on_host = {s.segment_id for s in segment_host_mapping} for dhcp_agent in dhcp_agents: if agent_utils.is_agent_down(dhcp_agent.heartbeat_timestamp): LOG.warning('DHCP agent %s is not active', dhcp_agent.id) continue for net_id, is_routed_network in net_ids.items(): agents = plugin.get_dhcp_agents_hosting_networks( context, [net_id]) segments_on_network = net_segment_ids[net_id] if is_routed_network: if len(segments_on_network & segments_on_host) == 0: continue else: if len(agents) >= agents_per_network: continue if any(dhcp_agent.id == agent.id for agent in agents): continue net = plugin.get_network(context, net_id) az_hints = (net.get(az_def.AZ_HINTS) or cfg.CONF.default_availability_zones) if (az_hints and dhcp_agent['availability_zone'] not in az_hints): continue bindings_to_add.append((dhcp_agent, net_id)) # do it outside transaction so particular scheduling results don't # make other to fail for agent, net_id in bindings_to_add: self.resource_filter.bind(context, [agent], net_id) return True