source: trunk/server/source4/selftest/win/VMHost.pm

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 9.0 KB
Line 
1#!/usr/bin/perl -w
2
3# A perl object to provide a simple, unified method of handling some
4# VMware Server VM management functions using the perl and VIX API's.
5# Copyright Brad Henry <brad@samba.org> 2006
6# Released under the GNU GPL version 3 or later.
7
8# VMware Perl API
9use VMware::VmPerl;
10use VMware::VmPerl::VM;
11use VMware::VmPerl::ConnectParams;
12
13# VMware C bindings
14use VMware::Vix::Simple;
15use VMware::Vix::API::Constants;
16
17# Create a class to abstract from the Vix and VMPerl APIs.
18{ package VMHost;
19 my $perl_vm = VMware::VmPerl::VM::new();
20 my $perl_vm_credentials;
21 my $vix_vm;
22 my $vix_vm_host;
23
24 my $err_code = 0;
25 my $err_str = "";
26
27 my $hostname;
28 my $port;
29 my $username;
30 my $password;
31 my $vm_cfg_path;
32 my $guest_admin_username;
33 my $guest_admin_password;
34
35 sub error {
36 my $old_err_code = $err_code;
37 my $old_err_str = $err_str;
38 $err_code = 0;
39 $err_str = "";
40 return ($old_err_code, $old_err_str);
41 }
42
43 # Power on the guest if it isn't already running.
44 # Returns 0 when the guest is already running, and
45 # if not, it waits until it is started.
46 sub start_guest {
47 my $vm_power_state = $perl_vm->get_execution_state();
48 if (!defined($vm_power_state)) {
49 ($err_code, $err_str) = $perl_vm->get_last_error();
50 return ($err_code);
51 }
52 if ($vm_power_state == VMware::VmPerl::VM_EXECUTION_STATE_OFF
53 || $vm_power_state ==
54 VMware::VmPerl::VM_EXECUTION_STATE_SUSPENDED)
55 {
56 if (!$perl_vm->start()) {
57 ($err_code, $err_str) =
58 $perl_vm->get_last_error();
59 return ($err_code);
60 }
61 while ($perl_vm->get_tools_last_active() == 0) {
62 sleep(60);
63 }
64 }
65 return ($err_code);
66 }
67
68 sub host_connect {
69 # When called as a method, the first parameter passed is the
70 # name of the method. Called locally, this function will lose
71 # the first parameter.
72 shift @_;
73 ($hostname, $port, $username, $password, $vm_cfg_path,
74 $guest_admin_username, $guest_admin_password) = @_;
75
76 # Connect to host using vmperl api.
77 $perl_vm_credentials =
78 VMware::VmPerl::ConnectParams::new($hostname, $port,
79 $username, $password);
80 if (!$perl_vm->connect($perl_vm_credentials, $vm_cfg_path)) {
81 ($err_code, $err_str) = $perl_vm->get_last_error();
82 undef $perl_vm;
83 return ($err_code);
84 }
85
86 # Connect to host using vix api.
87 ($err_code, $vix_vm_host) =
88 VMware::Vix::Simple::HostConnect(
89 VMware::Vix::Simple::VIX_API_VERSION,
90 VMware::Vix::Simple::VIX_SERVICEPROVIDER_VMWARE_SERVER,
91 $hostname, $port, $username, $password,
92 0, VMware::Vix::Simple::VIX_INVALID_HANDLE);
93 if ($err_code != VMware::Vix::Simple::VIX_OK) {
94 $err_str =
95 VMware::Vix::Simple::GetErrorText($err_code);
96 undef $perl_vm;
97 undef $vix_vm;
98 undef $vix_vm_host;
99 return ($err_code);
100 }
101
102 # Power on our guest os if it isn't already running.
103 $err_code = start_guest();
104 if ($err_code != 0) {
105 my $old_err_str = $err_str;
106 $err_str = "Starting guest power after connect " .
107 "failed: " . $old_err_str;
108 undef $perl_vm;
109 undef $vix_vm;
110 undef $vix_vm_host;
111 return ($err_code);
112 }
113
114 # Open VM.
115 ($err_code, $vix_vm) =
116 VMware::Vix::Simple::VMOpen($vix_vm_host, $vm_cfg_path);
117 if ($err_code != VMware::Vix::Simple::VIX_OK) {
118 $err_str =
119 VMware::Vix::Simple::GetErrorText($err_code);
120 undef $perl_vm;
121 undef $vix_vm;
122 undef $vix_vm_host;
123 return ($err_code);
124 }
125
126 # Login to $vix_vm guest OS.
127 $err_code = VMware::Vix::Simple::VMLoginInGuest($vix_vm,
128 $guest_admin_username, $guest_admin_password,
129 0);
130 if ($err_code != VMware::Vix::Simple::VIX_OK) {
131 $err_str =
132 VMware::Vix::Simple::GetErrorText($err_code);
133 undef $perl_vm;
134 undef $vix_vm;
135 undef $vix_vm_host;
136 return ($err_code);
137 }
138 return ($err_code);
139 }
140
141 sub host_disconnect {
142 undef $perl_vm;
143
144 $perl_vm = VMware::VmPerl::VM::new();
145 if (!$perl_vm) {
146 $err_code = 1;
147 $err_str = "Error creating new VmPerl object";
148 }
149
150 undef $vix_vm;
151 VMware::Vix::Simple::HostDisconnect($vix_vm_host);
152 VMware::Vix::Simple::ReleaseHandle($vix_vm_host);
153 return ($err_code);
154 }
155
156 sub host_reconnect {
157 $err_code = host_disconnect();
158 if ($err_code != 0) {
159 my $old_err_str = $err_str;
160 $err_str = "Disconnecting from host failed: " .
161 $old_err_str;
162 return ($err_code);
163 }
164
165 $err_code = host_connect(NULL, $hostname, $port, $username,
166 $password, $vm_cfg_path, $guest_admin_username,
167 $guest_admin_password);
168 if ($err_code != 0) {
169 my $old_err_str = $err_str;
170 $err_str = "Re-connecting to host failed: " .
171 $old_err_str;
172 return ($err_code);
173 }
174 return ($err_code);
175 }
176
177 sub create_snapshot {
178 my $snapshot;
179
180 ($err_code, $snapshot) =
181 VMware::Vix::Simple::VMCreateSnapshot($vix_vm,
182 "Snapshot", "Created by vm_setup.pl", 0,
183 VMware::Vix::Simple::VIX_INVALID_HANDLE);
184
185 VMware::Vix::Simple::ReleaseHandle($snapshot);
186
187 if ($err_code != VMware::Vix::Simple::VIX_OK) {
188 $err_str =
189 VMware::Vix::Simple::GetErrorText($err_code);
190 return $err_code;
191 }
192
193 $err_code = host_reconnect();
194 if ($err_code != 0) {
195 my $old_err_str = $err_str;
196 $err_str = "Reconnecting to host after creating " .
197 "snapshot: " . $old_err_str;
198 return ($err_code);
199 }
200 return ($err_code);
201 }
202
203 sub revert_snapshot {
204 # Because of problems with VMRevertToSnapshot(), we have to
205 # rely on the guest having set 'Revert to Snapshot' following
206 # a power-off event.
207 $err_code = VMware::Vix::Simple::VMPowerOff($vix_vm, 0);
208 if ($err_code != VMware::Vix::Simple::VIX_OK) {
209 $err_str =
210 VMware::Vix::Simple::GetErrorText($err_code);
211 return $err_code;
212 }
213
214 # host_reconnect() will power-on a guest in a non-running state.
215 $err_code = host_reconnect();
216 if ($err_code != 0) {
217 my $old_err_str = $err_str;
218 $err_str = "Reconnecting to host after reverting " .
219 "snapshot: " . $old_err_str;
220 return ($err_code);
221 }
222 return ($err_code);
223 }
224
225 # $dest_path must exist. It doesn't get created.
226 sub copy_files_to_guest {
227 shift @_;
228 my (%files) = @_;
229
230 my $src_file;
231 my $dest_file;
232
233 foreach $src_file (keys(%files)) {
234 $dest_file = $files{$src_file};
235 $err_code =
236 VMware::Vix::Simple::VMCopyFileFromHostToGuest(
237 $vix_vm, $src_file, $dest_file, 0,
238 VMware::Vix::Simple::VIX_INVALID_HANDLE);
239 if ($err_code != VMware::Vix::Simple::VIX_OK) {
240 $err_str = "Copying $src_file: " .
241 VMware::Vix::Simple::GetErrorText(
242 $err_code);
243 return $err_code;
244 }
245 }
246 return $err_code;
247 }
248
249 sub copy_to_guest {
250 # Read parameters $src_path, $dest_path.
251 shift @_;
252 my ($src_path, $dest_dir) = @_;
253
254 my $len = length($dest_dir);
255 my $idx = rindex($dest_dir, '\\');
256 if ($idx != ($len - 1)) {
257 $err_code = -1;
258 $err_str = "Destination $dest_dir must be a " .
259 "directory path";
260 return ($err_code);
261 }
262
263 # Create the directory $dest_path on the guest VM filesystem.
264 my $cmd = "cmd.exe ";
265 my $cmd_args = "/C MKDIR " . $dest_dir;
266 $err_code = run_on_guest(NULL, $cmd, $cmd_args);
267 if ( $err_code != 0) {
268 my $old_err_str = $err_str;
269 $err_str = "Creating directory $dest_dir on host: " .
270 $old_err_str;
271 return ($err_code);
272 }
273
274 # If $src_filepath specifies a file, create it in $dest_path
275 # and keep the same name.
276 # If $src_path is a directory, create the files it contains in
277 # $dest_path, keeping the same names.
278 $len = length($src_path);
279 my %files;
280 $idx = rindex($src_path, '/');
281 if ($idx == ($len - 1)) {
282 # $src_path is a directory.
283 if (!opendir (DIR_HANDLE, $src_path)) {
284 $err_code = -1;
285 $err_str = "Error opening directory $src_path";
286 return $err_code;
287 }
288
289 foreach $file (readdir DIR_HANDLE) {
290 my $src_file = $src_path . $file;
291
292 if (!opendir(DIR_HANDLE2, $src_file)) {
293 # We aren't interested in subdirs.
294 my $dest_path = $dest_dir . $file;
295 $files{$src_file} = $dest_path;
296 } else {
297 closedir(DIR_HANDLE2);
298 }
299 }
300 } else {
301 # Strip if preceeding path from $src_path.
302 my $src_file = substr($src_path, ($idx + 1), $len);
303 my $dest_path = $dest_dir . $src_file;
304
305 # Add $src_path => $dest_path to %files.
306 $files{$src_path} = $dest_path;
307 }
308
309 $err_code = copy_files_to_guest(NULL, %files);
310 if ($err_code != 0) {
311 my $old_err_str = $err_str;
312 $err_str = "Copying files to host after " .
313 "populating %files: " . $old_err_str;
314 return ($err_code);
315 }
316 return ($err_code);
317 }
318
319 sub run_on_guest {
320 # Read parameters $cmd, $cmd_args.
321 shift @_;
322 my ($cmd, $cmd_args) = @_;
323
324 $err_code = VMware::Vix::Simple::VMRunProgramInGuest($vix_vm,
325 $cmd, $cmd_args, 0,
326 VMware::Vix::Simple::VIX_INVALID_HANDLE);
327 if ($err_code != VMware::Vix::Simple::VIX_OK) {
328 $err_str = VMware::Vix::Simple::GetErrorText(
329 $err_code);
330 return ($err_code);
331 }
332
333 return ($err_code);
334 }
335
336 sub get_guest_ip {
337 my $guest_ip = $perl_vm->get_guest_info('ip');
338
339 if (!defined($guest_ip)) {
340 ($err_code, $err_str) = $perl_vm->get_last_error();
341 return NULL;
342 }
343
344 if (!($guest_ip)) {
345 $err_code = 1;
346 $err_str = "Guest did not set the 'ip' variable";
347 return NULL;
348 }
349 return $guest_ip;
350 }
351
352 sub DESTROY {
353 host_disconnect();
354 undef $perl_vm;
355 undef $vix_vm_host;
356 }
357}
358
359return TRUE;
Note: See TracBrowser for help on using the repository browser.