Skip to content
This repository has been archived by the owner on Nov 9, 2020. It is now read-only.

tenant modify #781

Merged
merged 6 commits into from
Dec 8, 2016
Merged

tenant modify #781

merged 6 commits into from
Dec 8, 2016

Conversation

lipingxue
Copy link
Contributor

This PR includes:

  1. AdminCLI to support "tenant modify"
  2. API to support "tenant modify"
  3. corresponding vmdkops changes. Before this change, a directory /vmfs/volumes/datastore_name/dockvol/tenant_name will be created to store all volumes created by a tenant. In order to support tenant rename, we decide to create the directory with "/vmfs/volumes/datastore_name/dockvol/tenant_uuid, and then create a symlink like "/vmfs/volumes/datastore_name/dockvol/tenant_name" which points to that directory.
    Then during tenant rename, we don't delete the directory itself, we just unlink the old symlink and recreate the new symlink.
  4. extend unit test in vmdk_ops_test.py to test vmdk ops after tenant rename.
  5. Add code to enable logging in auth*.py.

'help': 'The new name of the tenant',
'required': False
},
'--description': {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing "tenant create" command does not support "description" argument. If it's not trivial to fix it in the current change, can you please file a tracking issue?

if error_info:
return error_info
if new_name:
error_info = tenant.set_name(auth_mgr.conn, name, new_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks to me unnatural to pass auth_mrg.conn parameter here. Why can't we get the DB connection in the backend (inside the tenant class or its dependents) to free up the API user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API user does not need to worry about the connection. API user only need to call _tenant_modify API. The DB connection is generated inside AuthorizationDataManager class. We can make the change to get the DB connection in the backend, but that will need a lot of code refactoring. I will not do it for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is true the _tenant_update API user doesn't need to worry about the connection. However, in my opinion the user of DockerVolumeTenant.set_name() API should not worry about the connection either. Basically we should isolate the DB operation to any upper-level business logic.

Anyway, I agree this will need a lot of code refactoring. We can address this later.

@@ -196,6 +211,29 @@ def _tenant_create(name, description, default_datastore, default_privileges, vm_

return None, tenant

def _tenant_modify(name, new_name=None, description=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like all API methods are following a different naming convention:

  1. Start with understore "_"
  2. A noun followed by a verb

Other non-API methods in this module are not following this convention. Since Python doesn't provide access modifiers to differentiate public and private methods, maybe we should consider refactoring the module (split it into two?) so that all methods in one module follow the same naming convention?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will file a issue to track this code refactoring.

if error_info:
return error_info
if description:
error_info = tenant.set_description(auth_mgr.conn, description)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

# unlink the old symbol link /vmfs/volumes/datastore_name/tenant_name
# create the new symbol link /vmfs/volumes/datastore_name/new_tenant_name
# which point to path /vmfs/volumes/datastore_name/tenant_uuid
lock = threadutils.get_lock()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some duplicate logic in this paragraph (line 135-156) and the other one (line 695-709). Can we refactor the code to extract them into separate methods and eliminate the duplication?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please address this comment?

@lipingxue
Copy link
Contributor Author

@msterin Please review this change.

Copy link
Contributor

@pdhamdhere pdhamdhere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some clarifying questions below.

@@ -204,6 +205,24 @@ def commands():
}
}
},
'modify': {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change modify => update?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

logging.debug("set_name: try to update the symlink to path %s", tenant_path)

if os.path.isdir(tenant_path):
lock.acquire()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly this lock is protecting?

Is there anything that synchronizes docker volume create and admin_cli tenant update happening at the same time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lock is to make sure if two users (from CLI and UI) try to modify the tenant, for example, CLI start first, it wants to rename "tenant" to "tenant1" and UI wants to rename "tenant" to "tenant2", then the final result should be "tenant" is renamed to "tenant2". Without this lock, it is quite possible that the result is "tenant" is renamed to "tenant1".
I think we can use os.rename here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the change to use os.rename.

os.remove(exist_symlink_path)
logging.debug("Remove the symbol link %s", exist_symlink_path)

new_symlink_path = os.path.join(dock_vol_path, new_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "renaming" (mv oldSymLink newSymLink) not an option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "renaming" should work here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@lipingxue
Copy link
Contributor Author

I have addressed comments from Sam and Prashant. Please review it @shaominchen @pdhamdhere

Copy link
Contributor

@shaominchen shaominchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. As I mentioned in one comment, the DB connections are exposed in many classes. We should refactor this code to have a persistence layer (or DAO layer) to handle DB operations. Other core business logic should not handle DB connections. This way different layers can evolve separately.

@msterin
Copy link
Contributor

msterin commented Dec 7, 2016

+1 on @shaominchen comment wrt DAO / DB connection consolidation. Please file an issue. The rest is LGTM too.

Copy link
Contributor

@msterin msterin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few format / message changes are needed - pls take a look before the merge. other than that LGTM

exist_symlink_path = os.path.join(dock_vol_path, name)
new_symlink_path = os.path.join(dock_vol_path, new_name)
if os.path.isdir(exist_symlink_path):
logging.info("Rename the symlink %s to %s", exist_symlink_path, new_symlink_path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Renaming

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

for (datastore, url_name, path) in vmdk_utils.get_datastores():
dock_vol_path = os.path.join("/vmfs/volumes", datastore, vmdk_ops.DOCK_VOLS_DIR)
tenant_path = os.path.join(dock_vol_path, tenant_id)
logging.debug("remove volumes for tenant: try to remove the symlink to path %s", tenant_path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

message is a bit unclear. Maybe "Tenant removal: removing symlink " ?
And the rest of the messages should be similar. Also please avoid copy-n-paste for logging format,
instead use something like

VOL_RM_LOG_PREFIX = ""Tenant <name> removal: "

 logging.debug(VOL_RM_LOG_PREFIX + "Removing  symlink to  %s", tenant_id, tenant_path)

(or any other reusabe code)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

exist_symlink_path = os.path.join(dock_vol_path, tenant_name)
if os.path.isdir(exist_symlink_path):
os.remove(exist_symlink_path)
logging.debug("remove volumes for tenant: Remove the symbol link %s", exist_symlink_path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"removing symlink %s"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@lipingxue
Copy link
Contributor Author

Thanks @shaominchen @msterin

Issue #803 is filed to address your DAO layer related comments.

@lipingxue
Copy link
Contributor Author

Fixes #715

@lipingxue lipingxue deleted the issue_715.liping branch December 8, 2016 21:27
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants