-
Notifications
You must be signed in to change notification settings - Fork 95
Support for default_datastore and data privileges change #828
Conversation
Unit test for new feature has been included in this PR. "make test-esx" passed. |
Please review @msterin @shaominchen. |
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 good. Please check the CI test failure.
This PR is too big to give a thorough review - at least the versions related logic should have been done in a separate PR.
}, | ||
'--allow-create': { | ||
'help': 'Allow create and delete on datastore if set to True', | ||
'action': 'store_true' |
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 guess the most common case when user creates a privilege is to assign full permissions, so probably we should set this to "store_false" instead?
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.
Let us keep it as is for now. We can make the change later if user complains about 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.
What is default? "allow-create = true"?
'metavar': 'create,delete,mount,all' | ||
'--allow-create': { | ||
'help': 'Allow create and delete on datastore if set to True', | ||
'action': 'store_true' |
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.
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
vms.append((vm_uuid, vm_name)) | ||
|
||
return None, vms | ||
|
||
def tenant_create(args): | ||
""" Handle tenant create command """ | ||
error_info, tenant = auth_api._tenant_create( | ||
name=args.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: remove the space before ","
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.
@@ -35,6 +35,7 @@ | |||
SIZE = 'size' | |||
DEFAULT_TENANT = '_DEFAULT' | |||
DEFAULT_DS = '_DEFAULT' | |||
DEFAULT_DS_URL = DEFAULT_DS + "_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.
Nit: let's use capital letters consistently for these constants, i.e. "_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.
def has_privilege(privileges, type=None): | ||
""" Check the privileges has the specific type of privilege set. | ||
if param "allow_create" is None or False, which means check | ||
the input "privileges" has "mount_only" privileges or not |
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: "mount_only "privileges => "mount_only" privilege
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.
List all tenants or tenant with the name specified | ||
Params: | ||
-- name: if "name" is specified, return a list of one tenant with name specified | ||
if "name" is not specified, return a list of all tenant |
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: all tenant => all tenants
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.
@@ -115,84 +124,99 @@ def generate_tuple_from_vm_list(vm_list): | |||
return None, vms, not_found_vms | |||
|
|||
def default_privileges(): | |||
""" return a privilege object with default value """ |
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.
Why do we remove this comment? It seems useful to me.
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 it back.
@@ -374,6 +376,58 @@ def create_default_privileges(self): | |||
err = error_code.TENANT_SET_ACCESS_PRIVILEGES_FAILED.format(auth.DEFAULT_TENANT, auth.DEFAULT_DS, error_info) | |||
logging.warning(err) | |||
|
|||
def get_db_version(self): | |||
""" | |||
Get DB schema version from auth-db |
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: keep the indent consistent
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.
|
||
def need_upgrade_db(self): | ||
""" | ||
Check auth-db schema need to be upgraded or not |
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: Check if auth-db ...
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.
tenant = DockerVolumeTenant(name=name, | ||
description=description, | ||
vms=vms, | ||
privileges=privileges, |
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.
The current privileges field contains specific DB column information. As we discussed offline, the API layer should return a pure data object so that above layer (such as VMODL) can get the data directly without having dependency on DB specifics.
We can address this in a separate PR.
@@ -221,6 +221,9 @@ def commands(): | |||
}, | |||
'--description': { | |||
'help': 'The new description of the tenant', | |||
}, | |||
'--default-datastore': { | |||
'help': 'The name of new 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.
The name of the new 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.
another nit - the flag is default-datastore (with -) and the help says default_datastore (with underscore), the help should say "the name of the datastore to be used by default for volumes placement"
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.
What's the plan to add documentation for the 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.
It's a big change and I have a set of nits (inside) but nothing major. I'd suggest adding to the PR description a few examples of setting the defaut_datastore and privileges, and running docker volume create and docker volume ls.
LGTM after addressing (fixing or commenting) on the nits.
@@ -221,6 +221,9 @@ def commands(): | |||
}, | |||
'--description': { | |||
'help': 'The new description of the tenant', | |||
}, | |||
'--default-datastore': { | |||
'help': 'The name of new 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.
another nit - the flag is default-datastore (with -) and the help says default_datastore (with underscore), the help should say "the name of the datastore to be used by default for volumes placement"
'choices': ['create', 'delete', 'mount', 'all'], | ||
'metavar': 'create,delete,mount' | ||
'--switch-default-datastore': { | ||
'help': "Switch default datastore for this tenant", |
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.
why not simply 'default-datastore' ? How the command would look like ?
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.
Command is like this:
- The datastore in the first privilege added for a tenant will be set to "default_datastore" automatically even if --switch-default-datastore is not specified
Example:
[root@localhost:~] /usr/lib/vmware/vmdkops/bin/vmdkops_admin.py tenant access add --name=tenant1 --datastore=datastore1 --volume-maxsize=500MB --volume-totalsize=1GB
tenant access add succeeded
[root@localhost:~] /usr/lib/vmware/vmdkops/bin/vmdkops_admin.py tenant ls
Uuid Name Description Default_datastore VM_list
------------------------------------ -------- ------------------------ ----------------- -------
93377b1e-af74-47ca-888e-75fd0a2a4aba _DEFAULT This is a default tenant
948f0edc-3a06-4d95-8b8c-8cf278154fc3 tenant1 datastore1 photon4
- when you add the second privilege for a tenant, and if "--switch-default-datastore" is specified, "default_datastore" will be switch to the datastore used in the second privilege, see the following example:
/usr/lib/vmware/vmdkops/bin/vmdkops_admin.py tenant access add --name=tenant1 --datastore=datastore2 --allow-create --switch-default-datastore --volume-maxsize=500MB --volume-tot
alsize=1GB
tenant access add succeeded
[root@localhost:~] /usr/lib/vmware/vmdkops/bin/vmdkops_admin.py tenant ls
Uuid Name Description Default_datastore VM_list
------------------------------------ -------- ------------------------ ----------------- -------
93377b1e-af74-47ca-888e-75fd0a2a4aba _DEFAULT This is a default tenant
948f0edc-3a06-4d95-8b8c-8cf278154fc3 tenant1 datastore2 photon4
That is why the param is called "--switch-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.
It does not really answer the questions. Why does it need "switch" in the name ? It is confusing, inconsistent and does not really add anything. --default-datastore
should be perfectly fine.
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.
OK. I change the param to "--default-datastore".
|
||
def tenant_access_add(args): | ||
""" Handle tenant access command """ | ||
error_info = auth_api._tenant_access_add(name=args.name, | ||
datastore=args.datastore, | ||
rights=args.rights, | ||
switch_default_datastore=args.switch_default_datastore, | ||
allow_create=args.allow_create, |
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: the rest of params do not say "switch_allow_create", why default_datastore does ?
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.
if major_ver != DB_MAJOR_VER or minor_ver != DB_MINOR_VER: | ||
auth_db_ver = get_version_str(major_ver, minor_ver) | ||
curr_db_ver = get_version_str(DB_MAJOR_VER, DB_MINOR_VER) | ||
logging.error("version %s in auth-db does not match latest DB version %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.
need some info on what to do next :-).
E.g. "DB upgrade is not supported. Please remove the DB and create new configuration using "
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.
@@ -305,6 +305,16 @@ def log_volume_lsof(vol_name): | |||
cartel, name, ftype, fd, desc) | |||
logging.info("Volume open descriptor: %s", msg) | |||
|
|||
def get_datastore_url(datastore): | |||
si = vmdk_ops.get_si() | |||
res = [d.info.url for d in si.content.rootFolder.childEntity[0].datastore if d.info.name == 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.
pls wrap si.content.rootFolder.childEntity[0].datastore
in some named function and reuse in line 315 as well
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.
@@ -885,22 +878,29 @@ def test_vmdkops_on_tenant_vm(self): | |||
vm_list=[self.vm1_name]) | |||
self.assertEqual(None, error_info) | |||
|
|||
# run create command, which should succeed since we have DEFAULT privilege set | |||
# run create command, which should fail since "default_datastore" is not set for tenant1 |
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.
why create() should fail without default_datastore ? I thought we wanted to keep the current behavior (i.e. use VM datastore) ? If this is not the case then we need to make setting default_datastore mandatory on tenant creation
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.
OK. I agree with you and make the change.
Now the logic is if "default_datastore" is not specified for a tenant, a volume will be created in the datastore where the VM lives in if the user specify the name with the short notion.
# run create command again, which should succeed since "default_datastore" is set for tenant1 now | ||
opts={u'fstype': u'ext4'} | ||
error_info = vmdk_ops.executeRequest(vm1_uuid, self.vm1_name, self.vm1_config_path, auth.CMD_CREATE, self.tenant1_vol1_name, opts) | ||
self.assertEqual(None, error_info) |
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.
we also need to check that the volume is created in correct place.
We also need to check that if we 'ls' volume it's name does not have datastore if it's on 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.
Done. Change the listVMDK logic as we discussed. Now listVMDK will show volume with format like vol_name@datastore
@@ -1082,6 +1084,87 @@ def test_vmdkops_on_different_tenants(self): | |||
self.assertEqual("tenant2_vol1", result[0]['Name']) | |||
self.assertEqual("tenant2_vol2", result[1]['Name']) | |||
self.assertEqual("tenant2_vol3", result[2]['Name']) | |||
|
|||
@unittest.skipIf(len(vmdk_utils.get_datastores()) < 2, | |||
"second datastore is not found - skipping this test") |
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 think that If we need 2 DS for a test, then we need to request it and make sure test bed has 2 datastores - instead of skipping the test.
@kerneltime - comments ?
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 agree with you on this and will wait for Ritesh's comments on how to do 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.
As we discussed yesterday, I will keep this code as it is.
I will file a new issue to track:
-- testbed in CI need to make sure it have 2 datastores in order to run this test successfully
-- contributing.md need to be updated to let user know they need to have 2 datastores to run the test
# there should be two volumes shown as "tenant1_vol1"" and "tenant1_vol2" | ||
self.assertEqual(len(result), 2) | ||
self.assertEqual("tenant1_vol1", result[0]['Name']) | ||
self.assertEqual("tenant1_vol2", result[1]['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.
Is it checking that @default_datastore is stripped from the name?
Then pls ad this to the comments
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.
Since listVMDK now return volume with format like vol_name@datastore, this test has been changed accordingly.
c20a4d1
to
644c3d1
Compare
ae7132a
to
8106310
Compare
Hi Mark, This are the steps before I run "docker volume ls"
|
Btw: What do you mean "Good to go, not good to fi"? I assume the PR is approved by you and I can merge it after the CI failure is resolved. |
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
""" Check whether the param "privileges" has the specific type of privilege set. | ||
There are two types of privilege: | ||
- "mount_only" which means only mount and unmount are allowed | ||
- "fully_access" which means create, remove, mount, unmount are |
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.
fully_access => full_access here and other places.
}, | ||
'--allow-create': { | ||
'help': 'Allow create and delete on datastore if set to True', | ||
'action': 'store_true' |
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 is default? "allow-create = true"?
…eturns volume with format like "vol_name@datastore". Need to ignore the "@datastore" part when check whether the volume exists or not.
8106310
to
cd6d93d
Compare
This change includes: