File: rtconf.py

package info (click to toggle)
python-os-ken 3.1.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 21,320 kB
  • sloc: python: 100,703; erlang: 14,517; ansic: 594; sh: 338; makefile: 136
file content (325 lines) | stat: -rw-r--r-- 11,415 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
#
# 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.

"""
 Runtime configuration manager.
"""
import logging

from os_ken.services.protocols.bgp.api.base import register
from os_ken.services.protocols.bgp.api.base import RegisterWithArgChecks
from os_ken.services.protocols.bgp.api.base import FLOWSPEC_FAMILY
from os_ken.services.protocols.bgp.api.base import FLOWSPEC_RULES
from os_ken.services.protocols.bgp.api.base import FLOWSPEC_ACTIONS
from os_ken.services.protocols.bgp.core_manager import CORE_MANAGER
from os_ken.services.protocols.bgp.rtconf.base import ConfWithId
from os_ken.services.protocols.bgp.rtconf.base import RuntimeConfigError
from os_ken.services.protocols.bgp.rtconf import neighbors
from os_ken.services.protocols.bgp.rtconf.neighbors import NeighborConf
from os_ken.services.protocols.bgp.rtconf.vrfs import ROUTE_DISTINGUISHER
from os_ken.services.protocols.bgp.rtconf.vrfs import VRF_RF
from os_ken.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
from os_ken.services.protocols.bgp.rtconf.vrfs import VrfConf
from os_ken.services.protocols.bgp import constants as const

LOG = logging.getLogger('bgpspeaker.api.rtconf')


# =============================================================================
# Neighbor configuration related APIs
# =============================================================================


def _get_neighbor_conf(neigh_ip_address):
    """Returns neighbor configuration for given neighbor ip address.

    Raises exception if no neighbor with `neigh_ip_address` exists.
    """
    neigh_conf = \
        CORE_MANAGER.neighbors_conf.get_neighbor_conf(neigh_ip_address)
    if not neigh_conf:
        raise RuntimeConfigError(desc='No Neighbor configuration with IP'
                                 ' address %s' % neigh_ip_address)
    assert isinstance(neigh_conf, NeighborConf)
    return neigh_conf


@register(name='neighbor.create')
def create_neighbor(**kwargs):
    neigh_conf = NeighborConf(**kwargs)
    CORE_MANAGER.neighbors_conf.add_neighbor_conf(neigh_conf)
    return True


@RegisterWithArgChecks(name='neighbor.update_enabled',
                       req_args=[neighbors.IP_ADDRESS, neighbors.ENABLED])
def update_neighbor_enabled(neigh_ip_address, enabled):
    neigh_conf = _get_neighbor_conf(neigh_ip_address)
    neigh_conf.enabled = enabled
    return True


@RegisterWithArgChecks(name='neighbor.update',
                       req_args=[neighbors.IP_ADDRESS, neighbors.CHANGES])
def update_neighbor(neigh_ip_address, changes):
    rets = []
    for k, v in changes.items():
        if k == neighbors.MULTI_EXIT_DISC:
            rets.append(_update_med(neigh_ip_address, v))

        if k == neighbors.ENABLED:
            rets.append(update_neighbor_enabled(neigh_ip_address, v))

        if k == neighbors.CONNECT_MODE:
            rets.append(_update_connect_mode(neigh_ip_address, v))

    return all(rets)


def _update_med(neigh_ip_address, value):
    neigh_conf = _get_neighbor_conf(neigh_ip_address)
    neigh_conf.multi_exit_disc = value
    LOG.info('MED value for neigh: %s updated to %s', neigh_conf, value)
    return True


def _update_connect_mode(neigh_ip_address, value):
    neigh_conf = _get_neighbor_conf(neigh_ip_address)
    neigh_conf.connect_mode = value
    return True


@RegisterWithArgChecks(name='neighbor.delete',
                       req_args=[neighbors.IP_ADDRESS])
def delete_neighbor(neigh_ip_address):
    neigh_conf = _get_neighbor_conf(neigh_ip_address)
    if neigh_conf:
        neigh_conf.enabled = False
        CORE_MANAGER.neighbors_conf.remove_neighbor_conf(neigh_ip_address)
        return True
    return False


@RegisterWithArgChecks(name='neighbor.get',
                       req_args=[neighbors.IP_ADDRESS])
def get_neighbor_conf(neigh_ip_address):
    """Returns a neighbor configuration for given ip address if exists."""
    neigh_conf = _get_neighbor_conf(neigh_ip_address)
    return neigh_conf.settings


@register(name='neighbors.get')
def get_neighbors_conf():
    return CORE_MANAGER.neighbors_conf.settings


@RegisterWithArgChecks(name='neighbor.in_filter.get',
                       req_args=[neighbors.IP_ADDRESS])
def get_neighbor_in_filter(neigh_ip_address):
    """Returns a neighbor in_filter for given ip address if exists."""
    core = CORE_MANAGER.get_core_service()
    peer = core.peer_manager.get_by_addr(neigh_ip_address)
    return peer.in_filters


@RegisterWithArgChecks(name='neighbor.in_filter.set',
                       req_args=[neighbors.IP_ADDRESS, neighbors.IN_FILTER])
def set_neighbor_in_filter(neigh_ip_address, filters):
    """Returns a neighbor in_filter for given ip address if exists."""
    core = CORE_MANAGER.get_core_service()
    peer = core.peer_manager.get_by_addr(neigh_ip_address)
    peer.in_filters = filters
    return True


@RegisterWithArgChecks(name='neighbor.out_filter.get',
                       req_args=[neighbors.IP_ADDRESS])
def get_neighbor_out_filter(neigh_ip_address):
    """Returns a neighbor out_filter for given ip address if exists."""
    core = CORE_MANAGER.get_core_service()
    ret = core.peer_manager.get_by_addr(neigh_ip_address).out_filters
    return ret


@RegisterWithArgChecks(name='neighbor.out_filter.set',
                       req_args=[neighbors.IP_ADDRESS, neighbors.OUT_FILTER])
def set_neighbor_out_filter(neigh_ip_address, filters):
    """Sets the out_filter of a neighbor."""
    core = CORE_MANAGER.get_core_service()
    peer = core.peer_manager.get_by_addr(neigh_ip_address)
    peer.out_filters = filters
    return True


@RegisterWithArgChecks(name='neighbor.attribute_map.set',
                       req_args=[neighbors.IP_ADDRESS,
                                 neighbors.ATTRIBUTE_MAP],
                       opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
def set_neighbor_attribute_map(neigh_ip_address, at_maps,
                               route_dist=None, route_family=VRF_RF_IPV4):
    """set attribute_maps to the neighbor."""
    core = CORE_MANAGER.get_core_service()
    peer = core.peer_manager.get_by_addr(neigh_ip_address)

    at_maps_key = const.ATTR_MAPS_LABEL_DEFAULT
    at_maps_dict = {}

    if route_dist is not None:
        vrf_conf =\
            CORE_MANAGER.vrfs_conf.get_vrf_conf(route_dist, route_family)
        if vrf_conf:
            at_maps_key = ':'.join([route_dist, route_family])
        else:
            raise RuntimeConfigError(desc='No VrfConf with rd %s' %
                                          route_dist)

    at_maps_dict[const.ATTR_MAPS_LABEL_KEY] = at_maps_key
    at_maps_dict[const.ATTR_MAPS_VALUE] = at_maps
    peer.attribute_maps = at_maps_dict

    return True


@RegisterWithArgChecks(name='neighbor.attribute_map.get',
                       req_args=[neighbors.IP_ADDRESS],
                       opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
def get_neighbor_attribute_map(neigh_ip_address, route_dist=None,
                               route_family=VRF_RF_IPV4):
    """Returns a neighbor attribute_map for given ip address if exists."""
    core = CORE_MANAGER.get_core_service()
    peer = core.peer_manager.get_by_addr(neigh_ip_address)
    at_maps_key = const.ATTR_MAPS_LABEL_DEFAULT

    if route_dist is not None:
        at_maps_key = ':'.join([route_dist, route_family])
    at_maps = peer.attribute_maps.get(at_maps_key)
    if at_maps:
        return at_maps.get(const.ATTR_MAPS_ORG_KEY)
    else:
        return []

# =============================================================================
# VRF configuration related APIs
# =============================================================================


@register(name='vrf.create')
def create_vrf(**kwargs):
    vrf_conf = VrfConf(**kwargs)
    CORE_MANAGER.vrfs_conf.add_vrf_conf(vrf_conf)
    return True


@register(name='vrf.update')
def update_vrf(**kwargs):
    route_dist = kwargs.get(ROUTE_DISTINGUISHER)
    vrf_id = kwargs.get(ConfWithId.ID)
    vrf_rf = kwargs.get(VRF_RF)
    vrf_conf = CORE_MANAGER.vrfs_conf.get_vrf_conf(
        route_dist, vrf_rf, vrf_id=vrf_id
    )

    # If we do not have a VrfConf with given id, we create one.
    if not vrf_conf:
        create_vrf(**kwargs)
    else:
        vrf_conf.update(**kwargs)
    return True


@RegisterWithArgChecks(name='vrf.delete', req_args=[ROUTE_DISTINGUISHER])
def delete_vrf(route_dist):
    vrf_conf = CORE_MANAGER.vrfs_conf.remove_vrf_conf(route_dist)
    if vrf_conf:
        return True

    return False


@RegisterWithArgChecks(
    name='vrf.get',
    req_args=[ROUTE_DISTINGUISHER],
    opt_args=[VRF_RF])
def get_vrf(route_dist, route_family=VRF_RF_IPV4):
    vrf_conf = CORE_MANAGER.vrfs_conf.get_vrf_conf(
        route_dist, vrf_rf=route_family
    )
    if not vrf_conf:
        raise RuntimeConfigError(desc='No VrfConf with vpn id %s' %
                                 route_dist)
    return vrf_conf.settings


@register(name='vrfs.get')
def get_vrfs_conf():
    vrfs_conf = CORE_MANAGER.vrfs_conf
    return vrfs_conf.settings

# =============================================================================
# network configuration related APIs
# =============================================================================


@register(name='network.add')
def add_network(prefix, next_hop=None):
    tm = CORE_MANAGER.get_core_service().table_manager
    tm.update_global_table(prefix, next_hop)
    return True


@register(name='network.del')
def del_network(prefix):
    tm = CORE_MANAGER.get_core_service().table_manager
    tm.update_global_table(prefix, is_withdraw=True)
    return True

# =============================================================================
# BMP configuration related APIs
# =============================================================================


@register(name='bmp.start')
def bmp_start(host, port):
    core = CORE_MANAGER.get_core_service()
    return core.start_bmp(host, port)


@register(name='bmp.stop')
def bmp_stop(host, port):
    core = CORE_MANAGER.get_core_service()
    return core.stop_bmp(host, port)


# =============================================================================
# BGP Flow Specification Routes related APIs
# =============================================================================

@RegisterWithArgChecks(
    name='flowspec.add',
    req_args=[FLOWSPEC_FAMILY, FLOWSPEC_RULES],
    opt_args=[FLOWSPEC_ACTIONS])
def add_flowspec(flowspec_family, rules, **kwargs):
    tm = CORE_MANAGER.get_core_service().table_manager
    tm.update_flowspec_global_table(flowspec_family, rules, **kwargs)
    return True


@RegisterWithArgChecks(
    name='flowspec.del',
    req_args=[FLOWSPEC_FAMILY, FLOWSPEC_RULES])
def del_flowspec(flowspec_family, rules):
    tm = CORE_MANAGER.get_core_service().table_manager
    tm.update_flowspec_global_table(flowspec_family, rules, is_withdraw=True)
    return True