blob: 06a0363f578e508c20565ee19328096670d0fdd4 [file] [log] [blame]
Oleksiy Petrenkocaad2032018-04-20 14:42:46 +03001import logging
2
3log = logging.getLogger(__name__)
4
5
6def __virtual__():
7 return 'neutronv2' if 'neutronv2.subnet_list' in __salt__ else False
8
9
10def _neutronv2_call(fname, *args, **kwargs):
11 return __salt__['neutronv2.{}'.format(fname)](*args, **kwargs)
12
13
14def _resource_present(resource, name, changeable_params, cloud_name, **kwargs):
15 try:
16 method_name = '{}_get_details'.format(resource)
17 exact_resource = _neutronv2_call(
18 method_name, name=name, cloud_name=cloud_name
19 )[resource]
20 except Exception as e:
21 if 'ResourceNotFound' in repr(e):
22 try:
23 method_name = '{}_create'.format(resource)
24 resp = _neutronv2_call(
25 method_name, name=name, cloud_name=cloud_name, **kwargs
26 )
27 except Exception as e:
28 log.exception('Neutron {0} create failed with {1}'.
29 format(resource, e))
30 return _failed('create', name, resource)
31 return _succeeded('create', name, resource, resp)
32 elif 'MultipleResourcesFound' in repr(e):
33 return _failed('find', name, resource)
34 else:
35 raise
36
37 to_update = {}
38 for key in kwargs:
39 if key in changeable_params and (key not in exact_resource
40 or kwargs[key] != exact_resource[key]):
41 to_update[key] = kwargs[key]
42 try:
43 method_name = '{}_update'.format(resource)
44 resp = _neutronv2_call(
45 method_name, name=name, cloud_name=cloud_name, **to_update
46 )
47 except Exception as e:
48 log.exception('Neutron {0} update failed with {1}'.format(resource, e))
49 return _failed('update', name, resource)
50 return _succeeded('update', name, resource, resp)
51
52
53def _resource_absent(resource, name, cloud_name):
54 try:
55 method_name = '{}_get_details'.format(resource)
56 _neutronv2_call(
57 method_name, name=name, cloud_name=cloud_name
58 )[resource]
59 except Exception as e:
60 if 'ResourceNotFound' in repr(e):
61 return _succeeded('absent', name, resource)
62 if 'MultipleResourcesFound' in repr(e):
63 return _failed('find', name, resource)
64 try:
65 method_name = '{}_delete'.format(resource)
66 _neutronv2_call(
67 method_name, name=name, cloud_name=cloud_name
68 )
69 except Exception as e:
70 log.error('Neutron delete {0} failed with {1}'.format(resource, e))
71 return _failed('delete', name, resource)
72 return _succeeded('delete', name, resource)
73
74
75def network_present(name, cloud_name, **kwargs):
76 changeable = (
77 'admin_state_up', 'dns_domain', 'mtu', 'port_security_enabled',
78 'provider:network_type', 'provider:physical_network',
79 'provider:segmentation_id', 'qos_policy_id', 'router:external',
80 'segments', 'shared', 'description', 'is_default'
81 )
82
83 return _resource_present('network', name, changeable, cloud_name, **kwargs)
84
85
86def network_absent(name, cloud_name):
87 return _resource_absent('network', name, cloud_name)
88
89
90def subnet_present(name, cloud_name, network_id, ip_version, cidr, **kwargs):
91 kwargs.update({'network_id': network_id,
92 'ip_version': ip_version,
93 'cidr': cidr})
94 changeable = (
95 'name', 'enable_dhcp', 'dns_nameservers', 'allocation_pools',
96 'host_routes', 'gateway_ip', 'description', 'service_types',
97 )
98
99 return _resource_present('subnet', name, changeable, cloud_name, **kwargs)
100
101
102def subnet_absent(name, cloud_name):
103 return _resource_absent('subnet', name, cloud_name)
104
105
106def subnetpool_present(name, cloud_name, prefixes, **kwargs):
107 kwargs.update({'prefixes': prefixes})
108 changeable = (
109 'default_quota', 'min_prefixlen', 'address_scope_id',
110 'default_prefixlen', 'description'
111 )
112
113 return _resource_present('subnetpool', name, changeable, cloud_name, **kwargs)
114
115
116def subnetpool_absent(name, cloud_name):
117 return _resource_absent('subnetpool', name, cloud_name)
118
119
120def _succeeded(op, name, resource, changes=None):
121 msg_map = {
122 'create': '{0} {1} created',
123 'delete': '{0} {1} removed',
124 'update': '{0} {1} updated',
125 'no_changes': '{0} {1} is in desired state',
126 'absent': '{0} {1} not present'
127 }
128 changes_dict = {
129 'name': name,
130 'result': True,
131 'comment': msg_map[op].format(resource, name),
132 'changes': changes or {},
133 }
134 return changes_dict
135
136
137def _failed(op, name, resource):
138 msg_map = {
139 'create': '{0} {1} failed to create',
140 'delete': '{0} {1} failed to delete',
141 'update': '{0} {1} failed to update',
142 'find': '{0} {1} found multiple {0}'
143 }
144 changes_dict = {
145 'name': name,
146 'result': False,
147 'comment': msg_map[op].format(resource, name),
148 'changes': {},
149 }
150 return changes_dict