Initial commit: VMware vSphere API simulator scaffold.
Add the FastAPI app, PostgreSQL migrations, Docker/Helm packaging, API contracts, docs, client examples, and the unit/integration/compatibility test suite for local client and tooling labs without a real vCenter.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
use HTTP::Tiny;
|
||||
use JSON qw(decode_json encode_json);
|
||||
use MIME::Base64 qw(encode_base64);
|
||||
use Time::HiRes qw(sleep);
|
||||
|
||||
my $base = $ENV{VSPHERE_BASE} // 'https://localhost';
|
||||
my $user = $ENV{VSPHERE_USER} // 'administrator@vsphere.local';
|
||||
my $password = $ENV{VSPHERE_PASSWORD} // 'VMware1!';
|
||||
my $vm_name = $ENV{VSPHERE_VM_NAME} // 'perl-lab-01';
|
||||
|
||||
# Lab self-signed certificate only — do not disable verification against a real vCenter.
|
||||
my $http = HTTP::Tiny->new(timeout => 60, verify_SSL => 0);
|
||||
|
||||
sub api {
|
||||
my ($method, $path, %opts) = @_;
|
||||
my $res = $http->request($method, "$base$path", \%opts);
|
||||
die "$method $path failed: $res->{status} $res->{content}\n" unless $res->{success};
|
||||
return $res->{content};
|
||||
}
|
||||
|
||||
sub json_field {
|
||||
my ($body, $field) = @_;
|
||||
my $data = decode_json($body);
|
||||
return $data->{$field};
|
||||
}
|
||||
|
||||
sub wait_task {
|
||||
my ($task, $headers) = @_;
|
||||
return unless $task;
|
||||
my $deadline = time + 120;
|
||||
while (time < $deadline) {
|
||||
my $body = api('GET', "/api/cis/tasks/$task", headers => $headers);
|
||||
my $status = json_field($body, 'status');
|
||||
return if $status eq 'SUCCEEDED' || $status eq 'FAILED';
|
||||
sleep(0.3);
|
||||
}
|
||||
die "timeout waiting for task $task\n";
|
||||
}
|
||||
|
||||
my $auth = 'Basic ' . encode_base64("$user:$password", '');
|
||||
my $session_body = api('POST', '/api/session', headers => { Authorization => $auth });
|
||||
(my $session_id = $session_body) =~ s/^"(.*)"$/$1/;
|
||||
print "session: $session_id\n";
|
||||
|
||||
my %headers = ('vmware-api-session-id' => $session_id);
|
||||
|
||||
my $vms_before = api('GET', '/api/vcenter/vm', headers => \%headers);
|
||||
print 'vms before: ', scalar(@{ decode_json($vms_before) }), "\n";
|
||||
|
||||
my $create_body = encode_json({
|
||||
name => $vm_name,
|
||||
guest_OS => 'OTHER_GUEST_64',
|
||||
placement => {
|
||||
folder => 'group-v23',
|
||||
host => 'host-11',
|
||||
datastore => 'datastore-31',
|
||||
resource_pool => 'resgroup-22',
|
||||
},
|
||||
cpu => { count => 1 },
|
||||
memory => { size_MiB => 512 },
|
||||
});
|
||||
my $created = api(
|
||||
'POST', '/api/vcenter/vm',
|
||||
headers => { %headers, 'Content-Type' => 'application/json' },
|
||||
content => $create_body,
|
||||
);
|
||||
(my $moid = $created) =~ s/^"(.*)"$/$1/;
|
||||
print "created: $moid\n";
|
||||
|
||||
my $power = api('POST', "/api/vcenter/vm/$moid/power?action=start", headers => \%headers);
|
||||
wait_task(json_field($power, 'task'), \%headers);
|
||||
|
||||
my $detail = api('GET', "/api/vcenter/vm/$moid", headers => \%headers);
|
||||
print 'power_state: ', json_field($detail, 'power_state'), "\n";
|
||||
|
||||
$power = api('POST', "/api/vcenter/vm/$moid/power?action=stop", headers => \%headers);
|
||||
wait_task(json_field($power, 'task'), \%headers);
|
||||
|
||||
api('DELETE', "/api/vcenter/vm/$moid", headers => \%headers);
|
||||
api('DELETE', '/api/session', headers => \%headers);
|
||||
print "ok\n";
|
||||
@@ -0,0 +1,3 @@
|
||||
requires 'HTTP::Tiny';
|
||||
requires 'JSON';
|
||||
requires 'IO::Socket::SSL';
|
||||
Reference in New Issue
Block a user