Implement neutron venv support

This commit conditionally allows the os_neutron role to
install build and deploy within a venv. This is the new
default behavior of the role however the functionality
can be disabled.

In this PR, like all of the other venv related PRs, the 
`is_metal` flag was removed from the role however unlike 
some of the other PRs this removal required moving some 
of the `is_metal` logic out of the role and into the 
play. This was done for consistency as well as making 
the role more standalone. The only thing that the role 
should care about, in terms of installation, is whether 
or not to install in a venv.

Implements: blueprint enable-venv-support-within-the-roles

Change-Id: I85aadc43e1c21f296b2fb5932a17eddce57b9ece
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
This commit is contained in:
Kevin Carter 2015-10-03 00:32:12 -05:00
parent 29376e5ebc
commit 2d5fdca577
27 changed files with 220 additions and 70 deletions

View File

@ -19,6 +19,25 @@ is_metal: true
## Verbosity Options ## Verbosity Options
debug: False debug: False
verbose: True verbose: True
# Name of the virtual env to deploy into
neutron_venv_tag: untagged
neutron_venv_bin: "/openstack/venvs/neutron-{{ neutron_venv_tag }}/bin"
# Set this to enable or disable installing in a venv
neutron_venv_enabled: true
# The bin path defaults to the venv path however if installation in a
# venv is disabled the bin path will be dynamically set based on the
# system path used when the installing.
neutron_bin: "{{ neutron_venv_bin }}"
# Set the lib dir path to that of the local python path where neutron is installed.
# This is used for role access to the db migrations.
# Example:
# neutron_lib_dir: "/usr/local/lib/python2.7/dist-packages/neutron"
neutron_lib_dir: "{{ neutron_bin | dirname }}/lib/python2.7/site-packages/neutron"
neutron_fatal_deprecations: False neutron_fatal_deprecations: False
## neutron User / Group ## neutron User / Group
@ -250,6 +269,8 @@ neutron_vxlan_group: ""
# network_vlan_ranges: "vlan:1:1,vlan:1024:1025" # network_vlan_ranges: "vlan:1:1,vlan:1024:1025"
# network_vxlan_ranges: "1:1000" # network_vxlan_ranges: "1:1000"
neutron_vxlan_enabled: true
neutron_dhcp_domain: openstacklocal neutron_dhcp_domain: openstacklocal
neutron_dhcp_delete_namespaces: True neutron_dhcp_delete_namespaces: True
# Comma-separated list of DNS servers which will be used by dnsmasq as forwarders. # Comma-separated list of DNS servers which will be used by dnsmasq as forwarders.
@ -273,6 +294,9 @@ neutron_rpc_response_timeout: 60
# "create_subnet": "rule:admin_or_network_owner" # "create_subnet": "rule:admin_or_network_owner"
# "get_subnet": "rule:admin_or_owner or rule:shared" # "get_subnet": "rule:admin_or_owner or rule:shared"
# neutron_local_ip is used for the VXLAN local tunnel endpoint
neutron_local_ip: 127.0.0.1
neutron_apt_packages: neutron_apt_packages:
- conntrack - conntrack
- dnsmasq-base - dnsmasq-base
@ -286,6 +310,11 @@ neutron_apt_packages:
neutron_apt_remove_packages: neutron_apt_remove_packages:
- conntrackd - conntrackd
# neutron packages that must be installed before anything else
neutron_requires_pip_packages:
- virtualenv
- python-keystoneclient # Keystoneclient needed to OSA keystone lib
neutron_pip_packages: neutron_pip_packages:
- configobj - configobj
- cliff - cliff

View File

