예제 #1
0
    def test_redirect(self):
        test_tree = tree.Tree(self.config)

        # Create some channels and aliases
        test_tree.create_channel("parent")
        test_tree.create_channel_redirect("redirect", "parent")

        # Test standard failure cases
        self.assertRaises(KeyError, test_tree.create_channel_redirect,
                          "redirect", "parent")
        self.assertRaises(KeyError, test_tree.create_channel_redirect,
                          "redirect1", "parent1")
        self.assertRaises(KeyError, test_tree.sync_redirects, "parent1")

        # Publish a basic image
        test_tree.create_device("parent", "device")

        # # First file
        first = os.path.join(self.config.publish_path, "parent/device/full")
        open(first, "w+").close()
        gpg.sign_file(self.config, "image-signing", first)

        # # Second file
        second = os.path.join(self.config.publish_path,
                              "parent/device/version-1234.tar.xz")

        tools.generate_version_tarball(self.config, "parent", "test", "1234",
                                       second.replace(".xz", ""))
        tools.xz_compress(second.replace(".xz", ""))
        os.remove(second.replace(".xz", ""))
        gpg.sign_file(self.config, "image-signing", second)

        with open(second.replace(".tar.xz", ".json"), "w+") as fd:
            metadata = {}
            metadata['channel.ini'] = {}
            metadata['channel.ini']['version_detail'] = "test"
            fd.write(json.dumps(metadata))
        gpg.sign_file(self.config, "image-signing",
                      second.replace(".tar.xz", ".json"))

        # # Adding the entry
        device = test_tree.get_device("parent", "device")
        device.create_image(
            "full", 1234, "abc",
            ["parent/device/full", "parent/device/version-1234.tar.xz"])
        device.set_phased_percentage(1234, 50)

        # # Sync the redirects
        test_tree.sync_redirects("parent")

        # # Get the target
        target = test_tree.get_device("redirect", "device")

        # Confirm the fs layout
        self.assertTrue(not os.path.exists(
            os.path.join(self.config.publish_path, "redirect")))
        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "parent", "device")))
        self.assertEqual(device.list_images(), target.list_images())
예제 #2
0
    def test_rename_with_redirects(self):
        test_tree = tree.Tree(self.config)

        # Create some channels
        test_tree.create_channel("old")
        test_tree.create_channel("redirect")

        # Create basic devices
        test_tree.create_device("old", "device")
        test_tree.create_device("redirect", "other")

        # Create a redirect
        test_tree.create_per_device_channel_redirect("device", "redirect",
                                                     "old")

        # Rename
        self.assertTrue(test_tree.rename_channel("old", "new"))

        channels = test_tree.list_channels()
        self.assertIn("device", channels['redirect']['devices'])
        self.assertIn("other", channels['redirect']['devices'])
        device = channels['redirect']['devices']['device']
        self.assertIn("redirect", device)
        self.assertEqual(device['redirect'], "new")
        self.assertEqual(device['index'], "/new/device/index.json")
예제 #3
0
    def test_file_lists(self):
        test_tree = tree.Tree(self.config)
        test_tree.create_channel("test")
        test_tree.create_device("test", "test")

        self.assertEqual(test_tree.list_missing_files(), [])
        self.assertEqual(test_tree.list_orphaned_files(), [])

        # Confirm that the gpg directory is ignored
        if not os.path.exists(os.path.join(test_tree.path, "gpg")):
            os.mkdir(os.path.join(test_tree.path, "gpg"))
        self.assertEqual(test_tree.list_orphaned_files(), [])

        # Confirm that it picks up extra directories
        os.mkdir(os.path.join(test_tree.path, "invalid"))
        self.assertEqual(test_tree.list_orphaned_files(),
                         [os.path.join(test_tree.path, "invalid")])

        # And that it gets cleared up
        test_tree.cleanup_tree()
        self.assertEqual(test_tree.list_orphaned_files(), [])

        # Confirm that it picks up extra files
        open(os.path.join(test_tree.path, "invalid"), "w+").close()
        self.assertEqual(test_tree.list_orphaned_files(),
                         [os.path.join(test_tree.path, "invalid")])

        # And that it gets cleared up
        test_tree.cleanup_tree()
        self.assertEqual(test_tree.list_orphaned_files(), [])

        # Test that keyrings aren't considered as orphaned files
        keyring_path = os.path.join(test_tree.path, "gpg", "device.tar.xz")
        open(keyring_path, "w+").close()
        gpg.sign_file(self.config, "image-signing", keyring_path)
        test_tree.set_device_keyring("test", "test", keyring_path)
        self.assertEqual(test_tree.list_orphaned_files(), [])

        # Test that images aren't considered as orphaned files
        image_path = os.path.join(test_tree.path, "test", "test",
                                  "image.tar.xz")
        open(image_path, "w+").close()
        gpg.sign_file(self.config, "image-signing", image_path)
        open(image_path.replace(".tar.xz", ".json"), "w+").close()
        gpg.sign_file(self.config, "image-signing",
                      image_path.replace(".tar.xz", ".json"))
        device = test_tree.get_device("test", "test")
        device.create_image("full", 12345, "test", [image_path])
        self.assertEqual(test_tree.list_orphaned_files(), [])
예제 #4
0
    def test_cleanup_device_redirects(self):
        test_tree = tree.Tree(self.config)

        # Create some channels and devices
        test_tree.create_channel("parent")
        test_tree.create_channel("redirect1")
        test_tree.create_channel("redirect2")
        test_tree.create_channel("ignore")

        test_tree.create_device("parent", "device")
        test_tree.create_device("parent", "other")
        test_tree.create_device("parent", "ignore")

        test_tree.create_device("redirect1", "other")

        # Create per-device redirects
        test_tree.create_per_device_channel_redirect("device", "redirect1",
                                                     "parent")
        test_tree.create_per_device_channel_redirect("other", "redirect2",
                                                     "parent")

        # Check if removal of an unrelated channel does nothing
        channels = test_tree.list_channels()
        devices_before1 = dict(channels['redirect1']['devices'])
        devices_before2 = dict(channels['redirect2']['devices'])
        test_tree.remove_channel("ignore")
        channels = test_tree.list_channels()
        self.assertEqual(devices_before1, channels['redirect1']['devices'])
        self.assertEqual(devices_before2, channels['redirect2']['devices'])

        # Check if removal of an unrelated device does nothing
        channels = test_tree.list_channels()
        devices_before1 = dict(channels['redirect1']['devices'])
        devices_before2 = dict(channels['redirect2']['devices'])
        test_tree.remove_device("parent", "ignore")
        channels = test_tree.list_channels()
        self.assertEqual(devices_before1, channels['redirect1']['devices'])
        self.assertEqual(devices_before2, channels['redirect2']['devices'])

        # Check cleanup after single device removal
        test_tree.remove_device("parent", "device")
        channels = test_tree.list_channels()
        self.assertNotIn("device", channels['redirect1']['devices'])
        self.assertIn("other", channels['redirect1']['devices'])

        # Check cleanup after whole channel removal
        test_tree.remove_channel("parent")
        channels = test_tree.list_channels()
        self.assertNotIn("other", channels['redirect2']['devices'])
