<commit_before>
from openerp import fields, models, exceptions, api, _
import base64
import csv
import cStringIO

class ImportInventory(models.TransientModel):
    _name = 'import.inventory'
    _description = 'Import inventory'

    def _get_default_location(self):
        ctx = self._context
        if 'active_id' in ctx:
            inventory_obj = self.env['stock.inventory']
            inventory = inventory_obj.browse(ctx['active_id'])
        return inventory.location_id

    data = fields.Binary('File', required=True)
    name = fields.Char('Filename')
    delimeter = fields.Char('Delimeter', default=',',
                            help='Default delimeter is ","')
    location = fields.Many2one('stock.location', 'Default Location',
                               default=_get_default_location, required=True)

    @api.one
    def action_import(self):
        """Load Inventory data from the CSV file."""
        ctx = self._context
        stloc_obj = self.env['stock.location']
        inventory_obj = self.env['stock.inventory']
        inv_imporline_obj = self.env['stock.inventory.import.line']
        product_obj = self.env['product.product']
        if 'active_id' in ctx:
            inventory = inventory_obj.browse(ctx['active_id'])
        if not self.data:
            raise exceptions.Warning(_("You need to select a file!"))
        # Decode the file data
        data = base64.b64decode(self.data)
        file_input = cStringIO.StringIO(data)
        file_input.seek(0)
        location = self.location
        reader_info = []
        if self.delimeter:
            delimeter = str(self.delimeter)
        else:
            delimeter = ','
        reader = csv.reader(file_input, delimiter=delimeter,
                            lineterminator='\r\n')
        try:
            reader_info.extend(reader)
        except Exception:
            raise exceptions.Warning(_("Not a valid file!"))
        keys = reader_info[0]
        # check if keys exist
        if not isinstance(keys, list) or ('code' not in keys or
                                          'quantity' not in keys):
            raise exceptions.Warning(
                _("Not 'code' or 'quantity' keys found"))
        del reader_info[0]
        values = {}
        actual_date = fields.Date.today()
        inv_name = self.name + ' - ' + actual_date
        inventory.write({'name': inv_name,
                         'date': fields.Datetime.now(),
                         'imported': True, 'state': 'confirm'})
        for i in range(len(reader_info)):
            val = {}
            field = reader_info[i]
            values = dict(zip(keys, field))
            prod_location = location.id
            if 'location' in values and values['location']:
                locat_lst = stloc_obj.search([('name', '=',
                                               values['location'])])
                if locat_lst:
                    prod_location = locat_lst[0]
            prod_lst = product_obj.search([('default_code', '=',
                                            values['code'])])
            if prod_lst:
                val['product'] = prod_lst[0].id
            if 'lot' in values and values['lot']:
                val['lot'] = values['lot']
            val['code'] = values['code']
            val['quantity'] = values['quantity']
            val['location_id'] = prod_location
            val['inventory_id'] = inventory.id
            val['fail'] = True
            val['fail_reason'] = _('No processed')
            inv_imporline_obj.create(val)

class StockInventoryImportLine(models.Model):
    _name = "stock.inventory.import.line"
    _description = "Stock Inventory Import Line"

    code = fields.Char('Product Code')
    product = fields.Many2one('product.product', 'Found Product')
    quantity = fields.Float('Quantity')
    inventory_id = fields.Many2one('stock.inventory', 'Inventory',
                                   readonly=True)
    location_id = fields.Many2one('stock.location', 'Location')
    lot = fields.Char('Product Lot')
    fail = fields.Boolean('Fail')
    fail_reason = fields.Char('Fail Reason')
<commit_msg>[FIX] Inventory Import with location in csv<commit_after>
from openerp import fields, models, exceptions, api, _
import base64
import csv
import cStringIO

class ImportInventory(models.TransientModel):
    _name = 'import.inventory'
    _description = 'Import inventory'

    def _get_default_location(self):
        ctx = self._context
        if 'active_id' in ctx:
            inventory_obj = self.env['stock.inventory']
            inventory = inventory_obj.browse(ctx['active_id'])
        return inventory.location_id

    data = fields.Binary('File', required=True)
    name = fields.Char('Filename')
    delimeter = fields.Char('Delimeter', default=',',
                            help='Default delimeter is ","')
    location = fields.Many2one('stock.location', 'Default Location',
                               default=_get_default_location, required=True)

    @api.one
    def action_import(self):
        """Load Inventory data from the CSV file."""
        ctx = self._context
        stloc_obj = self.env['stock.location']
        inventory_obj = self.env['stock.inventory']
        inv_imporline_obj = self.env['stock.inventory.import.line']
        product_obj = self.env['product.product']
        if 'active_id' in ctx:
            inventory = inventory_obj.browse(ctx['active_id'])
        if not self.data:
            raise exceptions.Warning(_("You need to select a file!"))
        # Decode the file data
        data = base64.b64decode(self.data)
        file_input = cStringIO.StringIO(data)
        file_input.seek(0)
        location = self.location
        reader_info = []
        if self.delimeter:
            delimeter = str(self.delimeter)
        else:
            delimeter = ','
        reader = csv.reader(file_input, delimiter=delimeter,
                            lineterminator='\r\n')
        try:
            reader_info.extend(reader)
        except Exception:
            raise exceptions.Warning(_("Not a valid file!"))
        keys = reader_info[0]
        # check if keys exist
        if not isinstance(keys, list) or ('code' not in keys or
                                          'quantity' not in keys):
            raise exceptions.Warning(
                _("Not 'code' or 'quantity' keys found"))
        del reader_info[0]
        values = {}
        actual_date = fields.Date.today()
        inv_name = self.name + ' - ' + actual_date
        inventory.write({'name': inv_name,
                         'date': fields.Datetime.now(),
                         'imported': True, 'state': 'confirm'})
        for i in range(len(reader_info)):
            val = {}
            field = reader_info[i]
            values = dict(zip(keys, field))
            prod_location = location.id
            if 'location' in values and values['location']:
                locat_lst = stloc_obj.search([('name', '=',
                                               values['location'])])
                if locat_lst:
                    prod_location = locat_lst[0].id
            prod_lst = product_obj.search([('default_code', '=',
                                            values['code'])])
            if prod_lst:
                val['product'] = prod_lst[0].id
            if 'lot' in values and values['lot']:
                val['lot'] = values['lot']
            val['code'] = values['code']
            val['quantity'] = values['quantity']
            val['location_id'] = prod_location
            val['inventory_id'] = inventory.id
            val['fail'] = True
            val['fail_reason'] = _('No processed')
            inv_imporline_obj.create(val)

class StockInventoryImportLine(models.Model):
    _name = "stock.inventory.import.line"
    _description = "Stock Inventory Import Line"

    code = fields.Char('Product Code')
    product = fields.Many2one('product.product', 'Found Product')
    quantity = fields.Float('Quantity')
    inventory_id = fields.Many2one('stock.inventory', 'Inventory',
                                   readonly=True)
    location_id = fields.Many2one('stock.location', 'Location')
    lot = fields.Char('Product Lot')
    fail = fields.Boolean('Fail')
    fail_reason = fields.Char('Fail Reason')
<|endoftext|>


<commit_before>import numpy
import pyfftw
import pickle
import pathlib

from . import fft

PRECISION = {
    32: numpy.float32,
    64: numpy.float64
}

PRECISION_FFT = {
    32: numpy.complex64,
    64: numpy.complex128
}

def store_plan_hints(filename, locking=True, reload_first=True):
    """Store data about the best FFT plans for this computer.

    FFT planning can take quite a while. After planning, the knowledge about
    the best plan for a given computer and given transform parameters can be
    written to disk so that the next time, planning can make use of that
    knowledge.

    Parameters:
        filename: file to write hints to.
        locking: if True, attempt to acquire an exclusive lock before writing
            which can otherwise cause problems if multiple processes are
            attempting to write to the same plan hints file.
        reload_first: if True, if the file exists, load the plan hints before
            storing them back. Safer in a multi-process setting where the hints
            may be written by a different process.

    """
    filename = pathlib.Path(filename)
    if not filename.exists():
        filename.touch() # can't open a file for read/write updating if it doesn't exist...
    with filename.open('r+b') as f:
        if locking:
            import fcntl
            fcntl.flock(f, fcntl.LOCK_EX)
        if reload_first:
            try:
                pyfftw.import_wisdom(pickle.load(f))
            except:
                pass
            f.seek(0)
        pickle.dump(pyfftw.export_wisdom(), f)
        if locking:
            fcntl.flock(f, fcntl.LOCK_UN)

def load_plan_hints(filename, locking=True):
    """Load data about the best FFT plans for this computer.

    FFT planning can take quite a while. After planning, the knowledge about
    the best plan for a given computer and given transform parameters can be
    written to disk so that the next time, planning can make use of that
    knowledge.

    Parameters:
        filename: file to read hints from.
        locking: if True, attempt to acquire an exclusive lock before reading
            which can otherwise cause problems if multiple processes are
            attempting to write to the same plan hints file.

    """
    with open(filename, 'rb') as f:
        if locking:
            import fcntl
            fcntl.flock(f, fcntl.LOCK_EX)
        pyfftw.import_wisdom(pickle.load(f))
        if locking:
            fcntl.flock(f, fcntl.LOCK_UN)

class FilterBase:
    def __init__(self, shape, precision=32, threads=4, better_plan=False):
        """Base class for FFT filtering.

        Constructor parameters:
            shape: shape of the images to be filtered (must be 2d)
            precision: 32 or 64. Refers to the floating-point precision with
                which the FFT used for filtering is to be calculated.
            threads: number of threads to use for FFT computation.
            better_plan: if True, spend time (possibly minutes) identifying the
                best FFT plan. This can dramatically speed future FFTs. The
                functions 'store_plan_hints()' and 'load_plan_hints()' can be
                used to store the planning data so that this time-cost need only
                be paid once.
        """
        assert precision in PRECISION.keys()
        n = pyfftw.simd_alignment
        self.image_arr = pyfftw.n_byte_align_empty(shape, n, dtype=PRECISION[precision], order='F')
        fft_shape = list(shape)
        fft_shape[1] = fft_shape[1] // 2 + 1
        self.fft_arr = pyfftw.n_byte_align_empty(fft_shape, n, dtype=PRECISION_FFT[precision], order='F')
        effort = 'FFTW_PATIENT' if better_plan else 'FFTW_MEASURE'
        flags = (effort, 'FFTW_DESTROY_INPUT')
        self.fft = pyfftw.FFTW(self.image_arr, self.fft_arr, axes=(0,1), direction='FFTW_FORWARD', flags=flags, threads=threads)
        self.ifft = pyfftw.FFTW(self.fft_arr, self.image_arr, axes=(0,1), direction='FFTW_BACKWARD', flags=flags, threads=threads)

class SpatialFilter(FilterBase):
    def __init__(self, shape, period_range, spacing=1.0, order=2, keep_dc=False, precision=32, threads=4, better_plan=False):
        """Class to apply the same filter over a multiple images.

        Constructor parameters:
            shape: shape of the images to be filtered (must be 2d)
            period_range: (min_size, max_size) tuple representing the minimum
                and maximum spatial size of objects in the filter's pass-band.
                Objects smaller than min_size and larger than max_size will be
                filtered out of the image. Either value can be None, indicating
                that there should be no size limit at that end of the scale.
            spacing: allows the physical spacing between array elements to be
                specified, so that the size values (above) can be given in
                physical units. This parameter can either be a scalar or a list
                of spacings in each dimension.
            order: controls the order of the butterworth filter. Higher order
                filters remove more of the structure in the stop-bands
                (specifically, those near the transition between pass-band and
                stop-band), but may introduce ringing artifacts.
            keep_dc: if True, then the DC component of the array will not be
                removed; otherwise it will. (If the DC component is removed,
                then the average array value will be zero; otherwise the
                average value will remain unchanged.)
            precision: 32 or 64. Refers to the floating-point precision with
                which the FFT used for filtering is to be calculated.
            threads: number of threads to use for FFT computation.
            better_plan: if True, spend time (possibly minutes) identifying the
                best FFT plan. This can dramatically speed future FFTs. The
                functions 'store_plan_hints()' and 'load_plan_hints()' can be
                used to store the planning data so that this time-cost need only
                be paid once.
        """
        super().__init__(shape, precision, threads, better_plan)
        filter_coeffs = fft.make_spatial_filter(shape, period_range, spacing, order, keep_dc)
        self.filter_coeffs = filter_coeffs.astype(PRECISION[precision], order='F')

    def filter(self, image):
        """Filter a given image as specified in the SpatialFilter constructor.

        Returns: filtered image, of dtype numpy.float32 or numpy.float64,
            depending on the 'precision' parameter to the constructor.
            NB: the returned image WILL be overwritten by future calls to
            filter(). If this image needs to be kept past subsequent filter()
            calls, a copy must be made.
        """
        assert image.shape == self.image_arr.shape
        self.image_arr[:] = image
        self.fft()
        self.fft_arr.real *= self.filter_coeffs
        self.ifft()
        return self.image_arr

class MultiFilter(FilterBase):
    def __init__(self, shape, filters, precision=32, threads=4, better_plan=False):
        """Class to efficiently apply multiple FFT filters to each of many images.

        Constructor parameters:
            shape: shape of the images to be filtered (must be 2d)
            filters: list of filter coefficients generated with, e.g.
                fft.make_spatial_filter()
            precision: 32 or 64. Refers to the floating-point precision with
                which the FFT used for filtering is to be calculated.
            threads: number of threads to use for FFT computation.
            better_plan: if True, spend time (possibly minutes) identifying the
                best FFT plan. This can dramatically speed future FFTs. The
                functions 'store_plan_hints()' and 'load_plan_hints()' can be
                used to store the planning data so that this time-cost need only
                be paid once.
        """
        super().__init__(shape, precision, threads, better_plan)
        self.filters = [fc.astype(PRECISION[precision], order='F') for fc in filters]

    def filter(self, image):
        """Filter a given image with each of the FFT filters, and return a list
        of the filtered images.
        """
        assert image.shape == self.image_arr.shape
        self.image_arr[:] = image
        self.fft()
        fft_vals = self.fft_arr.real.copy()
        images_out = []
        for filter_coeffs in self.filters:
            self.fft_arr.real = fft_vals * filter_coeffs
            self.ifft()
            images_out.append(self.image_arr.copy())
        return images_out

<commit_msg>now fast_fft actually works<commit_after>import numpy
import pyfftw
import pickle
import pathlib

from . import fft

PRECISION = {
    32: numpy.float32,
    64: numpy.float64
}

PRECISION_FFT = {
    32: numpy.complex64,
    64: numpy.complex128
}

def store_plan_hints(filename, locking=True, reload_first=True):
    """Store data about the best FFT plans for this computer.

    FFT planning can take quite a while. After planning, the knowledge about
    the best plan for a given computer and given transform parameters can be
    written to disk so that the next time, planning can make use of that
    knowledge.

    Parameters:
        filename: file to write hints to.
        locking: if True, attempt to acquire an exclusive lock before writing
            which can otherwise cause problems if multiple processes are
            attempting to write to the same plan hints file.
        reload_first: if True, if the file exists, load the plan hints before
            storing them back. Safer in a multi-process setting where the hints
            may be written by a different process.

    """
    filename = pathlib.Path(filename)
    if not filename.exists():
        filename.touch() # can't open a file for read/write updating if it doesn't exist...
    with filename.open('r+b') as f:
        if locking:
            import fcntl
            fcntl.flock(f, fcntl.LOCK_EX)
        if reload_first:
            try:
                pyfftw.import_wisdom(pickle.load(f))
            except:
                pass
            f.seek(0)
        pickle.dump(pyfftw.export_wisdom(), f)
        if locking:
            fcntl.flock(f, fcntl.LOCK_UN)

def load_plan_hints(filename, locking=True):
    """Load data about the best FFT plans for this computer.

    FFT planning can take quite a while. After planning, the knowledge about
    the best plan for a given computer and given transform parameters can be
    written to disk so that the next time, planning can make use of that
    knowledge.

    Parameters:
        filename: file to read hints from.
        locking: if True, attempt to acquire an exclusive lock before reading
            which can otherwise cause problems if multiple processes are
            attempting to write to the same plan hints file.

    """
    with open(filename, 'rb') as f:
        if locking:
            import fcntl
            fcntl.flock(f, fcntl.LOCK_EX)
        pyfftw.import_wisdom(pickle.load(f))
        if locking:
            fcntl.flock(f, fcntl.LOCK_UN)

class FilterBase:
    def __init__(self, shape, precision=32, threads=4, better_plan=False):
        """Base class for FFT filtering.

        Constructor parameters:
            shape: shape of the images to be filtered (must be 2d)
            precision: 32 or 64. Refers to the floating-point precision with
                which the FFT used for filtering is to be calculated.
            threads: number of threads to use for FFT computation.
            better_plan: if True, spend time (possibly minutes) identifying the
                best FFT plan. This can dramatically speed future FFTs. The
                functions 'store_plan_hints()' and 'load_plan_hints()' can be
                used to store the planning data so that this time-cost need only
                be paid once.
        """
        assert precision in PRECISION.keys()
        n = pyfftw.simd_alignment
        self.image_arr = pyfftw.n_byte_align_empty(shape, n, dtype=PRECISION[precision], order='F')
        fft_shape = list(shape)
        fft_shape[1] = fft_shape[1] // 2 + 1
        self.fft_arr = pyfftw.n_byte_align_empty(fft_shape, n, dtype=PRECISION_FFT[precision], order='F')
        effort = 'FFTW_PATIENT' if better_plan else 'FFTW_MEASURE'
        flags = (effort, 'FFTW_DESTROY_INPUT')
        self.fft = pyfftw.FFTW(self.image_arr, self.fft_arr, axes=(0,1), direction='FFTW_FORWARD', flags=flags, threads=threads)
        self.ifft = pyfftw.FFTW(self.fft_arr, self.image_arr, axes=(0,1), direction='FFTW_BACKWARD', flags=flags, threads=threads)

class SpatialFilter(FilterBase):
    def __init__(self, shape, period_range, spacing=1.0, order=2, keep_dc=False, precision=32, threads=4, better_plan=False):
        """Class to apply the same filter over a multiple images.

        Constructor parameters:
            shape: shape of the images to be filtered (must be 2d)
            period_range: (min_size, max_size) tuple representing the minimum
                and maximum spatial size of objects in the filter's pass-band.
                Objects smaller than min_size and larger than max_size will be
                filtered out of the image. Either value can be None, indicating
                that there should be no size limit at that end of the scale.
            spacing: allows the physical spacing between array elements to be
                specified, so that the size values (above) can be given in
                physical units. This parameter can either be a scalar or a list
                of spacings in each dimension.
            order: controls the order of the butterworth filter. Higher order
                filters remove more of the structure in the stop-bands
                (specifically, those near the transition between pass-band and
                stop-band), but may introduce ringing artifacts.
            keep_dc: if True, then the DC component of the array will not be
                removed; otherwise it will. (If the DC component is removed,
                then the average array value will be zero; otherwise the
                average value will remain unchanged.)
            precision: 32 or 64. Refers to the floating-point precision with
                which the FFT used for filtering is to be calculated.
            threads: number of threads to use for FFT computation.
            better_plan: if True, spend time (possibly minutes) identifying the
                best FFT plan. This can dramatically speed future FFTs. The
                functions 'store_plan_hints()' and 'load_plan_hints()' can be
                used to store the planning data so that this time-cost need only
                be paid once.
        """
        super().__init__(shape, precision, threads, better_plan)
        filter_coeffs = fft.make_spatial_filter(shape, period_range, spacing, order, keep_dc)
        self.filter_coeffs = filter_coeffs.astype(PRECISION[precision], order='F')

    def filter(self, image):
        """Filter a given image as specified in the SpatialFilter constructor.

        Returns: filtered image, of dtype numpy.float32 or numpy.float64,
            depending on the 'precision' parameter to the constructor.
            NB: the returned image WILL be overwritten by future calls to
            filter(). If this image needs to be kept past subsequent filter()
            calls, a copy must be made.
        """
        assert image.shape == self.image_arr.shape
        self.image_arr[:] = image
        self.fft()
        self.fft_arr *= self.filter_coeffs
        self.ifft()
        return self.image_arr

class MultiFilter(FilterBase):
    def __init__(self, shape, filters, precision=32, threads=4, better_plan=False):
        """Class to efficiently apply multiple FFT filters to each of many images.

        Constructor parameters:
            shape: shape of the images to be filtered (must be 2d)
            filters: list of filter coefficients generated with, e.g.
                fft.make_spatial_filter()
            precision: 32 or 64. Refers to the floating-point precision with
                which the FFT used for filtering is to be calculated.
            threads: number of threads to use for FFT computation.
            better_plan: if True, spend time (possibly minutes) identifying the
                best FFT plan. This can dramatically speed future FFTs. The
                functions 'store_plan_hints()' and 'load_plan_hints()' can be
                used to store the planning data so that this time-cost need only
                be paid once.
        """
        super().__init__(shape, precision, threads, better_plan)
        self.filters = [fc.astype(PRECISION[precision], order='F') for fc in filters]

    def filter(self, image):
        """Filter a given image with each of the FFT filters, and return a list
        of the filtered images.
        """
        assert image.shape == self.image_arr.shape
        self.image_arr[:] = image
        self.fft()
        fft_vals = self.fft_arr.real.copy()
        images_out = []
        for filter_coeffs in self.filters:
            self.fft_arr.real = fft_vals * filter_coeffs
            self.ifft()
            images_out.append(self.image_arr.copy())
        return images_out

<|endoftext|>


<commit_before>##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import api, models

class StockImmediateTransfer(models.TransientModel):
    _inherit = 'stock.immediate.transfer'

    # @api.model
    # def default_get(self, fields):
    #     res = {}
    #     print ' xxxxxxxxxxx'
    #     active_id = self._context.get('picking_id')
    #     if active_id:
    #         res = {'pick_id': active_id}
    #     return res

    @api.multi
    def process(self):
        super(StockImmediateTransfer, self).process()
        picking = self.env['stock.picking'].browse(
            # if we came, for eg, from a sale order, active_id would be the
            # sale order id
            # self._context.get('active_id'))
            # TODO we should also fix odoo methods
            self._context.get('picking_id'))
        if picking.book_required:
            return {
                'actions': [
                    {'type': 'ir.actions.act_window_close'},
                    picking.do_print_voucher(),
                ],
                'type': 'ir.actions.act_multi',
            }
<commit_msg>[FIX] inmediate transfer<commit_after>##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import api, models

class StockImmediateTransfer(models.TransientModel):
    _inherit = 'stock.immediate.transfer'

    # @api.model
    # def default_get(self, fields):
    #     res = {}
    #     print ' xxxxxxxxxxx'
    #     active_id = self._context.get('picking_id')
    #     if active_id:
    #         res = {'pick_id': active_id}
    #     return res

    @api.multi
    def process(self):
        res = super(StockImmediateTransfer, self).process()
        picking = self.env['stock.picking'].browse(
            # if we came, for eg, from a sale order, active_id would be the
            # sale order id
            # self._context.get('active_id'))
            # TODO we should also fix odoo methods
            self._context.get('picking_id'))
        if picking.book_required:
            return {
                'actions': [
                    res,
                    picking.do_print_voucher(),
                ],
                'type': 'ir.actions.act_multi',
            }
        else:
            return res
<|endoftext|>


<commit_before># Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.

from ZSI.wstools.Utility import SplitQName
from ZSI.wstools.Namespaces import WSDL
from ZSI import *
from ZSI.client import *
from ZSI.TC import Any
from ZSI.typeinterpreter import BaseTypeInterpreter
import wstools
from wstools.Utility import DOM
from urlparse import urlparse
import weakref

class ServiceProxy:
    """A ServiceProxy provides a convenient way to call a remote web
       service that is described with WSDL. The proxy exposes methods
       that reflect the methods of the remote web service."""

    def __init__(self, wsdl, service=None, port=None, tracefile=None,
                 nsdict=None, transdict=None):
        """
        Parameters:
           wsdl -- WSDLTools.WSDL instance or URL of WSDL.
           service -- service name or index
           port -- port name or index
           tracefile --
           nsdict -- key prefix to namespace mappings for serialization
              in SOAP Envelope.
           transdict -- arguments to pass into HTTPConnection constructor.
        """
        self._tracefile = tracefile
        self._nsdict = nsdict or {}
        self._transdict = transdict
        self._wsdl = wsdl
        if isinstance(wsdl, basestring) is True:
            self._wsdl = wstools.WSDLTools.WSDLReader().loadFromURL(wsdl)

        assert isinstance(self._wsdl, wstools.WSDLTools.WSDL), 'expecting a WSDL instance'
        self._service = wsdl.services[service or 0]
        self.__doc__ = self._service.documentation
        self._port = self._service.ports[port or 0]
        self._name = self._service.name

        binding = self._port.getBinding()
        portType = binding.getPortType()
        for item in portType.operations:
            callinfo = wstools.WSDLTools.callInfoFromWSDL(self._port, item.name)
            method = MethodProxy(self, callinfo)
            setattr(self, item.name, method)

    def _call(self, name, *args, **kwargs):
        """Call the named remote web service method."""
        if len(args) and len(kwargs):
            raise TypeError(
                'Use positional or keyword argument only.'
                )

        callinfo = getattr(self, name).callinfo
        soapAction = callinfo.soapAction
        url = callinfo.location
        (protocol, host, uri, query, fragment, identifier) = urlparse(url)
        port = None
        if host.find(':') >= 0:
            host, port = host.split(':')

        if protocol == 'http':
            transport = httplib.HTTPConnection
        elif protocol == 'https':
            transport = httplib.HTTPSConnection
        else:
            raise RuntimeError, 'Unknown protocol %s' %protocol

        binding = Binding(host=host, tracefile=self._tracefile,
                          transport=transport,transdict=self._transdict,
                          port=port, url=url, nsdict=self._nsdict,
                          soapaction=soapAction,)

        request, response = self._getTypeCodes(callinfo)
        if len(kwargs): args = kwargs
        if request is None:
            request = Any(oname=name)
        binding.Send(url=uri, opname=None, obj=args,
                     nsdict=self._nsdict, soapaction=soapAction, requesttypecode=request)
        return binding.Receive(replytype=response)

    def _getTypeCodes(self, callinfo):
        """Returns typecodes representing input and output messages, if request and/or
           response fails to be generated return None for either or both.

           callinfo --  WSDLTools.SOAPCallInfo instance describing an operation.
        """
        prefix = None
        self._resetPrefixDict()
        if callinfo.use == 'encoded':
            prefix = self._getPrefix(callinfo.namespace)
        try:
            requestTC = self._getTypeCode(parameters=callinfo.getInParameters(), literal=(callinfo.use=='literal'))
        except EvaluateException, ex:
            print "DEBUG: Request Failed to generate --", ex
            requestTC = None

        self._resetPrefixDict()
        try:
            replyTC = self._getTypeCode(parameters=callinfo.getOutParameters(), literal=(callinfo.use=='literal'))
        except EvaluateException, ex:
            print "DEBUG: Response Failed to generate --", ex
            replyTC = None

        request = response = None
        if callinfo.style == 'rpc':
            if requestTC: request = TC.Struct(pyclass=None, ofwhat=requestTC, pname=callinfo.methodName)
            if replyTC: response = TC.Struct(pyclass=None, ofwhat=replyTC, pname='%sResponse' %callinfo.methodName)
        else:
            if requestTC: request = requestTC[0]
            if replyTC: response = replyTC[0]

        #THIS IS FOR RPC/ENCODED, DOC/ENCODED Wrapper
        if request and prefix and callinfo.use == 'encoded':
            request.oname = '%(prefix)s:%(name)s xmlns:%(prefix)s="%(namespaceURI)s"' \
                %{'prefix':prefix, 'name':request.oname, 'namespaceURI':callinfo.namespace}

        return request, response

    def _getTypeCode(self, parameters, literal=False):
        """Returns typecodes representing a parameter set
           parameters -- list of WSDLTools.ParameterInfo instances representing
              the parts of a WSDL Message.
        """
        ofwhat = []
        for part in parameters:
            namespaceURI,localName = part.type

            if part.element_type:
                #global element
                element = self._wsdl.types[namespaceURI].elements[localName]
                tc = self._getElement(element, literal=literal, local=False, namespaceURI=namespaceURI)
            else:
                #local element
                name = part.name
                typeClass = self._getTypeClass(namespaceURI, localName)
                if not typeClass:
                    tp = self._wsdl.types[namespaceURI].types[localName]
                    tc = self._getType(tp, name, literal, local=True, namespaceURI=namespaceURI)
                else:
                    tc = typeClass(name)
            ofwhat.append(tc)
        return ofwhat

    def _globalElement(self, typeCode, namespaceURI, literal):
        """namespaces typecodes representing global elements with
             literal encoding.
           typeCode -- typecode representing an element.
           namespaceURI -- namespace
           literal -- True/False
        """
        if literal:
            typeCode.oname = '%(prefix)s:%(name)s xmlns:%(prefix)s="%(namespaceURI)s"' \
                %{'prefix':self._getPrefix(namespaceURI), 'name':typeCode.oname, 'namespaceURI':namespaceURI}

    def _getPrefix(self, namespaceURI):
        """Retrieves a prefix/namespace mapping.
           namespaceURI -- namespace
        """
        prefixDict = self._getPrefixDict()
        if prefixDict.has_key(namespaceURI):
            prefix = prefixDict[namespaceURI]
        else:
            prefix = 'ns1'
            while prefix in prefixDict.values():
                prefix = 'ns%d' %int(prefix[-1]) + 1
            prefixDict[namespaceURI] = prefix
        return prefix

    def _getPrefixDict(self):
        """Used to hide the actual prefix dictionary.
        """
        if not hasattr(self, '_prefixDict'):
            self.__prefixDict = {}
        return self.__prefixDict

    def _resetPrefixDict(self):
        """Clears the prefix dictionary, this needs to be done
           before creating a new typecode for a message
           (ie. before, and after creating a new message typecode)
        """
        self._getPrefixDict().clear()

    def _getElement(self, element, literal=False, local=False, namespaceURI=None):
        """Returns a typecode instance representing the passed in element.
           element -- XMLSchema.ElementDeclaration instance
           literal -- literal encoding?
           local -- is locally defined?
           namespaceURI -- namespace
        """
        if not element.isElement():
            raise TypeError, 'Expecting an ElementDeclaration'

        tc = None
        elementName = element.getAttribute('name')
        tp = element.getTypeDefinition('type')

        typeObj = None
        if not (tp or element.content):
            nsuriType,localName = element.getAttribute('type')
            typeClass = self._getTypeClass(nsuriType,localName)

            typeObj = typeClass(elementName)
        elif not tp:
            tp = element.content

        if not typeObj:
            typeObj = self._getType(tp, elementName, literal, local, namespaceURI)

        minOccurs = int(element.getAttribute('minOccurs'))
        typeObj.optional = not minOccurs

        maxOccurs = element.getAttribute('maxOccurs')
        typeObj.repeatable = (maxOccurs == 'unbounded') or (int(maxOccurs) > 1)

        return typeObj

    def _getType(self, tp, name, literal, local, namespaceURI):
        """Returns a typecode instance representing the passed in type and name.
           tp -- XMLSchema.TypeDefinition instance
           name -- element name
           literal -- literal encoding?
           local -- is locally defined?
           namespaceURI -- namespace
        """
        ofwhat = []
        if not (tp.isDefinition() and tp.isComplex()):
            raise EvaluateException, 'only supporting complexType definition'
        elif tp.content.isComplex():
            if hasattr(tp.content, 'derivation') and tp.content.derivation.isRestriction():
                derived = tp.content.derivation
                typeClass = self._getTypeClass(*derived.getAttribute('base'))
                if typeClass == TC.Array:
                    attrs = derived.attr_content[0].attributes[WSDL.BASE]
                    prefix, localName = SplitQName(attrs['arrayType'])
                    nsuri = derived.attr_content[0].getXMLNS(prefix=prefix)
                    localName = localName.split('[')[0]
                    simpleTypeClass = self._getTypeClass(namespaceURI=nsuri, localName=localName)
                    if simpleTypeClass:
                        ofwhat = simpleTypeClass()
                    else:
                        tp = self._wsdl.types[nsuri].types[localName]
                        ofwhat = self._getType(tp=tp, name=None, literal=literal, local=True, namespaceURI=nsuri)
                else:
                    raise EvaluateException, 'only support soapenc:Array restrictions'
                return typeClass(atype=name, ofwhat=ofwhat, pname=name, childNames='item')
            else:
                raise EvaluateException, 'complexContent only supported for soapenc:Array derivations'
        elif tp.content.isModelGroup():
            modelGroup = tp.content
            for item in modelGroup.content:
                ofwhat.append(self._getElement(item, literal=literal, local=True))

            tc = TC.Struct(pyclass=None, ofwhat=ofwhat, pname=name)
            if not local:
                self._globalElement(tc, namespaceURI=namespaceURI, literal=literal)
            return tc

        raise EvaluateException, 'only supporting complexType w/ model group, or soapenc:Array restriction'

    def _getTypeClass(self, namespaceURI, localName):
        """Returns a typecode class representing the type we are looking for.
           localName -- name of the type we are looking for.
           namespaceURI -- defining XMLSchema targetNamespace.
        """
        bti = BaseTypeInterpreter()
        simpleTypeClass = bti.get_typeclass(localName, namespaceURI)
        return simpleTypeClass

class MethodProxy:
    """ """
    def __init__(self, parent, callinfo):
        self.__name__ = callinfo.methodName
        self.__doc__ = callinfo.documentation
        self.callinfo = callinfo
        self.parent = weakref.ref(parent)

    def __call__(self, *args, **kwargs):
        return self.parent()._call(self.__name__, *args, **kwargs)
<commit_msg>re-merged changes that were inadvertently merged out<commit_after># Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.

from ZSI.wstools.Utility import SplitQName
from ZSI.wstools.Namespaces import WSDL
from ZSI import *
from ZSI.client import *
from ZSI.TC import Any
from ZSI.typeinterpreter import BaseTypeInterpreter
import wstools
from wstools.Utility import DOM
from urlparse import urlparse
import weakref