@ -18,6 +18,7 @@ import re
import subprocess import subprocess
from ansible.module_utils.basic import * from ansible.module_utils.basic import *
DOCUMENTATION = """ DOCUMENTATION = """
--- ---
module: neutron_migrations_facts module: neutron_migrations_facts
@ -38,45 +39,89 @@ options:
- This is the OpenStack release you're running, used when - This is the OpenStack release you're running, used when
searching for migration revisions in the neutron code. searching for migration revisions in the neutron code.
default: liberty default: liberty
library_path:
description:
- Local path to the location where the neutron python package
is installed.
default: /usr/local/lib/python2.7/dist-packages/neutron
bin_path:
description:
- Local path to the where the neutron binaries are.
default: /usr/local/bin
author: Rcbops author: Rcbops
""" """
EXAMPLES = """ EXAMPLES = """
- name: Gather neutron migration facts - name: Gather neutron migration facts
neutron_migrations_facts: neutron_migrations_facts:
release: mitaka release: mitaka
""" """
MIGRATIONS = {'expand': {'revision': None, 'head': None},
'contract': {'revision': None, 'head': None}} MIGRATIONS = {
'expand': {
'revision': None,
'head': None
},
'contract': {
'revision': None,
'head': None
}
}
def get_branch(release, revision): def get_branch(release, revision, library_path):
migrations_dir = '/usr/local/lib/python2.7/dist-packages/neutron/db/' \ migrations_dir = (
'migration/alembic_migrations/versions/%s/' % release '%s/db/migration/alembic_migrations/versions/%s/' % (
library_path,
release,
)
)
for branch in MIGRATIONS.keys(): for branch in MIGRATIONS.keys():
for file in os.listdir('%s/%s' % (migrations_dir, branch)): migration_dir = os.path.join(get_abs_path(migrations_dir), branch)
for file in os.listdir(migration_dir):
if file.endswith('.py') and file.split('_')[0] == revision: if file.endswith('.py') and file.split('_')[0] == revision:
return branch return branch
def get_abs_path(path):
return os.path.abspath(
os.path.expanduser(
path
)
)
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
release=dict( release=dict(
type='str', type='str',
default='liberty' default='liberty'
),
library_path=dict(
type='str',
default='/usr/local/lib/python2.7/dist-packages/neutron'
),
bin_path=dict(
type='str',
default='/usr/local/bin'
) )
), ),
supports_check_mode=False supports_check_mode=False
) )
state_change = False state_change = False
command = [
'%s/neutron-db-manage' % get_abs_path(module.params['bin_path']),
'current'
]
try: try:
current = subprocess.check_output(['neutron-db-manage', 'current']) current = subprocess.check_output(command)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
message = 'neutron fact collection failed: "%s".' % e module.fail_json(msg='neutron fact collection failed: "%s".' % e)
module.fail_json(msg=message)
for line in current.splitlines(): for line in current.splitlines():
head = False head = False
@ -85,17 +130,25 @@ def main():
revision = match.group(1) revision = match.group(1)
if match.group(2): if match.group(2):
head = True head = True
branch = get_branch(module.params['release'], revision)
branch = get_branch(
release=module.params['release'],
revision=revision,
library_path=get_abs_path(module.params['library_path'])
)
if branch is None: if branch is None:
message = 'neutron fact collection failed: unable to find ' \ module.fail_json(
'migration with revision %s' % revision msg='neutron fact collection failed: unable to find'
module.fail_json(msg=message) ' migration with revision %s' % revision
)
MIGRATIONS[branch]['revision'] = revision MIGRATIONS[branch]['revision'] = revision
MIGRATIONS[branch]['head'] = head MIGRATIONS[branch]['head'] = head
module.exit_json(changed=state_change, module.exit_json(
ansible_facts={'neutron_migrations': MIGRATIONS}) changed=state_change,
ansible_facts={'neutron_migrations': MIGRATIONS}
)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -42,6 +42,8 @@
- name: Get neutron migrations facts - name: Get neutron migrations facts
neutron_migrations_facts: neutron_migrations_facts:
release: liberty release: liberty
library_path: "{{ neutron_lib_dir }}"
bin_path: "{{ neutron_bin }}"
tags: tags:
- neutron-db-setup - neutron-db-setup
- neutron-upgrade - neutron-upgrade
@ -54,7 +56,8 @@
- name: Perform a Neutron DB online upgrade (expand) - name: Perform a Neutron DB online upgrade (expand)
command: | command: |
neutron-db-manage --config-file {{ neutron_db_config }} {{ neutron_bin }}/neutron-db-manage
--config-file {{ neutron_db_config }}
--config-file {{ neutron_db_plugin }} --config-file {{ neutron_db_plugin }}
upgrade --expand upgrade --expand
sudo: yes sudo: yes
@ -78,7 +81,8 @@
- name: Perform a Neutron DB offline upgrade (contract) - name: Perform a Neutron DB offline upgrade (contract)
command: | command: |
neutron-db-manage --config-file {{ neutron_db_config }} {{ neutron_bin }}/neutron-db-manage
--config-file {{ neutron_db_config }}
--config-file {{ neutron_db_plugin }} --config-file {{ neutron_db_plugin }}
upgrade --contract upgrade --contract
sudo: yes sudo: yes

View File

@ -34,6 +34,7 @@
delay: 2 delay: 2
with_items: neutron_apt_packages with_items: neutron_apt_packages
tags: tags:
- neutron-install
- neutron-apt-packages - neutron-apt-packages
- name: remove specific apt packages - name: remove specific apt packages
@ -46,9 +47,43 @@
delay: 2 delay: 2
with_items: neutron_apt_remove_packages with_items: neutron_apt_remove_packages
tags: tags:
- neutron-install
- neutron-apt-packages - neutron-apt-packages
- name: Install pip packages - name: Install requires pip packages
pip:
name: "{{ item }}"
state: present
extra_args: "{{ pip_install_options|default('') }}"
register: install_packages
until: install_packages|success
retries: 5
delay: 2
with_items:
- "{{ neutron_requires_pip_packages }}"
tags:
- neutron-install
- neutron-pip-packages
- name: Install pip packages (venv)
pip:
name: "{{ item }}"
state: present
virtualenv: "{{ neutron_venv_bin | dirname }}"
virtualenv_site_packages: "no"
extra_args: "{{ pip_install_options|default('') }}"
register: install_packages
until: install_packages|success
retries: 5
delay: 2
with_items:
- "{{ neutron_pip_packages }}"
when: neutron_venv_enabled | bool
tags:
- neutron-install
- neutron-pip-packages
- name: Install pip packages (no venv)
pip: pip:
name: "{{ item }}" name: "{{ item }}"
state: present state: present
@ -59,5 +94,7 @@
delay: 2 delay: 2
with_items: with_items:
- "{{ neutron_pip_packages }}" - "{{ neutron_pip_packages }}"
when: not neutron_venv_enabled | bool
tags: tags:
- neutron-pip-packages - neutron-install
- neutron-pip-packages

View File

@ -17,8 +17,8 @@
# kilo_revision: true # kilo_revision: true
- name: "Drop AT&T neutron ha tool" - name: "Drop AT&T neutron ha tool"
copy: template:
src: "neutron-ha-tool.py" src: "neutron-ha-tool.py.j2"
dest: "/opt/neutron-ha-tool.py" dest: "/opt/neutron-ha-tool.py"
owner: "root" owner: "root"
group: "root" group: "root"

View File

@ -13,19 +13,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
- name: Ensure service tenant
shell: |
. {{ ansible_env.HOME }}/openrc && keystone tenant-list | awk '/service/ {print $2}'
register: service_id
tags:
- neutron-config
- name: Set service tenant id
set_fact:
nova_admin_tenant_id: "{{ service_id.stdout }}"
tags:
- neutron-config
- name: Copy neutron config - name: Copy neutron config
config_template: config_template:
src: "{{ item.src }}" src: "{{ item.src }}"
@ -97,29 +84,29 @@
- neutron-config - neutron-config
- name: Drop neutron Configs - name: Drop neutron Configs
copy: template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ item.dest }}" dest: "{{ item.dest }}"
owner: "{{ neutron_system_user_name }}" owner: "{{ neutron_system_user_name }}"
group: "{{ neutron_system_group_name }}" group: "{{ neutron_system_group_name }}"
with_items: with_items:
- { src: "rootwrap.d/debug.filters", dest: "/etc/neutron/rootwrap.d/debug.filters" } - { src: "rootwrap.d/debug.filters.j2", dest: "/etc/neutron/rootwrap.d/debug.filters" }
- { src: "rootwrap.d/ipset-firewall.filters", dest: "/etc/neutron/rootwrap.d/ipset-firewall.filters" } - { src: "rootwrap.d/ipset-firewall.filters.j2", dest: "/etc/neutron/rootwrap.d/ipset-firewall.filters" }
- { src: "rootwrap.d/iptables-firewall.filters", dest: "/etc/neutron/rootwrap.d/iptables-firewall.filters" } - { src: "rootwrap.d/iptables-firewall.filters.j2", dest: "/etc/neutron/rootwrap.d/iptables-firewall.filters" }
- { src: "rootwrap.d/nec-plugin.filters", dest: "/etc/neutron/rootwrap.d/nec-plugin.filters" } - { src: "rootwrap.d/nec-plugin.filters.j2", dest: "/etc/neutron/rootwrap.d/nec-plugin.filters" }
- { src: "rootwrap.d/openvswitch-plugin.filters", dest: "/etc/neutron/rootwrap.d/openvswitch-plugin.filters" } - { src: "rootwrap.d/openvswitch-plugin.filters.j2", dest: "/etc/neutron/rootwrap.d/openvswitch-plugin.filters" }
- { src: "rootwrap.d/ryu-plugin.filters", dest: "/etc/neutron/rootwrap.d/ryu-plugin.filters" } - { src: "rootwrap.d/ryu-plugin.filters.j2", dest: "/etc/neutron/rootwrap.d/ryu-plugin.filters" }
- { src: "rootwrap.d/lbaas-haproxy.filters", dest: "/etc/neutron/rootwrap.d/lbaas-haproxy.filters" } - { src: "rootwrap.d/lbaas-haproxy.filters.j2", dest: "/etc/neutron/rootwrap.d/lbaas-haproxy.filters" }
- { src: "rootwrap.d/vpnaas.filters", dest: "/etc/neutron/rootwrap.d/vpnaas.filters" } - { src: "rootwrap.d/vpnaas.filters.j2", dest: "/etc/neutron/rootwrap.d/vpnaas.filters" }
- { src: "rootwrap.d/ebtables.filters", dest: "/etc/neutron/rootwrap.d/ebtables.filters" } - { src: "rootwrap.d/ebtables.filters.j2", dest: "/etc/neutron/rootwrap.d/ebtables.filters" }
notify: notify:
- Restart neutron services - Restart neutron services
tags: tags:
- neutron-config - neutron-config
- name: Drop neutron agent filters - name: Drop neutron agent filters
copy: template:
src: "{{ item.value.service_rootwrap }}" src: "{{ item.value.service_rootwrap }}.j2"
dest: "/etc/neutron/{{ item.value.service_rootwrap }}" dest: "/etc/neutron/{{ item.value.service_rootwrap }}"
owner: "{{ neutron_system_user_name }}" owner: "{{ neutron_system_user_name }}"
group: "{{ neutron_system_group_name }}" group: "{{ neutron_system_group_name }}"
@ -156,3 +143,19 @@
- name: Setup PLUMgrid config - name: Setup PLUMgrid config
include: plumgrid_config.yml include: plumgrid_config.yml
when: neutron_plugin_type == 'plumgrid' when: neutron_plugin_type == 'plumgrid'
- name: Get neutron command path
command: which neutron
register: neutron_command_path
when:
- not neutron_venv_enabled | bool
tags:
- neutron-command-bin
- name: Set neutron command path
set_fact:
neutron_bin: "{{ neutron_command_path.stdout | dirname }}"
when:
- not neutron_venv_enabled | bool
tags:
- neutron-command-bin

View File

@ -40,6 +40,7 @@
owner: "{{ item.owner|default(neutron_system_user_name) }}" owner: "{{ item.owner|default(neutron_system_user_name) }}"
group: "{{ item.group|default(neutron_system_group_name) }}" group: "{{ item.group|default(neutron_system_group_name) }}"
with_items: with_items:
- { path: "/openstack", owner: "root", group: "root" }
- { path: "/etc/neutron" } - { path: "/etc/neutron" }
- { path: "/etc/neutron/plugins" } - { path: "/etc/neutron/plugins" }
- { path: "/etc/neutron/plugins/{{ neutron_plugin_type }}" } - { path: "/etc/neutron/plugins/{{ neutron_plugin_type }}" }
@ -53,6 +54,19 @@
tags: tags:
- neutron-dirs - neutron-dirs
- name: Create neutron venv dir
file:
path: "{{ item.path }}"
state: directory
owner: "{{ item.owner|default(neutron_system_user_name) }}"
group: "{{ item.group|default(neutron_system_group_name) }}"
with_items:
- { path: "/openstack/venvs", mode: "0755", owner: "root", group: "root" }
- { path: "{{ neutron_venv_bin }}" }
when: neutron_venv_enabled | bool
tags:
- neutron-dirs
- name: Test for log directory or link - name: Test for log directory or link
shell: | shell: |
if [ -h "/var/log/neutron" ]; then if [ -h "/var/log/neutron" ]; then

View File

@ -33,4 +33,7 @@
retries: 5 retries: 5
delay: 2 delay: 2
when: when:
inventory_hostname in groups['neutron_server'] - inventory_hostname in groups['neutron_server']
tags:
- neutron-install
- neutron-pip-packages

View File

@ -21,6 +21,14 @@ from collections import OrderedDict
import logging import logging
from logging.handlers import SysLogHandler from logging.handlers import SysLogHandler
import os import os
{% if neutron_venv_enabled | bool %}
activate_this = os.path.expanduser("{{ neutron_venv_bin }}/activate_this.py")
execfile(activate_this, dict(__file__=activate_this))
{% endif %}
import random import random
import sys import sys
import time import time

View File

@ -12,7 +12,7 @@ respawn
respawn limit 10 5 respawn limit 10 5
# Set the RUNBIN environment variable # Set the RUNBIN environment variable
env RUNBIN="/usr/local/bin/{{ program_name }}" env RUNBIN="{{ neutron_bin }}/{{ program_name }}"
# Change directory to service users home # Change directory to service users home
chdir "{{ service_home }}" chdir "{{ service_home }}"
@ -24,6 +24,11 @@ pre-start script
mkdir -p "/var/lock/{{ program_name }}" mkdir -p "/var/lock/{{ program_name }}"
chown {{ system_user }}:{{ system_group }} "/var/lock/{{ program_name }}" chown {{ system_user }}:{{ system_group }} "/var/lock/{{ program_name }}"
{% if neutron_venv_enabled | bool -%}
. {{ neutron_venv_bin }}/activate
{%- endif %}
end script end script
# Post stop actions # Post stop actions

View File

@ -146,7 +146,7 @@ service_provider = VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsec
[agent] [agent]
polling_interval = {{ neutron_agent_polling_interval|default(5) }} polling_interval = {{ neutron_agent_polling_interval|default(5) }}
report_interval = {{ neutron_report_interval|int }} report_interval = {{ neutron_report_interval|int }}
root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf root_helper = sudo {{ neutron_bin }}/neutron-rootwrap /etc/neutron/rootwrap.conf
# Messaging service # Messaging service
[oslo_messaging_rabbit] [oslo_messaging_rabbit]

View File

@ -30,7 +30,7 @@ network_vlan_ranges = {{ neutron_provider_networks.network_vlan_ranges }}
# ML2 VXLAN networks # ML2 VXLAN networks
[ml2_type_vxlan] [ml2_type_vxlan]
vxlan_group = {{ neutron_vxlan_group|default('') }} vxlan_group = {{ neutron_vxlan_group }}
vni_ranges = {{ neutron_provider_networks.network_vxlan_ranges }} vni_ranges = {{ neutron_provider_networks.network_vxlan_ranges }}
{% endif %} {% endif %}
@ -41,23 +41,13 @@ vni_ranges = {{ neutron_provider_networks.network_vxlan_ranges }}
# Linux bridge agent VXLAN networks # Linux bridge agent VXLAN networks
[vxlan] [vxlan]
{% if neutron_overlay_network %} {% if neutron_vxlan_enabled | bool %}
enable_vxlan = True enable_vxlan = True
vxlan_group = {{ neutron_vxlan_group|default('') }} vxlan_group = {{ neutron_vxlan_group }}
{% if (is_metal == true or is_metal == "True") and neutron_overlay_network.bridge is defined %} # VXLAN local tunnel endpoint
{% set on_metal_tunnel_bridge = 'ansible_' + neutron_overlay_network.bridge|replace('-', '_') %} local_ip = {{ neutron_local_ip }}
# VXLAN local tunnel endpoint (bare metal)
local_ip = {{ hostvars[inventory_hostname][on_metal_tunnel_bridge]['ipv4']['address'] }}
{% else %}
# VXLAN local tunnel endpoint (container)
local_ip = {{ neutron_overlay_network.address }}
{% endif %}
l2_population = {{ neutron_l2_population }} l2_population = {{ neutron_l2_population }}

View File

@ -40,7 +40,7 @@ metadata_mode = local
# Use "sudo neutron-rootwrap /etc/neutron/rootwrap.conf" to use the real # Use "sudo neutron-rootwrap /etc/neutron/rootwrap.conf" to use the real
# root filter facility. # root filter facility.
# Change to "sudo" to skip the filtering and just run the comand directly # Change to "sudo" to skip the filtering and just run the comand directly
root_helper_name = /usr/bin/neutron-rootwrap root_helper_name = {{ neutron_bin }}/neutron-rootwrap
[keystone_authtoken] [keystone_authtoken]
admin_user = {{ neutron_service_user_name }} admin_user = {{ neutron_service_user_name }}

View File

@ -10,7 +10,7 @@ filters_path=/etc/neutron/rootwrap.d,/usr/share/neutron/rootwrap
# explicitely specify a full path (separated by ',') # explicitely specify a full path (separated by ',')
# If not specified, defaults to system PATH environment variable. # If not specified, defaults to system PATH environment variable.
# These directories MUST all be only writeable by root ! # These directories MUST all be only writeable by root !
exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin exec_dirs={{ neutron_bin }},/sbin,/usr/sbin,/bin,/usr/bin
# Enable logging to syslog # Enable logging to syslog
# Default value is False # Default value is False

View File

@ -25,7 +25,8 @@ dhcp_release: CommandFilter, dhcp_release, root
metadata_proxy: CommandFilter, neutron-ns-metadata-proxy, root metadata_proxy: CommandFilter, neutron-ns-metadata-proxy, root
# If installed from source (say, by devstack), the prefix will be # If installed from source (say, by devstack), the prefix will be
# /usr/local instead of /usr/bin. # /usr/local instead of /usr/bin.
metadata_proxy_local: CommandFilter, /usr/local/bin/neutron-ns-metadata-proxy, root
metadata_proxy_local: CommandFilter, {{ neutron_bin }}/neutron-ns-metadata-proxy, root
# RHEL invocation of the metadata proxy will report /usr/bin/python # RHEL invocation of the metadata proxy will report /usr/bin/python
kill_metadata: KillFilter, root, python, -9 kill_metadata: KillFilter, root, python, -9
kill_metadata7: KillFilter, root, python2.7, -9 kill_metadata7: KillFilter, root, python2.7, -9

View File

@ -20,7 +20,8 @@ radvd: CommandFilter, radvd, root
metadata_proxy: CommandFilter, neutron-ns-metadata-proxy, root metadata_proxy: CommandFilter, neutron-ns-metadata-proxy, root
# If installed from source (say, by devstack), the prefix will be # If installed from source (say, by devstack), the prefix will be
# /usr/local instead of /usr/bin. # /usr/local instead of /usr/bin.
metadata_proxy_local: CommandFilter, /usr/local/bin/neutron-ns-metadata-proxy, root
metadata_proxy_local: CommandFilter, {{ neutron_bin }}/neutron-ns-metadata-proxy, root
# RHEL invocation of the metadata proxy will report /usr/bin/python # RHEL invocation of the metadata proxy will report /usr/bin/python
kill_metadata: KillFilter, root, python, -9 kill_metadata: KillFilter, root, python, -9
kill_metadata7: KillFilter, root, python2.7, -9 kill_metadata7: KillFilter, root, python2.7, -9

View File

@ -1,4 +1,6 @@
# {{ ansible_managed }} # {{ ansible_managed }}
# Defaults:{{ neutron_system_user_name }}!requiretty Defaults:{{ neutron_system_user_name }} !requiretty
{{ neutron_system_user_name }} ALL = (root) NOPASSWD: /usr/local/bin/{{ neutron_service_name }}-rootwrap Defaults:{{ neutron_system_user_name }} secure_path="{{ neutron_bin }}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
{{ neutron_system_user_name }} ALL = (root) NOPASSWD: {{ neutron_bin }}/{{ neutron_service_name }}-rootwrap