Openstack的horzion组件目前只提供了部分的Openstack管理操作,有些功能只能通过命令行完成,命令行对于没有技术背景的客户来说是一种很糟糕的体验。同时,horzion中一些功能的默认权限可能并不完全符合某些客户的应用场景,所有经常有必要对horizon进行一些定制化的处理。
Openstack admin guide只介绍了简单的定制化处理,包括网站的标题、logo以及一些css样式的定制化,远远没法满足定制化的需求。
这里简单记录一下通过policy来定制化horizon。
nova、keystone以及glance中默认的policy.json文件中只能识别admin角色:所有不需要admin角色的操作可以被相应tenant中的拥有任何角色的任何用户执行。
horizon中也会保存各个组件相应的policy.json文件,默认存放在horizon/openstack_dashboard/conf中。horizon会根据policy.json文件中的内容来为不同的用户显示不同的内容。下面举一个简单的例子说明:
需求: 默认情况下,普通的用户也可以创建网络,客户希望网络只能由管理员来创建。
实现: 修改horizon/openstack_dashboard/conf/neutron_policy.json
"create_network": "", 修改为 "create_network": "rule:admin_only" 实现起来很简单。
同时,horizon是怎么知道Openstack中开启了哪些服务:例如你的Openstack环境中没有启动swift服务,而此时horizon中却显示了对象存储服务的话,就会出现问题。
其实horizon根据的是keystone中是否存在相应service_type的endpoint。
代码见 openstack_auth项目的backend.py文件:
def get_all_permissions(self, user, obj=None):
"""Returns a set of permission strings that this user has through
his/her Keystone "roles".
The permissions are returned as ``"openstack.{{ role.name }}"``.
"""
if user.is_anonymous() or obj is not None:
return set()
# TODO(gabrielhurley): Integrate policy-driven RBAC
# when supported by Keystone.
role_perms = set(["openstack.roles.%s" % role['name'].lower()
for role in user.roles])
service_perms = set(["openstack.services.%s" % service['type'].lower()
for service in user.service_catalog
if user.services_region in
[endpoint.get('region', None) for endpoint
in service.get('endpoints', [])]])
return role_perms | service_perms
比如openstack_dashboard/dashboards/project/containers/panel.py 中
class Containers(horizon.Panel):
name = _("Containers")
slug = 'containers'
permissions = ('openstack.services.object-store',)
permission是"openstack.services.object-store" 表示keystone中必须有一个service_type为object-store的service,并且这个service存在endpoint。这样的基础上,horizon才会在project中显示相应的对象存储选项。
keystone中的service_type挺重要的,不能随便设置。
接下来希望对horizon的代码进行进一步的了解。