class ServiceProxy:
    """A ServiceProxy provides a convenient way to call a remote web
       service that is described with WSDL. The proxy exposes methods
       that reflect the methods of the remote web service."""

    def __init__(self, wsdl, service=None, port=None, tracefile=None,
                 nsdict=None, transdict=None):
        """
        Parameters:
           wsdl -- WSDLTools.WSDL instance or URL of WSDL.
           service -- service name or index
           port -- port name or index
           tracefile --
           nsdict -- key prefix to namespace mappings for serialization
              in SOAP Envelope.
           transdict -- arguments to pass into HTTPConnection constructor.
        """
        self._tracefile = tracefile
        self._nsdict = nsdict or {}
        self._transdict = transdict
        self._wsdl = wsdl
        if isinstance(wsdl, basestring) is True:
            self._wsdl = wstools.WSDLTools.WSDLReader().loadFromURL(wsdl)

        assert isinstance(self._wsdl, wstools.WSDLTools.WSDL), 'expecting a WSDL instance'
        self._service = self._wsdl.services[service or 0]
        self.__doc__ = self._service.documentation
        self._port = self._service.ports[port or 0]
        self._name = self._service.name
        self._methods = {}

        binding = self._port.getBinding()
        portType = binding.getPortType()
        for port in self._service.ports:
            for item in port.getPortType().operations:
                callinfo = wstools.WSDLTools.callInfoFromWSDL(port, item.name)
                method = MethodProxy(self, callinfo)
                setattr(self, item.name, method)
                self._methods.setdefault(item.name, []).append(method)

    def _call(self, name, *args, **kwargs):
        """Call the named remote web service method."""
        if len(args) and len(kwargs):
            raise TypeError(
                'Use positional or keyword argument only.'
                )

        callinfo = getattr(self, name).callinfo

        # go through the list of defined methods, and look for the one with
        # the same number of arguments as what was passed.  this is a weak
        # check that should probably be improved in the future to check the
        # types of the arguments to allow for polymorphism
        for method in self._methods[name]:
            if len(method.callinfo.inparams) == len(kwargs):
                callinfo = method.callinfo

        soapAction = callinfo.soapAction
        url = callinfo.location
        (protocol, host, uri, query, fragment, identifier) = urlparse(url)
        port = None
        if host.find(':') >= 0:
            host, port = host.split(':')

        if protocol == 'http':
            transport = httplib.HTTPConnection
        elif protocol == 'https':
            transport = httplib.HTTPSConnection
        else:
            raise RuntimeError, 'Unknown protocol %s' %protocol

        binding = Binding(host=host, tracefile=self._tracefile,
                          transport=transport,transdict=self._transdict,
                          port=port, url=url, nsdict=self._nsdict,
                          soapaction=soapAction,)

        request, response = self._getTypeCodes(callinfo)
        if len(kwargs): args = kwargs
        if request is None:
            request = Any(oname=name)
        binding.Send(url=url, opname=None, obj=args,
                     nsdict=self._nsdict, soapaction=soapAction, requesttypecode=request)
        return binding.Receive(replytype=response)

    def _getTypeCodes(self, callinfo):
        """Returns typecodes representing input and output messages, if request and/or
           response fails to be generated return None for either or both.

           callinfo --  WSDLTools.SOAPCallInfo instance describing an operation.
        """
        prefix = None
        self._resetPrefixDict()
        if callinfo.use == 'encoded':
            prefix = self._getPrefix(callinfo.namespace)
        try:
            requestTC = self._getTypeCode(parameters=callinfo.getInParameters(), literal=(callinfo.use=='literal'))
        except EvaluateException, ex:
            print "DEBUG: Request Failed to generate --", ex
            requestTC = None

        self._resetPrefixDict()
        try:
            replyTC = self._getTypeCode(parameters=callinfo.getOutParameters(), literal=(callinfo.use=='literal'))
        except EvaluateException, ex:
            print "DEBUG: Response Failed to generate --", ex
            replyTC = None

        request = response = None
        if callinfo.style == 'rpc':
            if requestTC: request = TC.Struct(pyclass=None, ofwhat=requestTC, pname=callinfo.methodName)
            if replyTC: response = TC.Struct(pyclass=None, ofwhat=replyTC, pname='%sResponse' %callinfo.methodName)
        else:
            if requestTC: request = requestTC[0]
            if replyTC: response = replyTC[0]

        #THIS IS FOR RPC/ENCODED, DOC/ENCODED Wrapper
        if request and prefix and callinfo.use == 'encoded':
            request.oname = '%(prefix)s:%(name)s xmlns:%(prefix)s="%(namespaceURI)s"' \
                %{'prefix':prefix, 'name':request.aname, 'namespaceURI':callinfo.namespace}

        return request, response

    def _getTypeCode(self, parameters, literal=False):
        """Returns typecodes representing a parameter set
           parameters -- list of WSDLTools.ParameterInfo instances representing
              the parts of a WSDL Message.
        """
        ofwhat = []
        for part in parameters:
            namespaceURI,localName = part.type

            if part.element_type:
                #global element
                element = self._wsdl.types[namespaceURI].elements[localName]
                tc = self._getElement(element, literal=literal, local=False, namespaceURI=namespaceURI)
            else:
                #local element
                name = part.name
                typeClass = self._getTypeClass(namespaceURI, localName)
                if not typeClass:
                    tp = self._wsdl.types[namespaceURI].types[localName]
                    tc = self._getType(tp, name, literal, local=True, namespaceURI=namespaceURI)
                else:
                    tc = typeClass(name)
            ofwhat.append(tc)
        return ofwhat

    def _globalElement(self, typeCode, namespaceURI, literal):
        """namespaces typecodes representing global elements with
             literal encoding.
           typeCode -- typecode representing an element.
           namespaceURI -- namespace
           literal -- True/False
        """
        if literal:
            typeCode.oname = '%(prefix)s:%(name)s xmlns:%(prefix)s="%(namespaceURI)s"' \
                %{'prefix':self._getPrefix(namespaceURI), 'name':typeCode.oname, 'namespaceURI':namespaceURI}

    def _getPrefix(self, namespaceURI):
        """Retrieves a prefix/namespace mapping.
           namespaceURI -- namespace
        """
        prefixDict = self._getPrefixDict()
        if prefixDict.has_key(namespaceURI):
            prefix = prefixDict[namespaceURI]
        else:
            prefix = 'ns1'
            while prefix in prefixDict.values():
                prefix = 'ns%d' %int(prefix[-1]) + 1
            prefixDict[namespaceURI] = prefix
        return prefix

    def _getPrefixDict(self):
        """Used to hide the actual prefix dictionary.
        """
        if not hasattr(self, '_prefixDict'):
            self.__prefixDict = {}
        return self.__prefixDict

    def _resetPrefixDict(self):
        """Clears the prefix dictionary, this needs to be done
           before creating a new typecode for a message
           (ie. before, and after creating a new message typecode)
        """
        self._getPrefixDict().clear()

    def _getElement(self, element, literal=False, local=False, namespaceURI=None):
        """Returns a typecode instance representing the passed in element.
           element -- XMLSchema.ElementDeclaration instance
           literal -- literal encoding?
           local -- is locally defined?
           namespaceURI -- namespace
        """
        if not element.isElement():
            raise TypeError, 'Expecting an ElementDeclaration'

        tc = None
        elementName = element.getAttribute('name')
        tp = element.getTypeDefinition('type')

        typeObj = None
        if not (tp or element.content):
            nsuriType,localName = element.getAttribute('type')
            typeClass = self._getTypeClass(nsuriType,localName)

            typeObj = typeClass(elementName)
        elif not tp:
            tp = element.content

        if not typeObj:
            typeObj = self._getType(tp, elementName, literal, local, namespaceURI)

        minOccurs = int(element.getAttribute('minOccurs'))
        typeObj.optional = not minOccurs
        typeObj.minOccurs = minOccurs

        maxOccurs = element.getAttribute('maxOccurs')
        typeObj.repeatable = (maxOccurs == 'unbounded') or (int(maxOccurs) > 1)

        return typeObj

    def _getType(self, tp, name, literal, local, namespaceURI):
        """Returns a typecode instance representing the passed in type and name.
           tp -- XMLSchema.TypeDefinition instance
           name -- element name
           literal -- literal encoding?
           local -- is locally defined?
           namespaceURI -- namespace
        """
        ofwhat = []
        if not (tp.isDefinition() and tp.isComplex()):
            raise EvaluateException, 'only supporting complexType definition'
        elif tp.content.isComplex():
            if hasattr(tp.content, 'derivation') and tp.content.derivation.isRestriction():
                derived = tp.content.derivation
                typeClass = self._getTypeClass(*derived.getAttribute('base'))
                if typeClass == TC.Array:
                    attrs = derived.attr_content[0].attributes[WSDL.BASE]
                    prefix, localName = SplitQName(attrs['arrayType'])
                    nsuri = derived.attr_content[0].getXMLNS(prefix=prefix)
                    localName = localName.split('[')[0]
                    simpleTypeClass = self._getTypeClass(namespaceURI=nsuri, localName=localName)
                    if simpleTypeClass:
                        ofwhat = simpleTypeClass()
                    else:
                        tp = self._wsdl.types[nsuri].types[localName]
                        ofwhat = self._getType(tp=tp, name=None, literal=literal, local=True, namespaceURI=nsuri)
                else:
                    raise EvaluateException, 'only support soapenc:Array restrictions'
                return typeClass(atype=name, ofwhat=ofwhat, pname=name, childNames='item')
            else:
                raise EvaluateException, 'complexContent only supported for soapenc:Array derivations'
        elif tp.content.isModelGroup():
            modelGroup = tp.content
            for item in modelGroup.content:
                ofwhat.append(self._getElement(item, literal=literal, local=True))

            tc = TC.Struct(pyclass=None, ofwhat=ofwhat, pname=name)
            if not local:
                self._globalElement(tc, namespaceURI=namespaceURI, literal=literal)
            return tc

        raise EvaluateException, 'only supporting complexType w/ model group, or soapenc:Array restriction'

    def _getTypeClass(self, namespaceURI, localName):
        """Returns a typecode class representing the type we are looking for.
           localName -- name of the type we are looking for.
           namespaceURI -- defining XMLSchema targetNamespace.
        """
        bti = BaseTypeInterpreter()
        simpleTypeClass = bti.get_typeclass(localName, namespaceURI)
        return simpleTypeClass

class MethodProxy:
    """ """
    def __init__(self, parent, callinfo):
        self.__name__ = callinfo.methodName
        self.__doc__ = callinfo.documentation
        self.callinfo = callinfo
        self.parent = weakref.ref(parent)

    def __call__(self, *args, **kwargs):
        return self.parent()._call(self.__name__, *args, **kwargs)
<|endoftext|>


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import logging

from fuel_health import heatmanager

LOG = logging.getLogger(__name__)

