From b56de3355c59c92cea3cc596c3ac6b94314e975d Mon Sep 17 00:00:00 2001 From: Jake Moshenko Date: Tue, 15 Sep 2015 11:53:31 -0400 Subject: [PATCH] Migrate data back to Image in preparation for v2 --- data/database.py | 6 ++++ ..._migrate_image_data_back_to_image_table.py | 34 ++++++++++++++++++ data/model/image.py | 16 +++++++-- endpoints/v1/registry.py | 5 +-- initdb.py | 9 ++++- test/data/test.db | Bin 815104 -> 847872 bytes test/test_gc.py | 8 ++++- 7 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 data/migrations/versions/545794454f49_migrate_image_data_back_to_image_table.py diff --git a/data/database.py b/data/database.py index cc802ac59..660976bcf 100644 --- a/data/database.py +++ b/data/database.py @@ -561,6 +561,12 @@ class Image(BaseModel): storage = ForeignKeyField(ImageStorage, index=True, null=True) + created = DateTimeField(null=True) + comment = TextField(null=True) + command = TextField(null=True) + aggregate_size = BigIntegerField(null=True) + v1_json_metadata = TextField(null=True) + class Meta: database = db read_slaves = (read_slave,) diff --git a/data/migrations/versions/545794454f49_migrate_image_data_back_to_image_table.py b/data/migrations/versions/545794454f49_migrate_image_data_back_to_image_table.py new file mode 100644 index 000000000..17af21eb3 --- /dev/null +++ b/data/migrations/versions/545794454f49_migrate_image_data_back_to_image_table.py @@ -0,0 +1,34 @@ +"""Migrate image data back to image table + +Revision ID: 545794454f49 +Revises: 3a3bb77e17d5 +Create Date: 2015-09-15 11:48:47.554255 + +""" + +# revision identifiers, used by Alembic. +revision = '545794454f49' +down_revision = '3a3bb77e17d5' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(tables): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('image', sa.Column('aggregate_size', sa.BigInteger(), nullable=True)) + op.add_column('image', sa.Column('command', sa.Text(), nullable=True)) + op.add_column('image', sa.Column('comment', sa.Text(), nullable=True)) + op.add_column('image', sa.Column('created', sa.DateTime(), nullable=True)) + op.add_column('image', sa.Column('v1_json_metadata', sa.Text(), nullable=True)) + ### end Alembic commands ### + + +def downgrade(tables): + ### commands auto generated by Alembic - please adjust! ### + op.drop_column('image', 'v1_json_metadata') + op.drop_column('image', 'created') + op.drop_column('image', 'comment') + op.drop_column('image', 'command') + op.drop_column('image', 'aggregate_size') + ### end Alembic commands ### diff --git a/data/model/image.py b/data/model/image.py index 0da208b46..aef076336 100644 --- a/data/model/image.py +++ b/data/model/image.py @@ -255,7 +255,7 @@ def find_create_or_link_image(docker_image_id, repo_obj, username, translations, def set_image_metadata(docker_image_id, namespace_name, repository_name, created_date_str, comment, - command, parent=None): + command, v1_json_metadata, parent=None): with db_transaction(): query = (Image .select(Image, ImageStorage) @@ -273,7 +273,10 @@ def set_image_metadata(docker_image_id, namespace_name, repository_name, created # We cleanup any old checksum in case it's a retry after a fail fetched.storage.checksum = None - fetched.storage.created = datetime.now() + now = datetime.now() + # TODO stop writing to storage when all readers are removed + fetched.storage.created = now + fetched.created = now if created_date_str is not None: try: @@ -282,8 +285,12 @@ def set_image_metadata(docker_image_id, namespace_name, repository_name, created # parse raises different exceptions, so we cannot use a specific kind of handler here. pass + # TODO stop writing to storage fields when all readers are removed fetched.storage.comment = comment fetched.storage.command = command + fetched.comment = comment + fetched.command = command + fetched.v1_json_metadata = v1_json_metadata if parent: fetched.ancestors = '%s%s/' % (parent.ancestors, parent.id) @@ -323,13 +330,18 @@ def set_image_size(docker_image_id, namespace_name, repository_name, image_size, .where(Image.id << ancestors) .scalar()) + image_size + # TODO stop writing to storage when all readers are removed image.storage.aggregate_size = total_size + image.aggregate_size = total_size except Image.DoesNotExist: pass else: + # TODO stop writing to storage when all readers are removed image.storage.aggregate_size = image_size + image.aggregate_size = image_size image.storage.save() + image.save() return image diff --git a/endpoints/v1/registry.py b/endpoints/v1/registry.py index e1838730d..5b94c48b5 100644 --- a/endpoints/v1/registry.py +++ b/endpoints/v1/registry.py @@ -456,7 +456,8 @@ def put_image_json(namespace, repository, image_id): logger.debug('Parsing image JSON') try: - data = json.loads(request.data.decode('utf8')) + v1_metadata = request.data + data = json.loads(v1_metadata.decode('utf8')) except ValueError: pass @@ -530,7 +531,7 @@ def put_image_json(namespace, repository, image_id): logger.debug('Setting image metadata') model.image.set_image_metadata(image_id, namespace, repository, data.get('created'), - data.get('comment'), command, parent_image) + data.get('comment'), command, v1_metadata, parent_image) logger.debug('Putting json path') store.put_content(repo_image.storage.locations, json_path, request.data) diff --git a/initdb.py b/initdb.py index 57024f00d..29b151601 100644 --- a/initdb.py +++ b/initdb.py @@ -99,9 +99,16 @@ def __create_subtree(repo, structure, creator_username, parent, tag_map): creation_time = REFERENCE_DATE + timedelta(weeks=image_num) + timedelta(days=model_num) command_list = SAMPLE_CMDS[image_num % len(SAMPLE_CMDS)] command = json.dumps(command_list) if command_list else None + + v1_metadata = { + 'id': docker_image_id, + } + if parent is not None: + v1_metadata['parent'] = parent.docker_image_id + new_image = model.image.set_image_metadata(docker_image_id, repo.namespace_user.username, repo.name, str(creation_time), 'no comment', command, - parent) + v1_metadata, parent) compressed_size = random.randrange(1, 1024 * 1024 * 1024) model.image.set_image_size(docker_image_id, repo.namespace_user.username, repo.name, diff --git a/test/data/test.db b/test/data/test.db index ec924222189c6f0386b5125c81985e123cddcdbb..762ad4378cd754cf9f9eac84483c7c46ca30d4df 100644 GIT binary patch delta 28988 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 R3G9D+-@H#}eS}K({{UQ~6%+sf delta 17258 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
J`C^$rx1^BsWP38j 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 Mr~aawnv