def select_destinations(self, context, spec_obj):
"""Selects a filtered set of hosts and nodes."""
self.notifier.info(
context, 'scheduler.select_destinations.start',
dict(request_spec=spec_obj.to_legacy_request_spec_dict()))
num_instances = spec_obj.num_instances
selected_hosts = self._schedule(context, spec_obj)
# Couldn't fulfill the request_spec
if len(selected_hosts) < num_instances:
# NOTE(Rui Chen): If multiple creates failed, set the updated time
# of selected HostState to None so that these HostStates are
# refreshed according to database in next schedule, and release
# the resource consumed by instance in the process of selecting
# host.
for host in selected_hosts:
host.obj.updated = None
# Log the details but don't put those into the reason since
# we don't want to give away too much information about our
# actual environment.
LOG.debug('There are %(hosts)d hosts available but '
'%(num_instances)d instances requested to build.',
{'hosts': len(selected_hosts),
'num_instances': num_instances})
reason = _('There are not enough hosts available.')
raise exception.NoValidHost(reason=reason)
dests = [dict(host=host.obj.host, nodename=host.obj.nodename,
limits=host.obj.limits) for host in selected_hosts]
self.notifier.info(
context, 'scheduler.select_destinations.end',
dict(request_spec=spec_obj.to_legacy_request_spec_dict()))
return dests
在FilterScheduler中的select_destinations 首先调用_schedule来选择一个host。得到selected_hosts后,判断
selected_hosts 判断是否小于需要创建的虚拟机数量num_instances
如果小于的话,直接返回
LOG.debug('There are %(hosts)d hosts available but '
'%(num_instances)d instances requested to build.',
{'hosts': len(selected_hosts),
'num_instances': num_instances})
否则的话就创建一个
dests = [dict(host=host.obj.host, nodename=host.obj.nodename,
limits=host.obj.limits) for host in selected_hosts]
返回.
下来看看_schedule的实现
def _schedule(self, context, spec_obj):
"""Returns a list of hosts that meet the required specs,
ordered by their fitness.
"""
elevated = context.elevated()
config_options = self._get_configuration_options()
# Find our local list of acceptable hosts by repeatedly
# filtering and weighing our options. Each time we choose a
# host, we virtually consume resources on it so subsequent
# selections can adjust accordingly.
# Note: remember, we are using an iterator here. So only
# traverse this list once. This can bite you if the hosts
# are being scanned in a filter or weighing function.
hosts = self._get_all_host_states(elevated)
selected_hosts = []
num_instances = spec_obj.num_instances
# NOTE(sbauza): Adding one field for any out-of-tree need
spec_obj.config_options = config_options
for num in range(num_instances):
# Filter local hosts based on requirements ...
hosts = self.host_manager.get_filtered_hosts(hosts,
spec_obj, index=num)
if not hosts:
# Can't get any more locally.
break
LOG.debug("Filtered %(hosts)s", {'hosts': hosts})
weighed_hosts = self.host_manager.get_weighed_hosts(hosts,
spec_obj)
LOG.debug("Weighed %(hosts)s", {'hosts': weighed_hosts})
scheduler_host_subset_size = max(1,
CONF.scheduler_host_subset_size)
if scheduler_host_subset_size < len(weighed_hosts):
weighed_hosts = weighed_hosts[0:scheduler_host_subset_size]
chosen_host = random.choice(weighed_hosts)
LOG.debug("Selected host: %(host)s", {'host': chosen_host})
selected_hosts.append(chosen_host)
# Now consume the resources so the filter/weights
# will change for the next instance.
chosen_host.obj.consume_from_request(spec_obj)
if spec_obj.instance_group is not None:
spec_obj.instance_group.hosts.append(chosen_host.obj.host)
# hosts has to be not part of the updates when saving
spec_obj.instance_group.obj_reset_changes(['hosts'])
return selected_hosts
在_schedule 中有三个关键的函数
1:hosts = self._get_all_host_states(elevated)
2:hosts = self.host_manager.get_filtered_hosts(hosts,spec_obj, index=num)
3:weighed_hosts = self.host_manager.get_weighed_hosts(hosts,spec_obj)
首先得到host,然后通过get_filtered_hosts 对host 过滤,通过get_weighed_hosts对host计算权重后,最后通过 chosen_host = random.choice(weighed_hosts) 随机返回一个选中的host。
其中会在config文件中host的数量,如果最后得到的weighed_hosts 大于规定的host数量scheduler_host_subset_size。就对weighed_hosts 截断,也就是最多返回weighed_hosts 个host.
scheduler_host_subset_size = max(1,CONF.scheduler_host_subset_size)
if scheduler_host_subset_size < len(weighed_hosts):
weighed_hosts = weighed_hosts[0:scheduler_host_subset_size]
最后将得到的chosen_host,组成一个list selected_hosts.append(chosen_host),然后返回.
"""Selects a filtered set of hosts and nodes."""
self.notifier.info(
context, 'scheduler.select_destinations.start',
dict(request_spec=spec_obj.to_legacy_request_spec_dict()))
num_instances = spec_obj.num_instances
selected_hosts = self._schedule(context, spec_obj)
# Couldn't fulfill the request_spec
if len(selected_hosts) < num_instances:
# NOTE(Rui Chen): If multiple creates failed, set the updated time
# of selected HostState to None so that these HostStates are
# refreshed according to database in next schedule, and release
# the resource consumed by instance in the process of selecting
# host.
for host in selected_hosts:
host.obj.updated = None
# Log the details but don't put those into the reason since
# we don't want to give away too much information about our
# actual environment.
LOG.debug('There are %(hosts)d hosts available but '
'%(num_instances)d instances requested to build.',
{'hosts': len(selected_hosts),
'num_instances': num_instances})
reason = _('There are not enough hosts available.')
raise exception.NoValidHost(reason=reason)
dests = [dict(host=host.obj.host, nodename=host.obj.nodename,
limits=host.obj.limits) for host in selected_hosts]
self.notifier.info(
context, 'scheduler.select_destinations.end',
dict(request_spec=spec_obj.to_legacy_request_spec_dict()))
return dests
在FilterScheduler中的select_destinations 首先调用_schedule来选择一个host。得到selected_hosts后,判断
selected_hosts 判断是否小于需要创建的虚拟机数量num_instances
如果小于的话,直接返回
LOG.debug('There are %(hosts)d hosts available but '
'%(num_instances)d instances requested to build.',
{'hosts': len(selected_hosts),
'num_instances': num_instances})
否则的话就创建一个
dests = [dict(host=host.obj.host, nodename=host.obj.nodename,
limits=host.obj.limits) for host in selected_hosts]
返回.
下来看看_schedule的实现
def _schedule(self, context, spec_obj):
"""Returns a list of hosts that meet the required specs,
ordered by their fitness.
"""
elevated = context.elevated()
config_options = self._get_configuration_options()
# Find our local list of acceptable hosts by repeatedly
# filtering and weighing our options. Each time we choose a
# host, we virtually consume resources on it so subsequent
# selections can adjust accordingly.
# Note: remember, we are using an iterator here. So only
# traverse this list once. This can bite you if the hosts
# are being scanned in a filter or weighing function.
hosts = self._get_all_host_states(elevated)
selected_hosts = []
num_instances = spec_obj.num_instances
# NOTE(sbauza): Adding one field for any out-of-tree need
spec_obj.config_options = config_options
for num in range(num_instances):
# Filter local hosts based on requirements ...
hosts = self.host_manager.get_filtered_hosts(hosts,
spec_obj, index=num)
if not hosts:
# Can't get any more locally.
break
LOG.debug("Filtered %(hosts)s", {'hosts': hosts})
weighed_hosts = self.host_manager.get_weighed_hosts(hosts,
spec_obj)
LOG.debug("Weighed %(hosts)s", {'hosts': weighed_hosts})
scheduler_host_subset_size = max(1,
CONF.scheduler_host_subset_size)
if scheduler_host_subset_size < len(weighed_hosts):
weighed_hosts = weighed_hosts[0:scheduler_host_subset_size]
chosen_host = random.choice(weighed_hosts)
LOG.debug("Selected host: %(host)s", {'host': chosen_host})
selected_hosts.append(chosen_host)
# Now consume the resources so the filter/weights
# will change for the next instance.
chosen_host.obj.consume_from_request(spec_obj)
if spec_obj.instance_group is not None:
spec_obj.instance_group.hosts.append(chosen_host.obj.host)
# hosts has to be not part of the updates when saving
spec_obj.instance_group.obj_reset_changes(['hosts'])
return selected_hosts
在_schedule 中有三个关键的函数
1:hosts = self._get_all_host_states(elevated)
2:hosts = self.host_manager.get_filtered_hosts(hosts,spec_obj, index=num)
3:weighed_hosts = self.host_manager.get_weighed_hosts(hosts,spec_obj)
首先得到host,然后通过get_filtered_hosts 对host 过滤,通过get_weighed_hosts对host计算权重后,最后通过 chosen_host = random.choice(weighed_hosts) 随机返回一个选中的host。
其中会在config文件中host的数量,如果最后得到的weighed_hosts 大于规定的host数量scheduler_host_subset_size。就对weighed_hosts 截断,也就是最多返回weighed_hosts 个host.
scheduler_host_subset_size = max(1,CONF.scheduler_host_subset_size)
if scheduler_host_subset_size < len(weighed_hosts):
weighed_hosts = weighed_hosts[0:scheduler_host_subset_size]
最后将得到的chosen_host,组成一个list selected_hosts.append(chosen_host),然后返回.