def provision_instance(self, instance, backend_flavor_id, system_volume_id=None, data_volume_id=None):
        logger.info('About to boot instance %s', instance.uuid)
        try:
            membership = instance.cloud_project_membership

            image = membership.cloud.images.get(
                template=instance.template,
            )

            session = self.create_session(membership=membership)

            nova = self.create_nova_client(session)
            cinder = self.create_cinder_client(session)
            neutron = self.create_neutron_client(session)

            # verify if the internal network to connect to exists
            try:
                neutron.show_network(membership.internal_network_id)
            except neutron_exceptions.NeutronClientException:
                logger.exception('Internal network with id of %s was not found',
                                 membership.internal_network_id)
                raise CloudBackendError('Unable to find network to attach instance to')

            # instance key name and fingerprint are optional
            if instance.key_name:
                safe_key_name = self.sanitize_key_name(instance.key_name)

                matching_keys = [
                    key
                    for key in nova.keypairs.findall(fingerprint=instance.key_fingerprint)
                    if key.name.endswith(safe_key_name)
                ]
                matching_keys_count = len(matching_keys)

                if matching_keys_count >= 1:
                    if matching_keys_count > 1:
                        # TODO: warning as we trust that fingerprint+name combo is unique. Potentially reconsider.
                        logger.warning('Found %d public keys with fingerprint "%s", expected exactly one.' +
                                       'Taking the first one',
                                       matching_keys_count, instance.key_fingerprint)
                    backend_public_key = matching_keys[0]
                elif matching_keys_count == 0:
                    logger.error('Found no public keys with fingerprint "%s", expected exactly one',
                                 instance.key_fingerprint)
                    # It is possible to fix this situation with OpenStack admin account. So not failing here.
                    # Error log is expected to be addressed.
                    # TODO: consider failing provisioning/putting this check into serializer/pre-save.
                    # reset failed key name/fingerprint
                    instance.key_name = ''  # has to be an empty string, if None will fail on MySQL backend
                    instance.key_fingerprint = ''
                    backend_public_key = None
                else:
                    backend_public_key = matching_keys[0]
            else:
                backend_public_key = None

            backend_flavor = nova.flavors.get(backend_flavor_id)

            if not system_volume_id:
                system_volume_name = '{0}-system'.format(instance.name)
                logger.info('Creating volume %s for instance %s', system_volume_name, instance.uuid)
                # TODO: need to update system_volume_size as well for the data to be precise
                size = self.get_backend_disk_size(instance.system_volume_size)
                system_volume = cinder.volumes.create(
                    size=size,
                    display_name=system_volume_name,
                    display_description='',
                    imageRef=image.backend_id,
                )
                system_volume_id = system_volume.id

            if not data_volume_id:
                data_volume_name = '{0}-data'.format(instance.name)
                logger.info('Creating volume %s for instance %s', data_volume_name, instance.uuid)
                # TODO: need to update data_volume_size as well for the data to be precise
                size = self.get_backend_disk_size(instance.data_volume_size)
                data_volume = cinder.volumes.create(
                    size=size,
                    display_name=data_volume_name,
                    display_description='',
                )
                data_volume_id = data_volume.id

            if not self._wait_for_volume_status(system_volume_id, cinder, 'available', 'error'):
                logger.error(
                    'Failed to boot instance %s: timed out waiting for system volume %s to become available',
                    instance.uuid, system_volume_id,
                )
                raise CloudBackendError('Timed out waiting for instance %s to boot' % instance.uuid)

            if not self._wait_for_volume_status(data_volume_id, cinder, 'available', 'error'):
                logger.error(
                    'Failed to boot instance %s: timed out waiting for data volume %s to become available',
                    instance.uuid, data_volume_id,
                )
                raise CloudBackendError('Timed out waiting for instance %s to boot' % instance.uuid)

            security_group_ids = instance.security_groups.values_list('security_group__backend_id', flat=True)

            server_create_parameters = dict(
                name=instance.name,
                image=None,  # Boot from volume, see boot_index below
                flavor=backend_flavor,
                block_device_mapping_v2=[
                    {
                        'boot_index': 0,
                        'destination_type': 'volume',
                        'device_type': 'disk',
                        'source_type': 'volume',
                        'uuid': system_volume_id,
                        'delete_on_termination': True,
                    },
                    {
                        'destination_type': 'volume',
                        'device_type': 'disk',
                        'source_type': 'volume',
                        'uuid': data_volume_id,
                        'delete_on_termination': True,
                    },
                    # This should have worked by creating an empty volume.
                    # But, as always, OpenStack doesn't work as advertised:
                    # see https://bugs.launchpad.net/nova/+bug/1347499
                    # equivalent nova boot options would be
                    # --block-device source=blank,dest=volume,size=10,type=disk
                    # {
                    # 'destination_type': 'blank',
                    #     'device_type': 'disk',
                    #     'source_type': 'image',
                    #     'uuid': backend_image.id,
                    #     'volume_size': 10,
                    #     'shutdown': 'remove',
                    # },
                ],
                nics=[
                    {'net-id': membership.internal_network_id}
                ],
                key_name=backend_public_key.name if backend_public_key is not None else None,
                security_groups=security_group_ids,
            )
            if membership.availability_zone:
                server_create_parameters['availability_zone'] = membership.availability_zone
            if instance.user_data:
                server_create_parameters['userdata'] = instance.user_data

            server = nova.servers.create(**server_create_parameters)

            instance.backend_id = server.id
            instance.system_volume_id = system_volume_id
            instance.data_volume_id = data_volume_id
            instance.save()

            if not self._wait_for_instance_status(server.id, nova, 'ACTIVE'):
                logger.error(
                    'Failed to boot instance %s: timed out while waiting for instance to become online',
                    instance.uuid,
                )
                raise CloudBackendError('Timed out waiting for instance %s to boot' % instance.uuid)
            instance.start_time = timezone.now()
            instance.save()

            logger.debug('About to infer internal ip addresses of instance %s', instance.uuid)
            try:
                server = nova.servers.get(server.id)
                fixed_address = server.addresses.values()[0][0]['addr']
            except (nova_exceptions.ClientException, __HOLE__, IndexError):
                logger.exception('Failed to infer internal ip addresses of instance %s',
                                 instance.uuid)
            else:
                instance.internal_ips = fixed_address
                instance.save()
                logger.info('Successfully inferred internal ip addresses of instance %s',
                            instance.uuid)

            # Floating ips initialization
            self.push_floating_ip_to_instance(server, instance, nova)

        except (glance_exceptions.ClientException,
                cinder_exceptions.ClientException,
                nova_exceptions.ClientException,
                neutron_exceptions.NeutronClientException) as e:
            logger.exception('Failed to boot instance %s', instance.uuid)

            event_logger.instance.error(
                'Virtual machine {instance_name} creation has failed.',
                event_type='iaas_instance_creation_failed',
                event_context={'instance': instance})
            six.reraise(CloudBackendError, e)
        else:
            logger.info('Successfully booted instance %s', instance.uuid)

            event_logger.instance.info(
                'Virtual machine {instance_name} has been created.',
                event_type='iaas_instance_creation_succeeded',
                event_context={'instance': instance})

            event_logger.instance.info(
                'Virtual machine {instance_name} has been started.',
                event_type='iaas_instance_start_succeeded',
                event_context={'instance': instance})

            licenses = instance.instance_licenses.all()
            event_logger.instance_licenses.info(
                'Licenses added to VM with name {instance_name}.',
                event_type='iaas_instance_licenses_added',
                event_context={
                    'instance': instance,
                    'licenses_types': [l.template_license.license_type for l in licenses],
                    'licenses_services_types': [l.template_license.service_type for l in licenses],
                }
            )
dataset/ETHPy150Open opennode/nodeconductor/nodeconductor/iaas/backend.py/OpenStackBackend.provision_instance