def setUp(self):
        # Capture warnings
        logger = logging.getLogger('glancesync')
        self.buffer_log = StringIO.StringIO()
        handler = logging.StreamHandler(self.buffer_log)
        logger.addHandler(handler)

        # Create master region dict
        self.master_region_dict = master_region_dict = dict()
        for i in range(11):
            image1 = self.create_image('Valladolid', i, '0')
            master_region_dict[image1.name] = image1

        # Make particular cases in the images
        master_region_dict['image00'].is_public = False
        master_region_dict['image00'].user_properties['okhronisable'] = True

        master_region_dict['image01'].user_properties['okhronisable'] = True
        master_region_dict['image01'].user_properties['key1'] = 1000

        master_region_dict['image02'].user_properties['okhronisable'] = True
        master_region_dict['image01'].user_properties['key1'] = 2000
        master_region_dict['image01'].user_properties['key2'] = 0

        master_region_dict['image03'].user_properties['okhronisable'] = True
        master_region_dict['image03'].user_properties['kernel_id'] = 'image01'
        master_region_dict['image03'].user_properties['ramdisk_id'] = 'image02'

        master_region_dict['image04'].user_properties['okhronisable'] = True
        master_region_dict['image04'].user_properties['domain'] = 'acl3'

        master_region_dict['image05'].user_properties['okhronisable'] = True
        master_region_dict['image05'].user_properties['zone'] = 'acl4'

        master_region_dict['image06'].user_properties['p1'] = 30
        master_region_dict['image06'].is_public = False

        master_region_dict['image07'].size = 100000
        master_region_dict['image07'].user_properties['okhronisable'] = True
        master_region_dict['image07'].user_properties['p1'] = 40

        master_region_dict['image08'].size = 5000
        master_region_dict['image08'].user_properties['okhronisable'] = False

        master_region_dict['image09'].user_properties['okhronisable'] = True

        master_region_dict['image10'].is_public = False

        # Now, build the region dict using the same values
        self.region_dict = region_dict = dict()
        for i in range(11):
            image_master = master_region_dict['image' + str(i).zfill(2)]
            image_region = self.dup_image(image_master, 'Burgos', i, '1')
            region_dict[image_region.name] = image_region

        # Fix kernel_id and ramdisk_id of regional images
        region_dict['image03'].user_properties['kernel_id'] = '101'
        region_dict['image03'].user_properties['ramdisk_id'] = '102'
        region_dict['image09'].user_properties['ramdisk_id'] = '104'

        # changes some values in properties: the values included in meta_set
        # should affect, but not the others...
        region_dict['image01'].user_properties['key1'] = 1
        region_dict['image02'].user_properties['key2'] = 1
        self.targets = dict()
        target = dict()
        # in this case we use metadata_set as 'forbidden' properties
        target['metadata_set'] = set(['key1'])
        target['forcesyncs'] = set()
        cond = "image.user_properties.get('okhronisable',False) and\
         not set(image.user_properties.keys()).intersection(set(['domain',\
        'zone'])) and image.size < 10000"
        target['metadata_condition'] = compile(cond, '', 'eval')
        target['only_tenant_images'] = False
        target['tenant_id'] = 'tenantid'
        target['dontupdate'] = set()
        target['replace'] = set()
        target['rename'] = set()

        self.targets['master'] = target
        self.master_region = GlanceSyncRegion('Valladolid', self.targets)
        self.region = GlanceSyncRegion('Burgos', self.targets)

        # Expected result of imges_to_sync_dict call
        self.expected_images_to_sync_dict = {
            'image00': self.master_region_dict['image00'],
            'image01': self.master_region_dict['image01'],
            'image02': self.master_region_dict['image02'],
            'image03': self.master_region_dict['image03'],
            'image09': self.master_region_dict['image09'],
        }
class TestGlanceSyncRegion(unittest.TestCase):
    def create_image(self, region, count, prefix):
        """Helper function for creating a sequence or regions"""
        count = str(count).zfill(2)
        return GlanceSyncImage(
            'image' + count, prefix + count, region, 'tenantid', True,
            'checksum', 1000, 'active', dict())

    def dup_image(self, image, region, count, prefix):
        """Helper function to create an image using another one, but for a
        different region"""
        count = str(count).zfill(2)
        new_image = copy.deepcopy(image)
        new_image.region = region
        new_image.id = prefix + count
        return new_image

    def assertNoWarnings(self):
        """Check that no warnings are generated by the test"""
        self.assertEquals(len(self.buffer_log.getvalue()), 0)

    def assertNumberWarnings(self, number):
        """Check that the number of warnings generated is the expected one"""
        self.assertEquals(len(self.buffer_log.getvalue().splitlines()), number)

    def setUp(self):
        # Capture warnings
        logger = logging.getLogger('glancesync')
        self.buffer_log = StringIO.StringIO()
        handler = logging.StreamHandler(self.buffer_log)
        logger.addHandler(handler)

        # Create master region dict
        self.master_region_dict = master_region_dict = dict()
        for i in range(11):
            image1 = self.create_image('Valladolid', i, '0')
            master_region_dict[image1.name] = image1

        # Make particular cases in the images
        master_region_dict['image00'].is_public = False
        master_region_dict['image00'].user_properties['okhronisable'] = True

        master_region_dict['image01'].user_properties['okhronisable'] = True
        master_region_dict['image01'].user_properties['key1'] = 1000

        master_region_dict['image02'].user_properties['okhronisable'] = True
        master_region_dict['image01'].user_properties['key1'] = 2000
        master_region_dict['image01'].user_properties['key2'] = 0

        master_region_dict['image03'].user_properties['okhronisable'] = True
        master_region_dict['image03'].user_properties['kernel_id'] = 'image01'
        master_region_dict['image03'].user_properties['ramdisk_id'] = 'image02'

        master_region_dict['image04'].user_properties['okhronisable'] = True
        master_region_dict['image04'].user_properties['domain'] = 'acl3'

        master_region_dict['image05'].user_properties['okhronisable'] = True
        master_region_dict['image05'].user_properties['zone'] = 'acl4'

        master_region_dict['image06'].user_properties['p1'] = 30
        master_region_dict['image06'].is_public = False

        master_region_dict['image07'].size = 100000
        master_region_dict['image07'].user_properties['okhronisable'] = True
        master_region_dict['image07'].user_properties['p1'] = 40

        master_region_dict['image08'].size = 5000
        master_region_dict['image08'].user_properties['okhronisable'] = False

        master_region_dict['image09'].user_properties['okhronisable'] = True

        master_region_dict['image10'].is_public = False

        # Now, build the region dict using the same values
        self.region_dict = region_dict = dict()
        for i in range(11):
            image_master = master_region_dict['image' + str(i).zfill(2)]
            image_region = self.dup_image(image_master, 'Burgos', i, '1')
            region_dict[image_region.name] = image_region

        # Fix kernel_id and ramdisk_id of regional images
        region_dict['image03'].user_properties['kernel_id'] = '101'
        region_dict['image03'].user_properties['ramdisk_id'] = '102'
        region_dict['image09'].user_properties['ramdisk_id'] = '104'

        # changes some values in properties: the values included in meta_set
        # should affect, but not the others...
        region_dict['image01'].user_properties['key1'] = 1
        region_dict['image02'].user_properties['key2'] = 1
        self.targets = dict()
        target = dict()
        # in this case we use metadata_set as 'forbidden' properties
        target['metadata_set'] = set(['key1'])
        target['forcesyncs'] = set()
        cond = "image.user_properties.get('okhronisable',False) and\
         not set(image.user_properties.keys()).intersection(set(['domain',\
        'zone'])) and image.size < 10000"
        target['metadata_condition'] = compile(cond, '', 'eval')
        target['only_tenant_images'] = False
        target['tenant_id'] = 'tenantid'
        target['dontupdate'] = set()
        target['replace'] = set()
        target['rename'] = set()

        self.targets['master'] = target
        self.master_region = GlanceSyncRegion('Valladolid', self.targets)
        self.region = GlanceSyncRegion('Burgos', self.targets)

        # Expected result of imges_to_sync_dict call
        self.expected_images_to_sync_dict = {
            'image00': self.master_region_dict['image00'],
            'image01': self.master_region_dict['image01'],
            'image02': self.master_region_dict['image02'],
            'image03': self.master_region_dict['image03'],
            'image09': self.master_region_dict['image09'],
        }

    def test_images_to_sync_dict_default(self):
        """test method images_to_sync_dict, without metadata_set nor
        metadata_condition"""
        self.targets['master']['metadata_set'] = set()
        self.targets['master']['metadata_condition'] = None
        new_dict = self.region.images_to_sync_dict(self.master_region_dict)
        expected = set(['image01', 'image02', 'image03', 'image04', 'image05',
                        'image07', 'image08', 'image09'])
        self.assertEquals(expected, set(new_dict.keys()))
        self.targets['master']['forcesyncs'] = set(['000', '010'])
        expected.add('image10')
        expected.add('image00')
        new_dict = self.region.images_to_sync_dict(self.master_region_dict)
        self.assertEquals(expected, set(new_dict.keys()))
        self.assertNoWarnings()

    def test_images_to_sync_dict_metadata(self):
        """test method images_to_sync_dict, without metadata_condition but
        with medata_set"""
        self.targets['master']['metadata_set'] = set(['p1'])
        self.targets['master']['metadata_condition'] = None
        new_dict = self.region.images_to_sync_dict(self.master_region_dict)
        expected = set(['image07'])
        self.assertEquals(expected, set(new_dict.keys()))
        self.assertNoWarnings()

    def test_images_to_sync_dict_func(self):
        """test method images_to_sync, with metadata_condition (see setUp)"""
        new_dict = self.region.images_to_sync_dict(self.master_region_dict)
        expected = set(['image00', 'image01', 'image02', 'image03', 'image09'])
        self.assertEquals(expected, set(new_dict.keys()))
        self.assertNoWarnings()

    def test_local_images_filtered(self):
        """test method region_filtered"""
        region_filtered = self.region.local_images_filtered(
            self.expected_images_to_sync_dict, self.region_dict.values())
        expected = set(['image00', 'image01', 'image02', 'image03', 'image09'])
        self.assertEquals(expected, set(region_filtered.keys()))
        self.assertNoWarnings()

    def test_local_images_filtered_owner(self):
        """Don't accept image if owner is not the tenant"""
        self.region_dict['image00'].owner = 'othertenantid'
        self.region.target['only_tenant_images'] = True
        region_filtered = self.region.local_images_filtered(
            self.expected_images_to_sync_dict, self.region_dict.values())
        expected = set(['image01', 'image02', 'image03', 'image09'])
        self.assertEquals(expected, set(region_filtered.keys()))
        self.assertNumberWarnings(1)

    def test_local_images_filtered_owner_warning(self):
        """Accept image owned by another tenant, but check warning"""
        self.region_dict['image00'].owner = 'othertenantid'
        region_filtered = self.region.local_images_filtered(
            self.expected_images_to_sync_dict, self.region_dict.values())
        expected = set(['image00', 'image01', 'image02', 'image03', 'image09'])
        self.assertEquals(expected, set(region_filtered.keys()))
        self.assertNumberWarnings(1)

    def test_local_images_filtered_duplicated(self):
        """Check warning because duplicated name"""
        region_list = self.region_dict.values()
        image_new = self.dup_image(self.region_dict['image00'], 'Burgos',
                                   11, '0')
        region_list.append(image_new)
        region_filtered = self.region.local_images_filtered(
            self.expected_images_to_sync_dict, region_list)
        expected = set(['image00', 'image01', 'image02', 'image03', 'image09'])
        self.assertEquals(expected, set(region_filtered.keys()))
        self.assertNumberWarnings(1)

    def test_image_list_to_sync(self):
        """ This function involves calling both images_to_sync_dict and
        local_images_filtered and a pair of methods of GlanceSyncRegion; it is
        more an integration function.
        """
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('pending_metadata', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('ok', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_missing(self):
        """ Check with one image missing; this implies also metadata missing
        of image03, because its kernel_id points to the missing image.
        """
        del(self.region_dict['image01'])
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('pending_upload', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('pending_ami', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_missing(self):
        """ Check with one image not active; this should be equivalent to
        a missing image, but also a warning is generated.
        """
        self.region_dict['image01'].status = 'pending'
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('pending_upload', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('pending_ami', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_checksum_error(self):
        """ Check with one image with different checksum
        """
        self.region_dict['image01'].checksum = 'otherchecksum'
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('error_checksum', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('ok', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_checksum_dont_update(self):
        """ Check with one image with different checksum, but included in
        dontupdate
        """
        self.region.target['dontupdate'] = set(['otherchecksum'])
        self.region_dict['image01'].checksum = 'otherchecksum'
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('ok_stalled_checksum', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('ok', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_checksum_replace(self):
        """ Check with one image with different checksum
        """
        self.region.target['replace'] = set(['otherchecksum'])
        self.region_dict['image01'].checksum = 'otherchecksum'
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('pending_replace', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('pending_ami', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_checksum_rename(self):
        """ Check with one image with different checksum
        """
        self.region.target['rename'] = set(['otherchecksum'])
        self.region_dict['image01'].checksum = 'otherchecksum'
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('pending_rename_n_replace', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('pending_ami', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_checksum_mixed(self):
        """ Check with one image with different checksum
        """
        self.region.target['dontupdate'] = set(['checksum1'])
        self.region.target['replace'] = set(['checksum2', 'any'])
        self.region.target['rename'] = set(['any'])
        self.region_dict['image01'].checksum = 'checksum1'
        self.region_dict['image00'].checksum = 'checksum2'
        self.region_dict['image03'].checksum = 'checksum3'
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('pending_replace', self.region_dict['image00']),
            ('ok_stalled_checksum', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('pending_rename_n_replace', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_ami(self):
        """Check changing ramdisk_id of image03 to point to a wrong, but
         existing image and image09 to a image that is not in the
         synchronisation set"""
        self.region_dict['image03'].user_properties['ramdisk_id'] = '101'
        self.master_region_dict['image09'].user_properties['kernel_id'] =\
            'image04'

        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('ok', self.region_dict['image00']),
            ('pending_metadata', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('pending_metadata', self.region_dict['image03']),
            ('error_ami', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)

    def test_image_list_to_sync_private(self):
        """Check image is_public differences between master and region"""
        self.master_region_dict['image00'].is_public = False
        self.region_dict['image00'].is_public = True
        self.master_region_dict['image01'].is_public = False
        self.region_dict['image01'].is_public = True
        result = self.region.image_list_to_sync(self.master_region_dict,
                                                self.region_dict.values())
        expected = [
            ('pending_metadata', self.region_dict['image00']),
            ('pending_metadata', self.region_dict['image01']),
            ('ok', self.region_dict['image02']),
            ('ok', self.region_dict['image03']),
            ('pending_metadata', self.region_dict['image09'])]
        result_as_list = list(x[1].name + '_' + x[0] for x in result)
        expected_as_list = list(x[1].name + '_' + x[0] for x in expected)
        self.assertEqual(expected_as_list, result_as_list)