our
$VERSION
=
'1.16.0'
;
BEGIN {
LWP::UserAgent->
use
;
}
sub
new {
my
$that
=
shift
;
my
$proto
=
ref
(
$that
) ||
$that
;
my
$self
= {
@_
};
bless
(
$self
,
$proto
);
$self
->{__auth} = {
user
=> Rex::Config->get_user(),
password
=> Rex::Config->get_password(),
private_key
=> Rex::Config->get_private_key(),
public_key
=> Rex::Config->get_public_key(),
};
Rex::Config->set_openssh_opt(
StrictHostKeyChecking
=>
"no"
,
UserKnownHostsFile
=>
"/dev/null"
,
LogLevel
=>
"QUIET"
);
return
$self
;
}
sub
info {
my
(
$self
) =
@_
;
return
$self
->{info};
}
sub
name {
my
(
$self
,
$name
) =
@_
;
$self
->{name} =
$name
;
}
sub
storage {
my
(
$self
,
$folder
) =
@_
;
$self
->{storage_path} =
$folder
;
}
sub
setup {
my
(
$self
,
@tasks
) =
@_
;
$self
->{__tasks} = \
@tasks
;
}
sub
import_vm {
my
(
$self
) =
@_
;
die
(
"This method must be overwritten."
);
}
sub
stop {
my
(
$self
) =
@_
;
$self
->info;
vm
shutdown
=>
$self
->{name};
}
sub
destroy {
my
(
$self
) =
@_
;
$self
->info;
vm
destroy
=>
$self
->{name};
}
sub
start {
my
(
$self
) =
@_
;
$self
->info;
vm
start
=>
$self
->{name};
}
sub
ip {
die
(
"Must be implemented by box class."
) }
sub
status {
my
(
$self
) =
@_
;
return
vm
status
=>
$self
->{name};
}
sub
provision_vm {
my
(
$self
,
@tasks
) =
@_
;
if
( !
@tasks
) {
@tasks
= @{
$self
->{__tasks} }
if
(
exists
$self
->{__tasks} );
}
$self
->wait_for_ssh();
for
my
$task
(
@tasks
) {
my
$task_o
= Rex::TaskList->create()->get_task(
$task
);
if
( !
$task_o
) {
die
"Task $task not found."
;
}
$task_o
->set_auth( %{
$self
->{__auth} } );
Rex::Commands::set(
"box_object"
,
$self
);
$task_o
->run(
$self
->ip );
Rex::Commands::set(
"box_object"
,
undef
);
}
}
sub
cpus {
my
(
$self
,
$cpus
) =
@_
;
$self
->{cpus} =
$cpus
;
}
sub
memory {
my
(
$self
,
$mem
) =
@_
;
$self
->{memory} =
$mem
;
}
sub
network {
my
(
$self
,
%option
) =
@_
;
$self
->{__network} = \
%option
;
}
sub
forward_port {
my
(
$self
,
%option
) =
@_
;
$self
->{__forward_port} = \
%option
;
}
sub
list_boxes {
my
(
$self
) =
@_
;
my
$vms
= vm
list
=>
"all"
;
return
@{
$vms
};
}
sub
url {
my
(
$self
,
$url
,
$force
) =
@_
;
$self
->{url} =
$url
;
$self
->{force} =
$force
;
}
sub
auth {
my
(
$self
,
%auth
) =
@_
;
if
(
%auth
) {
$self
->{__auth} = \
%auth
;
}
else
{
return
$self
->{__auth};
}
}
sub
options {
my
(
$self
,
%opt
) =
@_
;
if
(
%opt
) {
$self
->{__options} = \
%opt
;
}
else
{
return
$self
->{__options};
}
}
sub
wait_for_ssh {
my
(
$self
,
$ip
,
$port
) =
@_
;
if
( !
$ip
) {
(
$ip
,
$port
) = Rex::Helper::IP::get_server_and_port(
$self
->ip, 22 );
}
print
"Waiting for SSH to come up on $ip:$port."
;
while
( !is_port_open(
$ip
,
$port
) ) {
print
"."
;
sleep
1;
}
print
"\n"
;
}
sub
_download {
my
(
$self
) =
@_
;
my
$filename
= basename(
$self
->{url} );
my
$force
=
$self
->{force} || FALSE;
my
$fs
= Rex::Interface::Fs->create;
if
(
$fs
->is_file(
"./tmp/$filename"
) ) {
Rex::Logger::info(
"File already downloaded. Please remove the file ./tmp/$filename if you want to download a fresh copy."
);
}
else
{
$force
= TRUE;
}
if
(
$force
) {
Rex::Logger::info(
"Downloading $self->{url} to ./tmp/$filename"
);
mkdir
"tmp"
;
if
( Rex::is_local() ) {
my
$ua
= LWP::UserAgent->new();
$ua
->env_proxy;
my
$final_data
=
""
;
my
$current_size
= 0;
my
$current_modulo
= 0;
my
$start_time
= [ gettimeofday() ];
open
(
my
$fh
,
">"
,
"./tmp/$filename"
)
or
die
(
"Failed to open ./tmp/$filename for writing: $!"
);
binmode
$fh
;
my
$resp
=
$ua
->get(
$self
->{url},
':content_cb'
=>
sub
{
my
(
$data
,
$response
,
$protocol
) =
@_
;
$current_size
+=
length
(
$data
);
my
$content_length
=
$response
->header(
"content-length"
);
print
$fh
$data
;
my
$current_time
= [ gettimeofday() ];
my
$time_diff
= tv_interval(
$start_time
,
$current_time
);
my
$bytes_per_seconds
=
$current_size
/
$time_diff
;
my
$mbytes_per_seconds
=
$bytes_per_seconds
/ 1024 / 1024;
my
$mbytes_current
=
$current_size
/ 1024 / 1024;
my
$mbytes_total
=
$content_length
/ 1024 / 1024;
my
$left_bytes
=
$content_length
-
$current_size
;
my
$time_one_byte
=
$time_diff
/
$current_size
;
my
$time_all_bytes
=
$time_one_byte
* (
$content_length
-
$current_size
);
if
( ( (
$current_size
/ ( 1024 * 1024 ) ) % ( 1024 * 1024 ) ) >
$current_modulo
)
{
print
"."
;
$current_modulo
++;
if
(
$current_modulo
% 10 == 0 ) {
printf
(
". %.2f MBytes/s (%.2f MByte / %.2f MByte) %.2f secs left\n"
,
$mbytes_per_seconds
,
$mbytes_current
,
$mbytes_total
,
$time_all_bytes
);
}
}
}
);
close
(
$fh
);
if
(
$resp
->is_success ) {
print
" done.\n"
;
}
else
{
Rex::Logger::info(
"Error downloading box image."
,
"warn"
);
unlink
"./tmp/$filename"
;
}
}
else
{
i_exec
"wget"
,
"-c"
,
"-qO"
,
"./tmp/$filename"
,
$self
->{url};
if
( $? != 0 ) {
die
(
"Downloading of $self->{url} failed. Please verify if wget is installed and if you have the right permissions to download this box."
);
}
}
}
}
1;