Another use case:
1. In Horizon, create a non-public flavor as an admin user 2. Launch an instance against that flavor 3. Edit the flavor
Now, when attempting to view the instance as a non-admin user, Nova will throw errors.
Tracking this down with a debugger:
> /opt/stack/nova/nova/db/sqlalchemy/api.py(4293)_flavor_get_query() -> return query (Pdb) stmt = query.statement (Pdb) x = stmt.compile(compile_kwargs={'literal_binds': True}) (Pdb) print str(x) SELECT instance_types.created_at, instance_types.updated_at, instance_types.deleted_at, instance_types.deleted, instance_types.id, instance_types.name, instance_types.memory_mb, instance_types.vcpus, instance_types.root_gb, instance_types.ephemeral_gb, instance_types.flavorid, instance_types.swap, instance_types.rxtx_factor, instance_types.vcpu_weight, instance_types.disabled, instance_types.is_public, instance_type_extra_specs_1.created_at, instance_type_extra_specs_1.updated_at, instance_type_extra_specs_1.deleted_at, instance_type_extra_specs_1.deleted, instance_type_extra_specs_1.id, instance_type_extra_specs_1.key, instance_type_extra_specs_1.value, instance_type_extra_specs_1.instance_type_id FROM instance_types LEFT OUTER JOIN instance_type_extra_specs AS instance_type_extra_specs_1 ON instance_type_extra_specs_1.instance_type_id = instance_types.id AND instance_type_extra_specs_1.deleted = 0 WHERE instance_types.is_public = 1 OR (EXISTS (SELECT 1 FROM instance_type_projects WHERE instance_type_projects.instance_type_id = instance_types.id AND instance_type_projects.deleted = 0 AND instance_type_projects.project_id = '19cdefa3773642db8624a52d9b5d982e'))
...wait, what are those "deleted = 0" constraints? The query explicitly sets read_deleted=True !
Another use case:
1. In Horizon, create a non-public flavor as an admin user
2. Launch an instance against that flavor
3. Edit the flavor
Now, when attempting to view the instance as a non-admin user, Nova will throw errors.
Tracking this down with a debugger:
> /opt/stack/ nova/nova/ db/sqlalchemy/ api.py( 4293)_flavor_ get_query( ) compile_ kwargs= {'literal_ binds': True}) types.created_ at, instance_ types.updated_ at, instance_ types.deleted_ at, instance_ types.deleted, instance_types.id, instance_ types.name, instance_ types.memory_ mb, instance_ types.vcpus, instance_ types.root_ gb, instance_ types.ephemeral _gb, instance_ types.flavorid, instance_ types.swap, instance_ types.rxtx_ factor, instance_ types.vcpu_ weight, instance_ types.disabled, instance_ types.is_ public, instance_ type_extra_ specs_1. created_ at, instance_ type_extra_ specs_1. updated_ at, instance_ type_extra_ specs_1. deleted_ at, instance_ type_extra_ specs_1. deleted, instance_ type_extra_ specs_1. id, instance_ type_extra_ specs_1. key, instance_ type_extra_ specs_1. value, instance_ type_extra_ specs_1. instance_ type_id type_extra_ specs AS instance_ type_extra_ specs_1 ON instance_ type_extra_ specs_1. instance_ type_id = instance_types.id AND instance_ type_extra_ specs_1. deleted = 0 types.is_ public = 1 OR (EXISTS (SELECT 1 type_projects type_projects. instance_ type_id = instance_types.id AND instance_ type_projects. deleted = 0 AND instance_ type_projects. project_ id = '19cdefa3773642 db8624a52d9b5d9 82e'))
-> return query
(Pdb) stmt = query.statement
(Pdb) x = stmt.compile(
(Pdb) print str(x)
SELECT instance_
FROM instance_types LEFT OUTER JOIN instance_
WHERE instance_
FROM instance_
WHERE instance_
...wait, what are those "deleted = 0" constraints? The query explicitly sets read_deleted=True !