Skip to content

Commit c9ecced

Browse files
dougmdanielsdeleo
authored andcommitted
[CHEF-1569] add knife 'windows bootstrap' subcommand
1 parent e3fa822 commit c9ecced

1 file changed

Lines changed: 150 additions & 0 deletions

File tree

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#
2+
# Author:: Doug MacEachern <dougm@vmware.com>
3+
# Copyright:: Copyright (c) 2010 VMware, Inc.
4+
# License:: Apache License, Version 2.0
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
require 'fileutils'
20+
require 'chef/knife/bootstrap.rb'
21+
22+
class Chef
23+
class Knife
24+
class WindowsBootstrap < Chef::Knife::Bootstrap
25+
26+
banner "knife windows bootstrap FQDN [RUN LIST...] (options)"
27+
28+
option :user,
29+
:short => "-x USERNAME",
30+
:long => "--user USERNAME",
31+
:description => "The Windows username"
32+
33+
option :password,
34+
:short => "-P PASSWORD",
35+
:long => "--password PASSWORD",
36+
:description => "The Windows password"
37+
38+
option :chef_node_name,
39+
:short => "-N NAME",
40+
:long => "--node-name NAME",
41+
:description => "The Chef node name for your new node"
42+
43+
option :distro,
44+
:short => "-d DISTRO",
45+
:long => "--distro DISTRO",
46+
:description => "Bootstrap a distro using a template",
47+
:default => "windows-gems"
48+
49+
option :template_file,
50+
:long => "--template-file TEMPLATE",
51+
:description => "Full path to location of template to use",
52+
:default => false
53+
54+
option :run_list,
55+
:short => "-r RUN_LIST",
56+
:long => "--run-list RUN_LIST",
57+
:description => "Comma separated list of roles/recipes to apply",
58+
:proc => lambda { |o| o.split(",") },
59+
:default => []
60+
61+
def is_mounted
62+
@net_use ||= Chef::Util::Windows::NetUse.new(@admin_share)
63+
begin
64+
@net_use.get_info
65+
return true
66+
rescue
67+
return false
68+
end
69+
end
70+
71+
def mount_admin_share
72+
if @add_mount && !is_mounted
73+
use = {
74+
:remote => @admin_share, :local => '',
75+
:username => config[:user], :password => config[:password]
76+
}
77+
@net_use.add(use)
78+
if is_mounted
79+
Chef::Log.info("Mounted #{@admin_share} for copying files")
80+
else
81+
Chef::Log.fatal("Failed to mount #{@admin_share}")
82+
exit 1
83+
end
84+
end
85+
end
86+
87+
def unmount_admin_share
88+
if @add_mount && is_mounted
89+
Chef::Log.debug("Unmounting #{@admin_share}")
90+
@net_use.delete
91+
end
92+
end
93+
94+
def psexec(args)
95+
cmd = ['psexec', @unc_path, "-w", 'c:\chef']
96+
if config[:user]
97+
cmd << "-u" << config[:user]
98+
end
99+
if config[:password]
100+
cmd << "-p" << config[:password]
101+
end
102+
cmd << args
103+
cmd = cmd.join(' ')
104+
Chef::Log.debug("system #{cmd}")
105+
system(cmd)
106+
end
107+
108+
def run
109+
require 'chef/util/windows/net_use'
110+
111+
if @name_args.first == nil
112+
Chef::Log.error("Must pass a node name/ip to windows bootstrap")
113+
exit 1
114+
end
115+
116+
config[:server_name] = @name_args.first
117+
if Chef::Config[:http_proxy]
118+
uri = URI.parse(Chef::Config[:http_proxy])
119+
config[:proxy] = "#{uri.host}:#{uri.port}"
120+
end
121+
122+
@unc_path = "\\\\#{config[:server_name]}"
123+
@admin_share = "#{@unc_path}\\c$"
124+
path = "#{@admin_share}\\chef"
125+
126+
$stdout.sync = true
127+
128+
command = render_template(load_template(config[:bootstrap_template]))
129+
130+
Chef::Log.info("Bootstrapping Chef on #{config[:server_name]}")
131+
132+
@add_mount = config[:user] != nil && !is_mounted
133+
mount_admin_share
134+
135+
begin
136+
unless File.exists?(path)
137+
Chef::Log.debug("mkdir #{path}")
138+
FileUtils.mkdir(path)
139+
end
140+
File.open("#{path}\\bootstrap.bat", 'w') {|f| f.write(command) }
141+
FileUtils.cp(File.join(File.dirname(__FILE__), 'bootstrap', 'client-install.vbs'), path)
142+
FileUtils.cp(Chef::Config[:validation_key], path)
143+
psexec("cmd.exe /c bootstrap.bat")
144+
ensure
145+
unmount_admin_share
146+
end
147+
end
148+
end
149+
end
150+
end

0 commit comments

Comments
 (0)