blob: c66333faeedcac7310e99d319665644fc9cecd8b [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
Vasyl Saienkob10b7202017-09-05 14:19:03 +0300378def logical_interface_present(name, parent_names, parent_type, vlan_tag=None, interface_type="L2",
379 vmis=None, **kwargs):
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200380 '''
381 Ensures that the Contrail logical interface exists.
382
383 :param name: Logical interface name
384 :param parent_names: List of parents
385 :param parent_type Parent resource type. Any of ['physical-router', 'physical-interface']
386 :param vlan_tag: VLAN tag (.1Q) classifier for this logical interface.
Vasyl Saienkob10b7202017-09-05 14:19:03 +0300387 :param interface_type: Logical interface type can be L2 or L3.
388 :param vmis: Virtual machine interface name associate with
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200389 '''
390 ret = {'name': name,
391 'changes': {},
392 'result': True,
393 'comment': 'Logical interface "{0}" already exists'.format(name)}
394 logical_interface = __salt__['contrail.logical_interface_get'](name, parent_names, parent_type, **kwargs)
395 if 'Error' not in logical_interface:
396 pass
397 else:
398 result = __salt__['contrail.logical_interface_create'](name, parent_names, parent_type, vlan_tag,
Vasyl Saienkob10b7202017-09-05 14:19:03 +0300399 interface_type, vmis=vmis, **kwargs)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200400 if 'Error' in result:
401 return False
402
403 ret['comment'] = 'Logical interface {0} has been created'.format(name)
404 ret['changes']['LogicalInterface'] = result
405 return ret
406
407
408def logical_interface_absent(name, parent_names, parent_type=None, **kwargs):
409 '''
410 Ensure that the Contrail logical interface doesn't exist
411
412 :param name: The name of the logical interface that should not exist
413 :param parent_names: List of parent names. Example ['phr01','ge-0/1/0']
414 :param parent_type: Parent resource type. Any of ['physical-router', 'physical-interface']
415 '''
416 ret = {'name': name,
417 'changes': {},
418 'result': True,
419 'comment': 'logical interface "{0}" is already absent'.format(name)}
420 logical_interface = __salt__['contrail.logical_interface_get'](name, parent_names, parent_type, **kwargs)
421 if 'Error' not in logical_interface:
422 result = __salt__['contrail.logical_interface_delete'](name, parent_names, parent_type, **kwargs)
423 ret['comment'] = 'Logical interface {0} has been deleted'.format(name)
424 ret['changes']['LogicalInterface'] = result
425 return ret
426
427
428def global_vrouter_config_present(name, parent_type, encap_priority="MPLSoUDP,MPLSoGRE", vxlan_vn_id_mode="automatic",
429 *fq_names, **kwargs):
430 '''
431 Ensures that the Contrail global vrouter config exists.
432
433 :param name: Global vrouter config name
434 :param parent_type: Parent resource type
435 :param encap_priority: Ordered list of encapsulations that vrouter will use in priority order
436 :param vxlan_vn_id_mode: Method of allocation of VxLAN VNI(s).
437 :param fq_names: Fully Qualified Name of resource devided <string>array
438 '''
439 ret = {'name': name,
440 'changes': {},
441 'result': True,
442 'comment': 'Global vrouter config "{0}" already exists'.format(name)}
443
444 result = __salt__['contrail.global_vrouter_config_create'](name, parent_type, encap_priority, vxlan_vn_id_mode,
445 *fq_names, **kwargs)
446 if 'OK' in result:
447 ret['comment'] = result
448 pass
449 else:
450 ret['comment'] = 'Global vrouter config {0} has been created'.format(name)
451 ret['changes']['GlobalVRouterConfig'] = result
452 return ret
453
454
455def global_vrouter_config_absent(name, **kwargs):
456 '''
457 Ensure that the Contrail global vrouter config doesn't exist
458
459 :param name: The name of the global vrouter config that should not exist
460 '''
461 ret = {'name': name,
462 'changes': {},
463 'result': True,
464 'comment': 'Global vrouter config "{0}" is already absent'.format(name)}
465 vrouter_conf = __salt__['contrail.global_vrouter_config_get'](name, **kwargs)
466 if 'Error' not in vrouter_conf:
467 result = __salt__['contrail.global_vrouter_config_delete'](name, **kwargs)
468 ret['comment'] = 'Global vrouter config {0} has been deleted'.format(name)
469 ret['changes']['GlobalVRouterConfig'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100470 return ret
471
472
Petr Jediný5f3efe32017-05-26 17:55:09 +0200473def linklocal_service_present(name, lls_ip, lls_port, ipf_addresses, ipf_port, **kwargs):
474 '''
475 Ensures that the Contrail link local service entry exists.
476
477 :param name: Link local service name
478 :param lls_ip: Link local ip address
479 :param lls_port: Link local service port
480 :param ipf_addresses: IP fabric dns name or list of IP fabric ip addresses
481 :param ipf_port: IP fabric port
482 '''
483 ret = {'name': name,
484 'changes': {},
485 'result': True,
486 'comment': 'Link local service "{0}" already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200487
488 result = __salt__['contrail.linklocal_service_create'](name, lls_ip, lls_port, ipf_addresses, ipf_port, **kwargs)
489 if 'OK' in result:
490 ret['comment'] = result
491 pass
492 else:
Petr Jediný5f3efe32017-05-26 17:55:09 +0200493 ret['comment'] = 'Link local service "{0}" has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200494 ret['changes']['LinkLocalService'] = result
Petr Jediný5f3efe32017-05-26 17:55:09 +0200495 return ret
496
497
498def linklocal_service_absent(name, **kwargs):
499 '''
500 Ensure that the Contrail link local service entry doesn't exist
501
502 :param name: The name of the link local service entry
503 '''
504 ret = {'name': name,
505 'changes': {},
506 'result': True,
507 'comment': ' "{0}" is already absent'.format(name)}
508 lls = __salt__['contrail.linklocal_service_get'](name, **kwargs)
509 if 'Error' not in lls:
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200510 result = __salt__['contrail.linklocal_service_delete'](name, **kwargs)
Petr Jediný5f3efe32017-05-26 17:55:09 +0200511 ret['comment'] = 'Link local service "{0}" has been deleted'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200512 ret['changes']['LinkLocalService'] = result
Petr Jediný5f3efe32017-05-26 17:55:09 +0200513 return ret
514
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200515
Ales Komarekad46d2e2017-03-09 17:16:38 +0100516def analytics_node_present(name, ip_address, **kwargs):
517 '''
518 Ensures that the Contrail analytics node exists.
519
520 :param name: Analytics node name
521 '''
522 ret = {'name': name,
523 'changes': {},
524 'result': True,
525 'comment': 'Analytics node {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200526
527 result = __salt__['contrail.analytics_node_create'](name, ip_address, **kwargs)
528 if 'OK' in result:
529 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100530 pass
531 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100532 ret['comment'] = 'Analytics node {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200533 ret['changes']['AnalyticsNode'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100534 return ret
535
536
537def config_node_present(name, ip_address, **kwargs):
538 '''
539 Ensures that the Contrail config node exists.
540
541 :param name: Config node name
542 '''
543 ret = {'name': name,
544 'changes': {},
545 'result': True,
546 'comment': 'Config node {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200547 result = __salt__['contrail.config_node_create'](name, ip_address, **kwargs)
548
549 if 'OK' in result:
550 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100551 pass
552 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100553 ret['comment'] = 'Config node {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200554 ret['changes']['ConfigNode'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100555 return ret
556
557
558def bgp_router_present(name, type, ip_address, asn=64512, **kwargs):
559 '''
560 Ensures that the Contrail BGP router exists.
561
562 :param name: BGP router name
563 '''
564 ret = {'name': name,
565 'changes': {},
566 'result': True,
567 'comment': 'BGP router {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200568
569 result = __salt__['contrail.bgp_router_create'](name, type, ip_address, asn, **kwargs)
570 if 'OK' in result:
571 ret['comment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100572 pass
573 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100574 ret['comment'] = 'BGP router {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200575 ret['changes']['BgpRouter'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100576 return ret
577
578
579def database_node_present(name, ip_address, **kwargs):
580 '''
581 Ensures that the Contrail database node exists.
582
583 :param name: Database node name
584 '''
585 ret = {'name': name,
586 'changes': {},
587 'result': True,
588 'comment': 'Database node {0} already exists'.format(name)}
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200589
590 result = __salt__['contrail.database_node_create'](name, ip_address, **kwargs)
591 if 'OK' in result:
592 ret['coment'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100593 pass
594 else:
Ales Komarekad46d2e2017-03-09 17:16:38 +0100595 ret['comment'] = 'Database node {0} has been created'.format(name)
Pavel Svimbersky483a19e2017-08-22 09:50:29 +0200596 ret['changes']['DatabaseNode'] = result
Ales Komarekad46d2e2017-03-09 17:16:38 +0100597 return ret
Vasyl Saienkob10b7202017-09-05 14:19:03 +0300598
599
600def virtual_machine_interface_present(name,
601 virtual_network,
602 mac_address=None,
603 ip_address=None,
604 security_group=None,
605 **kwargs):
606 '''
607 Ensures that the Contrail virtual machine interface exists.
608
609 :param name: Virtual machine interface name
610 :param virtual_network: Network name
611 :param mac_address: Mac address of vmi interface
612 :param ip_address: Virtual machine interface ip address
613 '''
614 ret = {'name': name,
615 'changes': {},
616 'result': True,
617 'comment': 'Virtual machine interface "{0}" already exists'.format(name)}
618
619 vmis = __salt__['contrail.virtual_machine_interface_list'](**kwargs)
620
621 for vmi in vmis:
622 if vmi['name'] == name:
623 return ret
624
625 vmi = __salt__['contrail.virtual_machine_interface_create'](name, virtual_network,
626 mac_address=mac_address,
627 ip_address=ip_address,
628 security_group=security_group,
629 **kwargs)
630 if vmi['name'] == name:
631 ret['comment'] = 'Virtual machine interface {0} has been created'.format(name)
632 ret['result'] = True
633 else:
634 ret['comment'] = 'Virtual machine interface {0} creation failed'.format(name)
635 ret['result'] = False
636 return ret