We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
No openstack floating ip support
# Issue Type

- Bug report

# Molecule and Ansible details

```
molecule, version 1.16.1
```

- Molecule installation method: pip

# Desired Behaviour

The openstack provider creates an openstack instance, associates a floating ip to it and connects to the instance using the floating ip.

# Actual Behaviour (Bug report only)

The openstack provider creates an openstack instance and tries to connects to the private ip which obviously doesn't work.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `molecule/driver/openstackdriver.py`
Content:
```
1 #  Copyright (c) 2015-2016 Cisco Systems, Inc.
2 #
3 #  Permission is hereby granted, free of charge, to any person obtaining a copy
4 #  of this software and associated documentation files (the "Software"), to
5 #  deal in the Software without restriction, including without limitation the
6 #  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 #  sell copies of the Software, and to permit persons to whom the Software is
8 #  furnished to do so, subject to the following conditions:
9 #
10 #  The above copyright notice and this permission notice shall be included in
11 #  all copies or substantial portions of the Software.
12 #
13 #  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 #  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 #  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 #  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 #  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 #  DEALINGS IN THE SOFTWARE.
20 
21 import collections
22 import hashlib
23 import os
24 import socket
25 import sys
26 import time
27 
28 import paramiko
29 try:
30     import shade
31 except ImportError:  # pragma: no cover
32     sys.exit('ERROR: Driver missing, install shade.')
33 
34 from molecule import util
35 from molecule.driver import basedriver
36 
37 
38 class OpenstackDriver(basedriver.BaseDriver):
39     def __init__(self, molecule):
40         super(OpenstackDriver, self).__init__(molecule)
41         self._provider = self._get_provider()
42         self._platform = self._get_platform()
43         self._openstack = shade.openstack_cloud()
44 
45     @property
46     def name(self):
47         return 'openstack'
48 
49     @property
50     def instances(self):
51         return self.molecule.config.config['openstack']['instances']
52 
53     @property
54     def default_provider(self):
55         return self._provider
56 
57     @property
58     def default_platform(self):
59         return self._platform
60 
61     @property
62     def provider(self):
63         return self._provider
64 
65     @property
66     def platform(self):
67         return self._platform
68 
69     @platform.setter
70     def platform(self, val):
71         self._platform = val
72 
73     @property
74     def valid_providers(self):
75         return [{'name': self.provider}]
76 
77     @property
78     def valid_platforms(self):
79         return [{'name': self.platform}]
80 
81     @property
82     def ssh_config_file(self):
83         return
84 
85     @property
86     def ansible_connection_params(self):
87         return {'connection': 'ssh'}
88 
89     @property
90     def testinfra_args(self):
91         return {
92             'ansible_inventory':
93             self.molecule.config.config['ansible']['inventory_file'],
94             'connection': 'ansible'
95         }
96 
97     @property
98     def serverspec_args(self):
99         return {}
100 
101     def up(self, no_provision=True):
102         self.molecule.state.change_state('driver', self.name)
103         kpn = self._get_keypair()
104 
105         active_instances = self._openstack.list_servers()
106         active_instance_names = {
107             instance['name']: instance['status']
108             for instance in active_instances
109         }
110 
111         util.print_warn('Creating openstack instances...')
112         for instance in self.instances:
113             if instance['name'] not in active_instance_names:
114                 msg = '\tBringing up {}...'.format(instance['name'])
115                 util.print_info(msg)
116                 server = self._openstack.create_server(
117                     name=instance['name'],
118                     image=self._openstack.get_image(instance['image']),
119                     flavor=self._openstack.get_flavor(instance['flavor']),
120                     auto_ip=True,
121                     wait=True,
122                     key_name=kpn,
123                     security_groups=instance['security_groups']
124                     if 'security_groups' in instance else None)
125                 self._reset_known_host_key(server['interface_ip'])
126                 instance['created'] = True
127                 num_retries = 0
128                 while not self._check_ssh_availability(
129                         server['interface_ip'],
130                         instance['sshuser'],
131                         timeout=6,
132                         sshkey_filename=self._get_keyfile(
133                         )) or num_retries == 5:
134                     util.print_info('\t Waiting for ssh availability...')
135                     num_retries += 1
136 
137     def destroy(self):
138         util.print_info('Deleting openstack instances...')
139 
140         active_instances = self._openstack.list_servers()
141         active_instance_names = {
142             instance['name']: instance['id']
143             for instance in active_instances
144         }
145 
146         for instance in self.instances:
147             util.print_warn('\tRemoving {}...'.format(instance['name']))
148             if instance['name'] in active_instance_names:
149                 if not self._openstack.delete_server(
150                         active_instance_names[instance['name']], wait=True):
151                     msg = 'Unable to remove {}.'.format(instance['name'])
152                     util.print_error(msg)
153                 else:
154                     util.print_success('\tRemoved {}.'.format(instance[
155                         'name']))
156                     instance['created'] = False
157 
158         # cleanup any molecule generated ssh keysfiles
159         self._cleanup_temp_keypair()
160         self._cleanup_temp_keyfile()
161 
162     def status(self):
163         Status = collections.namedtuple('Status',
164                                         ['name', 'state', 'provider'])
165         status_list = []
166         for instance in self.instances:
167             if self._instance_is_accessible(instance):
168                 status_list.append(
169                     Status(
170                         name=instance['name'],
171                         state='UP',
172                         provider=self.provider))
173             else:
174                 status_list.append(
175                     Status(
176                         name=instance['name'],
177                         state='not_created',
178                         provider=self.provider))
179 
180         return status_list
181 
182     def conf(self, name=None, ssh_config=False):
183         inventory_file = self.molecule.config.config['ansible'][
184             'inventory_file']
185         if os.path.exists(inventory_file):
186             with open(inventory_file) as stream:
187                 for line in stream:
188                     if len(line.split()) > 0 and line.split()[0] == name:
189                         ansible_host = line.split()[1]
190                         host_address = ansible_host.split('=')[1]
191                         return host_address
192         return
193 
194     def inventory_entry(self, instance):
195         template = self._host_template()
196 
197         for server in self._openstack.list_servers(detailed=False):
198             if server['name'] == instance['name']:
199                 server_config = {
200                     'hostname': instance['name'],
201                     'interface_ip_address': server['interface_ip'],
202                     'ssh_username': instance['sshuser'],
203                     'ssh_key_filename': self._get_keyfile()
204                 }
205                 return template.format(**server_config)
206         return ''
207 
208     def login_cmd(self, instance_name):
209         return 'ssh {} -l {} -i {}'
210 
211     def login_args(self, instance_name):
212         # Try to retrieve the SSH configuration of the host.
213         conf = self.conf(name=instance_name)
214         user = ''
215         keyfile = self._get_keyfile()
216 
217         for instance in self.instances:
218             if instance_name == instance['name']:
219                 user = instance['sshuser']
220 
221         return [conf, user, keyfile]
222 
223     def _get_provider(self):
224         return 'openstack'
225 
226     def _get_platform(self):
227         return 'openstack'
228 
229     def _get_keypair(self):
230         if ('keypair' in self.molecule.config.config['openstack']):
231             return self.molecule.config.config['openstack']['keypair']
232         else:
233             return self._get_temp_keypair()
234 
235     def _get_keyfile(self):
236         if ('keyfile' in self.molecule.config.config['openstack']):
237             return os.path.expanduser(self.molecule.config.config['openstack'][
238                 'keyfile'])
239         else:
240             return self._get_temp_keyfile()
241 
242     def _get_temp_keypair(self):
243         kpn = self._get_temp_keyname()
244 
245         if not self._openstack.search_keypairs(kpn):
246             msg = '\tCreating openstack keypair {}...'.format(kpn)
247             util.print_info(msg)
248             pub_key_file = self._get_keyfile() + '.pub'
249             self._openstack.create_keypair(kpn,
250                                            open(pub_key_file,
251                                                 'r').read().strip())
252 
253         return kpn
254 
255     def _get_temp_keyfile(self):
256         kn = self._get_temp_keyname()
257         kl = self._get_temp_keylocation()
258         pvtloc = kl + '/' + kn
259         publoc = kl + '/' + kn + '.pub'
260 
261         if not os.path.exists(pvtloc):
262             util.print_info('\tCreating local ssh key {}...'.format(pvtloc))
263             k = paramiko.RSAKey.generate(2048)
264             k.write_private_key_file(pvtloc)
265             # write the public key too
266             pub = paramiko.RSAKey(filename=pvtloc)
267             with open(publoc, 'w') as f:
268                 f.write("%s %s" % (pub.get_name(), pub.get_base64()))
269 
270         return pvtloc
271 
272     def _get_temp_keyname(self):
273         mpath = os.path.abspath(self.molecule.config.config['molecule'][
274             'molecule_dir'])
275         return 'molecule_' + hashlib.sha256(mpath).hexdigest()[:10]
276 
277     def _get_temp_keylocation(self):
278         loc = self.molecule.config.config['molecule']['molecule_dir'] + '/.ssh'
279         if not os.path.exists(loc):
280             os.makedirs(loc)
281         return os.path.abspath(loc)
282 
283     def _reset_known_host_key(self, hostname):
284         return os.system('ssh-keygen -R {}'.format(hostname))
285 
286     def _check_ssh_availability(self, hostip, user, timeout, sshkey_filename):
287         ssh = paramiko.SSHClient()
288         ssh.load_system_host_keys()
289         ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
290         try:
291             ssh.connect(hostip, username=user, key_filename=sshkey_filename)
292             return True
293         except (paramiko.BadHostKeyException, paramiko.AuthenticationException,
294                 paramiko.SSHException, socket.error):
295             time.sleep(timeout)
296             return False
297 
298     def _cleanup_temp_keypair(self):
299         # if we don't have a keypair config, delete the temp one
300         if ('keypair' not in self.molecule.config.config['openstack']):
301             kpn = self._get_temp_keyname()
302             if self._openstack.search_keypairs(kpn):
303                 msg = '\tRemoving openstack keypair {}...'.format(kpn)
304                 util.print_warn(msg)
305                 if not self._openstack.delete_keypair(kpn):
306                     msg = 'Unable to remove openstack keypair {}.'.format(kpn)
307                     util.print_error(msg)
308                 else:
309                     msg = '\tRemoved openstack keypair {}.'.format(kpn)
310                     util.print_success(msg)
311 
312     def _cleanup_temp_keyfile(self):
313         # if we don't have a keyfile config, delete the temp one
314         if ('keyfile' not in self.molecule.config.config['openstack']):
315             kn = self._get_temp_keyname()
316             kl = self._get_temp_keylocation()
317             pvtloc = kl + '/' + kn
318             publoc = kl + '/' + kn + '.pub'
319             if os.path.exists(pvtloc):
320                 util.print_warn('\tRemoving {}...'.format(pvtloc))
321                 os.remove(pvtloc)
322             if os.path.exists(publoc):
323                 util.print_warn('\tRemoving {}...'.format(publoc))
324                 os.remove(publoc)
325 
326     def _host_template(self):
327         return ('{hostname} ansible_ssh_host={interface_ip_address} '
328                 'ansible_ssh_user={ssh_username} '
329                 'ansible_ssh_private_key_file={ssh_key_filename} '
330                 'ansible_ssh_extra_args="-o ConnectionAttempts=5"\n')
331 
332     def _instance_is_accessible(self, instance):
333         instance_ip = self.conf(instance['name'])
334         if instance_ip is not None:
335             return self._check_ssh_availability(
336                 instance_ip,
337                 instance['sshuser'],
338                 timeout=0,
339                 sshkey_filename=self._get_keyfile())
340         return False
341
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/molecule/driver/openstackdriver.py b/molecule/driver/openstackdriver.py
--- a/molecule/driver/openstackdriver.py
+++ b/molecule/driver/openstackdriver.py
@@ -50,6 +50,10 @@
     def instances(self):
         return self.molecule.config.config['openstack']['instances']
 
+    @property
+    def ip_pool(self):
+        return self.molecule.config.config['openstack'].get('ip_pool')
+
     @property
     def default_provider(self):
         return self._provider
@@ -120,6 +124,8 @@
                     auto_ip=True,
                     wait=True,
                     key_name=kpn,
+                    ip_pool=instance.get('ip_pool')
+                    if instance.get('ip_pool') else self.ip_pool,
                     security_groups=instance['security_groups']
                     if 'security_groups' in instance else None)
                 self._reset_known_host_key(server['interface_ip'])

{"golden_diff": "diff --git a/molecule/driver/openstackdriver.py b/molecule/driver/openstackdriver.py\n--- a/molecule/driver/openstackdriver.py\n+++ b/molecule/driver/openstackdriver.py\n@@ -50,6 +50,10 @@\n     def instances(self):\n         return self.molecule.config.config['openstack']['instances']\n \n+    @property\n+    def ip_pool(self):\n+        return self.molecule.config.config['openstack'].get('ip_pool')\n+\n     @property\n     def default_provider(self):\n         return self._provider\n@@ -120,6 +124,8 @@\n                     auto_ip=True,\n                     wait=True,\n                     key_name=kpn,\n+                    ip_pool=instance.get('ip_pool')\n+                    if instance.get('ip_pool') else self.ip_pool,\n                     security_groups=instance['security_groups']\n                     if 'security_groups' in instance else None)\n                 self._reset_known_host_key(server['interface_ip'])\n", "issue": "No openstack floating ip support\n# Issue Type\r\n\r\n- Bug report\r\n\r\n# Molecule and Ansible details\r\n\r\n```\r\nmolecule, version 1.16.1\r\n```\r\n\r\n- Molecule installation method: pip\r\n\r\n# Desired Behaviour\r\n\r\nThe openstack provider creates an openstack instance, associates a floating ip to it and connects to the instance using the floating ip.\r\n\r\n# Actual Behaviour (Bug report only)\r\n\r\nThe openstack provider creates an openstack instance and tries to connects to the private ip which obviously doesn't work.\n", "before_files": [{"content": "#  Copyright (c) 2015-2016 Cisco Systems, Inc.\n#\n#  Permission is hereby granted, free of charge, to any person obtaining a copy\n#  of this software and associated documentation files (the \"Software\"), to\n#  deal in the Software without restriction, including without limitation the\n#  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n#  sell copies of the Software, and to permit persons to whom the Software is\n#  furnished to do so, subject to the following conditions:\n#\n#  The above copyright notice and this permission notice shall be included in\n#  all copies or substantial portions of the Software.\n#\n#  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n#  DEALINGS IN THE SOFTWARE.\n\nimport collections\nimport hashlib\nimport os\nimport socket\nimport sys\nimport time\n\nimport paramiko\ntry:\n    import shade\nexcept ImportError:  # pragma: no cover\n    sys.exit('ERROR: Driver missing, install shade.')\n\nfrom molecule import util\nfrom molecule.driver import basedriver\n\n\nclass OpenstackDriver(basedriver.BaseDriver):\n    def __init__(self, molecule):\n        super(OpenstackDriver, self).__init__(molecule)\n        self._provider = self._get_provider()\n        self._platform = self._get_platform()\n        self._openstack = shade.openstack_cloud()\n\n    @property\n    def name(self):\n        return 'openstack'\n\n    @property\n    def instances(self):\n        return self.molecule.config.config['openstack']['instances']\n\n    @property\n    def default_provider(self):\n        return self._provider\n\n    @property\n    def default_platform(self):\n        return self._platform\n\n    @property\n    def provider(self):\n        return self._provider\n\n    @property\n    def platform(self):\n        return self._platform\n\n    @platform.setter\n    def platform(self, val):\n        self._platform = val\n\n    @property\n    def valid_providers(self):\n        return [{'name': self.provider}]\n\n    @property\n    def valid_platforms(self):\n        return [{'name': self.platform}]\n\n    @property\n    def ssh_config_file(self):\n        return\n\n    @property\n    def ansible_connection_params(self):\n        return {'connection': 'ssh'}\n\n    @property\n    def testinfra_args(self):\n        return {\n            'ansible_inventory':\n            self.molecule.config.config['ansible']['inventory_file'],\n            'connection': 'ansible'\n        }\n\n    @property\n    def serverspec_args(self):\n        return {}\n\n    def up(self, no_provision=True):\n        self.molecule.state.change_state('driver', self.name)\n        kpn = self._get_keypair()\n\n        active_instances = self._openstack.list_servers()\n        active_instance_names = {\n            instance['name']: instance['status']\n            for instance in active_instances\n        }\n\n        util.print_warn('Creating openstack instances...')\n        for instance in self.instances:\n            if instance['name'] not in active_instance_names:\n                msg = '\\tBringing up {}...'.format(instance['name'])\n                util.print_info(msg)\n                server = self._openstack.create_server(\n                    name=instance['name'],\n                    image=self._openstack.get_image(instance['image']),\n                    flavor=self._openstack.get_flavor(instance['flavor']),\n                    auto_ip=True,\n                    wait=True,\n                    key_name=kpn,\n                    security_groups=instance['security_groups']\n                    if 'security_groups' in instance else None)\n                self._reset_known_host_key(server['interface_ip'])\n                instance['created'] = True\n                num_retries = 0\n                while not self._check_ssh_availability(\n                        server['interface_ip'],\n                        instance['sshuser'],\n                        timeout=6,\n                        sshkey_filename=self._get_keyfile(\n                        )) or num_retries == 5:\n                    util.print_info('\\t Waiting for ssh availability...')\n                    num_retries += 1\n\n    def destroy(self):\n        util.print_info('Deleting openstack instances...')\n\n        active_instances = self._openstack.list_servers()\n        active_instance_names = {\n            instance['name']: instance['id']\n            for instance in active_instances\n        }\n\n        for instance in self.instances:\n            util.print_warn('\\tRemoving {}...'.format(instance['name']))\n            if instance['name'] in active_instance_names:\n                if not self._openstack.delete_server(\n                        active_instance_names[instance['name']], wait=True):\n                    msg = 'Unable to remove {}.'.format(instance['name'])\n                    util.print_error(msg)\n                else:\n                    util.print_success('\\tRemoved {}.'.format(instance[\n                        'name']))\n                    instance['created'] = False\n\n        # cleanup any molecule generated ssh keysfiles\n        self._cleanup_temp_keypair()\n        self._cleanup_temp_keyfile()\n\n    def status(self):\n        Status = collections.namedtuple('Status',\n                                        ['name', 'state', 'provider'])\n        status_list = []\n        for instance in self.instances:\n            if self._instance_is_accessible(instance):\n                status_list.append(\n                    Status(\n                        name=instance['name'],\n                        state='UP',\n                        provider=self.provider))\n            else:\n                status_list.append(\n                    Status(\n                        name=instance['name'],\n                        state='not_created',\n                        provider=self.provider))\n\n        return status_list\n\n    def conf(self, name=None, ssh_config=False):\n        inventory_file = self.molecule.config.config['ansible'][\n            'inventory_file']\n        if os.path.exists(inventory_file):\n            with open(inventory_file) as stream:\n                for line in stream:\n                    if len(line.split()) > 0 and line.split()[0] == name:\n                        ansible_host = line.split()[1]\n                        host_address = ansible_host.split('=')[1]\n                        return host_address\n        return\n\n    def inventory_entry(self, instance):\n        template = self._host_template()\n\n        for server in self._openstack.list_servers(detailed=False):\n            if server['name'] == instance['name']:\n                server_config = {\n                    'hostname': instance['name'],\n                    'interface_ip_address': server['interface_ip'],\n                    'ssh_username': instance['sshuser'],\n                    'ssh_key_filename': self._get_keyfile()\n                }\n                return template.format(**server_config)\n        return ''\n\n    def login_cmd(self, instance_name):\n        return 'ssh {} -l {} -i {}'\n\n    def login_args(self, instance_name):\n        # Try to retrieve the SSH configuration of the host.\n        conf = self.conf(name=instance_name)\n        user = ''\n        keyfile = self._get_keyfile()\n\n        for instance in self.instances:\n            if instance_name == instance['name']:\n                user = instance['sshuser']\n\n        return [conf, user, keyfile]\n\n    def _get_provider(self):\n        return 'openstack'\n\n    def _get_platform(self):\n        return 'openstack'\n\n    def _get_keypair(self):\n        if ('keypair' in self.molecule.config.config['openstack']):\n            return self.molecule.config.config['openstack']['keypair']\n        else:\n            return self._get_temp_keypair()\n\n    def _get_keyfile(self):\n        if ('keyfile' in self.molecule.config.config['openstack']):\n            return os.path.expanduser(self.molecule.config.config['openstack'][\n                'keyfile'])\n        else:\n            return self._get_temp_keyfile()\n\n    def _get_temp_keypair(self):\n        kpn = self._get_temp_keyname()\n\n        if not self._openstack.search_keypairs(kpn):\n            msg = '\\tCreating openstack keypair {}...'.format(kpn)\n            util.print_info(msg)\n            pub_key_file = self._get_keyfile() + '.pub'\n            self._openstack.create_keypair(kpn,\n                                           open(pub_key_file,\n                                                'r').read().strip())\n\n        return kpn\n\n    def _get_temp_keyfile(self):\n        kn = self._get_temp_keyname()\n        kl = self._get_temp_keylocation()\n        pvtloc = kl + '/' + kn\n        publoc = kl + '/' + kn + '.pub'\n\n        if not os.path.exists(pvtloc):\n            util.print_info('\\tCreating local ssh key {}...'.format(pvtloc))\n            k = paramiko.RSAKey.generate(2048)\n            k.write_private_key_file(pvtloc)\n            # write the public key too\n            pub = paramiko.RSAKey(filename=pvtloc)\n            with open(publoc, 'w') as f:\n                f.write(\"%s %s\" % (pub.get_name(), pub.get_base64()))\n\n        return pvtloc\n\n    def _get_temp_keyname(self):\n        mpath = os.path.abspath(self.molecule.config.config['molecule'][\n            'molecule_dir'])\n        return 'molecule_' + hashlib.sha256(mpath).hexdigest()[:10]\n\n    def _get_temp_keylocation(self):\n        loc = self.molecule.config.config['molecule']['molecule_dir'] + '/.ssh'\n        if not os.path.exists(loc):\n            os.makedirs(loc)\n        return os.path.abspath(loc)\n\n    def _reset_known_host_key(self, hostname):\n        return os.system('ssh-keygen -R {}'.format(hostname))\n\n    def _check_ssh_availability(self, hostip, user, timeout, sshkey_filename):\n        ssh = paramiko.SSHClient()\n        ssh.load_system_host_keys()\n        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())\n        try:\n            ssh.connect(hostip, username=user, key_filename=sshkey_filename)\n            return True\n        except (paramiko.BadHostKeyException, paramiko.AuthenticationException,\n                paramiko.SSHException, socket.error):\n            time.sleep(timeout)\n            return False\n\n    def _cleanup_temp_keypair(self):\n        # if we don't have a keypair config, delete the temp one\n        if ('keypair' not in self.molecule.config.config['openstack']):\n            kpn = self._get_temp_keyname()\n            if self._openstack.search_keypairs(kpn):\n                msg = '\\tRemoving openstack keypair {}...'.format(kpn)\n                util.print_warn(msg)\n                if not self._openstack.delete_keypair(kpn):\n                    msg = 'Unable to remove openstack keypair {}.'.format(kpn)\n                    util.print_error(msg)\n                else:\n                    msg = '\\tRemoved openstack keypair {}.'.format(kpn)\n                    util.print_success(msg)\n\n    def _cleanup_temp_keyfile(self):\n        # if we don't have a keyfile config, delete the temp one\n        if ('keyfile' not in self.molecule.config.config['openstack']):\n            kn = self._get_temp_keyname()\n            kl = self._get_temp_keylocation()\n            pvtloc = kl + '/' + kn\n            publoc = kl + '/' + kn + '.pub'\n            if os.path.exists(pvtloc):\n                util.print_warn('\\tRemoving {}...'.format(pvtloc))\n                os.remove(pvtloc)\n            if os.path.exists(publoc):\n                util.print_warn('\\tRemoving {}...'.format(publoc))\n                os.remove(publoc)\n\n    def _host_template(self):\n        return ('{hostname} ansible_ssh_host={interface_ip_address} '\n                'ansible_ssh_user={ssh_username} '\n                'ansible_ssh_private_key_file={ssh_key_filename} '\n                'ansible_ssh_extra_args=\"-o ConnectionAttempts=5\"\\n')\n\n    def _instance_is_accessible(self, instance):\n        instance_ip = self.conf(instance['name'])\n        if instance_ip is not None:\n            return self._check_ssh_availability(\n                instance_ip,\n                instance['sshuser'],\n                timeout=0,\n                sshkey_filename=self._get_keyfile())\n        return False\n", "path": "molecule/driver/openstackdriver.py"}], "after_files": [{"content": "#  Copyright (c) 2015-2016 Cisco Systems, Inc.\n#\n#  Permission is hereby granted, free of charge, to any person obtaining a copy\n#  of this software and associated documentation files (the \"Software\"), to\n#  deal in the Software without restriction, including without limitation the\n#  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n#  sell copies of the Software, and to permit persons to whom the Software is\n#  furnished to do so, subject to the following conditions:\n#\n#  The above copyright notice and this permission notice shall be included in\n#  all copies or substantial portions of the Software.\n#\n#  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n#  DEALINGS IN THE SOFTWARE.\n\nimport collections\nimport hashlib\nimport os\nimport socket\nimport sys\nimport time\n\nimport paramiko\ntry:\n    import shade\nexcept ImportError:  # pragma: no cover\n    sys.exit('ERROR: Driver missing, install shade.')\n\nfrom molecule import util\nfrom molecule.driver import basedriver\n\n\nclass OpenstackDriver(basedriver.BaseDriver):\n    def __init__(self, molecule):\n        super(OpenstackDriver, self).__init__(molecule)\n        self._provider = self._get_provider()\n        self._platform = self._get_platform()\n        self._openstack = shade.openstack_cloud()\n\n    @property\n    def name(self):\n        return 'openstack'\n\n    @property\n    def instances(self):\n        return self.molecule.config.config['openstack']['instances']\n\n    @property\n    def ip_pool(self):\n        return self.molecule.config.config['openstack'].get('ip_pool')\n\n    @property\n    def default_provider(self):\n        return self._provider\n\n    @property\n    def default_platform(self):\n        return self._platform\n\n    @property\n    def provider(self):\n        return self._provider\n\n    @property\n    def platform(self):\n        return self._platform\n\n    @platform.setter\n    def platform(self, val):\n        self._platform = val\n\n    @property\n    def valid_providers(self):\n        return [{'name': self.provider}]\n\n    @property\n    def valid_platforms(self):\n        return [{'name': self.platform}]\n\n    @property\n    def ssh_config_file(self):\n        return\n\n    @property\n    def ansible_connection_params(self):\n        return {'connection': 'ssh'}\n\n    @property\n    def testinfra_args(self):\n        return {\n            'ansible_inventory':\n            self.molecule.config.config['ansible']['inventory_file'],\n            'connection': 'ansible'\n        }\n\n    @property\n    def serverspec_args(self):\n        return {}\n\n    def up(self, no_provision=True):\n        self.molecule.state.change_state('driver', self.name)\n        kpn = self._get_keypair()\n\n        active_instances = self._openstack.list_servers()\n        active_instance_names = {\n            instance['name']: instance['status']\n            for instance in active_instances\n        }\n\n        util.print_warn('Creating openstack instances...')\n        for instance in self.instances:\n            if instance['name'] not in active_instance_names:\n                msg = '\\tBringing up {}...'.format(instance['name'])\n                util.print_info(msg)\n                server = self._openstack.create_server(\n                    name=instance['name'],\n                    image=self._openstack.get_image(instance['image']),\n                    flavor=self._openstack.get_flavor(instance['flavor']),\n                    auto_ip=True,\n                    wait=True,\n                    key_name=kpn,\n                    ip_pool=instance.get('ip_pool')\n                    if instance.get('ip_pool') else self.ip_pool,\n                    security_groups=instance['security_groups']\n                    if 'security_groups' in instance else None)\n                self._reset_known_host_key(server['interface_ip'])\n                instance['created'] = True\n                num_retries = 0\n                while not self._check_ssh_availability(\n                        server['interface_ip'],\n                        instance['sshuser'],\n                        timeout=6,\n                        sshkey_filename=self._get_keyfile(\n                        )) or num_retries == 5:\n                    util.print_info('\\t Waiting for ssh availability...')\n                    num_retries += 1\n\n    def destroy(self):\n        util.print_info('Deleting openstack instances...')\n\n        active_instances = self._openstack.list_servers()\n        active_instance_names = {\n            instance['name']: instance['id']\n            for instance in active_instances\n        }\n\n        for instance in self.instances:\n            util.print_warn('\\tRemoving {}...'.format(instance['name']))\n            if instance['name'] in active_instance_names:\n                if not self._openstack.delete_server(\n                        active_instance_names[instance['name']], wait=True):\n                    msg = 'Unable to remove {}.'.format(instance['name'])\n                    util.print_error(msg)\n                else:\n                    util.print_success('\\tRemoved {}.'.format(instance[\n                        'name']))\n                    instance['created'] = False\n\n        # cleanup any molecule generated ssh keysfiles\n        self._cleanup_temp_keypair()\n        self._cleanup_temp_keyfile()\n\n    def status(self):\n        Status = collections.namedtuple('Status',\n                                        ['name', 'state', 'provider'])\n        status_list = []\n        for instance in self.instances:\n            if self._instance_is_accessible(instance):\n                status_list.append(\n                    Status(\n                        name=instance['name'],\n                        state='UP',\n                        provider=self.provider))\n            else:\n                status_list.append(\n                    Status(\n                        name=instance['name'],\n                        state='not_created',\n                        provider=self.provider))\n\n        return status_list\n\n    def conf(self, name=None, ssh_config=False):\n        inventory_file = self.molecule.config.config['ansible'][\n            'inventory_file']\n        if os.path.exists(inventory_file):\n            with open(inventory_file) as stream:\n                for line in stream:\n                    if len(line.split()) > 0 and line.split()[0] == name:\n                        ansible_host = line.split()[1]\n                        host_address = ansible_host.split('=')[1]\n                        return host_address\n        return\n\n    def inventory_entry(self, instance):\n        template = self._host_template()\n\n        for server in self._openstack.list_servers(detailed=False):\n            if server['name'] == instance['name']:\n                server_config = {\n                    'hostname': instance['name'],\n                    'interface_ip_address': server['interface_ip'],\n                    'ssh_username': instance['sshuser'],\n                    'ssh_key_filename': self._get_keyfile()\n                }\n                return template.format(**server_config)\n        return ''\n\n    def login_cmd(self, instance_name):\n        return 'ssh {} -l {} -i {}'\n\n    def login_args(self, instance_name):\n        # Try to retrieve the SSH configuration of the host.\n        conf = self.conf(name=instance_name)\n        user = ''\n        keyfile = self._get_keyfile()\n\n        for instance in self.instances:\n            if instance_name == instance['name']:\n                user = instance['sshuser']\n\n        return [conf, user, keyfile]\n\n    def _get_provider(self):\n        return 'openstack'\n\n    def _get_platform(self):\n        return 'openstack'\n\n    def _get_keypair(self):\n        if ('keypair' in self.molecule.config.config['openstack']):\n            return self.molecule.config.config['openstack']['keypair']\n        else:\n            return self._get_temp_keypair()\n\n    def _get_keyfile(self):\n        if ('keyfile' in self.molecule.config.config['openstack']):\n            return os.path.expanduser(self.molecule.config.config['openstack'][\n                'keyfile'])\n        else:\n            return self._get_temp_keyfile()\n\n    def _get_temp_keypair(self):\n        kpn = self._get_temp_keyname()\n\n        if not self._openstack.search_keypairs(kpn):\n            msg = '\\tCreating openstack keypair {}...'.format(kpn)\n            util.print_info(msg)\n            pub_key_file = self._get_keyfile() + '.pub'\n            self._openstack.create_keypair(kpn,\n                                           open(pub_key_file,\n                                                'r').read().strip())\n\n        return kpn\n\n    def _get_temp_keyfile(self):\n        kn = self._get_temp_keyname()\n        kl = self._get_temp_keylocation()\n        pvtloc = kl + '/' + kn\n        publoc = kl + '/' + kn + '.pub'\n\n        if not os.path.exists(pvtloc):\n            util.print_info('\\tCreating local ssh key {}...'.format(pvtloc))\n            k = paramiko.RSAKey.generate(2048)\n            k.write_private_key_file(pvtloc)\n            # write the public key too\n            pub = paramiko.RSAKey(filename=pvtloc)\n            with open(publoc, 'w') as f:\n                f.write(\"%s %s\" % (pub.get_name(), pub.get_base64()))\n\n        return pvtloc\n\n    def _get_temp_keyname(self):\n        mpath = os.path.abspath(self.molecule.config.config['molecule'][\n            'molecule_dir'])\n        return 'molecule_' + hashlib.sha256(mpath).hexdigest()[:10]\n\n    def _get_temp_keylocation(self):\n        loc = self.molecule.config.config['molecule']['molecule_dir'] + '/.ssh'\n        if not os.path.exists(loc):\n            os.makedirs(loc)\n        return os.path.abspath(loc)\n\n    def _reset_known_host_key(self, hostname):\n        return os.system('ssh-keygen -R {}'.format(hostname))\n\n    def _check_ssh_availability(self, hostip, user, timeout, sshkey_filename):\n        ssh = paramiko.SSHClient()\n        ssh.load_system_host_keys()\n        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())\n        try:\n            ssh.connect(hostip, username=user, key_filename=sshkey_filename)\n            return True\n        except (paramiko.BadHostKeyException, paramiko.AuthenticationException,\n                paramiko.SSHException, socket.error):\n            time.sleep(timeout)\n            return False\n\n    def _cleanup_temp_keypair(self):\n        # if we don't have a keypair config, delete the temp one\n        if ('keypair' not in self.molecule.config.config['openstack']):\n            kpn = self._get_temp_keyname()\n            if self._openstack.search_keypairs(kpn):\n                msg = '\\tRemoving openstack keypair {}...'.format(kpn)\n                util.print_warn(msg)\n                if not self._openstack.delete_keypair(kpn):\n                    msg = 'Unable to remove openstack keypair {}.'.format(kpn)\n                    util.print_error(msg)\n                else:\n                    msg = '\\tRemoved openstack keypair {}.'.format(kpn)\n                    util.print_success(msg)\n\n    def _cleanup_temp_keyfile(self):\n        # if we don't have a keyfile config, delete the temp one\n        if ('keyfile' not in self.molecule.config.config['openstack']):\n            kn = self._get_temp_keyname()\n            kl = self._get_temp_keylocation()\n            pvtloc = kl + '/' + kn\n            publoc = kl + '/' + kn + '.pub'\n            if os.path.exists(pvtloc):\n                util.print_warn('\\tRemoving {}...'.format(pvtloc))\n                os.remove(pvtloc)\n            if os.path.exists(publoc):\n                util.print_warn('\\tRemoving {}...'.format(publoc))\n                os.remove(publoc)\n\n    def _host_template(self):\n        return ('{hostname} ansible_ssh_host={interface_ip_address} '\n                'ansible_ssh_user={ssh_username} '\n                'ansible_ssh_private_key_file={ssh_key_filename} '\n                'ansible_ssh_extra_args=\"-o ConnectionAttempts=5\"\\n')\n\n    def _instance_is_accessible(self, instance):\n        instance_ip = self.conf(instance['name'])\n        if instance_ip is not None:\n            return self._check_ssh_availability(\n                instance_ip,\n                instance['sshuser'],\n                timeout=0,\n                sshkey_filename=self._get_keyfile())\n        return False\n", "path": "molecule/driver/openstackdriver.py"}]}