class HeatSmokeTests(heatmanager.HeatBaseTest):
    """
    Test class verifies Heat API calls, rollback and autoscaling use-cases.
    Special requirements:
        1. Fedora-17 image with pre-installed cfntools and cloud-init packages
           should be imported.
    """
    def setUp(self):
        super(HeatSmokeTests, self).setUp()
        self.instance = []

    def test_actions(self):
        """Typical stack actions: create, update, delete, show details, etc.
        Target component: Heat

        Scenario:
            1. Create a stack.
            2. Wait for the stack status to change to 'CREATE_COMPLETE'.
            3. Get the details of the created stack by its name.
            4. Get the resources list of the created stack.
            5. Get the details of the stack resource.
            6. Get the events list of the created stack.
            7. Get the details of the stack event.
            8. Update the stack.
            9. Wait for the stack to update.
            10. Get the stack template details.
            11. Get the resources list of the updated stack.
            12. Delete the stack.
            13. Wait for the stack to be deleted.
        Duration: 440 s.
        """

        template = """
            AWSTemplateFormatVersion: "2013-11-01"
            Parameters:
              ImageId:
                Type: String
              InstanceType:
                Type: String
              Subnet:
                Type: String
                Default: ''
            Resources:
              MyInstance:
                Type: AWS::EC2::Instance
                Properties:
                  ImageId: {Ref: ImageId}
                  InstanceType: {Ref: InstanceType}
                  SubnetId: {Ref: Subnet}
            """

        parameters = {
            "InstanceType": self.testvm_flavor.name,
            "ImageId": self.config.compute.image_name
        }
        if 'neutron' in self.config.network.network_provider:
            parameters['Subnet'] = self._get_subnet_id()
        else:
            template = self._customize_template(template)

        fail_msg = "Stack was not created properly."
        # create stack
        stack = self.verify(20, self._create_stack, 1,
                            fail_msg,
                            "stack creation",
                            self.heat_client,
                            template,
                            parameters=parameters)

        self.verify(100, self._wait_for_stack_status, 2,
                    fail_msg,
                    "stack status becoming 'CREATE_COMPLETE'",
                    stack.id, 'CREATE_COMPLETE')

        # get stack details
        details = self.verify(20, self.heat_client.stacks.get, 3,
                              "Cannot retrieve stack details.",
                              "retrieving stack details",
                              stack.stack_name)

        fail_msg = "Stack details contain incorrect values."
        self.verify_response_body_content(details.id, stack.id,
                                          fail_msg, 3)
        self.verify_response_body_content(self.config.compute.image_name,
                                          details.parameters['ImageId'],
                                          fail_msg, 3)
        self.verify_response_body_content(details.stack_status,
                                          'CREATE_COMPLETE',
                                          fail_msg, 3)
        # get resources list
        fail_msg = "Cannot retrieve list of stack resources."
        resources = self.verify(10, self.heat_client.resources.list, 4,
                                fail_msg,
                                "retrieving list of stack resources",
                                stack.id)
        self.verify_response_body_content(len(resources), 1, fail_msg, 4)
        resource_id = resources[0].logical_resource_id
        self.verify_response_body_content("MyInstance", resource_id,
                                          fail_msg, 4)

        # get resource details
        res_details = self.verify(10, self.heat_client.resources.get, 5,
                                  "Cannot retrieve stack resource details.",
                                  "retrieving stack resource details",
                                  stack.id, resource_id)

        fail_msg = "Resource details contain incorrect values."
        self.verify_response_body_content("CREATE_COMPLETE",
                                          res_details.resource_status,
                                          fail_msg, 5)
        self.verify_response_body_content("AWS::EC2::Instance",
                                          res_details.resource_type,
                                          fail_msg, 5)
        # get events list
        fail_msg = "Cannot retrieve list of stack events."
        events = self.verify(10, self.heat_client.events.list, 6,
                             fail_msg, "retrieving list of stack events",
                             stack.id)
        self.verify_response_body_not_equal(0, len(events), fail_msg, 6)

        fail_msg = "Event details contain incorrect values."
        self.verify_response_body_content("MyInstance",
                                          events[0].logical_resource_id,
                                          fail_msg, 6)
        # get event details
        event_id = events[0].id
        ev_details = self.verify(10, self.heat_client.events.get, 7,
                                 "Cannot retrieve stack event details.",
                                 "retrieving stack event details",
                                 stack.id, resource_id, event_id)

        fail_msg = "Event details contain incorrect values."
        self.verify_response_body_content(ev_details.id, event_id,
                                          fail_msg, 7)
        self.verify_response_body_content(ev_details.logical_resource_id,
                                          "MyInstance", fail_msg, 7)

        # update stack
        template = template.replace("MyInstance", "UpdatedInstance")
        fail_msg = "Cannot update stack."
        stack = self.verify(20, self._update_stack, 8,
                            fail_msg,
                            "updating stack.",
                            self.heat_client, stack.id,
                            template,
                            parameters=parameters)
        self.verify(100, self._wait_for_stack_status, 9,
                    fail_msg,
                    "stack status becoming 'UPDATE_COMPLETE'",
                    stack.id, 'UPDATE_COMPLETE')

        # show template
        fail_msg = "Cannot retrieve template of the stack."
        act_tpl = self.verify(10, self.heat_client.stacks.template,
                              10,
                              fail_msg,
                              "retrieving stack template",
                              stack.id)

        check_content = lambda: ("InstanceType" in act_tpl["Parameters"] and
                                 "MyInstance" in act_tpl["Resources"])
        self.verify(10, check_content, 10,
                    fail_msg, "verifying template content")

        # get updated resources list
        resources = self.verify(10, self.heat_client.resources.list, 11,
                                "Cannot retrieve list of stack resources.",
                                "retrieving list of stack resources",
                                stack.id)
        resource_id = resources[0].logical_resource_id
        self.verify_response_body_content("UpdatedInstance", resource_id,
                                          fail_msg, 11)

        # delete stack
        fail_msg = "Cannot delete stack."
        self.verify(20, self.heat_client.stacks.delete, 12,
                    fail_msg,
                    "deleting stack",
                    stack.id)

        self.verify(100, self._wait_for_stack_deleted, 13,
                    fail_msg,
                    "deleting stack",
                    stack.id)

    def test_autoscaling(self):
        """Check stack autoscaling
        Target component: Heat

        Scenario:
            1. Image with cfntools package should be imported.
            2. Create a flavor.
            3. Create a keypair.
            4. Save generated private key to file on Controller node.
            5. Create a security group.
            6. Create a stack.
            7. Wait for the stack status to change to 'CREATE_COMPLETE'.
            8. Create a floating ip.
            9. Assign the floating ip to the instance of the stack.
            10. Wait for cloud_init procedure to be completed on the instance.
            11. Load the instance CPU to initiate the stack scaling up.
            12. Wait for the 2nd instance to be launched.
            13. Release the instance CPU to initiate the stack scaling down.
            14. Wait for the 2nd instance to be terminated.
            15. Delete the file with private key.
            16. Delete the stack.
            17. Wait for the stack to be deleted.
        Duration: 2600 s.
        """
        image_name = "F17-x86_64-cfntools"
        fail_msg = ("Image with cfntools package wasn't "
                    "imported into Glance, please check "
                    "http://docs.mirantis.com/fuel/fuel-4.0/user-guide.html"
                    "#platform-tests-description")

        image_available = self.verify(10, self._find_heat_image, 1,
                                      fail_msg,
                                      "checking if %s image is registered "
                                      "in Glance" % image_name,
                                      image_name)

        self.verify_response_true(image_available,
                                  "Step 1 failed: %s." % fail_msg)

        flavor = self.verify(10, self._create_flavors, 2,
                             "Flavor can not be created.",
                             "flavor creation",
                             self.compute_client, 382, 12)

        keypair = self.verify(10, self._create_keypair, 3,
                              'Keypair can not be created.',
                              'keypair creation',
                              self.compute_client)

        path_to_key = self.verify(10, self._save_key_to_file, 4,
                                  "Private key can not be saved to file.",
                                  "saving private key to the file",
                                  keypair.private_key)

        sec_group = self.verify(10, self._create_security_group, 5,
                                'Security group can not be created.',
                                'security group creation',
                                self.compute_client, 'ost1_test-sgroup')

        template = self._load_template('heat_autoscaling_template.yaml')
        parameters = {
            "KeyName": keypair.name,
            "InstanceType": flavor.name,
            "ImageId": image_name,
            "SecurityGroup": sec_group.name
        }
        if 'neutron' in self.config.network.network_provider:
            parameters['Subnet'] = self._get_subnet_id()
        else:
            template = self._customize_template(template)

        #create stack
        fail_msg = "Stack was not created properly."
        stack = self.verify(20, self._create_stack, 6,
                            fail_msg, "stack creation",
                            self.heat_client, template,
                            parameters=parameters)

        self.verify(600, self._wait_for_stack_status, 7,
                    fail_msg,
                    "stack status becoming 'CREATE_COMPLETE'",
                    stack.id, 'CREATE_COMPLETE', 600, 15)

        # find just created instance
        instance_list = self.compute_client.servers.list()
        LOG.info('servers list is {0}'.format(instance_list))
        img_id = self._find_heat_image_id('F17-x86_64-cfntools')[0]
        LOG.info('expected img_id is {0}'.format(img_id))

        for i in instance_list:
            details = self.compute_client.servers.get(server=i)
            LOG.info('instance details is {0}'.format(details.image))
            if details.image['id'] == img_id:
                self.instance.append(i)

        if not self.instance:
            self.fail("Failed step: 7 Instance for the {0} stack "
                      "was not created.".format(self.instance))

        floating_ip = self.verify(10, self._create_floating_ip, 8,
                                  "Floating IP can not be created.",
                                  'floating IP creation')

        self.verify(10, self._assign_floating_ip_to_instance, 9,
                    "Floating IP can not be assigned.",
                    'assigning floating IP',
                    self.compute_client, self.instance[0], floating_ip)

        vm_connection = "ssh -o StrictHostKeyChecking=no -i %s %s@%s" % (
            path_to_key, "ec2-user", floating_ip.ip)

        self.verify(1000, self._wait_for_cloudinit, 10,
                    "Cloud-init script cannot finish within timeout.",
                    "cloud-init script execution on VM",
                    vm_connection, 1000, 15)

        self.verify(60, self._load_vm_cpu, 11,
                    "Cannot create a process to load VM CPU.",
                    "loading VM CPU",
                    vm_connection)

        self.verify(180,
                    self._wait_for_autoscaling, 12,
                    "Stack failed to launch the 2nd instance "
                    "per autoscaling alarm.",
                    "launching the new instance per autoscaling alarm",
                    len(instance_list) + 1, 180, 10)

        self.verify(180, self._release_vm_cpu, 13,
                    "Cannot kill the process on VM to turn CPU load off.",
                    "turning off VM CPU load",
                    vm_connection)

        self.verify(500, self._wait_for_autoscaling, 14,
                    "Stack failed to terminate the 2nd instance "
                    "per autoscaling alarm.",
                    "terminating the 2nd instance per autoscaling alarm",
                    len(instance_list), 300, 10)

        # delete private key file
        self.verify(10, self._delete_key_file, 15,
                    "The file with private key cannot be deleted.",
                    "deleting the file with private key",
                    path_to_key)

        fail_msg = "Cannot delete stack."
        self.verify(20, self.heat_client.stacks.delete, 16,
                    fail_msg,
                    "deleting stack",
                    stack.id)

        self.verify(100, self._wait_for_stack_deleted, 17,
                    fail_msg,
                    "deleting stack",
                    stack.id)

    def test_rollback(self):
        """Check stack rollback
        Target component: Heat

        Scenario:
            1. Start stack creation with rollback enabled.
            2. Verify the stack appears with status 'CREATE_IN_PROGRESS'.
            3. Wait for the stack to be deleted in result of rollback after
               expiration of timeout defined in WaitHandle resource
               of the stack.
            4. Verify the instance of the stack has been deleted.
        Duration: 140 s.
        """

        template = """
            HeatTemplateFormatVersion: '2013-11-01'
            Description: Template which creates single EC2 instance
            Parameters:
              InstanceType:
                Type: String
              ImageId:
                Type: String
              Subnet:
                Type: String
                Default: ''
            Resources:
              WaitHandle:
                Type: AWS::CloudFormation::WaitConditionHandle
              WaitCondition:
                Type: AWS::CloudFormation::WaitCondition
                DependsOn: SmokeServer
                Properties:
                  Handle: {Ref: WaitHandle}
                  Timeout: '30'
              SmokeServer:
                Type: AWS::EC2::Instance
                Properties:
                  ImageId: {Ref: ImageId}
                  InstanceType: {Ref: InstanceType}
                  SubnetId: {Ref: Subnet}
                  UserData:
                    Fn::Base64:
                      Fn::Join:
                      - ''
                      - - '#!/bin/bash -v

                          '
                        - ' sleep 40

                          '
        """

        parameters = {
            "InstanceType": self.testvm_flavor.name,
            "ImageId": self.config.compute.image_name
        }
        if 'neutron' in self.config.network.network_provider:
            parameters['Subnet'] = self._get_subnet_id()
        else:
            template = self._customize_template(template)

        fail_msg = "Stack creation was not started."
        stack = self.verify(20, self._create_stack, 1,
                            fail_msg, "starting stack creation",
                            self.heat_client, template,
                            disable_rollback=False,
                            parameters=parameters)

        self.verify_response_body_content("CREATE_IN_PROGRESS",
                                          stack.stack_status,
                                          fail_msg, 2)

        self.verify(100, self._wait_for_stack_deleted, 3,
                    "Rollback of the stack failed.",
                    "rolling back the stack after its creation failed",
                    stack.id)

        instances = [i for i in self.compute_client.servers.list()
                     if i.name.startswith(stack.stack_name)]
        self.verify(20, self.assertTrue, 4,
                    "The stack instance rollback failed.",
                    "verifying if the instance was rolled back",
                    len(instances) == 0)
