1
# Copyright 2014-2015 Canonical Limited.
3
# This file is part of charm-helpers.
5
# charm-helpers is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU Lesser General Public License version 3 as
7
# published by the Free Software Foundation.
9
# charm-helpers is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU Lesser General Public License for more details.
14
# You should have received a copy of the GNU Lesser General Public License
15
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
17
# Various utilies for dealing with Neutron and the renaming from Quantum.
20
from subprocess import check_output
22
from charmhelpers.core.hookenv import (
28
from charmhelpers.contrib.openstack.utils import os_release
31
def headers_package():
32
"""Ensures correct linux-headers for running kernel are installed,
33
for building DKMS package"""
34
kver = check_output(['uname', '-r']).decode('UTF-8').strip()
35
return 'linux-headers-%s' % kver
37
QUANTUM_CONF_DIR = '/etc/quantum'
41
""" Retrieve the current major kernel version as a tuple e.g. (3, 13) """
42
kver = check_output(['uname', '-r']).decode('UTF-8').strip()
43
kver = kver.split('.')
44
return (int(kver[0]), int(kver[1]))
47
def determine_dkms_package():
48
""" Determine which DKMS package should be used based on kernel version """
49
# NOTE: 3.13 kernels have support for GRE and VXLAN native
50
if kernel_version() >= (3, 13):
53
return ['openvswitch-datapath-dkms']
59
def quantum_plugins():
60
from charmhelpers.contrib.openstack import context
63
'config': '/etc/quantum/plugins/openvswitch/'
64
'ovs_quantum_plugin.ini',
65
'driver': 'quantum.plugins.openvswitch.ovs_quantum_plugin.'
68
context.SharedDBContext(user=config('neutron-database-user'),
69
database=config('neutron-database'),
70
relation_prefix='neutron',
71
ssl_dir=QUANTUM_CONF_DIR)],
72
'services': ['quantum-plugin-openvswitch-agent'],
73
'packages': [[headers_package()] + determine_dkms_package(),
74
['quantum-plugin-openvswitch-agent']],
75
'server_packages': ['quantum-server',
76
'quantum-plugin-openvswitch'],
77
'server_services': ['quantum-server']
80
'config': '/etc/quantum/plugins/nicira/nvp.ini',
81
'driver': 'quantum.plugins.nicira.nicira_nvp_plugin.'
82
'QuantumPlugin.NvpPluginV2',
84
context.SharedDBContext(user=config('neutron-database-user'),
85
database=config('neutron-database'),
86
relation_prefix='neutron',
87
ssl_dir=QUANTUM_CONF_DIR)],
90
'server_packages': ['quantum-server',
91
'quantum-plugin-nicira'],
92
'server_services': ['quantum-server']
96
NEUTRON_CONF_DIR = '/etc/neutron'
99
def neutron_plugins():
100
from charmhelpers.contrib.openstack import context
101
release = os_release('nova-common')
104
'config': '/etc/neutron/plugins/openvswitch/'
105
'ovs_neutron_plugin.ini',
106
'driver': 'neutron.plugins.openvswitch.ovs_neutron_plugin.'
107
'OVSNeutronPluginV2',
109
context.SharedDBContext(user=config('neutron-database-user'),
110
database=config('neutron-database'),
111
relation_prefix='neutron',
112
ssl_dir=NEUTRON_CONF_DIR)],
113
'services': ['neutron-plugin-openvswitch-agent'],
114
'packages': [[headers_package()] + determine_dkms_package(),
115
['neutron-plugin-openvswitch-agent']],
116
'server_packages': ['neutron-server',
117
'neutron-plugin-openvswitch'],
118
'server_services': ['neutron-server']
121
'config': '/etc/neutron/plugins/nicira/nvp.ini',
122
'driver': 'neutron.plugins.nicira.nicira_nvp_plugin.'
123
'NeutronPlugin.NvpPluginV2',
125
context.SharedDBContext(user=config('neutron-database-user'),
126
database=config('neutron-database'),
127
relation_prefix='neutron',
128
ssl_dir=NEUTRON_CONF_DIR)],
131
'server_packages': ['neutron-server',
132
'neutron-plugin-nicira'],
133
'server_services': ['neutron-server']
136
'config': '/etc/neutron/plugins/vmware/nsx.ini',
139
context.SharedDBContext(user=config('neutron-database-user'),
140
database=config('neutron-database'),
141
relation_prefix='neutron',
142
ssl_dir=NEUTRON_CONF_DIR)],
145
'server_packages': ['neutron-server',
146
'neutron-plugin-vmware'],
147
'server_services': ['neutron-server']
150
'config': '/etc/neutron/plugins/cisco/cisco_plugins.ini',
151
'driver': 'neutron.plugins.cisco.network_plugin.PluginV2',
153
context.SharedDBContext(user=config('neutron-database-user'),
154
database=config('neutron-database'),
155
relation_prefix='neutron',
156
ssl_dir=NEUTRON_CONF_DIR)],
158
'packages': [[headers_package()] + determine_dkms_package(),
159
['neutron-plugin-cisco']],
160
'server_packages': ['neutron-server',
161
'neutron-plugin-cisco'],
162
'server_services': ['neutron-server']
165
'config': '/etc/neutron/plugins/ml2/ml2_conf.ini',
166
'driver': 'neutron.plugins.ml2.plugin.Ml2Plugin',
168
context.SharedDBContext(user=config('neutron-database-user'),
169
database=config('neutron-database'),
170
relation_prefix='neutron',
171
ssl_dir=NEUTRON_CONF_DIR)],
172
'services': ['calico-felix',
174
'neutron-dhcp-agent',
177
'packages': [[headers_package()] + determine_dkms_package(),
180
'neutron-dhcp-agent',
183
'server_packages': ['neutron-server', 'calico-control', 'etcd'],
184
'server_services': ['neutron-server', 'etcd']
187
'config': '/etc/neutron/plugins/nuage/nuage_plugin.ini',
188
'driver': 'neutron.plugins.nuage.plugin.NuagePlugin',
190
context.SharedDBContext(user=config('neutron-database-user'),
191
database=config('neutron-database'),
192
relation_prefix='neutron',
193
ssl_dir=NEUTRON_CONF_DIR)],
196
'server_packages': ['neutron-server', 'neutron-plugin-nuage'],
197
'server_services': ['neutron-server']
200
'config': '/etc/neutron/plugins/plumgrid/plumgrid.ini',
201
'driver': 'neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin.NeutronPluginPLUMgridV2',
203
context.SharedDBContext(user=config('database-user'),
204
database=config('database'),
205
ssl_dir=NEUTRON_CONF_DIR)],
207
'packages': [['plumgrid-lxc'],
209
'server_packages': ['neutron-server',
210
'neutron-plugin-plumgrid'],
211
'server_services': ['neutron-server']
214
'config': '/etc/neutron/plugins/midonet/midonet.ini',
215
'driver': 'midonet.neutron.plugin.MidonetPluginV2',
217
context.SharedDBContext(user=config('neutron-database-user'),
218
database=config('neutron-database'),
219
relation_prefix='neutron',
220
ssl_dir=NEUTRON_CONF_DIR)],
222
'packages': [[headers_package()] + determine_dkms_package()],
223
'server_packages': ['neutron-server',
224
'python-neutron-plugin-midonet'],
225
'server_services': ['neutron-server']
228
if release >= 'icehouse':
229
# NOTE: patch in ml2 plugin for icehouse onwards
230
plugins['ovs']['config'] = '/etc/neutron/plugins/ml2/ml2_conf.ini'
231
plugins['ovs']['driver'] = 'neutron.plugins.ml2.plugin.Ml2Plugin'
232
plugins['ovs']['server_packages'] = ['neutron-server',
233
'neutron-plugin-ml2']
234
# NOTE: patch in vmware renames nvp->nsx for icehouse onwards
235
plugins['nvp'] = plugins['nsx']
239
def neutron_plugin_attribute(plugin, attr, net_manager=None):
240
manager = net_manager or network_manager()
241
if manager == 'quantum':
242
plugins = quantum_plugins()
243
elif manager == 'neutron':
244
plugins = neutron_plugins()
246
log("Network manager '%s' does not support plugins." % (manager),
251
_plugin = plugins[plugin]
253
log('Unrecognised plugin for %s: %s' % (manager, plugin), level=ERROR)
262
def network_manager():
264
Deals with the renaming of Quantum to Neutron in H and any situations
265
that require compatability (eg, deploying H with network-manager=quantum,
268
release = os_release('nova-common')
269
manager = config('network-manager').lower()
271
if manager not in ['quantum', 'neutron']:
274
if release in ['essex']:
275
# E does not support neutron
276
log('Neutron networking not supported in Essex.', level=ERROR)
278
elif release in ['folsom', 'grizzly']:
279
# neutron is named quantum in F and G
282
# ensure accurate naming for all releases post-H
286
def parse_mappings(mappings, key_rvalue=False):
287
"""By default mappings are lvalue keyed.
289
If key_rvalue is True, the mapping will be reversed to allow multiple
290
configs for the same lvalue.
294
mappings = mappings.split()
301
# if there is no rvalue skip to next
308
key = p[key_index].strip()
309
parsed[key] = p[val_index].strip()
314
def parse_bridge_mappings(mappings):
315
"""Parse bridge mappings.
317
Mappings must be a space-delimited list of provider:bridge mappings.
319
Returns dict of the form {provider:bridge}.
321
return parse_mappings(mappings)
324
def parse_data_port_mappings(mappings, default_bridge='br-data'):
325
"""Parse data port mappings.
327
Mappings must be a space-delimited list of bridge:port.
329
Returns dict of the form {port:bridge} where ports may be mac addresses or
333
# NOTE(dosaboy): we use rvalue for key to allow multiple values to be
334
# proposed for <port> since it may be a mac address which will differ
335
# across units this allowing first-known-good to be chosen.
336
_mappings = parse_mappings(mappings, key_rvalue=True)
337
if not _mappings or list(_mappings.values()) == ['']:
341
# For backwards-compatibility we need to support port-only provided in
343
_mappings = {mappings.split()[0]: default_bridge}
345
ports = _mappings.keys()
346
if len(set(ports)) != len(ports):
347
raise Exception("It is not allowed to have the same port configured "
348
"on more than one bridge")
353
def parse_vlan_range_mappings(mappings):
354
"""Parse vlan range mappings.
356
Mappings must be a space-delimited list of provider:start:end mappings.
358
The start:end range is optional and may be omitted.
360
Returns dict of the form {provider: (start, end)}.
362
_mappings = parse_mappings(mappings)
367
for p, r in six.iteritems(_mappings):
368
mappings[p] = tuple(r.split(':'))