-
Notifications
You must be signed in to change notification settings - Fork 95
Make change to authorize() function to take "datastore_url" and volume create fail after datastore rename #979
Conversation
Testing Done: Configuration 1: Case 1.1: after VM datastore "datastore1" rename, create volume with short name succeeded.
Case1.2: after VM datastore "datastore1" rename, create volume with volname@old-datastore failed, and create volume with volname@new-datastore succeeded.
Configuration2: Case2.1: after default datastore "datastore1", rename, create volume with short name succeeded.
Case2.2: after non default datastore "datastore2" rename, create volume with full name volname@old-datastore failed, and create volume with volname@new-datastore succeeded.
|
@msterin @shaominchen Please review it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good change. Comments inside - mainly about some refactoring and a few nits.
Also, did you test (manually or automated) setting limits on a tenant (default tenant is the best to test here) ?
@@ -288,7 +288,7 @@ def setUp(self): | |||
""" Setup run before each test """ | |||
self.vol_count = 0 | |||
self.cleanup() | |||
for (datastore, url_name, path) in vmdk_utils.get_datastores(): | |||
for (datastore, url_name, path, url) in vmdk_utils.get_datastores(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the difference between url_name and url ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the same confusion. We should rename these 2 variables to clarify the difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
url_name is part of url.
As we discussed offline, will remove "url_name" from vmdk_utils.get_datastores()
esx_service/utils/auth_api.py
Outdated
@@ -250,7 +244,7 @@ def generate_privileges_dict(privileges): | |||
|
|||
def get_default_datastore(name): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: better to rename to get_default_datastore_url.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with Mark.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
esx_service/utils/auth_data.py
Outdated
@@ -227,7 +227,7 @@ def set_name(self, conn, name, new_name): | |||
# rename the old symbol link /vmfs/volumes/datastore_name/tenant_name | |||
# to a new name /vmfs/volumes/datastore_name/new_tenant_name | |||
# which still point to path /vmfs/volumes/datastore_name/tenant_uuid | |||
for (datastore, url_name, path) in vmdk_utils.get_datastores(): | |||
for (datastore, url_name, path, url) in vmdk_utils.get_datastores(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same question - what's the difference between url_name and url ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
esx_service/utils/auth_data.py
Outdated
if err: | ||
logging.error("remove vmdk %s failed with error %s", vmdk_path, err) | ||
error_msg += str(err) | ||
|
||
VOL_RM_LOG_PREFIX = "Tenant <name> %s removal: " | ||
# delete the symlink /vmfs/volume/datastore_name/tenant_name | ||
# which point to /vmfs/volumes/datastore_name/tenant_uuid | ||
for (datastore, url_name, path) in vmdk_utils.get_datastores(): | ||
for (datastore, url_name, path, url) in vmdk_utils.get_datastores(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - this section seems to be cut-n-pasted afew times, better to have a function
esx_service/vmdk_ops.py
Outdated
% (config_path, config_ds_url)) | ||
return config_ds_url | ||
|
||
def datastore_path_exist(datastore): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: either datastore_name or
just name
(instead of 'datastore
) in params. Datastore is confusing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
esx_service/vmdk_ops.py
Outdated
@@ -764,24 +773,45 @@ def executeRequest(vm_uuid, vm_name, config_path, cmd, full_vol_name, opts): | |||
Returns None (if all OK) or error string | |||
""" | |||
logging.debug("config_path=%s", config_path) | |||
vm_datastore = get_datastore_name(config_path) | |||
vm_datastore_url = get_datastore_url_from_config_path(config_path) | |||
vm_datastore = vmdk_utils.get_datastore_name(vm_datastore_url) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this block spreads the knowledge about cache manipulation onto too many places.
I think it would be way better to hide it , say in get_datastore_name() ... it can check get_datastores() and reset the cache internally if needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
esx_service/vmdk_ops.py
Outdated
default_datastore = vm_datastore | ||
else: | ||
default_datastore = vmdk_utils.get_datastore_name(default_datastore_url) | ||
if not datastore_path_exist(default_datastore): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as above , plus copy-n-paste is evil :-) (makes it much harder to change later) .
Please consider hiding the path check and cache update inside of get_datastore_name()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree - cache manipulation (refresh on demand) is the API's responsibility, not the API user's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
if not vmdk_utils.validate_datastore(datastore): | ||
if datastore and not vmdk_utils.validate_datastore(datastore): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's better to hide a check for if datastore
inside of validate datastore, which should always return False if passed None ? (depends on other places in the code, so it's a nit)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here "datastore==None" means the volume which user passed is a short name(no datastore is specified by user), so no need to validate "datastore" in this case.
esx_service/vmdk_ops.py
Outdated
if error_info: | ||
return err(error_info) | ||
|
||
# get /vmfs/volumes/<volid>/dockvols path on ESX: | ||
datastore = vmdk_utils.get_datastore_name(datastore_url) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and another confirmation that we need to hide this in get_datastore_name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks great.
@@ -288,7 +288,7 @@ def setUp(self): | |||
""" Setup run before each test """ | |||
self.vol_count = 0 | |||
self.cleanup() | |||
for (datastore, url_name, path) in vmdk_utils.get_datastores(): | |||
for (datastore, url_name, path, url) in vmdk_utils.get_datastores(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the same confusion. We should rename these 2 variables to clarify the difference.
esx_service/utils/auth_api.py
Outdated
@@ -250,7 +244,7 @@ def generate_privileges_dict(privileges): | |||
|
|||
def get_default_datastore(name): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with Mark.
esx_service/utils/auth_data.py
Outdated
|
||
Return value: | ||
error_msg: return None on success or error info on failure | ||
datastore: return default_datastore name on success or None on failure | ||
datastore: return default_datastore url on success or None on failure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: datastore => datastore_url
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
esx_service/utils/vmdk_utils.py
Outdated
@@ -74,7 +74,8 @@ def init_datastoreCache(): | |||
continue | |||
datastores.append((datastore.info.name, | |||
os.path.split(datastore.info.url)[1], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt this statement may not really work. I tried to run this statement with a real datastore url, it always return empty:
import os
url =os.path.split("ds:///vmfs/volumes/vsan:525ab51e793147fd-c0f242a06e800fc2/")[1]
print(url)
If this field is incorrect and it's not being used anywhere, we should just get rid of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
esx_service/utils/vmdk_utils.py
Outdated
@@ -331,7 +336,7 @@ def get_datastore_name(datastore_url): | |||
return auth.DEFAULT_DS | |||
|
|||
# Query datastore name from VIM API | |||
res = [d.info.name for d in get_datastore_objects() if d.info.url == datastore_url] | |||
res = [d[0] for d in get_datastores() if d[3] == datastore_url] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to improve the readability to avoid the magic d[0] and d[3]?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add some comments here.
esx_service/vmdk_ops.py
Outdated
else: | ||
logging.debug(error_code.error_code_to_message[ErrorCode.VM_NOT_BELONG_TO_TENANT].format(vm_name)) | ||
|
||
|
||
def cloneVMDK(vm_name, vmdk_path, opts={}, vm_uuid=None, vm_datastore=None): | ||
logging.info("*** cloneVMDK: %s opts = %s", vmdk_path, opts) | ||
def cloneVMDK(vm_name, vmdk_path, opts={}, vm_uuid=None, vm_datastore_url=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for consistency: rename vm_datastore_url to datastore_url.
esx_service/vmdk_ops.py
Outdated
default_datastore = vm_datastore | ||
else: | ||
default_datastore = vmdk_utils.get_datastore_name(default_datastore_url) | ||
if not datastore_path_exist(default_datastore): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree - cache manipulation (refresh on demand) is the API's responsibility, not the API user's.
454140c
to
7a59ceb
Compare
I also did the following test to make sure max_vol_size and total_size(quota) limit for tenant is not broken by this change.
|
|
||
# dockvol_path has the format like "/vmfs/volumes/<datastore_name>" | ||
# tenant_path has the format like "/vmfs/volumes/<datastore_name>/tenant_id" | ||
dockvol_path = os.path.join("/vmfs/volumes", datastore_name, vmdk_ops.DOCK_VOLS_DIR) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: can we define /vmfs/volumes
as constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree with this but it should delay the merge
esx_service/vmdk_ops.py
Outdated
# path can be /vmfs/volumes/<datastore_url_name>/... | ||
# or /vmfs/volumes/datastore_name/... | ||
# so extract datastore_url_name: | ||
config_ds_url = os.path.join("/vmfs/volumes/", os.path.realpath(config_path).split("/")[3]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seen multiple occurrence of /vmfs/volumes/
; it is better to declare as constant. Please refactor for each occurrences.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally think "/vmfs/volumes" is more readable in the context of the code, so will drop this comment.
esx_service/vmdk_ops.py
Outdated
logging.error("get_datastore_name: found more than one match: %s" % ds_name) | ||
logging.debug("get_datastore_name: path=%s name=%s" % (config_ds_name, ds_name)) | ||
return ds_name[0] | ||
def get_datastore_url_from_config_path(config_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this be moved to vmdk_utils as part of this PR (seems the whole method is refactored)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
esx_service/vmdk_ops.py
Outdated
% (config_path, config_ds_url)) | ||
return config_ds_url | ||
|
||
def datastore_path_exist(datastore_name): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above .. it is better to move to vmdk_utils.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will keep it here for now since now no other callers need this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall look good to me .. supplying some minor comments.
esx_service/utils/vmdk_utils.py
Outdated
@@ -324,6 +324,8 @@ def get_datastore_url(datastore_name): | |||
return None | |||
|
|||
# Query datastore URL from VIM API | |||
# get_datastores() return a list of tuple | |||
# each tuple has for format like (datastore_name, datastore_url, dockvol_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: remove the redundant "for"
esx_service/utils/vmdk_utils.py
Outdated
@@ -335,6 +337,8 @@ def get_datastore_name(datastore_url): | |||
return auth.DEFAULT_DS | |||
|
|||
# Query datastore name from VIM API | |||
# get_datastores() return a list of tuple | |||
# each tuple has for format like (datastore_name, datastore_url, dockvol_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: same as above.
esx_service/vmdk_ops.py
Outdated
""" Get datastore_name with given datastore_url """ | ||
datastore_name = vmdk_utils.get_datastore_name(datastore_url) | ||
datastore_path = os.path.join("/vmfs/volumes/", datastore_name) | ||
if not datastore_path_exist(datastore_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we pass the datastore_name instead of datastore_path here? See the API signature at line 757.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good catch!
fdfedd2
to
4b23184
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Please do not forget to squash the commits
…f "datastore_name" Fix the issue that volume create fail after datastore rename.
4b23184
to
12b03d0
Compare
This PR is the second part of fix for #818. This PR includes: