blob: e64948e67e6b853062a5f7505bf5aa359ca46987 [file] [log] [blame]
Ales Komarekad46d2e2017-03-09 17:16:38 +01001#!/usr/bin/python
2# Copyright 2017 Mirantis, Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15'''
16Management of Contrail resources
17================================
18
19:depends: - vnc_api Python module
20
21
22Enforce the virtual router existence
23------------------------------------
24
25.. code-block:: yaml
26
27 virtual_router:
28 contrail.virtual_router_present:
Pavel Svimbersky483a19e2017-08-22 09:50:29 +020029 name: tor01
Ales Komarekad46d2e2017-03-09 17:16:38 +010030 ip_address: 10.0.0.23
31 dpdk_enabled: False
Pavel Svimbersky483a19e2017-08-22 09:50:29 +020032 router_type: tor-agent
Ales Komarekad46d2e2017-03-09 17:16:38 +010033
34
35Enforce the virtual router absence
36----------------------------------
37
38.. code-block:: yaml
39
Pavel Svimbersky483a19e2017-08-22 09:50:29 +020040 virtual_router_tor01:
Ales Komarekad46d2e2017-03-09 17:16:38 +010041 contrail.virtual_router_absent:
Pavel Svimbersky483a19e2017-08-22 09:50:29 +020042 name: tor01
43
44
45Enforce the physical router existence
46------------------------------------
47
48.. code-block:: yaml
49
50 physical_router_phr01:
51 contrail.physical_router_present:
52 name: phr01
53 parent_type: global-system-config
54 management_ip: 10.167.4.206
55 dataplane_ip: 172.17.56.9
56 vendor_name: MyVendor
57 product_name: MyProduct
58 agents:
59 - tor01
60 - tns01
61
62
63Enforce the physical router absence
64----------------------------------
65
66.. code-block:: yaml
67
68 physical_router_delete_phr01:
69 contrail.physical_router_absent:
70 name: phr01
71
72
73Enforce the physical interface present
74----------------------------------
75
76.. code-block:: yaml
77
78 create physical interface ge-0/1/10 for phr01:
79 contrail.physical_interface_present:
80 - name: ge-0/1/10
81 - physical_router: prh01
82
83
84Enforce the physical interface absence
85----------------------------------
86
87.. code-block:: yaml
88
89 physical_interface_delete ge-0/1/10:
90 contrail.physical_interface_absent:
91 name: ge-0/1/10
92
93
94Enforce the logical interface present
95----------------------------------
96
97.. code-block:: yaml
98
99 create logical interface 11/15:
100 contrail.logical_interface_present:
101 - name: ge-0/1/11.15
102 - parent_names:
103 - ge-0/1/11
104 - phr01
105 - parent_type: physical-interface
106 - vlan_tag: 15
107 - interface_type: L3
108
109
110Enforce the logical interface absence
111----------------------------------
112
113.. code-block:: yaml
114
115 logical interface delete ge-0/1/10.0 phr02:
116 contrail.logical_interface_absent:
117 - name: ge-0/1/10.0
118 - parent_names:
119 - ge-0/1/10
120 - phr02
121 - parent_type: physical-interface
122
123
124Enforce the global vrouter existence
125------------------------------------
126
127.. code-block:: yaml
128
129 #Example
130 opencontrail_client_virtual_router_global_conf_create:
131 contrail.global_vrouter_config_present:
132 - name: "global-vrouter-config"
133 - parent_type: "global-system-config"
134 - encap_priority : "MPLSoUDP,MPLSoGRE"
135 - vxlan_vn_id_mode : "automatic"
136 - fq_names:
137 - default-global-system-config
138 - default-global-vrouter-config
139
140
141Enforce the global vrouter absence
142----------------------------------
143
144.. code-block:: yaml
145
146 #Example
147 opencontrail_client_virtual_router_global_conf_delete:
148 contrail.global_vrouter_config_absent:
149 - name: "global-vrouter-config"
Ales Komarekad46d2e2017-03-09 17:16:38 +0100150
151
Petr Jediný5f3efe32017-05-26 17:55:09 +0200152Enforce the link local service entry existence
153----------------------------------------------
154
155.. code-block:: yaml
156
157 # Example with dns name, only one is permited
158 lls_meta1:
159 contrail.linklocal_service_present:
160 - name: meta1
161 - lls_ip: 10.0.0.23
162 - lls_port: 80
163 - ipf_addresses: "meta.example.com"
164 - ipf_port: 80
165
166 # Example with multiple ip addresses
167 lls_meta2:
168 contrail.linklocal_service_present:
169 - name: meta2
170 - lls_ip: 10.0.0.23
171 - lls_port: 80
172 - ipf_addresses:
173 - 10.10.10.10
174 - 10.20.20.20
175 - 10.30.30.30
176 - ipf_port: 80
177
178 # Example with one ip addresses
179 lls_meta3:
180 contrail.linklocal_service_present:
181 - name: meta3
182 - lls_ip: 10.0.0.23
183 - lls_port: 80
184 - ipf_addresses:
185 - 10.10.10.10
186 - ipf_port: 80
187
188
189Enforce the link local service entry absence
190--------------------------------------------
191
192.. code-block:: yaml
193
194 lls_meta1_delete:
195 contrail.linklocal_service_absent:
196 - name: cmp01
197
198
Ales Komarekad46d2e2017-03-09 17:16:38 +0100199Enforce the analytics node existence
200------------------------------------
201
202.. code-block:: yaml
203
204 analytics_node01:
205 contrail.analytics_node_present:
206 name: nal01
207 ip_address: 10.0.0.13
208
209
210Enforce the config node existence
211---------------------------------
212
213.. code-block:: yaml
214
215 config_node01:
216 contrail.config_node_present:
217 name: ntw01
218 ip_address: 10.0.0.23
219
220
221Enforce the database node existence
222-----------------------------------
223
224.. code-block:: yaml
225
226 config_node01:
227 contrail.database_node_present:
228 name: ntw01
229 ip_address: 10.0.0.33
230
231'''
232
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200233
Ales Komarekad46d2e2017-03-09 17:16:38 +0100234def __virtual__():
235 '''
236 Load Contrail module
237 '''
238 return 'contrail'
239
240
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200241def virtual_router_present(name, ip_address, router_type=None, dpdk_enabled=False, **kwargs):
Ales Komarekad46d2e2017-03-09 17:16:38 +0100242 '''
243 Ensures that the Contrail virtual router exists.
244
245 :param name: Virtual router name
246 :param ip_address: Virtual router IP address
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200247 :param router_type: Any of ['tor-agent', 'tor-service-node', 'embedded']
Ales Komarekad46d2e2017-03-09 17:16:38 +0100248 '''
249 ret = {'name': name,
250 'changes': {},
251 'result': True,
252 'comment': 'Virtual router "{0}" already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200253 result = __salt__['contrail.virtual_router_create'](name, ip_address, router_type, dpdk_enabled, **kwargs)
254 if 'OK' in result:
255 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100256 pass
257 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100258 ret['comment'] = 'Virtual router {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200259 ret['changes']['VirtualRouter'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100260 return ret
261
262
263def virtual_router_absent(name, **kwargs):
264 '''
265 Ensure that the Contrail virtual router doesn't exist
266
267 :param name: The name of the virtual router that should not exist
268 '''
269 ret = {'name': name,
270 'changes': {},
271 'result': True,
272 'comment': 'Virtual router "{0}" is already absent'.format(name)}
273 virtual_router = __salt__['contrail.virtual_router_get'](name, **kwargs)
274 if 'Error' not in virtual_router:
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200275 result = __salt__['contrail.virtual_router_delete'](name, **kwargs)
Ales Komarekad46d2e2017-03-09 17:16:38 +0100276 ret['comment'] = 'Virtual router {0} has been deleted'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200277 ret['changes']['VirtualRouter'] = result
278 return ret
Ales Komarekad46d2e2017-03-09 17:16:38 +0100279
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200280
281def physical_router_present(name, parent_type=None,
282 management_ip=None,
283 dataplane_ip=None, # VTEP address in web GUI
284 vendor_name=None,
285 product_name=None,
286 vnc_managed=None,
287 junos_service_ports=None,
288 agents=None, **kwargs):
289 '''
290 Ensures that the Contrail virtual router exists.
291
292 :param name: Physical router name
293 :param parent_type: Parent resource type: Any of ['global-system-config']
294 :param management_ip: Management ip for this physical router. It is used by the device manager to perform netconf and by SNMP collector if enabled.
295 :param dataplane_ip: VTEP address in web GUI. This is ip address in the ip-fabric(underlay) network that can be used in data plane by physical router. Usually it is the VTEP address in VxLAN for the TOR switch.
296 :param vendor_name: Vendor name of the physical router (e.g juniper). Used by the device manager to select driver.
297 :param product_name: Model name of the physical router (e.g juniper). Used by the device manager to select driver.
298 :param vnc_managed: This physical router is enabled to be configured by device manager.
299 :param user_credentials: Username and password for netconf to the physical router by device manager.
300 :param junos_service_ports: Juniper JUNOS specific service interfaces name to perform services like NAT.
301 :param agents: List of virtual-router references
302 '''
303 ret = {'name': name,
304 'changes': {},
305 'result': True,
306 'comment': 'Physical router "{0}" already exists'.format(name)}
307 result = __salt__['contrail.physical_router_create'](name, parent_type, management_ip, dataplane_ip, vendor_name,
308 product_name, vnc_managed, junos_service_ports, agents,
309 **kwargs)
310 if 'OK' in result:
311 ret['comment'] = result
312 pass
313 else:
314 ret['comment'] = 'Physical router {0} has been created'.format(name)
315 ret['changes']['PhysicalRouter'] = result
316 return ret
317
318
319def physical_router_absent(name, **kwargs):
320 '''
321 Ensure that the Contrail physical router doesn't exist
322
323 :param name: The name of the physical router that should not exist
324 '''
325 ret = {'name': name,
326 'changes': {},
327 'result': True,
328 'comment': 'Physical router "{0}" is already absent'.format(name)}
329 physical_router = __salt__['contrail.physical_router_get'](name, **kwargs)
330 if 'Error' not in physical_router:
331 result = __salt__['contrail.physical_router_delete'](name, **kwargs)
332 ret['comment'] = 'Physical router {0} has been deleted'.format(name)
333 ret['changes']['PhysicalRouter'] = result
334 return ret
335
336
337def physical_interface_present(name, physical_router, **kwargs):
338 '''
339 Ensures that the Contrail physical interface exists.
340
341 :param name: Physical interface name
342 :param physical_router: Name of existing physical router
343 '''
344 ret = {'name': name,
345 'changes': {},
346 'result': True,
347 'comment': 'Physical interface "{0}" already exists'.format(name)}
348
349 result = __salt__['contrail.physical_interface_create'](name, physical_router, **kwargs)
350 if 'OK' in result:
351 ret['comment'] = result
352 pass
353 else:
354 ret['comment'] = 'Physical interface {0} has been created'.format(name)
355 ret['changes']['PhysicalInterface'] = result
356 return ret
357
358
359def physical_interface_absent(name, physical_router, **kwargs):
360 '''
361 Ensure that the Contrail physical interface doesn't exist
362
363 :param name: The name of the physical interface that should not exist
364 :param physical_router: Physical router name
365 '''
366 ret = {'name': name,
367 'changes': {},
368 'result': True,
369 'comment': 'Physical interface "{0}" is already absent'.format(name)}
370 physical_interface = __salt__['contrail.physical_interface_get'](name, physical_router, **kwargs)
371 if 'Error' not in physical_interface:
372 result = __salt__['contrail.physical_interface_delete'](name, physical_router, **kwargs)
373 ret['comment'] = 'Physical interface {0} has been deleted'.format(name)
374 ret['changes']['PhysicalInterface'] = result
375 return ret
376
377
378def logical_interface_present(name, parent_names, parent_type, vlan_tag=None, interface_type="L2", **kwargs):
379 '''
380 Ensures that the Contrail logical interface exists.
381
382 :param name: Logical interface name
383 :param parent_names: List of parents
384 :param parent_type Parent resource type. Any of ['physical-router', 'physical-interface']
385 :param vlan_tag: VLAN tag (.1Q) classifier for this logical interface.
386 :param interface_type Logical interface type can be L2 or L3.
387 '''
388 ret = {'name': name,
389 'changes': {},
390 'result': True,
391 'comment': 'Logical interface "{0}" already exists'.format(name)}
392 logical_interface = __salt__['contrail.logical_interface_get'](name, parent_names, parent_type, **kwargs)
393 if 'Error' not in logical_interface:
394 pass
395 else:
396 result = __salt__['contrail.logical_interface_create'](name, parent_names, parent_type, vlan_tag,
397 interface_type, **kwargs)
398 if 'Error' in result:
399 return False
400
401 ret['comment'] = 'Logical interface {0} has been created'.format(name)
402 ret['changes']['LogicalInterface'] = result
403 return ret
404
405
406def logical_interface_absent(name, parent_names, parent_type=None, **kwargs):
407 '''
408 Ensure that the Contrail logical interface doesn't exist
409
410 :param name: The name of the logical interface that should not exist
411 :param parent_names: List of parent names. Example ['phr01','ge-0/1/0']
412 :param parent_type: Parent resource type. Any of ['physical-router', 'physical-interface']
413 '''
414 ret = {'name': name,
415 'changes': {},
416 'result': True,
417 'comment': 'logical interface "{0}" is already absent'.format(name)}
418 logical_interface = __salt__['contrail.logical_interface_get'](name, parent_names, parent_type, **kwargs)
419 if 'Error' not in logical_interface:
420 result = __salt__['contrail.logical_interface_delete'](name, parent_names, parent_type, **kwargs)
421 ret['comment'] = 'Logical interface {0} has been deleted'.format(name)
422 ret['changes']['LogicalInterface'] = result
423 return ret
424
425
426def global_vrouter_config_present(name, parent_type, encap_priority="MPLSoUDP,MPLSoGRE", vxlan_vn_id_mode="automatic",
427 *fq_names, **kwargs):
428 '''
429 Ensures that the Contrail global vrouter config exists.
430
431 :param name: Global vrouter config name
432 :param parent_type: Parent resource type
433 :param encap_priority: Ordered list of encapsulations that vrouter will use in priority order
434 :param vxlan_vn_id_mode: Method of allocation of VxLAN VNI(s).
435 :param fq_names: Fully Qualified Name of resource devided <string>array
436 '''
437 ret = {'name': name,
438 'changes': {},
439 'result': True,
440 'comment': 'Global vrouter config "{0}" already exists'.format(name)}
441
442 result = __salt__['contrail.global_vrouter_config_create'](name, parent_type, encap_priority, vxlan_vn_id_mode,
443 *fq_names, **kwargs)
444 if 'OK' in result:
445 ret['comment'] = result
446 pass
447 else:
448 ret['comment'] = 'Global vrouter config {0} has been created'.format(name)
449 ret['changes']['GlobalVRouterConfig'] = result
450 return ret
451
452
453def global_vrouter_config_absent(name, **kwargs):
454 '''
455 Ensure that the Contrail global vrouter config doesn't exist
456
457 :param name: The name of the global vrouter config that should not exist
458 '''
459 ret = {'name': name,
460 'changes': {},
461 'result': True,
462 'comment': 'Global vrouter config "{0}" is already absent'.format(name)}
463 vrouter_conf = __salt__['contrail.global_vrouter_config_get'](name, **kwargs)
464 if 'Error' not in vrouter_conf:
465 result = __salt__['contrail.global_vrouter_config_delete'](name, **kwargs)
466 ret['comment'] = 'Global vrouter config {0} has been deleted'.format(name)
467 ret['changes']['GlobalVRouterConfig'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100468 return ret
469
470
Petr Jediný5f3efe32017-05-26 17:55:09 +0200471def linklocal_service_present(name, lls_ip, lls_port, ipf_addresses, ipf_port, **kwargs):
472 '''
473 Ensures that the Contrail link local service entry exists.
474
475 :param name: Link local service name
476 :param lls_ip: Link local ip address
477 :param lls_port: Link local service port
478 :param ipf_addresses: IP fabric dns name or list of IP fabric ip addresses
479 :param ipf_port: IP fabric port
480 '''
481 ret = {'name': name,
482 'changes': {},
483 'result': True,
484 'comment': 'Link local service "{0}" already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200485
486 result = __salt__['contrail.linklocal_service_create'](name, lls_ip, lls_port, ipf_addresses, ipf_port, **kwargs)
487 if 'OK' in result:
488 ret['comment'] = result
489 pass
490 else:
Petr Jediný5f3efe32017-05-26 17:55:09 +0200491 ret['comment'] = 'Link local service "{0}" has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200492 ret['changes']['LinkLocalService'] = result
Petr Jediný5f3efe32017-05-26 17:55:09 +0200493 return ret
494
495
496def linklocal_service_absent(name, **kwargs):
497 '''
498 Ensure that the Contrail link local service entry doesn't exist
499
500 :param name: The name of the link local service entry
501 '''
502 ret = {'name': name,
503 'changes': {},
504 'result': True,
505 'comment': ' "{0}" is already absent'.format(name)}
506 lls = __salt__['contrail.linklocal_service_get'](name, **kwargs)
507 if 'Error' not in lls:
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200508 result = __salt__['contrail.linklocal_service_delete'](name, **kwargs)
Petr Jediný5f3efe32017-05-26 17:55:09 +0200509 ret['comment'] = 'Link local service "{0}" has been deleted'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200510 ret['changes']['LinkLocalService'] = result
Petr Jediný5f3efe32017-05-26 17:55:09 +0200511 return ret
512
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200513
Ales Komarekad46d2e2017-03-09 17:16:38 +0100514def analytics_node_present(name, ip_address, **kwargs):
515 '''
516 Ensures that the Contrail analytics node exists.
517
518 :param name: Analytics node name
519 '''
520 ret = {'name': name,
521 'changes': {},
522 'result': True,
523 'comment': 'Analytics node {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200524
525 result = __salt__['contrail.analytics_node_create'](name, ip_address, **kwargs)
526 if 'OK' in result:
527 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100528 pass
529 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100530 ret['comment'] = 'Analytics node {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200531 ret['changes']['AnalyticsNode'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100532 return ret
533
534
535def config_node_present(name, ip_address, **kwargs):
536 '''
537 Ensures that the Contrail config node exists.
538
539 :param name: Config node name
540 '''
541 ret = {'name': name,
542 'changes': {},
543 'result': True,
544 'comment': 'Config node {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200545 result = __salt__['contrail.config_node_create'](name, ip_address, **kwargs)
546
547 if 'OK' in result:
548 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100549 pass
550 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100551 ret['comment'] = 'Config node {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200552 ret['changes']['ConfigNode'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100553 return ret
554
555
556def bgp_router_present(name, type, ip_address, asn=64512, **kwargs):
557 '''
558 Ensures that the Contrail BGP router exists.
559
560 :param name: BGP router name
561 '''
562 ret = {'name': name,
563 'changes': {},
564 'result': True,
565 'comment': 'BGP router {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200566
567 result = __salt__['contrail.bgp_router_create'](name, type, ip_address, asn, **kwargs)
568 if 'OK' in result:
569 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100570 pass
571 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100572 ret['comment'] = 'BGP router {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200573 ret['changes']['BgpRouter'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100574 return ret
575
576
577def database_node_present(name, ip_address, **kwargs):
578 '''
579 Ensures that the Contrail database node exists.
580
581 :param name: Database node name
582 '''
583 ret = {'name': name,
584 'changes': {},
585 'result': True,
586 'comment': 'Database node {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200587
588 result = __salt__['contrail.database_node_create'](name, ip_address, **kwargs)
589 if 'OK' in result:
590 ret['coment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100591 pass
592 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100593 ret['comment'] = 'Database node {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200594 ret['changes']['DatabaseNode'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100595 return ret