<commit_msg>Skip heat test in ha mode<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import logging

from fuel_health import heatmanager

LOG = logging.getLogger(__name__)

class HeatSmokeTests(heatmanager.HeatBaseTest):
    """
    Test class verifies Heat API calls, rollback and autoscaling use-cases.
    Special requirements:
        1. Fedora-17 image with pre-installed cfntools and cloud-init packages
           should be imported.
    """
    def setUp(self):
        super(HeatSmokeTests, self).setUp()
        if 'ha' in self.config.mode:
            self.fail('Is not implemented for this deployment mode')
        self.instance = []

    def test_actions(self):
        """Typical stack actions: create, update, delete, show details, etc.
        Target component: Heat

        Scenario:
            1. Create a stack.
            2. Wait for the stack status to change to 'CREATE_COMPLETE'.
            3. Get the details of the created stack by its name.
            4. Get the resources list of the created stack.
            5. Get the details of the stack resource.
            6. Get the events list of the created stack.
            7. Get the details of the stack event.
            8. Update the stack.
            9. Wait for the stack to update.
            10. Get the stack template details.
            11. Get the resources list of the updated stack.
            12. Delete the stack.
            13. Wait for the stack to be deleted.
        Duration: 440 s.
        """

        template = """
            AWSTemplateFormatVersion: "2013-11-01"
            Parameters:
              ImageId:
                Type: String
              InstanceType:
                Type: String
              Subnet:
                Type: String
                Default: ''
            Resources:
              MyInstance:
                Type: AWS::EC2::Instance
                Properties:
                  ImageId: {Ref: ImageId}
                  InstanceType: {Ref: InstanceType}
                  SubnetId: {Ref: Subnet}
            """

        parameters = {
            "InstanceType": self.testvm_flavor.name,
            "ImageId": self.config.compute.image_name
        }
        if 'neutron' in self.config.network.network_provider:
            parameters['Subnet'] = self._get_subnet_id()
        else:
            template = self._customize_template(template)

        fail_msg = "Stack was not created properly."
        # create stack
        stack = self.verify(20, self._create_stack, 1,
                            fail_msg,
                            "stack creation",
                            self.heat_client,
                            template,
                            parameters=parameters)

        self.verify(100, self._wait_for_stack_status, 2,
                    fail_msg,
                    "stack status becoming 'CREATE_COMPLETE'",
                    stack.id, 'CREATE_COMPLETE')

        # get stack details
        details = self.verify(20, self.heat_client.stacks.get, 3,
                              "Cannot retrieve stack details.",
                              "retrieving stack details",
                              stack.stack_name)

        fail_msg = "Stack details contain incorrect values."
        self.verify_response_body_content(details.id, stack.id,
                                          fail_msg, 3)
        self.verify_response_body_content(self.config.compute.image_name,
                                          details.parameters['ImageId'],
                                          fail_msg, 3)
        self.verify_response_body_content(details.stack_status,
                                          'CREATE_COMPLETE',
                                          fail_msg, 3)
        # get resources list
        fail_msg = "Cannot retrieve list of stack resources."
        resources = self.verify(10, self.heat_client.resources.list, 4,
                                fail_msg,
                                "retrieving list of stack resources",
                                stack.id)
        self.verify_response_body_content(len(resources), 1, fail_msg, 4)
        resource_id = resources[0].logical_resource_id
        self.verify_response_body_content("MyInstance", resource_id,
                                          fail_msg, 4)

        # get resource details
        res_details = self.verify(10, self.heat_client.resources.get, 5,
                                  "Cannot retrieve stack resource details.",
                                  "retrieving stack resource details",
                                  stack.id, resource_id)

        fail_msg = "Resource details contain incorrect values."
        self.verify_response_body_content("CREATE_COMPLETE",
                                          res_details.resource_status,
                                          fail_msg, 5)
        self.verify_response_body_content("AWS::EC2::Instance",
                                          res_details.resource_type,
                                          fail_msg, 5)
        # get events list
        fail_msg = "Cannot retrieve list of stack events."
        events = self.verify(10, self.heat_client.events.list, 6,
                             fail_msg, "retrieving list of stack events",
                             stack.id)
        self.verify_response_body_not_equal(0, len(events), fail_msg, 6)

        fail_msg = "Event details contain incorrect values."
        self.verify_response_body_content("MyInstance",
                                          events[0].logical_resource_id,
                                          fail_msg, 6)
        # get event details
        event_id = events[0].id
        ev_details = self.verify(10, self.heat_client.events.get, 7,
                                 "Cannot retrieve stack event details.",
                                 "retrieving stack event details",
                                 stack.id, resource_id, event_id)

        fail_msg = "Event details contain incorrect values."
        self.verify_response_body_content(ev_details.id, event_id,
                                          fail_msg, 7)
        self.verify_response_body_content(ev_details.logical_resource_id,
                                          "MyInstance", fail_msg, 7)

        # update stack
        template = template.replace("MyInstance", "UpdatedInstance")
        fail_msg = "Cannot update stack."
        stack = self.verify(20, self._update_stack, 8,
                            fail_msg,
                            "updating stack.",
                            self.heat_client, stack.id,
                            template,
                            parameters=parameters)
        self.verify(100, self._wait_for_stack_status, 9,
                    fail_msg,
                    "stack status becoming 'UPDATE_COMPLETE'",
                    stack.id, 'UPDATE_COMPLETE')

        # show template
        fail_msg = "Cannot retrieve template of the stack."
        act_tpl = self.verify(10, self.heat_client.stacks.template,
                              10,
                              fail_msg,
                              "retrieving stack template",
                              stack.id)

        check_content = lambda: ("InstanceType" in act_tpl["Parameters"] and
                                 "MyInstance" in act_tpl["Resources"])
        self.verify(10, check_content, 10,
                    fail_msg, "verifying template content")

        # get updated resources list
        resources = self.verify(10, self.heat_client.resources.list, 11,
                                "Cannot retrieve list of stack resources.",
                                "retrieving list of stack resources",
                                stack.id)
        resource_id = resources[0].logical_resource_id
        self.verify_response_body_content("UpdatedInstance", resource_id,
                                          fail_msg, 11)

        # delete stack
        fail_msg = "Cannot delete stack."
        self.verify(20, self.heat_client.stacks.delete, 12,
                    fail_msg,
                    "deleting stack",
                    stack.id)

        self.verify(100, self._wait_for_stack_deleted, 13,
                    fail_msg,
                    "deleting stack",
                    stack.id)

    def test_autoscaling(self):
        """Check stack autoscaling
        Target component: Heat

        Scenario:
            1. Image with cfntools package should be imported.
            2. Create a flavor.
            3. Create a keypair.
            4. Save generated private key to file on Controller node.
            5. Create a security group.
            6. Create a stack.
            7. Wait for the stack status to change to 'CREATE_COMPLETE'.
            8. Create a floating ip.
            9. Assign the floating ip to the instance of the stack.
            10. Wait for cloud_init procedure to be completed on the instance.
            11. Load the instance CPU to initiate the stack scaling up.
            12. Wait for the 2nd instance to be launched.
            13. Release the instance CPU to initiate the stack scaling down.
            14. Wait for the 2nd instance to be terminated.
            15. Delete the file with private key.
            16. Delete the stack.
            17. Wait for the stack to be deleted.
        Duration: 2600 s.
        """
        image_name = "F17-x86_64-cfntools"
        fail_msg = ("Image with cfntools package wasn't "
                    "imported into Glance, please check "
                    "http://docs.mirantis.com/fuel/fuel-4.0/user-guide.html"
                    "#platform-tests-description")

        image_available = self.verify(10, self._find_heat_image, 1,
                                      fail_msg,
                                      "checking if %s image is registered "
                                      "in Glance" % image_name,
                                      image_name)

        self.verify_response_true(image_available,
                                  "Step 1 failed: %s." % fail_msg)

        flavor = self.verify(10, self._create_flavors, 2,
                             "Flavor can not be created.",
                             "flavor creation",
                             self.compute_client, 382, 12)

        keypair = self.verify(10, self._create_keypair, 3,
                              'Keypair can not be created.',
                              'keypair creation',
                              self.compute_client)

        path_to_key = self.verify(10, self._save_key_to_file, 4,
                                  "Private key can not be saved to file.",
                                  "saving private key to the file",
                                  keypair.private_key)

        sec_group = self.verify(10, self._create_security_group, 5,
                                'Security group can not be created.',
                                'security group creation',
                                self.compute_client, 'ost1_test-sgroup')

        template = self._load_template('heat_autoscaling_template.yaml')
        parameters = {
            "KeyName": keypair.name,
            "InstanceType": flavor.name,
            "ImageId": image_name,
            "SecurityGroup": sec_group.name
        }
        if 'neutron' in self.config.network.network_provider:
            parameters['Subnet'] = self._get_subnet_id()
        else:
            template = self._customize_template(template)

        #create stack
        fail_msg = "Stack was not created properly."
        stack = self.verify(20, self._create_stack, 6,
                            fail_msg, "stack creation",
                            self.heat_client, template,
                            parameters=parameters)

        self.verify(600, self._wait_for_stack_status, 7,
                    fail_msg,
                    "stack status becoming 'CREATE_COMPLETE'",
                    stack.id, 'CREATE_COMPLETE', 600, 15)

        # find just created instance
        instance_list = self.compute_client.servers.list()
        LOG.info('servers list is {0}'.format(instance_list))
        img_id = self._find_heat_image_id('F17-x86_64-cfntools')[0]
        LOG.info('expected img_id is {0}'.format(img_id))

        for i in instance_list:
            details = self.compute_client.servers.get(server=i)
            LOG.info('instance details is {0}'.format(details.image))
            if details.image['id'] == img_id:
                self.instance.append(i)

        if not self.instance:
            self.fail("Failed step: 7 Instance for the {0} stack "
                      "was not created.".format(self.instance))

        floating_ip = self.verify(10, self._create_floating_ip, 8,
                                  "Floating IP can not be created.",
                                  'floating IP creation')

        self.verify(10, self._assign_floating_ip_to_instance, 9,
                    "Floating IP can not be assigned.",
                    'assigning floating IP',
                    self.compute_client, self.instance[0], floating_ip)

        vm_connection = "ssh -o StrictHostKeyChecking=no -i %s %s@%s" % (
            path_to_key, "ec2-user", floating_ip.ip)

        self.verify(1000, self._wait_for_cloudinit, 10,
                    "Cloud-init script cannot finish within timeout.",
                    "cloud-init script execution on VM",
                    vm_connection, 1000, 15)

        self.verify(60, self._load_vm_cpu, 11,
                    "Cannot create a process to load VM CPU.",
                    "loading VM CPU",
                    vm_connection)

        self.verify(180,
                    self._wait_for_autoscaling, 12,
                    "Stack failed to launch the 2nd instance "
                    "per autoscaling alarm.",
                    "launching the new instance per autoscaling alarm",
                    len(instance_list) + 1, 180, 10)

        self.verify(180, self._release_vm_cpu, 13,
                    "Cannot kill the process on VM to turn CPU load off.",
                    "turning off VM CPU load",
                    vm_connection)

        self.verify(500, self._wait_for_autoscaling, 14,
                    "Stack failed to terminate the 2nd instance "
                    "per autoscaling alarm.",
                    "terminating the 2nd instance per autoscaling alarm",
                    len(instance_list), 300, 10)

        # delete private key file
        self.verify(10, self._delete_key_file, 15,
                    "The file with private key cannot be deleted.",
                    "deleting the file with private key",
                    path_to_key)

        fail_msg = "Cannot delete stack."
        self.verify(20, self.heat_client.stacks.delete, 16,
                    fail_msg,
                    "deleting stack",
                    stack.id)

        self.verify(100, self._wait_for_stack_deleted, 17,
                    fail_msg,
                    "deleting stack",
                    stack.id)

    def test_rollback(self):
        """Check stack rollback
        Target component: Heat

        Scenario:
            1. Start stack creation with rollback enabled.
            2. Verify the stack appears with status 'CREATE_IN_PROGRESS'.
            3. Wait for the stack to be deleted in result of rollback after
               expiration of timeout defined in WaitHandle resource
               of the stack.
            4. Verify the instance of the stack has been deleted.
        Duration: 140 s.
        """

        template = """
            HeatTemplateFormatVersion: '2013-11-01'
            Description: Template which creates single EC2 instance
            Parameters:
              InstanceType:
                Type: String
              ImageId:
                Type: String
              Subnet:
                Type: String
                Default: ''
            Resources:
              WaitHandle:
                Type: AWS::CloudFormation::WaitConditionHandle
              WaitCondition:
                Type: AWS::CloudFormation::WaitCondition
                DependsOn: SmokeServer
                Properties:
                  Handle: {Ref: WaitHandle}
                  Timeout: '30'
              SmokeServer:
                Type: AWS::EC2::Instance
                Properties:
                  ImageId: {Ref: ImageId}
                  InstanceType: {Ref: InstanceType}
                  SubnetId: {Ref: Subnet}
                  UserData:
                    Fn::Base64:
                      Fn::Join:
                      - ''
                      - - '#!/bin/bash -v

                          '
                        - ' sleep 40

                          '
        """

        parameters = {
            "InstanceType": self.testvm_flavor.name,
            "ImageId": self.config.compute.image_name
        }
        if 'neutron' in self.config.network.network_provider:
            parameters['Subnet'] = self._get_subnet_id()
        else:
            template = self._customize_template(template)

        fail_msg = "Stack creation was not started."
        stack = self.verify(20, self._create_stack, 1,
                            fail_msg, "starting stack creation",
                            self.heat_client, template,
                            disable_rollback=False,
                            parameters=parameters)

        self.verify_response_body_content("CREATE_IN_PROGRESS",
                                          stack.stack_status,
                                          fail_msg, 2)

        self.verify(100, self._wait_for_stack_deleted, 3,
                    "Rollback of the stack failed.",
                    "rolling back the stack after its creation failed",
                    stack.id)

        instances = [i for i in self.compute_client.servers.list()
                     if i.name.startswith(stack.stack_name)]
        self.verify(20, self.assertTrue, 4,
                    "The stack instance rollback failed.",
                    "verifying if the instance was rolled back",
                    len(instances) == 0)
<|endoftext|>