Merge "Add helper function for allocating CPUs for DPDK pmd threads"

This commit is contained in:
Jenkins 2017-10-11 13:08:01 +00:00 committed by Gerrit Code Review
commit 6636c54af7
3 changed files with 288 additions and 2 deletions

View File

@ -33,7 +33,7 @@ from daisy.api.v1 import filters
from daisy.common import exception
from daisy.common import utils
from daisy.common import wsgi
from daisy.common import vcpu_pin
from daisy.common import vcpu_pin_dpdk
from daisy import i18n
from daisy import notifier
import daisy.registry.client.v1.api as registry
@ -704,7 +704,7 @@ class Controller(controller.BaseController):
os_handle.check_discover_state(req,
host_meta,
is_detail=True)
host_vcpu_pin = vcpu_pin.allocate_cpus(host_meta)
host_vcpu_pin = vcpu_pin_dpdk.allocate_cpus_for_dpdk(host_meta)
host_meta.update(host_vcpu_pin)
if 'role' in host_meta and 'CONTROLLER_HA' in host_meta['role']:
host_cluster_name = host_meta['cluster']

View File

@ -0,0 +1,265 @@
# Copyright 2017 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
DPDK CPU set helper functions.
"""
from oslo_config import cfg
from oslo_log import log as logging
from daisy.common import utils
from daisy import i18n
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
_ = i18n._
_LE = i18n._LE
# if numa nodes are not same, return -2
def get_numa_by_nic(nics_info, device_numa):
numa = []
try:
for nic in nics_info:
numa.append(device_numa[nic['bus']])
# Remove duplicated numa ids
numa = list(set(numa))
numa_info = (-100 if len(numa) > 1 else numa[0])
except Exception as e:
LOG.error("Error, exception message: %s" % e.message)
numa_info = -200
return numa_info
def dvs_get_cpu_sets(numa_cpus, nics_info, device_numa, num):
dvs_cpu_set = {}
dvsc_cpus = []
cpu_set = {}
msg = ''
return_code = 0
status = {}
if not numa_cpus or not numa_cpus['numa_node0']:
msg = "No NUMA info found for CPUs"
LOG.error(msg)
LOG.info("numa_cpus=%s" % numa_cpus)
return_code = 4
status['rc'] = return_code
status['msg'] = msg
cpu_set = {'high': [-4],
'low': [-4],
'dvs': {'dvsc': [-4],
'dvsp': [-4],
'dvsv': [-4]},
'numa_node': -4}
return (status, cpu_set)
# All DPDK nics should be located in a single NUMA region
numa_node = get_numa_by_nic(nics_info, device_numa)
if numa_node < 0:
if numa_node == -100:
msg = "Get more than one numa nodes for DVS, not supported"
return_code = 2
cpu_set = {'high': [-2],
'low': [-2],
'dvs': {'dvsc': [-2],
'dvsp': [-2],
'dvsv': [-2]},
'numa_node': -2}
elif numa_node == -200:
msg = "Get numa node failed for DVS"
return_code = 3
cpu_set = {'high': [-3],
'low': [-3],
'dvs': {'dvsc': [-3],
'dvsp': [-3],
'dvsv': [-3]},
'numa_node': -3}
else:
msg = "Invalid numa node '%s' for DVS, maybe you "\
"need to upgrade BIOS version" % numa_node
return_code = 1
cpu_set = {'high': [-1],
'low': [-1],
'dvs': {'dvsc': [-1],
'dvsp': [-1],
'dvsv': [-1]},
'numa_node': -1}
LOG.error(msg)
status['rc'] = return_code
status['msg'] = msg
return (status, cpu_set)
numa_key = "numa_node%s" % numa_node
if numa_key not in numa_cpus:
msg = "Unknown numa node '%s'for DVS nic, NUMA CPU is '%s' "\
% (numa_key, numa_cpus)
LOG.error(msg)
return_code = 5
status['rc'] = return_code
status['msg'] = msg
cpu_set = {'high': [-5],
'low': [-5],
'dvs': {'dvsc': [-5],
'dvsp': [-5],
'dvsv': [-5]},
'numa_node': -5}
return (status, cpu_set)
if len(numa_cpus[numa_key]) < 1 + num:
msg = "CPU on numa node '%s' is not enough for DVS" % numa_key
LOG.error(msg)
return_code = 6
status['rc'] = return_code
status['msg'] = msg
cpu_set = {'high': [-6],
'low': [-6],
'dvs': {'dvsc': [-6],
'dvsp': [-6],
'dvsv': [-6]},
'numa_node': -6}
return (status, cpu_set)
# Allocate num CPUs from each NUMA region for DPDK's pmd thread
for key in numa_cpus.keys():
# sort
numa_cpus[key] = sorted(numa_cpus[key])
dvsc_cpus += numa_cpus[key][1:1+num]
dvs_cpu_set['dvsc'] = dvsc_cpus # for pmd thread
dvs_cpu_set['dvsp'] = [-1] # Not used
dvs_cpu_set['dvsv'] = [-1] # Not used
cpu_set['numa_node'] = numa_node # Not used currently
cpu_set['dvs'] = dvs_cpu_set
cpu_set['high'] = [-1] # Not used
cpu_set['low'] = [-1] # Not used
LOG.info("cpu_set:%s" % cpu_set)
msg = 'Success'
status['rc'] = return_code
status['msg'] = msg
return (status, cpu_set)
def get_dvs_cpusets(numa_cpus, dvs_interfaces, host_hw_info, num):
nics_info = []
# For simplity, do not support bond interface currently
for dvs_interface in dvs_interfaces:
if dvs_interface['type'] == 'ether':
nics_info.append({'name': dvs_interface['name'],
'bus': dvs_interface['pci']})
dvs_cpusets = {}
if nics_info:
LOG.info("DVS netcard info: '%s'" % nics_info)
device_numa = {}
for device in host_hw_info['devices'].values():
device_numa.update(device)
(status, dvs_cpusets) = \
dvs_get_cpu_sets(numa_cpus,
nics_info,
device_numa)
if status['rc'] != 0:
msg = "Get dvs cpu sets for host '%s' failed,\
detail error is '%s'"\
% (host_hw_info['id'], status['msg'])
LOG.error(msg)
else:
dvs_cpusets = {'high': [-7],
'low': [-7],
'dvs': {'dvsc': [-7],
'dvsp': [-7],
'dvsv': [-7]},
'numa_node': -7}
msg = "Can't get DVS nics for host %s" % host_hw_info['id']
LOG.error(msg)
return dvs_cpusets
# If any interface is selected for dvs(dpdk), then allocate cpus for pmd thread
def allocate_dvs_cpus(host_detail, num):
dvs_cpu_sets = {}
host_interfaces = host_detail.get('interfaces')
if not host_interfaces:
return dvs_cpu_sets
# 'vswitch_type' in interface and
# interface['vswitch_type'] == 'dvs'
dvs_interfaces = utils.get_dvs_interfaces(host_interfaces)
if not dvs_interfaces:
return dvs_cpu_sets
# extract host_hw_info out from host_detail
host_hw_info = {'id': '', 'system': '', 'memory': '',
'cpu': '', 'disks': '', 'interfaces': '',
'pci': '', 'devices': ''}
host_obj = host_detail
for f in host_hw_info:
host_hw_info[f] = host_obj.get(f)
# Given host_hw_info.get('cpu', {}) =
# host_cpu = {"numa_node0": "0-7,16-23",
# "numa_node1": "8-15,24-31"}
# then get_numa_node_cpus will return cpu id list as follows:
# {'numa_node0': [0,1,2,3,4,5,6,7, 16,17,18,19,20,21,22,23],
# 'numa_node1': [8,9,10,11,12,13,14,15, 24,25,26,27,28,29,30,31]}
numa_cpus = utils.get_numa_node_cpus(host_hw_info.get('cpu', {}))
LOG.info("Get DVS cpusets of host '%s'" % host_hw_info.get('id'))
dvs_cpu_sets = get_dvs_cpusets(numa_cpus,
dvs_interfaces,
host_hw_info, num)
return dvs_cpu_sets
def allocate_cpus_for_dpdk(host_detail, num=1):
host_cpu_sets = {'suggest_dvs_high_cpuset': '',
'pci_high_cpuset': '',
'suggest_dvs_cpus': '',
'suggest_dvsc_cpus': '', # CPU Ids for pmd threads.
'suggest_dvsp_cpus': '',
'suggest_dvsv_cpus': '',
'suggest_os_cpus': '',
'numa_node': ''}
dvs_cpusets = allocate_dvs_cpus(host_detail, num)
if (not dvs_cpusets):
return host_cpu_sets
host_cpu_sets['numa_node'] = dvs_cpusets.get('numa_node', []) # Not used
if dvs_cpusets.get('dvs', {}):
if dvs_cpusets['dvs'].get('dvsc', []):
host_cpu_sets['suggest_dvsc_cpus'] =\
utils.cpu_list_to_str(dvs_cpusets['dvs'].get('dvsc', []))
host_cpu_sets['suggest_dvs_cpus'] =\
utils.cpu_list_to_str(dvs_cpusets['dvs'].get('dvsc', []))
host_cpu_sets['suggest_dvsp_cpus'] = [-1] # Not used
host_cpu_sets['suggest_dvsv_cpus'] = [-1] # Not used
host_cpu_sets['suggest_os_cpus'] = [-1] # Not used
host_cpu_sets['suggest_dvs_high_cpuset'] = [-1] # Not used
host_cpu_sets['pci_high_cpuset'] = [-1] # Not used
LOG.info("NUMA CPU usage for host %s: %s"
% (host_detail['id'], host_cpu_sets))
return host_cpu_sets

21
doc/zuul_setup.txt Normal file
View File

@ -0,0 +1,21 @@
Currently daisycloud-core use 3rd party fashion of check and gate job.
To setup zuul and jenkins job:
1. git clone https://github.com/huzhijiang/ansible-zuul,
2. Copy CMD to its parent directory and run CMD, this will setup zuul
on localhost.
3. Setup jenkins version 1.625.x on localhost. and make it run as root.
4. Add the following plugins to jenkins:
Gearman Plugin
Git plugin
Parameterized Trigger plugin
Post-Build Script Plug-in
SCP publisher plugin
5. Push all jobs in jjb directory/
6. Done.