数据库-SQLAlchemy 重要参数详解

sqlalchemy 连接参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 'pool_timeout' is the maximum number of seconds to wait when retrieving a
# new connection from the pool. After the specified amount of time, an
# exception will be thrown.
pool_timeout=30, # 30 seconds
# 'pool_recycle' is the maximum number of seconds a connection can persist.
# Connections that live longer than the specified amount of time will be
# re-established
pool_recycle=1800, # 30 minutes
# Pool size is the maximum number of permanent connections to keep.
pool_size=5,
# Temporarily exceeds the set pool_size if no connections are available.
max_overflow=2,
# The total number of concurrent connections for your application will be
# a total of pool_size and max_overflow.

如上所知如下:

  1. 应用程序最大db并发量 = pool_size + max_overflow

  2. 池子中的空闲conn 最大生存时间 1800s,超过的将被回收重建,此时client会和db主动断连

  3. 应用程序如果超过30s未从池子中取出可用conn,程序将触发exception

openstack-nova-虚机重启过程以及源码分析

基于openstack stein

api收到重启请求后, _action_reboot 调用 compute_api 进行reboot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
nova.api.openstack.compute.servers.ServersController
def _action_reboot(self, req, id, body):

reboot_type = body['reboot']['type'].upper()
context = req.environ['nova.context']
context.can(server_policies.SERVERS % 'reboot')
instance = self._get_server(context, req, id)

try:
self.compute_api.reboot(context, instance, reboot_type)
.................................................

nova.compute.api.API
@check_instance_lock
def reboot(self, context, instance, reboot_type):
"""Reboot the given instance."""
if reboot_type == 'SOFT':
self._soft_reboot(context, instance)
else:
self._hard_reboot(context, instance)

软重启和硬重启,将请求通过rpc 传给了nova compute

Read More

openstack-cinder-虚机挂载云盘cinder侧过程以及源码分析

本文基于openstack Stein 版本

上文分析nova挂载云盘过程中,提到调用cinder initialize_connection, 返回volume 的连接信息,比如rbd ceph 的connection info, 同时在 _parse_connection_options 中基于volume type 添加cinder io qos 信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cinder.volume.manager.VolumeManager.initialize_connection
def initialize_connection(self, context, volume, connector):
...............................................
try:
conn_info = self.driver.initialize_connection(volume, connector)
except Exception as err:
err_msg = (_("Driver initialize connection failed "
"(error: %(err)s).") % {'err': six.text_type(err)})
LOG.exception(err_msg, resource=volume)

self.driver.remove_export(context.elevated(), volume)

raise exception.VolumeBackendAPIException(data=err_msg)

conn_info = self._parse_connection_options(context, volume, conn_info)
LOG.info("Initialize volume connection completed successfully.",
resource=volume)
return conn_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def _parse_connection_options(self, context, volume, conn_info):
# Add qos_specs to connection info
typeid = volume.volume_type_id
specs = None
if typeid:
res = volume_types.get_volume_type_qos_specs(typeid)
qos = res['qos_specs']
# only pass qos_specs that is designated to be consumed by
# front-end, or both front-end and back-end.
if qos and qos.get('consumer') in ['front-end', 'both']:
specs = qos.get('specs')

# NOTE(mnaser): The following configures for per-GB QoS
if specs is not None:
volume_size = int(volume.size)
tune_opts = ('read_iops_sec', 'read_bytes_sec',
'write_iops_sec', 'write_bytes_sec',
'total_iops_sec', 'total_bytes_sec')

for option in tune_opts:
option_per_gb = '%s_per_gb' % option
option_per_gb_min = '%s_per_gb_min' % option
option_max = '%s_max' % option
option_base = '%s_base' % option
if option_per_gb in specs:
minimum_value = int(specs.pop(option_per_gb_min, 0))
value = int(specs[option_per_gb]) * volume_size
per_gb_value = max(minimum_value, value)
base_value = int(specs.pop(option_base, 0))
final_value = base_value + per_gb_value
max_value = int(specs.pop(option_max, final_value))
specs[option] = min(final_value, max_value)
specs.pop(option_per_gb)

qos_spec = dict(qos_specs=specs)
conn_info['data'].update(qos_spec)
...............................................

connection info 返回给了nova,nova侧使用即可,至于attachment 只是数据库里面变更一下记录而已。

openstack-nova-虚机挂载云盘过程以及源码分析

本文基于openstack Stein 版本

nova 侧虚机需要挂载云盘,包括创建时挂载系统盘以及普通数据盘

代码在 nova\compute]manager.py, nova 获取volume信息,并发起attach请求,最终调用cinder api发起了attach请求。

1
2
3
4
5
6
nova.compute.manager.ComputeManager._attach_volume:
try:
bdm.attach(context, instance, self.volume_api, self.driver,
do_driver_attach=True)
......................................

Read More

openstack cinder volume创建流程以及源码分析(三)

本文基于openstack Stein 版本

上文中,volume创建经scheduler 已经rpc cast 传给了 volume.

(1) cinder\volume\manager.py
VolumeManager.create_volume 函数对创建请求进行响应,并调用cinder.volume.flows.api.get_flow来创建。。

OnFailureReschedulerTask 当scheduer失败时重试,ExtractVolumeSpecTask 获取volume创建spec内容,NotifyVolumeActionTask 通知volume 创建动作,最终开始干活 CreateVolumeFromSpecTask 创建volume,以及 CreateVolumeOnFinishTask 通知volume创建完成。

Read More

openstack cinder volume创建流程以及源码分析(二)

本文基于openstack Stein 版本

上文中,volume创建经api已经rpc cast 传给了 scheduler.

(1) cinder\scheduler\manager.py
SchedulerManager.create_volume 函数对创建请求进行响应,并调用cinder.scheduler.flows.api.get_flow来创建。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cinder.scheduler.manager.SchedulerManager.create_volume
try:
flow_engine = create_volume.get_flow(context,
self.driver,
request_spec,
filter_properties,
volume,
snapshot_id,
image_id,
backup_id)
except Exception:
msg = _("Failed to create scheduler manager volume flow")
LOG.exception(msg)
raise exception.CinderException(msg)

Read More

openstack cinder volume创建流程以及源码分析(一)

本文基于openstack Stein 版本

1. cinder 创建整体流程

如整体架构图所示,创建卷涉及的答题步骤主要有以下几步:
a. Client发送请求,通过RESTFUL接口访问cinder-api。
b. Api解析响应请求,api解析由Client发送来的请求,并通过rpc进一步调用cinder-scheduler。
c. Scheduler对资源进行调度,scheduler选择合适的节点进行。
d. Volume调用Driver创建卷,volume通过指定Driver进行卷的创建。

2. 源码详解

Read More

虚拟化-ovs-常用命令集合

整理常用的ovs命令集合

基于Openvswitch 2.11
ovs-vsctl
1
2
3
4
5
6
显示主机已有网桥以及端口port信息,以及vxlan隧道信息
#ovs-vsctl show

添加网桥
#ovs-vsctl add-br br-test

ovs-ofctl
1
2
3
4
5
6
7
8
9
10
11
输出交换机信息,输出交换机上的网卡以及端口port信息
#ovs-ofctl show br-int

输出交换机的端口统计信息,包括收发包、丢包、错误包等数量
#ovs-ofctl dump-ports br-int -O openFlow13

查看交换机流表信息
#ovs-ofctl dump-flows br-int

添加交换机流表
#ovs-ofctl add-flow br-int ********
ovs-dpctl
1
2
3
显示所有datapath基本信息
#ovs-dpctl show

ovs-appctl
1
2
查询虚机mac fa:16:3e:ac:21:48 到 虚机 fa:16:3e:b0:bf:cc的流表trace路径
#ovs-appctl ofproto/trace br-int in_port=27,dl_src=fa:16:3e:ac:21:48,dl_dst=fa:16:3e:b0:bf:cc
例 : 查询虚机 test01 (宿主机 hyper123) 到虚机 test02(宿主机hyper09)的路径
1
2
3
4
5
6
7
8
9
10
1. 查询虚机test01 (tapa6df2bfb-e5)的 port id以及mac 
#ovs-ofctl show br-int -O openFlow13|grep tapa6df2bfb-e5 #查出是8号,mac fa:16:3e:f6:b8:81
2. 查询虚机test02 (tapf9689b0e-e4)的 port id
#ovs-ofctl show br-int -O openFlow13|grep tapf9689b0e-e4 查出是13号,mac是fa:16:3e:5a:35:74
3. 查询虚机test01到test02的icmp流表路径
#docker exec -it -uroot openvswitch_vswitchd bash
#ovs-appctl ofproto/trace br-int in_port=8,dl_src=fa:16:3e:f6:b8:81,dl_dst=fa:16:3e:5a:35:74

如果能在br-tun上送到 kernel tunnel代表正常

虚拟化-ovs-学习(1)

Open vSwitch

Open vSwitch 是一个开源的虚拟交换机实现。广泛应用在云计算行业,为网络管理员提供虚拟云主机之间和之内的流量可见性与可控性。Open vSwitch 旨在用虚拟化方案解决网络问题,与控制器软件一起实现分布式的虚拟交换技术。这意味着,交换机和控制器软件能够在多个服务器之间创建集群网络配置,从而不需要在每一台云主机和物理主机上单独配置网络。这个交换机还支持 VLAN 中继,通过 NetFlow、sFlow 和 RSPAN 实现可见性,通过 OpenFlow 协议进行管理。它还有其他一些特性:严格流量控制,它由 OpenFlow 交换协议实现;远程管理功能,它能通过网络策略实现更多控制。

在虚拟交换机的 Flow 控制器或管理工具方面,OvS 需要借助第三方控制器或管理工具实现复杂的转发策略。例如 OvS 支持 OpenFlow 协议,我们就可以使用任何支持 OpenFlow 协议的控制器来对 OvS 进行远程管理。但这并不意味着 OvS 必须要有一个控制器才能工作。在不连接外部控制器情况下,OvS 自身可以依靠 MAC 地址学习实现二层数据包转发功能,就像 Linux Bridge。

openstack-nova-虚拟机创建流程以及源码分析(二)

openstack 虚机创建流程以及源码分析(二)

基于openstack stein

前面调度完主机后开始rpc通知计算节点启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#nova/conductor/manager.py #
def build_instances(self, context, instances, image, filter_properties,
admin_password, injected_files, requested_networks,
security_groups, block_device_mapping=None, legacy_bdm=True,
request_spec=None, host_lists=None):
.......................
self.compute_rpcapi.build_and_run_instance(context,
instance=instance, host=host.service_host, image=image,
request_spec=local_reqspec,
filter_properties=local_filter_props,
admin_password=admin_password,
injected_files=injected_files,
requested_networks=requested_networks,
security_groups=security_groups,
block_device_mapping=bdms, node=host.nodename,
limits=host.limits, host_list=host_list)
1
2
3
4
5
6
7
def build_and_run_instance(self, ctxt, instance, host, image, request_spec,
filter_properties, admin_password=None, injected_files=None,
requested_networks=None, security_groups=None,
block_device_mapping=None, node=None, limits=None,
host_list=None):
.........
cctxt.cast(ctxt, 'build_and_run_instance', **kwargs)

自此消息cast 传给了compute 节点

Read More