python的mako、jinja2模板庫,確實好用!這里做個筆記,好記性不如爛筆頭。
#!/usr/bin/env?python
#encoding=utf-8
import?sys,yaml???????????????????????#?配置文件使用yaml格式
from?mako.template?import?Template??????#?加載mako庫的Template?Class
from?jinja2?import?Environment,FileSystemLoader??#?加載jinja2的Environment,FileSystemLoader?Class
'''
解析配置文件,返回值是一個dict
'''def?parse_pxe_config(filename):
config?=?yaml.load(file(filename,'r'))
return?config
'''
這個函數實現的功能
舉例來說,掩碼前綴為27轉換為255.255.255.224
'''def?int2mask(mask_str):
mask_int?=?int(mask_str)
mask_array?=?['0'?for?i?in?xrange(32)]???#?python?for循環,吊吧!一口氣生成32個list的元素
for?i?in?xrange(mask_int):
mask_array[i]?=?'1'
temp_mask?=?[''.join(mask_array[i*8:(i+1)*8])?for?i?in?xrange(4)]???#?每8位組成一個list元素
temp_mask?=?[str(int(i,2))?for?i?in?temp_mask]????#?int(i,2)?二進制轉換為十進制
return?'.'.join(temp_mask)
'''
根據網關地址和掩碼前綴得到管理網網段
'''def?get_manage_net(gateway,prefix_str):
prefix?=?int(prefix_str)
int2bin?=?[bin(int(i,10)).split('0b')[1]?for?i?in?gateway.split('.')]???#?bin(int(i,10))?十進制轉化為二進制
for?i?in?xrange(4):
if?len(int2bin[i])?
int2bin[i]?=?'0'*(8?-?len(int2bin[i]))?+?int2bin[i]
int2bin?=?''.join(int2bin)
int2bin?=?int2bin[0:prefix]+'0'*(32-prefix)
int2bin_list?=?[int2bin[8*i:(i+1)*8]?for?i?in?xrange(4)]
manage_net?=?[str(int(i,2))?for?i?in?int2bin_list]
return?'.'.join(manage_net)
'''
利用python模板庫渲染配置文件
'''def?create_pxe_config(config):
#??讀取配置文件中的配置項
system_common?=?config['system?common']
manage_prefix?=?system_common['manage_prefix']
manage_gateway?=?system_common['manage_gateway']
manage_mask?=?int2mask(manage_prefix)
manage_net?=?get_manage_net(manage_gateway,manage_prefix)
dns?=?system_common['dns']
fqdn?=?system_common['fqdn']
repo_url?=?system_common['repo_url']
password?=?system_common['password']
manage_nic?=?system_common['manage_nic']
storage_nic?=?system_common['storage_nic']
public_nic?=?system_common['public_nic']
data_nic?=?system_common['data_nic']
deploy_node?=?config['deploy?node']
deploy_node_ip?=?deploy_node['ip']
deploy_node_hostname?=?deploy_node['hostname']
dhcp_range_start?=?deploy_node['dhcp_range_start']
dhcp_range_end?=?deploy_node['dhcp_range_end']
compute_node?=?config['compute?node']
dhcp_template?=?Template(?????????????????????????????????????????#?創建一個Template對象
filename='./pxe_template/dhcpd.conf',
module_directory='/tmp/mako_modules'??????#?為了提高性能,從文件加載的?Template?還可以在文件系統中將生成的模塊緩存為一般的Python模塊文件,
)?????????????????????????????????????????#?下次同樣參數的Template?創建時,自動重用/tmp/mako_modules/目錄下的模塊文件。
dhcp_content?=?dhcp_template.render(??????????????????????????????#?傳給?Template?的文本參數被編譯為一個Python模塊。模塊包含一個?render_body()?函數,它產生模板的輸出。
manage_gateway?=?manage_gateway,??????????#?調用render()?方法時,Mako建立了一個模板的運行環境,并調用?render_body()?函數,把輸出保存到緩沖,返回它的字符串內容
dns?=?dns,
manage_mask?=?manage_mask,
fqdn?=?fqdn,
deploy_node_ip?=?deploy_node_ip,
manage_net?=?manage_net,
dhcp_range_start?=?dhcp_range_start,
dhcp_range_end?=?dhcp_range_end
)
fp?=?open('./pxe_config/dhcpd.conf','w')?????#?生成dhcpd.conf配置文件
fp.write(dhcp_content)
if?fp?!=?None:
fp.close()
ip_mac_template?=?Template(?????????????????????????????????????????#?ip-mac?綁定
filename='./pxe_template/ip_mac.conf',
module_directory='/tmp/mako_modules'
)
for?compute?in?compute_node:
ip_mac_content?=?ip_mac_template.render(
compute_hostname?=?compute['hostname'],
manage_mac?=?compute['manage_mac'],
manage_ip?=?compute['manage_ip']
)
fp?=?open('./pxe_config/dhcpd.conf','a')??????????????????????#?以append方式打開文件
fp.write('\n'+ip_mac_content)?????????????????????????????????#?追加內容
env?=?Environment(
loader?=?FileSystemLoader('./pxe_template')??????????#?這個類的實例被用于存儲配置信息,?全局對象,?從文件系統或其他位置加載模板,使用的加載器loader是FileSystemLoader類型,
)????????????????????????????????????????????????#?可以加載的模板是當前工作目錄下的templates目錄下的模板文件
ks_template?=?env.get_template("puppet.cfg")?????????????????????#?使用env的模板環境加載名為puppet.cfg的模板文件.
ks_content?=?ks_template.render(?????????????????????????????????#?渲染模板template
repo_url?=?repo_url,
password?=?password,
deploy_node_hostname?=?deploy_node_hostname,
fqdn?=?fqdn,
deploy_node_ip?=?deploy_node_ip,
public_nic?=?public_nic,
storage_nic?=?storage_nic,
data_nic?=?data_nic,
manage_gateway?=?manage_gateway,
manage_mask?=?manage_mask
)
fp?=?file('./pxe_config/puppet.cfg','w')
fp.write(ks_content)
if?fp?!=?None:
fp.close()if?__name__?==?'__main__':
if?len(sys.argv)?!=?2?or?sys.argv[1]?!=?'config.yaml':
print?"Usage:pxe-init.py?config.yaml"
sys.exit(-1)
config?=?parse_pxe_config(sys.argv[1])
create_pxe_config(config)
針對上面代碼的改良版,寫的不好的地方,歡迎大家指出!#!/usr/bin/env?python
#encoding=utf-8
import?sys,yaml
import?subprocess?????????????????????????????????#?用來創建一個子進程
from?jinja2?import?Environment,FileSystemLoader???#?統一使用jinja2模板
env?=?Environment(
loader?=?FileSystemLoader('./pxe_template')???#?env設為全局變量
)
def?parse_pxe_config(filename):
config?=?yaml.load(file(filename,'r'))
return?config
'''
'1'*4?==?'1111'
int('111',2)?==?7?二進制轉換十進制
從<
'''
def?int2mask(prefix):
return?'.'.join(str(int(('1'*(int(prefix))+'0'?\
*(32-int(prefix)))[i*8:(i+1)*8],2))?\
for?i?in?xrange(4))
'''
使用zip對兩個list同時遍歷,然后對各個元素進行&運算
192???168??2??????254
255???255??255??224
不知道通過ip和mask計算網絡號,google下!
'''
def?get_manage_net(gateway,prefix_str):
mask?=?int2mask(int(prefix_str))
return?'.'.join(str(int(m)?&?int(n))?\
for?m,n?in?zip(gateway.split('.'),mask.split('.')))
'''
模板渲染抽象為一個函數
渲染的時候可以傳進一個dict搞定,dict的key要和模板中的變量名對應(我老大實驗得到的)
'''
def?create_config_template(tem_name,tem_dict):
template?=?env.get_template(tem_name)
content?=?template.render(tem_dict)
return?content
'''
創建配置文件
'''
def?create_config_file(config_name,content,mode):
try:
fp?=?open(config_name,mode)
fp.write(content+'\n')
except?IOError:
print?"Error:?can\'t?find?file?or?read?data"
else:
fp.close()
'''
這部分內容比上面的搜身了不少吧,當然還有很多地方要改進的!
'''
def?create_pxe_config(config):
system_common?=?config.get('system?common')???????????#?字典使用get方法獲取key對應的value,如果key不存在,返回None。比config['system?common']友好多了。
manage_prefix?=?system_common.get('manage_prefix')
manage_gateway?=?system_common.get('manage_gateway')
manage_mask?=?int2mask(manage_prefix)
manage_net?=?get_manage_net(manage_gateway,manage_prefix)
deploy_node?=?config.get('deploy?node')
deploy_node['manage_gateway']?=?manage_gateway
deploy_node['manage_mask']?=?manage_mask
deploy_node['manage_net']?=?manage_net
dhcp_content?=?create_config_template('dhcpd.conf',deploy_node)
create_config_file('./pxe_config/dhcpd.conf',dhcp_content,'w')
compute_node?=?config['compute?node']
for?compute_name,compute_info?in?compute_node.items():
ip_mac_content?=?create_config_template("ip_mac.conf",compute_info)
create_config_file('./pxe_config/dhcpd.conf',ip_mac_content,'a')
subprocess.Popen('service?dhcpd?restart',shell?=?True)?????????????????#?開了子進程來重啟dhcpd服務,好讓修改的dhcp配置生效
deploy_node.update(system_common)
ks_content?=?create_config_template('puppet.cfg',deploy_node)
create_config_file('./pxe_config/puppet.cfg',ks_content,'w')
pxe_default_content?=?create_config_template('default',system_common)
create_config_file('./pxe_config/default',pxe_default_content,'w')
'''
這部分不變
'''
if?__name__?==?'__main__':
if?len(sys.argv)?!=?2?or?sys.argv[1]?!=?'config.yaml':
print?"Usage:pxe-init.py?config.yaml"
sys.exit(-1)
config?=?parse_pxe_config(sys.argv[1])
create_pxe_config(config)
參考鏈接