File Coverage

blib/lib/Ovirt/VM.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Ovirt::VM;
2              
3 1     1   1474 use v5.10;
  1         5  
  1         58  
4 1     1   5 use LWP::UserAgent;
  1         1  
  1         18  
5 1     1   176 use XML::LibXML;
  0            
  0            
6             use Carp;
7             use Moo;
8              
9             with 'Ovirt';
10             our $VERSION = '0.02';
11              
12             =head1 NAME
13              
14             Ovirt::VM - Bindings for Ovirt VM API
15              
16             =head1 VERSION
17              
18             Version 0.02
19              
20             =cut
21              
22             =head1 SYNOPSIS
23              
24             use Ovirt::VM;
25              
26             my %con = (
27             username => 'admin',
28             password => 'password',
29             manager => 'ovirt-mgr.example.com',
30             vm_output_attrs => 'id,name,state,description', # optional
31             vm_output_delimiter => '||', # optional
32             );
33              
34             my $vm = Ovirt::VM->new(%con);
35              
36             # return xml output
37             print $vm->list_xml;
38            
39             # list vm attributes
40             print $vm->list;
41            
42             # list specific vm
43             print $vm->list('b4738b0f-b73d-4a66-baa8-2ba465d63132');
44            
45             # create, remove vm
46             $vm->create('vm1','Default','CentOS7');
47             $vm->remove('2d83bb51-9a77-432d-939c-35be207017b9');
48            
49             # start, stop, reboot, migrate vm
50             $vm->start ('b4738b0f-b73d-4a66-baa8-2ba465d63132');
51             $vm->stop ('b4738b0f-b73d-4a66-baa8-2ba465d63132');
52             $vm->reboot ('b4738b0f-b73d-4a66-baa8-2ba465d63132');
53             $vm->migrate ('b4738b0f-b73d-4a66-baa8-2ba465d63132');
54              
55             # Output also available in hash
56             # for example to print all vm name and state
57             my $hash = $vm->hash_output;
58             for my $array (keys $hash->{vm}) {
59             print $hash->{vm}[$array]->{name} . " " .
60             $hash->{vm}[$array]->{status}->{state};
61             }
62            
63             # we can also specify specific vm 'id' when initiating an object
64             # so we can direct access the element for specific vm
65             print $vm->hash_output->{name};
66             print $vm->hash_output->{cluster}->{id};
67              
68             =head1 Attributes
69              
70             Other attributes is also inherited from Ovirt.pm
71             Check 'perldoc Ovirt' for detail
72            
73             notes :
74             ro = read only, can be specified only during initialization
75             rw = read write, user can set this attribute
76             rwp = read write protected, for internal class
77            
78             vm_url = (ro) store default vm url path
79             vm_cdrom_xml = (ro) store xml to be post on start/stop vm action with boot device set to cdrom
80             vm_hd_xml = (ro) store xml to be post on start/stop vm action with boot device set to hd
81             vm_boot_dev = (rw) set boot device when start / stopping vm, default to hd
82             vm_output_delimiter = (rw) specify output delimiter between attribute, default is '||'
83             vm_output_attrs = (rw) store vm attributes to be returned, default is (id, name, state)
84             supported attributes :
85             id name
86             memory description
87             state cpu_cores
88             cpu_sockets cpu_arch
89             cpu_shares os_type
90             boot_dev ha_enabled
91             ha_priority display_type
92             display_address display_port
93             cluster_id template_id
94             stop_time creation_time
95             timezone usb_enabled
96             host_id display_host_subject
97            
98             =cut
99              
100             has 'vm_url' => ( is => 'ro', default => '/api/vms' );
101             has 'vm_output_attrs' => ( is => 'rw', default => 'id,name,state',
102             isa => sub {
103             # store all output attribute into array split by ','
104             # $_[0] is the arguments spefied during initialization
105             my @attrs = split ',' => $_[0];
106            
107             croak "vm_output_attrs can't be empty"
108             unless @attrs;
109            
110             # check if provided attribute is valid / supported
111             my @supported_attr = qw |
112             id name
113             memory description
114             state cpu_cores
115             cpu_sockets cpu_arch
116             cpu_shares os_type
117             boot_dev ha_enabled
118             ha_priority display_type
119             display_address display_port
120             cluster_id template_id
121             stop_time creation_time
122             timezone usb_enabled
123             host_id display_host_subject
124             |;
125             for my $attr (@attrs) {
126             $attr = lc ($attr);
127             $attr = Ovirt->trim($attr);
128             croak "Attribute $attr is not valid / supported"
129             unless grep { /\b$attr\b/ } @supported_attr;
130             }
131             });
132            
133             has 'vm_output_delimiter' => ( is => 'rw', default => '||' );
134             has 'vm_cdrom_xml' => ( is => 'ro', default => '');
135             has 'vm_hd_xml' => ( is => 'ro', default => '');
136             has 'vm_boot_dev' => ( is => 'rw',
137             isa => sub {
138             my $dev = $_[0];
139             $dev = lc ($dev);
140            
141             croak "supported boot device is hd or cdrom"
142             unless $dev =~ /^(hd|cdrom)/;
143             },
144             default => 'hd');
145              
146             =head1 SUBROUTINES/METHODS
147              
148             =head2 BUILD
149              
150             The Constructor, build logging, call pass_log_obj method
151             Built root_url with vm_url
152             set output with get_api_response method from Ovirt.pm
153             check if output attributes is valid
154             =cut
155              
156             sub BUILD {
157             my $self = shift;
158            
159             $self->pass_log_obj;
160            
161             if ($self->id) {
162             $self->_set_root_url($self->vm_url . '/' . $self->id);
163             }
164             else {
165             $self->_set_root_url($self->vm_url);
166             }
167            
168             $self->get_api_response();
169             }
170              
171             =head2 list_xml
172              
173             return xml output
174             =cut
175              
176             sub list_xml {
177             my $self = shift;
178            
179             return $self->xml_output;
180             }
181              
182             =head2 vm_action_output
183              
184             this method handle the output e.g start / stop vm
185             required arguments ($xml), output passed by start/stop method
186             =cut
187              
188             sub vm_action_output {
189             my $self = shift;
190            
191             # xml output from action (start,stop,reboot, etc)
192             my $xml = shift;
193            
194             $self->log->debug($xml);
195            
196             return $xml;
197            
198             =comment
199             my $status = $xml->findnodes('/action/status/state');
200              
201             if ($status eq 'complete') {
202             my $jobid = $xml->findnodes('/action/job/@id');
203             print "status : $status\n";
204             print "jobid : $jobid\n";
205             }
206             elsif ($status =~ /failed/) {
207             # get fault reason and detail
208             my $reason = $xml->findnodes('/action/fault/reason');
209             my $detail = $xml->findnodes('/action/fault/detail');
210            
211             print "status : $status\n";
212             print "reason : $reason\n";
213             print "detail : $detail\n";
214             }
215             =cut
216             }
217              
218             =head2 remove
219              
220             remove vm
221              
222             =cut
223              
224             sub remove {
225             my $self = shift;
226            
227             my $vmid = shift || undef;
228             my $move_url;
229            
230             # set the move final url
231             if ($self->id) {
232             $move_url = $self->url;
233             }
234             else {
235             if ($vmid) {
236             my $is_valid = $self->is_vmid_valid($vmid);
237             croak "vm id not found" unless $is_valid;
238            
239             $move_url = $self->url . "/$vmid";
240             }
241             else {
242             croak "vm id is required";
243             }
244             }
245            
246             $self->log->debug("move action url = $move_url");
247            
248             # set user agent
249             my $ua = LWP::UserAgent->new();
250             my $action = $ua->delete($move_url);
251            
252             my $parser = XML::LibXML->new();
253             my $output = $parser->parse_string($action->decoded_content);
254            
255             $self->vm_action_output($output);
256             }
257              
258             =head2 create
259              
260             create vm using template
261             required arguments (vm name, cluster name, template name)
262             optional argument 'memory in bytes'
263             example :
264             # with memory specified
265             $vm->create('vm1', 'production_cluster', 'RHEL7', 1073741824);
266            
267             # without memory specified (will be based on template's memory)
268             $vm->create('vm1', 'production_cluster', 'RHEL7');
269            
270             =cut
271              
272             sub create {
273             my $self = shift;
274            
275             my ($vm_name, $cluster_name, $template_name, $memory) = @_;
276             croak "vm name required" unless $vm_name;
277             croak "cluster name required" unless $cluster_name;
278             croak "template name required" unless $template_name;
279            
280             $vm_name = $self->trim($vm_name);
281             $cluster_name = $self->trim($cluster_name);
282             $template_name = $self->trim($template_name);
283            
284             $self->log->debug("vm name = $vm_name");
285             $self->log->debug("cluster name = $cluster_name");
286             $self->log->debug("template name = $template_name");
287            
288             # create xml to be post
289             my $xml;
290            
291             if ($memory) {
292             $memory = $self->trim($memory);
293             croak "Memory did not look like number" unless $memory =~ /^\d+$/;
294            
295             $self->log->debug("memory = $memory");
296            
297             $xml = <
298            
299             $vm_name
300            
301             $cluster_name
302            
303            
306             $memory
307            
308            
309            
310            
311             EOF
312              
313             }
314             else {
315             $self->log->debug("memory not specified");
316             $xml = <
317            
318             $vm_name
319            
320             $cluster_name
321            
322            
325            
326            
327            
328            
329             EOF
330             }
331            
332             $self->log->debug($xml);
333            
334             my $create_url = $self->base_url . $self->vm_url;
335             $self->log->debug("create url = $create_url");
336            
337             # set user agent
338             my $ua = LWP::UserAgent->new();
339             my $action = $ua->post($create_url, Content_Type => 'application/xml', Content => $xml);
340            
341             my $parser = XML::LibXML->new();
342             my $output = $parser->parse_string($action->decoded_content);
343            
344             $self->log->debug($output);
345            
346             return $output;
347            
348             =comment
349             if ($action->is_success) {
350             my $status = $output->findnodes('/vm/creation_status/state');
351             print "status : $status\n";
352             }
353             else {
354             $self->log->debug("LWP Error : " . $action->status_line);
355            
356             my $status = $output->findnodes('/fault/reason');
357             my $detail = $output->findnodes('/fault/detail');
358             print "status : $status\n";
359             print "detail : $detail\n";
360             }
361             =cut
362             }
363              
364             =head2 start
365              
366             start vm
367             required arguments ($vmid)
368             if $self->id is set during initialization, argument is not required
369             =cut
370              
371             sub start {
372             my $self = shift;
373            
374             my $vmid = shift || undef;
375             my $start_url;
376            
377             # set the start final url
378             if ($self->id) {
379             $start_url = $self->url . "/start";
380             }
381             else {
382             if ($vmid) {
383             my $is_valid = $self->is_vmid_valid($vmid);
384             croak "vm id not found" unless $is_valid;
385            
386             $start_url = $self->url . "/$vmid/start";
387             }
388             else {
389             croak "vm id is required";
390             }
391             }
392            
393             $self->log->debug("start action url = $start_url");
394            
395             # set user agent
396             my $ua = LWP::UserAgent->new();
397             my $action;
398            
399             if ($self->vm_boot_dev eq 'hd') {
400             $action = $ua->post($start_url, Content_Type => 'application/xml', Content => $self->vm_hd_xml);
401             }
402             else {
403             $action = $ua->post($start_url, Content_Type => 'application/xml', Content => $self->vm_cdrom_xml);
404             }
405            
406             my $parser = XML::LibXML->new();
407             my $output = $parser->parse_string($action->decoded_content);
408            
409             $self->vm_action_output($output);
410             }
411              
412             =head2 stop
413              
414             stop vm
415             required arguments ($vmid)
416             if $self->id is set during initialization, argument is not required
417             =cut
418              
419             sub stop {
420             my $self = shift;
421            
422             my $vmid = shift || undef;
423             my $stop_url;
424            
425             # set the stop final url
426             if ($self->id) {
427             $stop_url = $self->url . "/stop";
428             }
429             else {
430             if ($vmid) {
431             my $is_valid = $self->is_vmid_valid($vmid);
432             croak "vm id not found" unless $is_valid;
433             $stop_url = $self->url . "/$vmid/stop";
434             }
435             else {
436             croak "vm id is required";
437             }
438             }
439            
440             $self->log->debug("stop action url = $stop_url");
441            
442             # set user agent
443             my $ua = LWP::UserAgent->new();
444             my $action;
445            
446             if ($self->vm_boot_dev eq 'hd') {
447             $action = $ua->post($stop_url, Content_Type => 'application/xml', Content => $self->vm_hd_xml);
448             }
449             else {
450             $action = $ua->post($stop_url, Content_Type => 'application/xml', Content => $self->vm_cdrom_xml);
451             }
452            
453             my $parser = XML::LibXML->new();
454             my $output = $parser->parse_string($action->decoded_content);
455            
456             $self->vm_action_output($output);
457             }
458              
459             =head2 reboot
460              
461             reboot vm
462             required arguments ($vmid)
463             if $self->id is set during initialization, argument is not required
464             =cut
465              
466             sub reboot {
467             my $self = shift;
468            
469             my $vmid = shift || undef;
470             my $reboot_url;
471            
472             # set the reboot final url
473             if ($self->id) {
474             $reboot_url = $self->url . "/reboot";
475             }
476             else {
477             if ($vmid) {
478             my $is_valid = $self->is_vmid_valid($vmid);
479             croak "vm id not found" unless $is_valid;
480            
481             $reboot_url = $self->url . "/$vmid/reboot";
482             }
483             else {
484             croak "vm id is required";
485             }
486             }
487            
488             $self->log->debug("reboot action url = $reboot_url");
489            
490             # set user agent
491             my $ua = LWP::UserAgent->new();
492             my $action;
493            
494             if ($self->vm_boot_dev eq 'hd') {
495             $action = $ua->post($reboot_url, Content_Type => 'application/xml', Content => $self->vm_hd_xml);
496             }
497             else {
498             $action = $ua->post($reboot_url, Content_Type => 'application/xml', Content => $self->vm_cdrom_xml);
499             }
500            
501             my $parser = XML::LibXML->new();
502             my $output = $parser->parse_string($action->decoded_content);
503            
504             $self->vm_action_output($output);
505             }
506              
507             =head2 suspend
508              
509             suspend vm
510             required arguments ($vmid)
511             if $self->id is set during initialization, argument is not required
512             =cut
513              
514             sub suspend {
515             my $self = shift;
516            
517             my $vmid = shift || undef;
518             my $suspend_url;
519            
520             # set the suspend final url
521             if ($self->id) {
522             $suspend_url = $self->url . "/suspend";
523             }
524             else {
525             if ($vmid) {
526             my $is_valid = $self->is_vmid_valid($vmid);
527             croak "vm id not found" unless $is_valid;
528            
529             $suspend_url = $self->url . "/$vmid/suspend";
530             }
531             else {
532             croak "vm id is required";
533             }
534             }
535            
536             $self->log->debug("suspend action url = $suspend_url");
537            
538             # set user agent
539             my $ua = LWP::UserAgent->new();
540             my $action;
541            
542             if ($self->vm_boot_dev eq 'hd') {
543             $action = $ua->post($suspend_url, Content_Type => 'application/xml', Content => $self->vm_hd_xml);
544             }
545             else {
546             $action = $ua->post($suspend_url, Content_Type => 'application/xml', Content => $self->vm_cdrom_xml);
547             }
548            
549             my $parser = XML::LibXML->new();
550             my $output = $parser->parse_string($action->decoded_content);
551            
552             $self->vm_action_output($output);
553             }
554              
555             =head2 migrate
556              
557             migrate vm
558             required arguments ($vmid)
559             if $self->id is set during initialization, argument is not required
560             =cut
561              
562             sub migrate {
563             my $self = shift;
564            
565             my $vmid = shift || undef;
566             my $migrate_url;
567            
568             # set the migrate final url
569             if ($self->id) {
570             $migrate_url = $self->url . "/migrate";
571             }
572             else {
573             if ($vmid) {
574             my $is_valid = $self->is_vmid_valid($vmid);
575             croak "vm id not found" unless $is_valid;
576            
577             $migrate_url = $self->url . "/$vmid/migrate";
578             }
579             else {
580             croak "vm id is required";
581             }
582             }
583            
584             $self->log->debug("migrate action url = $migrate_url");
585            
586             # set user agent
587             my $ua = LWP::UserAgent->new();
588             my $action;
589            
590             if ($self->vm_boot_dev eq 'hd') {
591             $action = $ua->post($migrate_url, Content_Type => 'application/xml', Content => $self->vm_hd_xml);
592             }
593             else {
594             $action = $ua->post($migrate_url, Content_Type => 'application/xml', Content => $self->vm_cdrom_xml);
595             }
596            
597             my $parser = XML::LibXML->new();
598             my $output = $parser->parse_string($action->decoded_content);
599            
600             $self->vm_action_output($output);
601             }
602              
603             =head2 is_vmid_valid
604              
605             return false if vmid not valid
606             =cut
607              
608             sub is_vmid_valid {
609             my $self = shift;
610             my $vmid = shift;
611            
612             croak "vm id required" unless $vmid;
613            
614             $vmid = $self->trim($vmid);
615             $self->log->debug("vm id = $vmid");
616            
617             # if vm id match, return 1
618             for my $element_id (0 .. $#{ $self->hash_output->{vm} }) {
619             if ($self->hash_output->{vm}[$element_id]->{id} eq $vmid) {
620             $self->log->debug("$vmid is valid");
621             return 1;
622             }
623             }
624            
625             $self->log->debug("$vmid is not valid");
626             return 0;
627             }
628              
629             =head2 list
630            
631             return vm's attributes text output from hash_output attribute
632             if no argument spesified, it will return all vm attributes (based on vm_output_attrs)
633             argument supported is 'vm id'
634             example :
635             $vm->list('b4738b0f-b73d-4a66-baa8-2ba465d63132');
636            
637             =cut
638              
639             sub list {
640             my $self = shift;
641            
642             my $vmid = shift || undef;
643            
644             # store the output and return it at the end
645             my $output;
646            
647             # store each attribute to array to be looped
648             my @attrs = split ',' => $self->vm_output_attrs;
649            
650             # store the last element to escape the vm_output_delimeter
651             my $last_element = pop (@attrs);
652             $self->log->debug("last element = $last_element");
653              
654             # if the id is defined during initialization
655             # the rest api output will only contain attributes for this id
656             # so it's not necessary to loop on vm element
657             if ($self->id) {
658             for my $attr (@attrs) {
659             $self->log->debug("requesting attribute $attr");
660            
661             my $attr_output = $self->get_vm_by_self_id($attr) || $self->not_available;
662             $output .= $attr_output . $self->vm_output_delimiter;
663             $self->log->debug("output for attribute $attr = " . $attr_output);
664             }
665            
666             #handle last element or the only element
667             $self->log->debug("requesting attribute $last_element");
668            
669             if (my $last_output = $self->get_vm_by_self_id($last_element) || $self->not_available) {
670             $output .= $last_output;
671             $self->log->debug("output for attribute $last_element = " . $last_output);
672             }
673            
674             $output .= "\n";
675             }
676             elsif ($vmid) {
677             #store vmid element
678             my $vmid_element;
679            
680             $vmid = $self->trim($vmid);
681            
682             # store hash to avoid keys on reference
683             #my %hash = $self->hash_output->{vm};
684            
685             for my $element_id ( 0 .. $#{ $self->hash_output->{vm} } ) {
686             next unless
687             $self->hash_output->{vm}[$element_id]->{id} eq $vmid;
688            
689             $vmid_element = $element_id;
690             }
691            
692             croak "vm id not found" unless $vmid_element >= 0;
693            
694             for my $attr (@attrs) {
695             $self->log->debug("requesting attribute $attr for element $vmid_element");
696            
697             my $attr_output = $self->get_vm_by_element_id($vmid_element, $attr) || $self->not_available;
698             $output .= $attr_output . $self->vm_output_delimiter;
699             $self->log->debug("output for attribute $attr element $vmid_element = " . $attr_output);
700             }
701            
702             #handle last element or the only element
703             $self->log->debug("requesting attribute $last_element for element $vmid_element");
704            
705             if (my $last_output = $self->get_vm_by_element_id($vmid_element, $last_element) || $self->not_available) {
706             $output .= $last_output;
707             $self->log->debug("output for attribute $last_element element $vmid_element = " . $last_output);
708             }
709            
710             $output .= "\n";
711             }
712             else {
713            
714             for my $element_id ( 0 .. $#{ $self->hash_output->{vm} } ) {
715            
716             # in case there's no any element left, the last element become the only attribute requested
717             if (@attrs) {
718             for my $attr (@attrs) {
719            
720             $self->log->debug("requesting attribute $attr for element $element_id");
721            
722             my $attr_output = $self->get_vm_by_element_id($element_id, $attr) || $self->not_available;
723             $output .= $attr_output . $self->vm_output_delimiter;
724             $self->log->debug("output for attribute $attr element $element_id = " . $attr_output);
725             }
726             }
727            
728             #handle last element or the only element
729             $self->log->debug("requesting attribute $last_element for element $element_id");
730            
731             if (my $last_output = $self->get_vm_by_element_id($element_id, $last_element) || $self->not_available) {
732             $output .= $last_output;
733             $self->log->debug("output for attribute $last_element element $element_id = " . $last_output);
734             }
735            
736             $output .= "\n";
737             }
738             }
739            
740             return $output;
741             }
742              
743             =head2 get_vm_by_element_id
744            
745             This method is used by list method to list all vm attribute requested
746             An array element id and attribute name is required
747             =cut
748              
749             sub get_vm_by_element_id {
750             my $self = shift;
751            
752             my ($element_id, $attr) = @_;
753            
754             croak "hash output is not defined"
755             unless $self->hash_output;
756            
757             $attr = $self->trim($attr);
758             $self->log->debug("element id = $element_id, attribute = $attr");
759            
760             if ($attr eq 'id') {
761             return $self->hash_output->{vm}[$element_id]->{id};
762             }
763             elsif ($attr eq 'name') {
764             return $self->hash_output->{vm}[$element_id]->{name};
765             }
766             elsif ($attr eq 'memory') {
767             return $self->hash_output->{vm}[$element_id]->{memory};
768             }
769             elsif ($attr eq 'state') {
770             return $self->hash_output->{vm}[$element_id]->{status}->{state};
771             }
772             elsif ($attr eq 'description') {
773             return $self->hash_output->{vm}[$element_id]->{description};
774             }
775             elsif ($attr eq 'cpu_cores') {
776             return $self->hash_output->{vm}[$element_id]->{cpu}->{topology}->{cores};
777             }
778             elsif ($attr eq 'cpu_sockets') {
779             return $self->hash_output->{vm}[$element_id]->{cpu}->{topology}->{sockets};
780             }
781             elsif ($attr eq 'cpu_arch') {
782             return $self->hash_output->{vm}[$element_id]->{cpu}->{architecture};
783             }
784             elsif ($attr eq 'cpu_shares') {
785             return $self->hash_output->{vm}[$element_id]->{cpu_shares};
786             }
787             elsif ($attr eq 'os_type') {
788             return $self->hash_output->{vm}[$element_id]->{os}->{type};
789             }
790             elsif ($attr eq 'boot_dev') {
791             return $self->hash_output->{vm}[$element_id]->{os}->{boot}->{dev};
792             }
793             elsif ($attr eq 'ha_enabled') {
794             return $self->hash_output->{vm}[$element_id]->{high_availability}->{enabled};
795             }
796             elsif ($attr eq 'ha_priority') {
797             return $self->hash_output->{vm}[$element_id]->{high_availability}->{priority};
798             }
799             elsif ($attr eq 'display_type') {
800             return $self->hash_output->{vm}[$element_id]->{display}->{type};
801             }
802             elsif ($attr eq 'display_address') {
803             return $self->hash_output->{vm}[$element_id]->{display}->{address};
804             }
805             elsif ($attr eq 'display_port') {
806             # spice will return secure_port
807             # vnc will return port
808             return $self->hash_output->{vm}[$element_id]->{display}->{secure_port}
809             if $self->hash_output->{vm}[$element_id]->{display}->{secure_port};
810             return $self->hash_output->{vm}[$element_id]->{display}->{port}
811             }
812             elsif ($attr eq 'display_host_subject') {
813             return $self->hash_output->{vm}[$element_id]->{display}->{certificate}->{subject};
814             }
815             elsif ($attr eq 'cluster_id') {
816             return $self->hash_output->{vm}[$element_id]->{cluster}->{id};
817             }
818             elsif ($attr eq 'template_id') {
819             return $self->hash_output->{vm}[$element_id]->{template}->{id};
820             }
821             elsif ($attr eq 'stop_time') {
822             return $self->hash_output->{vm}[$element_id]->{stop_time};
823             }
824             elsif ($attr eq 'creation_time') {
825             return $self->hash_output->{vm}[$element_id]->{creation_time};
826             }
827             elsif ($attr eq 'timezone') {
828             return $self->hash_output->{vm}[$element_id]->{timezone};
829             }
830             elsif ($attr eq 'usb_enabled') {
831             return $self->hash_output->{vm}[$element_id]->{usb}->{enabled};
832             }
833             elsif ($attr eq 'host_id') {
834             return $self->hash_output->{vm}[$element_id]->{host}->{id};
835             }
836             }
837              
838             =head2 get_vm_by_self_id
839            
840             This method is used by list method if $self->id is defined
841             The id is set during initialization (id => 'vmid')
842             attribute name is required
843             =cut
844              
845             sub get_vm_by_self_id {
846             my $self = shift;
847            
848             my $attr = shift;
849            
850             croak "hash output is not defined"
851             unless $self->hash_output;
852            
853             $attr = $self->trim($attr);
854             $self->log->debug("attribute = $attr");
855            
856             if ($attr eq 'id') {
857             return $self->hash_output->{id};
858             }
859             elsif ($attr eq 'name') {
860             return $self->hash_output->{name};
861             }
862             elsif ($attr eq 'memory') {
863             return $self->hash_output->{memory};
864             }
865             elsif ($attr eq 'state') {
866             return $self->hash_output->{status}->{state};
867             }
868             elsif ($attr eq 'description') {
869             return $self->hash_output->{description};
870             }
871             elsif ($attr eq 'cpu_cores') {
872             return $self->hash_output->{cpu}->{topology}->{cores};
873             }
874             elsif ($attr eq 'cpu_sockets') {
875             return $self->hash_output->{cpu}->{topology}->{sockets};
876             }
877             elsif ($attr eq 'cpu_arch') {
878             return $self->hash_output->{cpu}->{architecture};
879             }
880             elsif ($attr eq 'cpu_shares') {
881             return $self->hash_output->{cpu_shares};
882             }
883             elsif ($attr eq 'os_type') {
884             return $self->hash_output->{os}->{type};
885             }
886             elsif ($attr eq 'boot_dev') {
887             return $self->hash_output->{os}->{boot}->{dev};
888             }
889             elsif ($attr eq 'ha_enabled') {
890             return $self->hash_output->{high_availability}->{enabled};
891             }
892             elsif ($attr eq 'ha_priority') {
893             return $self->hash_output->{high_availability}->{priority};
894             }
895             elsif ($attr eq 'display_type') {
896             return $self->hash_output->{display}->{type};
897             }
898             elsif ($attr eq 'display_address') {
899             return $self->hash_output->{display}->{address};
900             }
901             elsif ($attr eq 'display_port') {
902             # spice will return secure_port
903             # vnc will return port
904             return $self->hash_output->{display}->{secure_port}
905             if $self->hash_output->{display}->{secure_port};
906             return $self->hash_output->{display}->{port};
907             }
908             elsif ($attr eq 'display_host_subject') {
909             return $self->hash_output->{display}->{certificate}->{subject};
910             }
911             elsif ($attr eq 'cluster_id') {
912             return $self->hash_output->{cluster}->{id};
913             }
914             elsif ($attr eq 'template_id') {
915             return $self->hash_output->{template}->{id};
916             }
917             elsif ($attr eq 'stop_time') {
918             return $self->hash_output->{stop_time};
919             }
920             elsif ($attr eq 'creation_time') {
921             return $self->hash_output->{creation_time};
922             }
923             elsif ($attr eq 'timezone') {
924             return $self->hash_output->{timezone};
925             }
926             elsif ($attr eq 'usb_enabled') {
927             return $self->hash_output->{usb}->{enabled};
928             }
929             elsif ($attr eq 'host_id') {
930             return $self->hash_output->{host}->{id};
931             }
932             }
933              
934             =head1 AUTHOR
935              
936             "Heince Kurniawan", C<< <"heince at cpan.org"> >>
937              
938             =head1 BUGS
939              
940             Please report any bugs or feature requests to C, or through
941             the web interface at L. I will be notified, and then you'll
942             automatically be notified of progress on your bug as I make changes.
943              
944             =head1 SUPPORT
945              
946             You can find documentation for this module with the perldoc command.
947              
948             perldoc Ovirt::VM
949              
950             =head1 ACKNOWLEDGEMENTS
951              
952              
953             =head1 LICENSE AND COPYRIGHT
954              
955             Copyright 2015 "Heince Kurniawan".
956              
957             This program is free software; you can redistribute it and/or modify it
958             under the terms of the the Artistic License (2.0). You may obtain a
959             copy of the full license at:
960              
961             L
962              
963             Any use, modification, and distribution of the Standard or Modified
964             Versions is governed by this Artistic License. By using, modifying or
965             distributing the Package, you accept this license. Do not use, modify,
966             or distribute the Package, if you do not accept this license.
967              
968             If your Modified Version has been derived from a Modified Version made
969             by someone other than you, you are nevertheless required to ensure that
970             your Modified Version complies with the requirements of this license.
971              
972             This license does not grant you the right to use any trademark, service
973             mark, tradename, or logo of the Copyright Holder.
974              
975             This license includes the non-exclusive, worldwide, free-of-charge
976             patent license to make, have made, use, offer to sell, sell, import and
977             otherwise transfer the Package with respect to any patent claims
978             licensable by the Copyright Holder that are necessarily infringed by the
979             Package. If you institute patent litigation (including a cross-claim or
980             counterclaim) against any party alleging that the Package constitutes
981             direct or contributory patent infringement, then this Artistic License
982             to you shall terminate on the date that such litigation is filed.
983              
984             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
985             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
986             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
987             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
988             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
989             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
990             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
991             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
992              
993              
994             =cut
995              
996             1;