1# -*- coding: utf-8 -*-
2# This code is part of Ansible, but is an independent component.
3# This particular file snippet, and this file snippet only, is BSD licensed.
4# Modules you write using this snippet, which is embedded dynamically by Ansible
5# still belong to the author of the module, and may assign their own license
6# to the complete work.
7#
8# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
9
10from __future__ import (absolute_import, division, print_function)
11__metaclass__ = type
12
13import time
14
15
16class OneAndOneResources:
17    firewall_policy = 'firewall_policy'
18    load_balancer = 'load_balancer'
19    monitoring_policy = 'monitoring_policy'
20    private_network = 'private_network'
21    public_ip = 'public_ip'
22    role = 'role'
23    server = 'server'
24    user = 'user'
25    vpn = 'vpn'
26
27
28def get_resource(oneandone_conn, resource_type, resource_id):
29    switcher = {
30        'firewall_policy': oneandone_conn.get_firewall,
31        'load_balancer': oneandone_conn.get_load_balancer,
32        'monitoring_policy': oneandone_conn.get_monitoring_policy,
33        'private_network': oneandone_conn.get_private_network,
34        'public_ip': oneandone_conn.get_public_ip,
35        'role': oneandone_conn.get_role,
36        'server': oneandone_conn.get_server,
37        'user': oneandone_conn.get_user,
38        'vpn': oneandone_conn.get_vpn,
39    }
40
41    return switcher.get(resource_type, None)(resource_id)
42
43
44def get_datacenter(oneandone_conn, datacenter, full_object=False):
45    """
46    Validates the datacenter exists by ID or country code.
47    Returns the datacenter ID.
48    """
49    for _datacenter in oneandone_conn.list_datacenters():
50        if datacenter in (_datacenter['id'], _datacenter['country_code']):
51            if full_object:
52                return _datacenter
53            return _datacenter['id']
54
55
56def get_fixed_instance_size(oneandone_conn, fixed_instance_size, full_object=False):
57    """
58    Validates the fixed instance size exists by ID or name.
59    Return the instance size ID.
60    """
61    for _fixed_instance_size in oneandone_conn.fixed_server_flavors():
62        if fixed_instance_size in (_fixed_instance_size['id'],
63                                   _fixed_instance_size['name']):
64            if full_object:
65                return _fixed_instance_size
66            return _fixed_instance_size['id']
67
68
69def get_appliance(oneandone_conn, appliance, full_object=False):
70    """
71    Validates the appliance exists by ID or name.
72    Return the appliance ID.
73    """
74    for _appliance in oneandone_conn.list_appliances(q='IMAGE'):
75        if appliance in (_appliance['id'], _appliance['name']):
76            if full_object:
77                return _appliance
78            return _appliance['id']
79
80
81def get_private_network(oneandone_conn, private_network, full_object=False):
82    """
83    Validates the private network exists by ID or name.
84    Return the private network ID.
85    """
86    for _private_network in oneandone_conn.list_private_networks():
87        if private_network in (_private_network['name'],
88                               _private_network['id']):
89            if full_object:
90                return _private_network
91            return _private_network['id']
92
93
94def get_monitoring_policy(oneandone_conn, monitoring_policy, full_object=False):
95    """
96    Validates the monitoring policy exists by ID or name.
97    Return the monitoring policy ID.
98    """
99    for _monitoring_policy in oneandone_conn.list_monitoring_policies():
100        if monitoring_policy in (_monitoring_policy['name'],
101                                 _monitoring_policy['id']):
102            if full_object:
103                return _monitoring_policy
104            return _monitoring_policy['id']
105
106
107def get_firewall_policy(oneandone_conn, firewall_policy, full_object=False):
108    """
109    Validates the firewall policy exists by ID or name.
110    Return the firewall policy ID.
111    """
112    for _firewall_policy in oneandone_conn.list_firewall_policies():
113        if firewall_policy in (_firewall_policy['name'],
114                               _firewall_policy['id']):
115            if full_object:
116                return _firewall_policy
117            return _firewall_policy['id']
118
119
120def get_load_balancer(oneandone_conn, load_balancer, full_object=False):
121    """
122    Validates the load balancer exists by ID or name.
123    Return the load balancer ID.
124    """
125    for _load_balancer in oneandone_conn.list_load_balancers():
126        if load_balancer in (_load_balancer['name'],
127                             _load_balancer['id']):
128            if full_object:
129                return _load_balancer
130            return _load_balancer['id']
131
132
133def get_server(oneandone_conn, instance, full_object=False):
134    """
135    Validates that the server exists whether by ID or name.
136    Returns the server if one was found.
137    """
138    for server in oneandone_conn.list_servers(per_page=1000):
139        if instance in (server['id'], server['name']):
140            if full_object:
141                return server
142            return server['id']
143
144
145def get_user(oneandone_conn, user, full_object=False):
146    """
147    Validates that the user exists by ID or a name.
148    Returns the user if one was found.
149    """
150    for _user in oneandone_conn.list_users(per_page=1000):
151        if user in (_user['id'], _user['name']):
152            if full_object:
153                return _user
154            return _user['id']
155
156
157def get_role(oneandone_conn, role, full_object=False):
158    """
159    Given a name, validates that the role exists
160    whether it is a proper ID or a name.
161    Returns the role if one was found, else None.
162    """
163    for _role in oneandone_conn.list_roles(per_page=1000):
164        if role in (_role['id'], _role['name']):
165            if full_object:
166                return _role
167            return _role['id']
168
169
170def get_vpn(oneandone_conn, vpn, full_object=False):
171    """
172    Validates that the vpn exists by ID or a name.
173    Returns the vpn if one was found.
174    """
175    for _vpn in oneandone_conn.list_vpns(per_page=1000):
176        if vpn in (_vpn['id'], _vpn['name']):
177            if full_object:
178                return _vpn
179            return _vpn['id']
180
181
182def get_public_ip(oneandone_conn, public_ip, full_object=False):
183    """
184    Validates that the public ip exists by ID or a name.
185    Returns the public ip if one was found.
186    """
187    for _public_ip in oneandone_conn.list_public_ips(per_page=1000):
188        if public_ip in (_public_ip['id'], _public_ip['ip']):
189            if full_object:
190                return _public_ip
191            return _public_ip['id']
192
193
194def wait_for_resource_creation_completion(oneandone_conn,
195                                          resource_type,
196                                          resource_id,
197                                          wait_timeout,
198                                          wait_interval):
199    """
200    Waits for the resource create operation to complete based on the timeout period.
201    """
202    wait_timeout = time.time() + wait_timeout
203    while wait_timeout > time.time():
204        time.sleep(wait_interval)
205
206        # Refresh the resource info
207        resource = get_resource(oneandone_conn, resource_type, resource_id)
208
209        if resource_type == OneAndOneResources.server:
210            resource_state = resource['status']['state']
211        else:
212            resource_state = resource['state']
213
214        if ((resource_type == OneAndOneResources.server and resource_state.lower() == 'powered_on') or
215                (resource_type != OneAndOneResources.server and resource_state.lower() == 'active')):
216            return
217        elif resource_state.lower() == 'failed':
218            raise Exception('%s creation failed for %s' % (resource_type, resource_id))
219        elif resource_state.lower() in ('active',
220                                        'enabled',
221                                        'deploying',
222                                        'configuring'):
223            continue
224        else:
225            raise Exception(
226                'Unknown %s state %s' % (resource_type, resource_state))
227
228    raise Exception(
229        'Timed out waiting for %s completion for %s' % (resource_type, resource_id))
230
231
232def wait_for_resource_deletion_completion(oneandone_conn,
233                                          resource_type,
234                                          resource_id,
235                                          wait_timeout,
236                                          wait_interval):
237    """
238    Waits for the resource delete operation to complete based on the timeout period.
239    """
240    wait_timeout = time.time() + wait_timeout
241    while wait_timeout > time.time():
242        time.sleep(wait_interval)
243
244        # Refresh the operation info
245        logs = oneandone_conn.list_logs(q='DELETE',
246                                        period='LAST_HOUR',
247                                        sort='-start_date')
248
249        if resource_type == OneAndOneResources.server:
250            _type = 'VM'
251        elif resource_type == OneAndOneResources.private_network:
252            _type = 'PRIVATENETWORK'
253        else:
254            raise Exception(
255                'Unsupported wait_for delete operation for %s resource' % resource_type)
256
257        for log in logs:
258            if (log['resource']['id'] == resource_id and
259                    log['action'] == 'DELETE' and
260                    log['type'] == _type and
261                    log['status']['state'] == 'OK'):
262                return
263    raise Exception(
264        'Timed out waiting for %s deletion for %s' % (resource_type, resource_id))
265