예제 #5
0
    def test_expiry(self):
        test_tree = tree.Tree(self.config)
        test_tree.create_channel("test")
        test_tree.create_device("test", "test")

        # Insert a few images
        image_path = os.path.join(test_tree.path, "test", "test",
                                  "image.tar.xz")
        open(image_path, "w+").close()
        gpg.sign_file(self.config, "image-signing", image_path)
        device = test_tree.get_device("test", "test")
        device.create_image("full", 1, "test", [image_path])
        device.create_image("full", 2, "test", [image_path])
        device.create_image("delta", 2, "test", [image_path], base=1)
        device.create_image("full", 3, "test", [image_path])
        device.create_image("delta", 3, "test", [image_path], base=2)
        device.create_image("delta", 3, "test", [image_path], base=1)
        device.create_image("full", 4, "test", [image_path])
        device.create_image("delta", 4, "test", [image_path], base=3)
        device.create_image("delta", 4, "test", [image_path], base=2)
        device.create_image("delta", 4, "test", [image_path], base=1)

        self.assertEqual(len(device.list_images()), 10)

        device.expire_images(10)
        self.assertEqual(len(device.list_images()), 10)

        device.expire_images(3)
        self.assertEqual(len(device.list_images()), 6)

        device.expire_images(3)
        self.assertEqual(len(device.list_images()), 6)

        device.expire_images(2)
        self.assertEqual(len(device.list_images()), 3)

        device.expire_images(1)
        self.assertEqual(len(device.list_images()), 1)

        device.expire_images(0)
        self.assertEqual(len(device.list_images()), 0)
예제 #6
0
    def test_redirect_alias(self):
        # LP: #1455119 - a channel which is both an alias and a redirect is
        # culled from sync_aliases().
        test_tree = tree.Tree(self.config)

        # Create some channels and aliases
        test_tree.create_channel("parent")
        test_tree.create_channel("overthere")
        test_tree.create_channel_redirect("redirect", "overthere")

        # Make the overthere channel both an alias and a redirect
        with tree.channels_json(test_tree.config, test_tree.indexpath,
                                True) as channels:
            channel = channels["overthere"]
            channel["alias"] = "redirect"
            channel["redirect"] = "overthere"

        # No sync_alias() call should be made on the this channel.
        with patch.object(test_tree, 'sync_alias') as mock:
            test_tree.sync_aliases("redirect")
        self.assertFalse(mock.called)
    def setUp(self):
        temp_directory = tempfile.mkdtemp()
        self.temp_directory = temp_directory

        os.mkdir(os.path.join(self.temp_directory, "etc"))
        config_path = os.path.join(self.temp_directory, "etc", "config")
        with open(config_path, "w+") as fd:
            fd.write("""[global]
base_path = %s
gpg_key_path = %s
public_fqdn = system-image.example.net
public_http_port = 880
public_https_port = 8443
""" % (self.temp_directory, os.path.join(os.getcwd(), "tools", "keys")))
        self.config = config.Config(config_path)

        os.mkdir(os.path.join(self.temp_directory, "www"))
        self.tree = tree.Tree(self.config)
        self.tree.create_channel("test")
        self.tree.create_device("test", "test")
        self.device = self.tree.get_device("test", "test")
예제 #8
0
    def test_phased_percentage(self):
        test_tree = tree.Tree(self.config)

        # Create a channel, device and images
        test_tree.create_channel("test")
        test_tree.create_device("test", "test")

        # # some file
        first = os.path.join(self.config.publish_path, "test/test/full")
        open(first, "w+").close()
        gpg.sign_file(self.config, "image-signing", first)

        # # Adding a first entry
        device = test_tree.get_device("test", "test")
        device.create_image("full", 1234, "abc", ["test/test/full"])
        device.set_phased_percentage(1234, 20)
        self.assertEqual(device.get_phased_percentage(1234), 20)

        # # Adding a second entry
        device = test_tree.get_device("test", "test")
        device.create_image("full", 1235, "abc", ["test/test/full"])

        self.assertEqual(device.get_phased_percentage(1235), 100)
        device.set_phased_percentage(1235, 0)

        device.set_phased_percentage(1235, 100)

        # Test standard failure cases
        self.assertRaises(TypeError, device.set_phased_percentage, 1235,
                          "invalid")
        self.assertRaises(TypeError, device.set_phased_percentage, 1235, 10.5)
        self.assertRaises(ValueError, device.set_phased_percentage, 1235, 101)
        self.assertRaises(ValueError, device.set_phased_percentage, 1235, -1)

        self.assertRaises(IndexError, device.set_phased_percentage, 4242, 50)
        self.assertRaises(Exception, device.set_phased_percentage, 1234, 50)

        self.assertRaises(IndexError, device.get_phased_percentage, 4242)
예제 #9
0
    def test_rename(self):
        test_tree = tree.Tree(self.config)

        # Create some channels and aliases
        test_tree.create_channel("old")
        test_tree.create_channel("existing")

        # Test standard failure cases
        self.assertRaises(KeyError, test_tree.rename_channel, "old1",
                          "test/new")
        self.assertRaises(KeyError, test_tree.rename_channel, "old",
                          "existing")

        # Publish a basic image
        test_tree.create_device("old", "device")

        # # First file
        first = os.path.join(self.config.publish_path, "old/device/full")
        open(first, "w+").close()
        gpg.sign_file(self.config, "image-signing", first)

        # # Second file
        second = os.path.join(self.config.publish_path,
                              "old/device/version-1234.tar.xz")

        tools.generate_version_tarball(self.config, "old", "test", "1234",
                                       second.replace(".xz", ""))
        tools.xz_compress(second.replace(".xz", ""))
        os.remove(second.replace(".xz", ""))
        gpg.sign_file(self.config, "image-signing", second)

        with open(second.replace(".tar.xz", ".json"), "w+") as fd:
            metadata = {}
            metadata['channel.ini'] = {}
            metadata['channel.ini']['version_detail'] = "test"
            fd.write(json.dumps(metadata))
        gpg.sign_file(self.config, "image-signing",
                      second.replace(".tar.xz", ".json"))

        # # Adding the entry
        device = test_tree.get_device("old", "device")
        device.create_image(
            "full", 1234, "abc",
            ["old/device/full", "old/device/version-1234.tar.xz"])
        device.set_phased_percentage(1234, 50)

        # Rename
        os.makedirs(os.path.join(self.config.publish_path, "test/new"))
        self.assertRaises(Exception, test_tree.rename_channel, "old",
                          "test/new")
        os.rmdir(os.path.join(self.config.publish_path, "test/new"))
        os.rmdir(os.path.join(self.config.publish_path, "test"))

        self.assertTrue(test_tree.rename_channel("old", "test/new"))

        self.assertEqual(
            test_tree.list_channels()['test/new'],
            {'devices': {
                'device': {
                    'index': '/test/new/device/index.json'
                }
            }})
예제 #10
0
    def test_channels(self):
        # Test getting a tree instance
        test_tree = tree.Tree(self.config)
        self.assertEqual(test_tree.list_channels(), {})

        # Test publishing a keyring
        keyring = gpg.Keyring(self.config, "image-signing")
        keyring.set_metadata("image-signing")
        keyring.import_keys(
            os.path.join(self.config.gpg_key_path, "image-signing"))
        self.assertRaises(Exception, test_tree.publish_keyring,
                          "image-signing")
        keyring_tar = keyring.generate_tarball()
        tools.xz_compress(keyring_tar)
        self.assertRaises(Exception, test_tree.publish_keyring,
                          "image-signing")
        gpg.sign_file(self.config, "image-master", "%s.xz" % keyring_tar)
        test_tree.publish_keyring("image-signing")

        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "gpg", "image-signing"
                             ".tar.xz")))

        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "gpg", "image-signing"
                             ".tar.xz.asc")))

        # Test invalid tree path
        self.assertRaises(Exception, tree.Tree, self.config,
                          os.path.join(self.temp_directory, "invalid"))

        # Test channel creation
        test_tree.create_channel("first")
        test_tree.create_channel("second")

        self.assertRaises(KeyError, test_tree.create_channel, "second")

        # Test channel removal
        test_tree.remove_channel("first")
        test_tree.remove_channel("second")

        self.assertRaises(KeyError, test_tree.remove_channel, "second")

        # Test invalid json
        with open(test_tree.indexpath, "w+") as fd:
            fd.write("[]")

        self.assertRaises(TypeError, test_tree.list_channels)

        with open(test_tree.indexpath, "w+") as fd:
            fd.write("{'a': 'a'}")
        self.assertRaises(ValueError, test_tree.list_channels)

        os.remove(test_tree.indexpath)

        # Test hidding a channel
        test_tree.create_channel("testing")
        self.assertEqual(test_tree.list_channels(),
                         {'testing': {
                             'devices': {}
                         }})

        test_tree.hide_channel("testing")
        self.assertEqual(test_tree.list_channels(),
                         {'testing': {
                             'devices': {},
                             'hidden': True
                         }})

        test_tree.show_channel("testing")
        self.assertEqual(test_tree.list_channels(),
                         {'testing': {
                             'devices': {}
                         }})

        self.assertRaises(KeyError, test_tree.hide_channel, "invalid")
        self.assertRaises(KeyError, test_tree.show_channel, "invalid")
        test_tree.remove_channel("testing")

        # Test device creation
        test_tree.create_channel("testing")
        test_tree.create_device("testing", "test")

        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "testing", "test",
                             "index.json")))

        self.assertEqual(
            test_tree.list_channels(), {
                'testing': {
                    'devices': {
                        'test': {
                            'index': '/testing/test/'
                            'index.json'
                        }
                    }
                }
            })

        self.assertRaises(KeyError, test_tree.create_device, "invalid", "test")
        self.assertRaises(KeyError, test_tree.create_device, "testing", "test")

        # Test listing devices
        self.assertRaises(KeyError, test_tree.list_devices, "invalid")
        self.assertEqual(test_tree.list_devices("testing"), ["test"])

        # Test the index generation
        os.mkdir(os.path.join(self.config.publish_path, "testing", "empty"))
        self.assertRaises(Exception, test_tree.generate_index)
        test_tree.generate_index("I know what I'm doing")
        self.assertEqual(
            test_tree.list_channels(), {
                'testing': {
                    'devices': {
                        'test': {
                            'index': '/testing/test/'
                            'index.json'
                        }
                    }
                }
            })

        device_keyring = os.path.join(self.config.publish_path, "testing",
                                      "test", "device.tar.xz")
        open(device_keyring, "w+").close()

        test_tree.generate_index("I know what I'm doing")
        self.assertEqual(
            test_tree.list_channels(), {
                'testing': {
                    'devices': {
                        'test': {
                            'index': '/testing/test/'
                            'index.json'
                        }
                    }
                }
            })

        gpg.sign_file(self.config, "image-signing", device_keyring)
        test_tree.generate_index("I know what I'm doing")
        self.assertEqual(
            test_tree.list_channels(), {
                'testing': {
                    'devices': {
                        'test': {
                            'index': '/testing/test/index.json',
                            'keyring': {
                                'path':
                                '/testing/test/'
                                'device.tar.xz',
                                'signature':
                                '/testing/test/'
                                'device.tar'
                                '.xz.asc'
                            }
                        }
                    }
                }
            })

        # Test grabbing a device entry
        self.assertRaises(KeyError, test_tree.get_device, "invalid", "test")
        self.assertRaises(KeyError, test_tree.get_device, "testing", "invalid")
        self.assertTrue(
            isinstance(test_tree.get_device("testing", "test"), tree.Device))

        # Test device removal
        test_tree.create_device("testing", "to-remove")
        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "testing", "to-remove",
                             "index.json")))
        self.assertRaises(KeyError, test_tree.remove_device, "invalid", "test")
        self.assertRaises(KeyError, test_tree.remove_device, "testing",
                          "invalid")
        test_tree.remove_device("testing", "to-remove")
        self.assertFalse(
            os.path.exists(
                os.path.join(self.config.publish_path, "testing", "to-remove",
                             "index.json")))

        self.assertEqual(
            test_tree.list_channels(), {
                'testing': {
                    'devices': {
                        'test': {
                            'index': '/testing/test/index.json',
                            'keyring': {
                                'path': '/testing/test/device'
                                '.tar.xz',
                                'signature': '/testing/test/devi'
                                'ce.tar.xz.asc'
                            }
                        }
                    }
                }
            })

        # Test setting the device keyring
        self.assertRaises(KeyError, test_tree.set_device_keyring, "invalid",
                          "test", "invalid")
        self.assertRaises(KeyError, test_tree.set_device_keyring, "testing",
                          "invalid", "invalid")
        test_tree.set_device_keyring("testing", "test",
                                     "testing/test/device.tar.xz")
        self.assertRaises(Exception, test_tree.set_device_keyring, "testing",
                          "test", "invalid")

        unsigned_path = os.path.join(self.config.publish_path, "unsigned")
        open(unsigned_path, "w+").close()
        self.assertRaises(Exception, test_tree.set_device_keyring, "testing",
                          "test", "unsigned")
        os.remove(unsigned_path)
예제 #11
0
    def test_per_device_redirect(self):
        """ """
        test_tree = tree.Tree(self.config)

        # Create some channels
        test_tree.create_channel("parent")
        test_tree.create_channel("redirect")

        # Create the required devices
        test_tree.create_device("parent", "device")
        test_tree.create_device("parent", "other")
        test_tree.create_device("redirect", "other")

        # Test standard failure cases
        self.assertRaises(KeyError,
                          test_tree.create_per_device_channel_redirect,
                          "device", "redirect1", "parent")
        self.assertRaises(KeyError,
                          test_tree.create_per_device_channel_redirect,
                          "other", "redirect", "parent")
        self.assertRaises(KeyError,
                          test_tree.create_per_device_channel_redirect,
                          "device", "redirect", "parent1")
        self.assertRaises(KeyError,
                          test_tree.create_per_device_channel_redirect,
                          "device2", "redirect", "parent")

        # Create the device channel redirect
        test_tree.create_per_device_channel_redirect("device", "redirect",
                                                     "parent")

        # Publish an image

        # # First file
        first = os.path.join(self.config.publish_path, "parent/device/full")
        open(first, "w+").close()
        gpg.sign_file(self.config, "image-signing", first)

        # # Second file
        second = os.path.join(self.config.publish_path,
                              "parent/device/version-1234.tar.xz")

        tools.generate_version_tarball(self.config, "parent", "test", "1234",
                                       second.replace(".xz", ""))
        tools.xz_compress(second.replace(".xz", ""))
        os.remove(second.replace(".xz", ""))
        gpg.sign_file(self.config, "image-signing", second)

        with open(second.replace(".tar.xz", ".json"), "w+") as fd:
            metadata = {}
            metadata['channel.ini'] = {}
            metadata['channel.ini']['version_detail'] = "test"
            fd.write(json.dumps(metadata))
        gpg.sign_file(self.config, "image-signing",
                      second.replace(".tar.xz", ".json"))

        # # Adding the entry
        device = test_tree.get_device("parent", "device")
        device.create_image(
            "full", 1234, "abc",
            ["parent/device/full", "parent/device/version-1234.tar.xz"])
        device.set_phased_percentage(1234, 50)

        # # Get the target
        target = test_tree.get_device("redirect", "device")

        # Confirm the fs layout
        self.assertTrue(
            os.path.exists(os.path.join(self.config.publish_path, "redirect")))
        self.assertFalse(
            os.path.exists(
                os.path.join(self.config.publish_path, "redirect", "device")))
        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "parent", "device")))
        self.assertEqual(device.list_images(), target.list_images())

        # Check the channels index
        channels = test_tree.list_channels()
        self.assertIn("other", channels['redirect']['devices'])
        self.assertEqual(channels['redirect']['devices']['other']['index'],
                         "/redirect/other/index.json")
        self.assertIn("device", channels['redirect']['devices'])
        self.assertEqual(channels['redirect']['devices']['device']['index'],
                         "/parent/device/index.json")
        self.assertIn("redirect", channels['redirect']['devices']['device'])

        # Try removing a per-channel redirect
        self.assertTrue(test_tree.remove_device("redirect", "device"))

        # Confirm files are not removed
        self.assertTrue(
            os.path.exists(
                os.path.join(self.config.publish_path, "parent", "device",
                             "index.json")))
예제 #12
0
    def test_alias(self):
        test_tree = tree.Tree(self.config)

        # Create some channels and aliases
        test_tree.create_channel("parent")
        test_tree.create_channel_alias("alias", "parent")
        test_tree.create_channel_redirect("redirect", "alias")

        # Test standard failure cases
        self.assertRaises(KeyError, test_tree.create_channel_alias, "alias",
                          "parent")

        self.assertRaises(KeyError, test_tree.create_channel_alias, "alias1",
                          "parent1")

        self.assertRaises(KeyError, test_tree.change_channel_alias, "alias1",
                          "parent")

        self.assertRaises(KeyError, test_tree.change_channel_alias, "alias",
                          "parent1")

        self.assertRaises(KeyError, test_tree.change_channel_alias, "parent",
                          "parent")

        self.assertRaises(KeyError, test_tree.change_channel_alias, "redirect",
                          "parent")

        self.assertRaises(KeyError, test_tree.sync_aliases, "missing")
        self.assertRaises(KeyError, test_tree.sync_alias, "missing")
        self.assertRaises(TypeError, test_tree.sync_alias, "parent")

        test_tree.remove_channel("parent")
        self.assertRaises(KeyError, test_tree.sync_alias, "alias")
        test_tree.create_channel("parent")

        # Publish a basic image
        test_tree.create_device("parent", "device")
        test_tree.create_device("parent", "device2")
        test_tree.create_device("parent", "device3")
        test_tree.create_device("alias", "device1")

        # # First file
        first = os.path.join(self.config.publish_path, "parent/device/full")
        open(first, "w+").close()
        gpg.sign_file(self.config, "image-signing", first)

        # # Second file
        second = os.path.join(self.config.publish_path,
                              "parent/device/version-1234.tar.xz")

        tools.generate_version_tarball(self.config, "parent", "test", "1234",
                                       second.replace(".xz", ""))
        tools.xz_compress(second.replace(".xz", ""))
        os.remove(second.replace(".xz", ""))
        gpg.sign_file(self.config, "image-signing", second)

        with open(second.replace(".tar.xz", ".json"), "w+") as fd:
            metadata = {}
            metadata['channel.ini'] = {}
            metadata['channel.ini']['version_detail'] = "test"
            fd.write(json.dumps(metadata))
        gpg.sign_file(self.config, "image-signing",
                      second.replace(".tar.xz", ".json"))

        # # Adding the entry
        device = test_tree.get_device("parent", "device")
        device.create_image(
            "full", 1234, "abc",
            ["parent/device/full", "parent/device/version-1234.tar.xz"])
        device.set_phased_percentage(1234, 50)

        # # Adding a fake entry to the alias channel
        device = test_tree.get_device("alias", "device")
        device.create_image(
            "full", 1235, "abc",
            ["parent/device/full", "parent/device/version-1234.tar.xz"])

        # Sync the alises
        device3 = test_tree.get_device("alias", "device3")
        shutil.rmtree(device3.path)
        test_tree.sync_aliases("parent")

        alias_device = test_tree.get_device("alias", "device")
        self.assertEqual(alias_device.get_phased_percentage(1234), 50)

        test_tree.create_channel("new_parent")
        test_tree.change_channel_alias("alias", "new_parent")

        test_tree.remove_channel("alias")
        test_tree.remove_channel("new_parent")
        test_tree.remove_channel("parent")