diff --git a/ci/olib.py b/ci/olib.py
index 8b68f1d127ec6cf2ca07f7ef0dcc63a2d13a58da..e7040c0d693cadcbe4991453e77b4fd0d3b350f1 100644
--- a/ci/olib.py
+++ b/ci/olib.py
@@ -748,3 +748,92 @@ def get_server_floating_ip_properties(server):
     return {}
 
 
+def compare_and_log_projects_quotas(args, log_prefix, src_connection, src_project_id, dst_connection, dst_project_id):
+    """ Log quotas comparison for 2 projects. """
+    src_quotas = get_project_quotas(src_connection, src_project_id)
+    dst_quotas = get_project_quotas(dst_connection, dst_project_id)
+    quota_comparison_dict = {
+        0: {"logger": args.logger.info, "comment": "Source and destination project quota equal"},
+        1: {"logger": args.logger.error, "comment": "Source project quota higher"},
+        -1: {"logger": args.logger.warn, "comment": "Destination project quota higher"},
+    }
+    for i_quota_resource, i_src_quota in src_quotas.items():
+        dst_quota = dst_quotas[i_quota_resource]
+        comparison_result = compare_quota_values(i_src_quota, dst_quota)
+        logger_function = quota_comparison_dict[comparison_result]["logger"]
+        comment = quota_comparison_dict[comparison_result]["comment"]
+        logger_function(f"{log_prefix} {comment}: {i_quota_resource}, src: {i_src_quota}, dst: {dst_quota}")
+
+
+# Define sets of names of quotas which we want to check explicitly,
+# in order to avoid dealing with irrelevant QuotaSet / Quota properties.
+quota_resources_compute = [
+    "cores",
+    "fixed_ips",
+    "injected_file_content_bytes",
+    "injected_file_path_bytes",
+    "injected_files",
+    "instances",
+    "key_pairs",
+    "metadata_items",
+    "ram",
+    "server_group_members",
+    "server_groups",
+]
+quota_resources_volume = [
+    "backup_gigabytes",
+    "backups",
+    "gigabytes",
+    "groups",
+    "per_volume_gigabytes",
+    "snapshots",
+    "volumes",
+]
+quota_resources_network = [
+    "floating_ips",
+    "networks",
+    "ports",
+    "rbac_policies",
+    "routers",
+    "security_group_rules",
+    "security_groups",
+    "subnet_pools",
+    "subnets",
+]
+
+
+def get_project_quotas(ostack_connection: openstack.connection.Connection, project_id):
+    """ Return all quotas (compute, volume, network) for given project. """
+    compute_quotas = ostack_connection.get_compute_quotas(project_id)
+    volume_quotas = ostack_connection.get_volume_quotas(project_id)
+    network_quotas = ostack_connection.get_network_quotas(project_id)
+    project_quotas = {}
+    project_quotas |= filter_quota_set(quota_resources_compute, compute_quotas)
+    project_quotas |= filter_quota_set(quota_resources_volume, volume_quotas)
+    project_quotas |= filter_quota_set(quota_resources_network, network_quotas)
+    return project_quotas
+
+
+def filter_quota_set(quota_resources, quotas):
+    """ Return a dictionary of quotas filtered by keys in quota_resources """
+    return {i_quota_resource: quotas[i_quota_resource] for i_quota_resource in quota_resources}
+
+
+def compare_quota_values(value_1, value_2):
+    """
+    Return integer representation of comparison of parameters:
+    value_1 == value_2: return 0
+    value_1 > value_2: return 1
+    value_1 < value_2: return -1
+
+    Treats `None` and `-1` values as unlimited, i.e. always bigger than any other limited value.
+    """
+    # treat None as unlimited quota, i.e. -1
+    val_1 = -1 if value_1 is None else value_1
+    val_2 = -1 if value_2 is None else value_2
+    if val_1 == val_2:
+        return 0
+    if val_1 > val_2 or val_1 == -1:
+        return 1
+    if val_1 < val_2 or val_2 == -1:
+        return -1
diff --git a/ci/project-migrator.py b/ci/project-migrator.py
index ccc4d7266d425c216d99b275ac048cd51e9caa26..41a18eb6960fb43a25d0c5845399b1b4160863e5 100755
--- a/ci/project-migrator.py
+++ b/ci/project-migrator.py
@@ -72,17 +72,11 @@ def main(args):
                           "B.14 Cloud group project migration is executed by authorized person (cloud/openstack team member).",
                           lib.executed_as_admin_user_in_ci())
 
-
-    # check user context switching & quotas
     source_project_conn = lib.get_ostack_connection(source_migrator_openrc | {'OS_PROJECT_NAME': source_project.name})
-    #source_project_quotas = source_project_conn.get_compute_quotas(source_project.id)
-    #lib.log_or_assert(args, f"C.1 Context switching to source OpenStack cloud project succeeded (id:{source_project.id})",
-    #              source_project_quotas and source_project_quotas.id == source_project.id)
-
     destination_project_conn = lib.get_ostack_connection(destination_migrator_openrc | {'OS_PROJECT_NAME': destination_project.name})
-    #destination_project_quotas = destination_project_conn.get_compute_quotas(destination_project.id)
-    #lib.log_or_assert(args, f"C.2 Context switching to destination OpenStack cloud project succeeded (id:{destination_project.id})",
-    #              destination_project_quotas and destination_project_quotas.id == destination_project.id)
+
+    args.logger.info(f"C.01 Source and destination project quotas comparison:")
+    olib.compare_and_log_projects_quotas(args, "C.01", source_project_conn, source_project.id, destination_project_conn, destination_project.id)
 
     # connect to migrator node
     reply_stdout, reply_stderr, reply_ecode = lib.remote_cmd_exec(args.ceph_migrator_host, args.ceph_migrator_user,