本文简单阐述一下如何在本地搭建一个Chef( Chef是什么? )的开发环境。
想达到的效果
- 开发的过程一定是尝试、失败、回滚的过程,快照功能必不可少
- 使用chef-solo运行,直接使用开发代码,而不必将代码提交到chef server。连chef-solo的配置都应该是本地的。
- 不必进入到虚拟机去触发测试,这样不方便,要支持本地一条命令就触发测试
- 这个方案要支持多种操作系统
思路
- 命令:使用 rake
- 远程触发:使用Telnet.可以跨平台
- 访问本地代码:使用VirtualBox的shared folder
- 快照功能: 使用VirtualBox的快照功能
方案
结构图如下:
- Test VM需要安装chef-client和Telnet Server.
- 开发目录如下
- 将当前开发目录设置成VirtualBox的shared folder
- Telnet上VM,使用net use(windows)或mount 挂载shared folder
- 还是Telnet,触发chef-solo。假设挂载到z:盘,那么运行
chef-solo -c z:/config/test_solo.rb -j z:/conifg/test_node
当然,以上的后4步一定是自动完成。因为chef代码是ruby写的,当然很自然,我们可以使用rake来开发这些命令。这是我开发的一些Task
rake check_cookbook[cookbook_name] # Check cookbook syntax in local
rake create_cookbook[cookbook_name] # Create new cookbook in local
rake delete_snapshot[name] # Vbox snapshot delete
rake down # Vm poweroff
rake list_snapshots # Vbox snapshot list
rake restore_snapshot[name] # Vbox snapshot restore
rake restore_to[snapshot_name] # Restore specific snapshot,start
rake take_snapshot[name] # Vbox snapshot take
rake test # Test cookbook.
rake test_from[snapshot_name] # Restore specific snapshot,start and ...
rake up # Vm start
关键步骤实现
虚拟机管理-快照恢复
desc "Restore specific snapshot,start"
task :restore_to,:snapshot_name do |t,args|
Rake::Task["down"].invoke
Rake::Task["restore_snapshot"].invoke(args.snapshot_name)
Rake::Task["up"].invoke
end
desc "Vm start"
task :up do |t|
vbox_command("startvm #{test_config.test_vm} --type gui")
puts 'waiting for vm started'
sleep(5) while not is_vm_started? test_config
puts "vm #{test_config.test_vm} started"
end
desc "Vm poweroff "
task :down do |t|
vbox_command("controlvm #{test_config.test_vm} poweroff")
sleep(5)
end
desc "Vbox snapshot restore"
task :restore_snapshot,:name do |t,args|
vbox_command("snapshot #{test_config.test_vm} restore \"#{args.name}\"")
end
def vbox_command(vboxCmd,display_result=true)
cmd="VBoxManage #{vboxCmd}"
puts "[execute] #{cmd}"
result=`#{cmd}`
puts result if display_result
result
end
触发测试
def windows_test(test_config)
telnet=os_telnet(test_config)
begin
out = lambda do |c| print c end
telnet.login(test_config.telnet_user,test_config.telnet_password,&out)
telnet.cmd("tlntadmn config timeoutactive=no",&out)
telnet.cmd("net use z: \\\\vboxsvr\\#{test_config.shared_folder_name}", &out)
telnet.cmd("set HTTP_PROXY=#{test_config.http_proxy}", &out) if test_config.http_proxy
telnet.cmd("set HTTPS_PROXY=#{test_config.https_proxy}", &out) if test_config.https_proxy
telnet.cmd("String"=>"cmd.exe /K chef-solo -c z:\\config\\test_solo.rb -j z:\\config\\test_node.json","Timeout"=>false,&out)
telnet.cmd("exit",&out)
ensure
telnet.close
end
end
def os_telnet(test_config)
if test_config.windows?
Net::Telnet::new("Host"=>"127.0.0.1","Port"=>test_config.telnet_port,"Prompt"=> /.:.*>/)
else
Net::Telnet::new("Host"=>"127.0.0.1","Port"=>test_config.telnet_port)
end
end
其他
ruby的Telnet库连接windows有问题,需要打一个猴子补丁。详细见我的帖子:http://ruby-china.org/topics/10774