类似于 availablity_zone,security_groups 和 security_group_rules 的实现也是通过 extension 来实现的。
neutron/extensions/securitygroup.py
这个模块中定义了实现为 security_groups 和 security_group_rules 提供接口的抽象基类:class SecurityGroupPluginBase(object)
neutron/db/security_groups_db.py 是真正的实现
这个模块就一个类 SecurityGroupDbMixin
,下面我们来详细讲一下这个类。
测试命令:
curl -s -X GET http://172.16.100.106:9696//v2.0/security-group-rules/090e66b6-fafe-4fd4-bb54-23effddc242c -H 'Content-Type: application/json' -H 'X-Auth-Token: 5f4e0cc153f64653bac02dab107e2151' | jq
- 调用
_get_security_group_rule
访问SecurityGroupRule
数据库,获取与security_group_rule_id
相符合和记录。 - 调用
_make_security_group_rule_dict
将数据库查询的结果构造成字典
测试数据:
{
"security_group_rule": {
"direction": "ingress",
"port_range_min": "80",
"ethertype": "IPv4",
"port_range_max": "80",
"protocol": "tcp",
"remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
"security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a"
}
}
该方法直接调用了 _create_security_group_rule
- 调用
_validate_security_group_rule
检验传递过来的数据的正确性 - 调用
registry.notify
发送通知消息 - 调用
_check_for_duplicate_rules
检查是否已经有相同的 rule 注册 - 检查通过后创建一条
SecurityGroupRule
数据库记录,并添加到回话中 - 调用
registry.notify
发送通知消息PRECOMMIT_CREATE
- 调用
_make_security_group_rule_dict
将创建的数据库对象解析成字典格式 - 再次调用
registry.notify
发送创建完成的通知AFTER_CREATE
- 返回第6步转化的字典
- 调用
_validate_port_range
检查端口范围是否合适 - 调用
_validate_ip_prefix
检查remote_ip_prefix
参数是否合法 - 调用
_validate_ethertype_and_protocol
检查ethertype
和protocol
参数是否合法 remote_ip_prefix
和remote_group_id
只能声明一个- 调用
get_security_group
检查remote_group_id
指定的 security_group 是否存在 - 调用
get_security_group
检查用户是否有权限在security_group_id
指定的 security_group 上增加 rule
- 调用
_rules_equal
判断客户端发出的请求中是否包含和相同的 rule - 调用
_check_for_duplicate_rules_in_db
判断数据库中是否存在了相同的 rule
- 调用
_make_security_group_rule_filter_dict
将客户端发送过来的请求数据转化为字典类型,用来构造数据了的 filter 选项。 - 调用
get_security_group_rules
获取符合过滤条件的 security_group_rules - 在排除
id
字段的情况下进行将客户端的数据与数据库的查询数据进行对比,查看该条规则是否已经存在
获取协议名称对应的协议号
获取协议名称以及协议号。
测试命令
curl -s -X DELETE http://172.16.100.106:9696/v2.0/security-group-rules/090e66b6-fafe-4fd4-bb54-23effddc242c -H 'Content-Type: application/json' -H 'X-Auth-Token: 5f4e0cc153f64653bac02dab107e2151'
- 调用
registry.notify
发送准备删除的通知BEFORE_DELETE
- 查询
SecurityGroupRule
数据库,获取与id
相同的记录 - 调用
registry.notify
发送准备删除的通知PRECOMMIT_DELETE
- 执行数据库的删除动作
- 调用
registry.notify
发送准备删除的通知AFTER_DELETE
def get_security_group_rules(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False)
测试命令:
curl -s -X GET http://172.16.100.106:9696//v2.0/security-group-rules -H 'Content-Type: application/json' -H 'X-Auth-Token: 5f4e0cc153f64653bac02dab107e2151'
- 调用
_get_marker_obj
获取用于分页作用 - 调用
common_db_mixin.CommonDbMixin._get_collection
来获取结果
批量创建 security_group_rule
直接调用 self._create_bulk
def _create_bulk(self, resource, context, request_items)
方法是在 neutron/db/db_base_plugin_v2.py 中的 NeutronDbPluginV2
中实现。这个方法也是循环的调用 create_security_group_rule
批量创建 security_group_rule 的本地(本类)实现
- 利用 sqlalchemy 的
scoped_session
来管理 session sqlalchemy 学习(二)scoped session - 调用
_validate_security_group_rules
检查用户发送过来的数据的有效性 - 调用
get_security_group
获取这个 rule 的所属组 - 调用
_check_for_duplicate_rules
检查是否有已经注册的 rule - 循环调用
_create_security_group_rule
实现 rule 的批量创建
判断 rule1 和 rule 除 id
属性外,其余属性是否一致
测试命令:
curl -s -X GET http://172.16.100.106:9696//v2.0/security-groups/e021afac-aa12-47c9-acec-5e2e1721a625 -H 'Content-Type: application/json' -H 'X-Auth-Token: 5f4e0cc153f64653bac02dab107e2151' | jq
- 调用
_get_security_group
根据id
获取SecurityGroup
数据库中的记录 - 调用
_make_security_group_dict
将数据库查询记录转化为字典形式 - 调用
get_security_group_rules
获取该 security_group 下的 rules 记录,并保存于刚才的字典中。 - 返回结果
测试命令:
curl -s -X DELETE http://172.16.100.106:9696//v2.0/security-groups/e021afac-aa12-47c9-acec-5e2e1721a625 -H 'Content-Type: application/json' -H 'X-Auth-Token: 5f4e0cc153f64653bac02dab107e2151'
- 调用
_get_port_security_group_bindings
查看是否有端口绑定在这个安全组上 - 默认的安全组非 admin 不可移除
- 调用
registry.notify
发送BEFORE_DELETE
的消息 - 调用
registry.notify
发送PRECOMMIT_DELETE
的消息 - 执行数据库的删除操作
- 调用
registry.notify
发送AFTER_DELETE
的消息
查询 SecurityGroupPortBinding
数据库查询与某个 security_group 绑定的 port信息
- 调用
registry.notify
发送BEFORE_UPDATE
的消息 - 非 admin 用户不能对默认的安全组执行更新操作
- 调用
registry.notify
发送PRECOMMIT_UPDATE
的消息 - 执行数据库的更新操作
- 调用
registry.notify
发送AFTER_UPDATE
的消息
- 用户端发送的数据示例:
{
"security_group": {
"name": "new-webservers",
"description": "security group for webservers"
}
}
- 调用
registry.notify
发送BEFORE_CREATE
的消息 - 调用
_ensure_default_security_group
先确保有一个默认的安全组存在 - 创建一条
SecurityGroup
数据库记录 - 若是创建默认的安全组的情况下会创建一条
DefaultSecurityGroup
数据库记录 - 若是创建默认的安全组的情况下回创建一条
SecurityGroupRule
数据库记录做默认规则 - 创建一条
SecurityGroupRule
数据库记录做本安全组的默认规则 - 调用
registry.notify
发送PRECOMMIT_CREATE
的消息 - 调用
_make_security_group_dict
将数据库记录转化为字典形式 - 调用
registry.notify
发送AFTER_CREATE
的消息 - 返回字典信息
确保该 tenant 下有一个默认的安全组。若是没有的话则会创建一个
def get_security_groups(self, context, filters=None, fields=None,
sorts=None, limit=None,
marker=None, page_reverse=False, default_sg=False)
测试命令:
curl -s -X GET http://172.16.100.106:9696//v2.0/security-groups -H 'Content-Type: application/json' -H 'X-Auth-Token: 5f4e0cc153f64653bac02dab107e2151'
- 根据分页需求调用
_get_marker_obj
- 调用
_get_collection
获取信息并返回
调用 _get_collection_count
获取数据库查询的结果个数
更新 port 上的安全组,这个方法会在 ml2 的 update_port
中调用
- 调用
utils.compare_elements
对比用户发送过来的 port 的安全组信息和 port 之前的安全组信息是否相同。若相同的话,则不会执行安全组的更新动作;不同的话,则更新 port 绑定的安全组。 - 若需要更新安全组,则调用
_get_security_groups_on_port
获取需要更新的安全组的信息 - 调用
_delete_port_security_group_bindings
删除SecurityGroupPortBingding
数据库中的关于此 port_id 的记录 - 调用
_process_port_create_security_group
创建SecurityGroupPortBingding
数据库记录
根据用户发送过来的 port 资源的相关数据,获取用户感兴趣的安全组数据。
根据 port_id 和 security_group_id 创建一条 SecurityGroupPortBingding
数据库记录。
当用户没有为 port 资源绑定安全组时,调用此方法为 port 资源绑定一个默认的安全组。
检查该 port(用户传递过来的数据) 是否分配了安全组来绑定。
与 _check_update_has_security_groups
有细微的差别,该方法检查port(用户传递过来的数据) 有安全组选项,但是为空或者 validators.is_attr_set
检测失败