From 53403399577bdca0e8f0886fa62ce0e75c14a8e0 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Wed, 2 Aug 2017 04:11:35 +0200 Subject: [PATCH] Add UUID Storage to Project --- app/models/concerns/storage/uuid_project.rb | 58 +++++++++++++++++++ app/models/project.rb | 9 ++- ...802013652_add_storage_fields_to_project.rb | 39 +++++++++++++ db/schema.rb | 3 + 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 app/models/concerns/storage/uuid_project.rb create mode 100644 db/migrate/20170802013652_add_storage_fields_to_project.rb diff --git a/app/models/concerns/storage/uuid_project.rb b/app/models/concerns/storage/uuid_project.rb new file mode 100644 index 00000000000..8a73287e518 --- /dev/null +++ b/app/models/concerns/storage/uuid_project.rb @@ -0,0 +1,58 @@ +module Storage + module UUIDProject + extend ActiveSupport::Concern + + def uuid_dir + %Q(#{uuid[0..1]}/#{uuid[2..3]}) + end + + def disk_path + %Q(#{uuid_dir}/#{uuid}) + end + + def ensure_storage_path_exist + gitlab_shell.add_namespace(repository_storage_path, uuid_dir) + end + + def rename_repo + # TODO: We cannot wipe most of this method until we provide migration path for Container Registries + path_was = previous_changes['path'].first + old_path_with_namespace = File.join(namespace.full_path, path_was) + new_path_with_namespace = File.join(namespace.full_path, path) + + Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}" + + if has_container_registry_tags? + Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!" + + # we currently doesn't support renaming repository if it contains images in container registry + raise StandardError.new('Project cannot be renamed, because images are present in its container registry') + end + + begin + # TODO: we can avoid cache expiration if cache is based on UUID or just project_id + expire_caches_before_rename(old_path_with_namespace) + expires_full_path_cache + + send_move_instructions(old_path_with_namespace) + + @old_path_with_namespace = old_path_with_namespace + + SystemHooksService.new.execute_hooks_for(self, :rename) + + @repository = nil + rescue => e + Rails.logger.error "Exception renaming #{old_path_with_namespace} -> #{new_path_with_namespace}: #{e}" + # Returning false does not rollback after_* transaction but gives + # us information about failing some of tasks + false + end + + Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}" + + # TODO: When we move Uploads and Pages to use UUID we can disable this transfers as well + Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path) + Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path) + end + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 570955e81dd..f0ea83dda0c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -17,7 +17,6 @@ class Project < ActiveRecord::Base include ProjectFeaturesCompatibility include SelectForProjectAuthorization include Routable - include Storage::LegacyProject extend Gitlab::ConfigHelper @@ -1424,6 +1423,14 @@ class Project < ActiveRecord::Base private + def load_storage + if self.storage_version > 1 + self.class.include Storage::UUIDProject + else + self.class.include Storage::LegacyProject + end + end + # set last_activity_at to the same as created_at def set_last_activity_at update_column(:last_activity_at, self.created_at) diff --git a/db/migrate/20170802013652_add_storage_fields_to_project.rb b/db/migrate/20170802013652_add_storage_fields_to_project.rb new file mode 100644 index 00000000000..269103cd472 --- /dev/null +++ b/db/migrate/20170802013652_add_storage_fields_to_project.rb @@ -0,0 +1,39 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddStorageFieldsToProject < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + # When a migration requires downtime you **must** uncomment the following + # constant and define a short and easy to understand explanation as to why the + # migration requires downtime. + # DOWNTIME_REASON = '' + + # When using the methods "add_concurrent_index", "remove_concurrent_index" or + # "add_column_with_default" you must disable the use of transactions + # as these methods can not run in an existing transaction. + # When using "add_concurrent_index" or "remove_concurrent_index" methods make sure + # that either of them is the _only_ method called in the migration, + # any other changes should go in a separate migration. + # This ensures that upon failure _only_ the index creation or removing fails + # and can be retried or reverted easily. + # + # To disable transactions uncomment the following line and remove these + # comments: + disable_ddl_transaction! + + def up + # rubocop:disable Migration/AddColumnWithDefaultToLargeTable + add_column :projects, :uuid, :uuid + add_column_with_default :projects, :storage_version, :integer, default: 0, limit: 1 + add_concurrent_index :projects, :uuid + end + + def down + remove_column :projects, :uuid + remove_column :projects, :storage_version + end +end diff --git a/db/schema.rb b/db/schema.rb index c31bff3a8f2..dcd9532e4be 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1208,6 +1208,8 @@ ActiveRecord::Schema.define(version: 20170820100558) do t.datetime "last_repository_updated_at" t.string "ci_config_path" t.text "delete_error" + t.uuid "uuid" + t.integer "storage_version", limit: 2, default: 0, null: false end add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree @@ -1224,6 +1226,7 @@ ActiveRecord::Schema.define(version: 20170820100558) do add_index "projects", ["pending_delete"], name: "index_projects_on_pending_delete", using: :btree add_index "projects", ["runners_token"], name: "index_projects_on_runners_token", using: :btree add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree + add_index "projects", ["uuid"], name: "index_projects_on_uuid", using: :btree add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree create_table "protected_branch_merge_access_levels", force: :cascade do |t| -- GitLab