问题描述
为了让Ambari支持内网安装HDP集群,我们通常会修改repoinfo.xml
(位于/var/lib/ambari-server/resources/stacks/HDP/[stack版本]/repos
)。如下图所示:
<reposinfo>
<!--
<latest>http://public-repo-1.hortonworks.com/HDP/hdp_urlinfo.json</latest>
-->
<latest>./hdp_urlinfo.json</latest>
<!-- 其余省略 -->
</reposinfo>
我们将latest
标签外网URL替换为一个保存在本地的json文件。该json文件是一个自己编写的版本描述文件,指定了具体组件版本描述xml文件的位置。
但在实际内网上机安装的时候发现如下问题:Ambari server安装执行ambari-server setup
的时候,会自动把HDP stack对应的repoinfo.xml
文件的latest标签内容修改为hdp官网相关链接,导致组件版本信息在内网环境无法获取。即使是再次手工将repoinfo.xml
文件的latest标签修改回来也无济于事,执行ambari-server setup
还是会自动修改为官网地址。
追溯根因
一时半会儿没有头绪,干脆从源代码入手。跟踪ambari-server setup
时候执行的源码serverSetup.py
,约1219行,会找到如下所示片段:
json_url = get_json_url_from_repo_file()
if json_url:
print "Ambari repo file contains latest json url {0}, updating stacks repoinfos with it...".format(json_url)
properties = get_ambari_properties()
stack_root = get_stack_location(properties)
update_latest_in_repoinfos_for_stacks(stack_root, json_url)
else:
print "Ambari repo file doesn't contain latest json url, skipping repoinfos modification"
这段代码的含义是如果get_json_url_from_repo_file()
函数获取到了json_url,会执行latest标签内容替换操作。
跟踪update_latest_in_repoinfos_for_stacks
方法代码,如下所示:
# Go though all stacks and update the repoinfo.xml files
# replace <latest> tag with the passed url
def update_latest_in_repoinfos_for_stacks(stacks_root, json_url_string, predicate=lambda stack_name: stack_name == 'HDP'):
for stack_name in os.walk(stacks_root).next()[1]:
if predicate(stack_name):
for stack_version in os.walk(os.path.join(stacks_root, stack_name)).next()[1]:
repoinfo_xml_path = os.path.join(stacks_root, stack_name, stack_version, "repos", "repoinfo.xml")
if os.path.exists(repoinfo_xml_path):
replace_latest(repoinfo_xml_path, json_url_string)
这段逻辑大意为如果HDP stack的目录结构中存在repoinfo.xml
,执行replace_latest
方法,替换latest标签的内容为json_url_string
变量。
replace_latest
方法:
# replace <latest> tag in the file with the passed url
def replace_latest(repoinfo_xml_path, json_url_string):
tree = ET.parse(repoinfo_xml_path)
root = tree.getroot()
latest_tag = root.find("latest")
if latest_tag is not None:
latest_tag.text = json_url_string
with open(repoinfo_xml_path, "w") as out:
out.write(XML_HEADER)
tree.write(out)
到此为止,我们已经定位到了引起问题的外层调用了。现在需要看下它是怎么获取json_url
的。
我们查看get_json_url_from_repo_file
方法内容。如下所示:
# parse ambari repo file and get the value of '#json.url = http://...'
def get_json_url_from_repo_file():
# 获取repo_file的路径全名
repo_file_path = get_ambari_repo_file_full_name()
if os.path.exists(repo_file_path):
with open(repo_file_path, 'r') as repo_file:
for line in repo_file:
line = line.rstrip()
# 如果找到json.url一行,返回这一行等号后的内容
if "json.url" in line:
json_url_string = line.split("=", 1)[1].strip()
return json_url_string
return None
上面的主要逻辑是解析repo_file
,找到json.url
配置项并返回它的值。
接来下的问题是,这个repo_file
在哪里呢?
我们查看get_ambari_repo_file_full_name
方法内容:
# Gets the full path of the ambari repo file for the current OS
def get_ambari_repo_file_full_name():
if OSCheck.is_ubuntu_family():
ambari_repo_file = "/etc/apt/sources.list.d/ambari.list"
elif OSCheck.is_redhat_family():
ambari_repo_file = "/etc/yum.repos.d/ambari.repo"
elif OSCheck.is_suse_family():
ambari_repo_file = "/etc/zypp/repos.d/ambari.repo"
elif OSCheck.is_windows_family():
ambari_repo_file = os.path.join(os.environ[ChocolateyConsts.CHOCOLATEY_INSTALL_VAR_NAME],
ChocolateyConsts.CHOCOLATEY_CONFIG_DIR, ChocolateyConsts.CHOCOLATEY_CONFIG_FILENAME)
else:
raise Exception('Ambari repo file path not set for current OS.')
return ambari_repo_file
到这里就真相大白了,原来ambari找的是Linux系统的软件源配置文件。根据操作系统发行版查找对应的配置文件。
我们出现问题的是CentOS系统,综合这两个方法我们发现,在CentOS中ambari会读取/etc/yum.repos.d/ambari.repo
文件,找到json.url
这一行,获取它的值,替换为repoinfo.xml
的latest
标签的内容。
现在就差最后一步,找到“罪魁祸首”。
我们查看服务器的/etc/yum.repos.d/ambari.repo
文件,发现如下配置:
[root@manager ~]# cat /etc/yum.repos.d/ambari.repo
#VERSION_NUMBER=2.7.1.0-169
[ambari-2.7.1.0]
#json.url = http://public-repo-1.hortonworks.com/HDP/hdp_urlinfo.json
name=ambari
baseurl=http://xxx.xxxx.xxx/xxx/manager/
gpgcheck=0
enabled=1
priority=1
注意被注释掉的json.url这一行,尽管是被注释掉的,但是根据上面分析,ambari在解析的时候没有考虑到注释。即注释掉也会被解析。
我们被注释的假象蒙骗了,Ambari解析的时候完全不理会这一行开头是否是#
号。我们把json.url
这一行删除,还原repoinfo.xml
之后再重新执行ambari-server setup
。问题完美解决。
网友评论