nova读取配置文件流程
在我们安装nova的过程中,设置它的配置文件/etc/nova/nova.conf是必不可少的一步。配置好nova.conf文件,nova-compute、nova-network等服务才有可能正常启动。当然在修改nova.conf文件后,必须重启nova的所有服务,新的配置才能生效。
其实我们的配置文件不一定非要存放为/etc/nova/nova.conf,也可以设置成任意目录下的任意文件。nova获取配置文件的方式有两种:
选项
--config-file
指定
任意文件为配置文件(当然前提是有读写权限)
。
/usr/bin/python /usr/bin/nova-compute--config-file=/etc/nova/nova.conf--config-file=/etc/nova/nova-compute.conf
通过--config-file选项,可以指定任意多个配置文件,上例给nova-compute服务指定了两个配置文件。此时,在这两个文件设置的配置项,都是有效的。但如果这两个文件有相同的配置项,而且这个配置项是不允许有多个值的,那会以哪个为有效指呢,还是会出现错误?
nova-api、nova-compute、nova-dhcpbridge、nova-network、nova-rootwrap。各个服务在启动时,读取配置文件的流程都是一样的。下面针对nova-compute的配置读取过程进行分析,其他的服务相同。
42 if __name__ == '__main__':
43
flags.parse_args(sys.argv)
44
logging.setup('nova')
45
utils.monkey_patch()
46
server = service.Service.create(binary='nova-compute')
47
service.serve(server)
48
service.wait()
36 FLAGS = cfg.CONF
37
38
39 def parse_args(argv,default_config_files=None):
40
FLAGS.disable_interspersed_args()
41
return argv[:1] + FLAGS(argv[1:],
42
project='nova',
43
default_config_files=default_config_files)
CONF =CommonConfigOpts()
CommonConfigOpts乃何许类也,它都干些什么呢?
CommonConfigOpts是ConfigOpts的子类,而在ConfigOpts中定义__call__函数,所以CommonConfigOpts对象可以像函数一样,被直接调用。为了能够理解这两个类是干什么的,我们需要先了解另外几个类:
#如果没有指定则为file
help="write report to FILE", metavar="FILE")
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
'ddd','ffff'],它是用于返回不能被OptionParser识别的参数。
"Caution: use these options at your own risk.
"
"It is believed that some of them bite.")
self.name = name
#name对应命令行参数名和配置文件中的配置项名
self.dest = dest #解析命令行参数时生成属性的名,通过该名可获取命令行参数值,如上例filename
self.short = short
#命令行参数的简写,如上例中f
self.default = default
#该选项的默认值
self.metavar = metavar
#用于在显示帮助信息时用的,如FILE
self.help = help
self.secret = secret
#bool类型,指定该选项是否为保密信息,这样在打印日志时会用特殊字符代替
self.required = required#是否为必填项,在读取配置文件后,会依据该值进行检查
self.deprecated_name = None
#该选项的备用名,可用作命令行参数名和配置项名
self.filename = filename
self.sections = sections
def parse(self):
with open(self.filename) as f:
returnsuper(ConfigParser, self).parse(f)
def parse(self, lineiter):
key = None
value = []
for line in lineiter:
self.lineno += 1
line =line.rstrip()
if notline:
# Blank line, ends multi-linevalues
if key:
key, value = self._assignment(key, value)
continue
elifline[0] in (' ', '\t'):
# Continuation of previousassignment,这里可以知道,为什么配置项不能以空格开始了
if key is None:
self.error_unexpected_continuation(line)
else:
value.append(line.lstrip())
continue
ifkey:
# Flush previous assignment,if any
key, value =self._assignment(key, value)
if line[0]== '[':
# Section start
section =self._get_section(line)
if section:
self.new_section(section)
elifline[0] in '#;':
#这里可以看出配置项的key和value可以通过#或;进行分隔
self.comment(line[1:].lstrip())
else:
key, value =self._split_key_value(line)
if not key:
return self.error_empty_key(line)
if key:#用作处理最后一个key value对
# Flushprevious assignment, if any
self._assignment(key, value)
def__init__(self):
self.parsed = []
def read(self,config_files):
read_ok = []
for filename in config_files:
sections ={}
parser =ConfigParser(filename, sections)
try:
parser.parse()
exceptIOError:
continue
self.parsed.insert(0, sections)
read_ok.append(filename)
return read_ok
def get(self, section,names, multi=False):
rvalue = []
for sections in self.parsed:
if sectionnot in sections:
continue
for namein names:
if name insections[section]:
if multi:
rvalue =sections[section][name] + rvalue
else:
returnsections[section][name]
if multi and rvalue != []:
returnrvalue
raise KeyError
这里需要注意一点,在往parsed中添加sections时,使用
parsed.insert(0,sections)。排在后面的配置文件,解析后会放在parsed的最前面。当调用get()获取配置项的时,如果该配置项不为多选项(multi),那么只会去parsed前面sections中的值。也就是说如果一个配置项在多个配置文件中被重复定义,那么只会读取最后一个配置文件中的值作为使用值。
好了,在了解了上面几个类之后,我们可以查看ConfigOpts和CommonConfigOpts类了。ConfigOpts的成员变量如下:
def__init__(self):
"""Construct a ConfigOpts object."""
self._opts = {}
# dict ofdicts of (opt:, override:, default:)
self._groups = {}
self._args = None
self._oparser = None
#命令行参数解释器,即一个OptionParser对象
self._cparser = None
#配置文件解释器,即一个MultiConfigParser对象
self._cli_values = {}
#程序启动时,通过_oparser解释的命令行参数值
self.__cache = {}
#缓存
self._config_opts = []
self._disable_interspersed_args = False
def_setup(self, project, prog, version, usage,default_config_files):
"""Initialize a ConfigOpts object for optionparsing."""
if prog is None:
prog =os.path.basename(sys.argv[0])
if default_config_files is None:
#在['~/.nova/', '~/', '/etc/nova/','/etc/']寻找配置文件nova.conf和nova-compute.conf
default_config_files = find_config_files(project, prog)
self._oparser =optparse.OptionParser(prog=prog,
version=version,
usage=usage)
if self._disable_interspersed_args:
self._oparser.disable_interspersed_args()
self._config_opts = [
MultiStrOpt('config-file',
default=default_config_files,
metavar='PATH',
help='Pathto a config file to use. Multiple config '
'files canbe specified, with values in later '
'filestaking precedence. The default files '
' used are:%s' % (default_config_files, )),
StrOpt('config-dir',
metavar='DIR',
help='Path to a config directory to pull *.conf'
'filesfrom. This file set is sorted, so as to '
'provide apredictable parse order if individual '
'optionsare over-ridden. The set is parsed after '
'thefile(s), if any, specified via --config-file, '
'henceover-ridden options in the directory take '
'precedence.'),
]
#注册命令行参数config-file和config-dir,这样就可以通过命令行指定该配置项了。
self.register_cli_opts(self._config_opts)
self.project = project
self.prog = prog
self.version = version
self.usage = usage
self.default_config_files =default_config_files
self._oparser =optparse.OptionParser(prog=prog, version=version,usage=usage)
"""Parse the config files from --config-file and--config-dir.
:raises: ConfigFilesNotFoundError
,ConfigFileParseError
"""
config_files = list(self.config_file)
if self.config_dir:
#如果指定了config_dir,那么该目录下所有匹配*.conf的文件,都会被当作配置文件
config_dir_glob = os.path.join(self.config_dir, '*.conf')
config_files += sorted(glob.glob(config_dir_glob))
config_files = [_fixpath(p) for p inconfig_files]
self._cparser = MultiConfigParser()
try:
read_ok =self._cparser.read(config_files)
except iniparser.ParseError as pe:
raiseConfigFileParseError(pe.filename, str(pe))
if read_ok != config_files:
not_read_ok = filter(lambda f: f not in read_ok,config_files)
raiseConfigFilesNotFoundError
(not_read_ok)
构造函数,在初始化对象时,注册了几个Opt对象:-d\-v\--log-config\--log-format\--log-date-format\--log-file\--log-dir\--use-syslog\--syslog-log-facility。这样就可以通过命令行参数对这些配置项进行设置。
def _do_get(self, name, group=None):
if group is None and name in self._groups:
returnself.GroupAttr(self, self._get_group(name))
#首先要获取该对象的注册信息,所以使用前必须先注册
info = self._get_opt_info(name, group)
opt = info['opt']
if 'override' in info:
returninfo['override']
values = []
if self._cparser is not None:
section =group.name if group is not None else 'DEFAULT'
try:
value =opt._get_from_config_parser(self._cparser, section)
exceptKeyError:
pass
exceptValueError as ve:
raiseConfigFileValueError(str(ve))
else:
if not opt.multi:
# No need to continue since the last valuewins
return value[-1]
values.extend(value)
name = name if group is None else group.name +'_' + name
value = self._cli_values.get(name)
if value is not None:
if notopt.multi:
return value
returnvalue + values
if values:
returnvalues
if 'default' in info:
returninfo['default']
cfg.StrOpt('instances_path',
default='$state_path/instances',
help='where instances arestored on disk'),
cfg.IntOpt('live_migration_retry_count',
default=30,
help="Number of 1 secondretries needed in live_migration"),
live_migration_retry_count
"""Int opt values areconverted to integers using the int() builtin."""
def_get_from_config_parser(self, cparser, section):
"""Retrieve the opt value as a integer fromConfigParser."""
return [int(v) for v inself._cparser_get_with_deprecated(cparser,
section)]
def_get_optparse_kwargs(self, group, **kwargs):
"""Extends the base optparse keyword dict forinteger options."""
return super(IntOpt,
self)._get_optparse_kwargs(group, type='int',**kwargs)
nova读取配置文件流程的更多相关文章
- SparkStreaming动态读取配置文件
SparkStreaming动态读取配置文件 标签: SparkStreaming HDFS 配置文件 MySql 需求 要实现SparkStreaming在流处理过程中能动态的获取到配置文件的改变 ...
- Spring读取配置文件 @Value
最近在学习Spring如何读取配置文件,记录下方便自己也方便别人: 大致分为两类吧,一种的思路是利用Spring的beanFactoryPostProcessor读取配置文件内容到内存中,也就是应用程 ...
- SpringBoot读取配置文件源码探究
1. SpringBoot读取配置文件源码探究 1.1. 概览 springboot的源码是再原来的Spring源码上又包了一层,看过spring源码都知道,当我们从入口debug进去的时候,原来的S ...
- 【无私分享:ASP.NET CORE 项目实战(第八章)】读取配置文件(二) 读取自定义配置文件
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 我们在 读取配置文件(一) appsettings.json 中介绍了,如何读取appsettings.json. 但随之产生 ...
- 解决IntelliJ IDEA无法读取配置文件的问题
解决IntelliJ IDEA无法读取配置文件的问题 最近在学Mybatis,按照视频的讲解在项目的某个包里建立配置文件,然后读取配置文件,但是一直提示异常. 读取配置文件的为官方代码: String ...
- java-工具类-读取配置文件
java读取配置文件,当发现文件被修改后则重新加载 package com.zg.config; import java.io.File; import java.io.FileInputStream ...
- java 4种方式读取配置文件 + 修改配置文件
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 方式一采用ServletContext读取读取配置文件的realpath然后通过文件流读取出来 方式二采用ResourceB ...
- 在IIS Express中调试时无法读取配置文件 错误
在IIS Express中调试代码时,如果出现"无法读取配置文件"的问题(如图),这种情况是IIS Express的"applicationhost.config&quo ...
- ASP.NET Core开发-读取配置文件Configuration
ASP.NET Core 是如何读取配置文件,今天我们来学习. ASP.NET Core的配置系统已经和之前版本的ASP.NET有所不同了,之前是依赖于System.Configuration和XML ...
随机推荐
- android开发 drawtext的开始坐标位置
我们canvas绘制文字的遇到一个不知道drawtext(str,x,y,paint) 中的x.y坐标值怎么定义,,如果设为(0,0)的话文字就不会出来了.因此查找到一下资料: 问:canvas.d ...
- 在ubuntu上搭建reviewboard
review board 2.0.5 ubuntu ubuntu-12.04.1-desktop-amd64 基本上基于这个教程:http://alephnullplex.appspot.com/bl ...
- Codeforces Round #354 (Div. 2) D. Theseus and labyrinth
题目链接: http://codeforces.com/contest/676/problem/D 题意: 如果两个相邻的格子都有对应朝向的门,则可以从一个格子到另一个格子,给你初始坐标xt,yt,终 ...
- 【转载】《Ext JS 4 First Look》翻译之一:新特性
免责声明: 本文转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除. 原文作者:^_^肥仔John 原文地址:http://www.cnblogs. ...
- Fiddler 过滤 css,图片等请求url 正则表达式
设置步骤: 1.勾选 Request Headers 中的 Hide if url contains 过滤项 2.贴入下方正则表达式 REGEX:(?insx)/[^?/]*.(css|ico|jpg ...
- org.apache.kafka.common.network.Selector
org.apache.kafka.common.client.Selector实现了Selectable接口,用于提供符合Kafka网络通讯特点的异步的.非阻塞的.面向多个连接的网络I/O. 这些网络 ...
- 怎样把网站js文件合并成一个?几种方法可以实现
我们在建网站时经常会用js特效代码以使页面更美观,比如js幻灯片代码.js下拉菜单等,但是网页特效一多,如果js文件没有合并的话会降低网站的性能,这时我们就要考虑合并js文件了,ytkah总结了以下几 ...
- nginx js、css多个请求合并为一个请求(concat模块)
模块介绍 mod_concat模块由淘宝开发,目前已经包含在tengine中,并且淘宝已经在使用这个nginx模块.不过塔暂时没有包含在nginx中.这个模块类似于apache中的modconcat. ...
- mouseover与mouseenter的区别
mouseenter事件在鼠标进入某个元素,或第一次进入这个元素的某个子元素时触发.一旦触发后,在mouseleave之前,鼠标在这个元素的子元素上触发mouseenter事件都不会触发这个元素的mo ...
- 直面Javascript面试题算法思路
一.字符串遍历类 1.获取符合条件的字符 思路:一般使用正则表达式会比遍历字符串简单.a=str.match(reg),a即为所得. 例子:a.判断字符串是否是这样组成的,第一个必须是字母,后面可以是 ...