File Coverage

blib/lib/Cisco/UCS.pm
Criterion Covered Total %
statement 42 256 16.4
branch 0 132 0.0
condition 0 34 0.0
subroutine 14 56 25.0
pod 36 36 100.0
total 92 514 17.9


line stmt bran cond sub pod time code
1             package Cisco::UCS;
2              
3 1     1   13416 use warnings;
  1         1  
  1         28  
4 1     1   3 use strict;
  1         1  
  1         15  
5              
6 1     1   353 use Cisco::UCS::Chassis;
  1         2  
  1         25  
7 1     1   701 use Cisco::UCS::Interconnect;
  1         2  
  1         27  
8 1     1   6 use Cisco::UCS::FEX;
  1         2  
  1         25  
9 1     1   385 use Cisco::UCS::Blade;
  1         2  
  1         23  
10 1     1   332 use Cisco::UCS::Fault;
  1         2  
  1         23  
11 1     1   332 use Cisco::UCS::MgmtEntity;
  1         2  
  1         30  
12 1     1   360 use Cisco::UCS::ServiceProfile;
  1         1  
  1         28  
13 1     1   482 use LWP;
  1         31796  
  1         31  
14 1     1   761 use XML::Simple;
  1         6250  
  1         7  
15 1     1   65 use Carp qw(croak carp cluck);
  1         2  
  1         55  
16              
17 1     1   4 use vars qw($VERSION);
  1         1  
  1         172  
18              
19             our $VERSION = '0.51';
20              
21             our @ATTRIBUTES = qw(dn cluster cookie);
22              
23             our %ATTRIBUTES = ();
24              
25             sub new {
26 0     0 1   my ( $class, %args ) = @_;
27              
28 0           my $self = {};
29 0           bless $self, $class;
30              
31             defined $args{cluster}
32             ? $self->{cluster} = $args{cluster}
33 0 0         : croak 'cluster not defined';
34              
35             defined $args{username}
36             ? $self->{username} = $args{username}
37 0 0         : croak 'username not defined';
38              
39             defined $args{passwd}
40             ? $self->{passwd} = $args{passwd}
41 0 0         : croak 'passwd not defined';
42              
43             defined $args{verify_hostname}
44             ? $self->{verify_hostname} = $args{verify_hostname}
45 0 0         : 0;
46              
47 0   0       $self->{port} = ( $args{port} or 443 );
48 0   0       $self->{proto} = ( $args{proto} or 'https' );
49 0   0       $self->{dn} = ( $args{dn} or 'sys' );
50              
51 0           return $self;
52             }
53              
54             {
55 1     1   4 no strict 'refs';
  1         1  
  1         2337  
56              
57             while ( my ($pseudo, $attribute) = each %ATTRIBUTES ) {
58             *{ __PACKAGE__ . '::' . $pseudo } = sub {
59             my $self = shift;
60             return $self->{$attribute}
61             }
62             }
63              
64             foreach my $attribute (@ATTRIBUTES) {
65             *{ __PACKAGE__ . '::' . $attribute } = sub {
66 0     0     my $self = shift;
67 0           return $self->{$attribute}
68             }
69             }
70             }
71              
72             sub login {
73 0     0 1   my $self = shift;
74              
75 0           undef $self->{error};
76              
77             $self->{ua} = LWP::UserAgent->new(
78             ssl_opts => {
79             verify_hostname => $self->{verify_hostname}
80             }
81 0           );
82              
83             $self->{uri} = $self->{proto}. '://' .$self->{cluster}
84 0           . ':' .$self->{port}. '/nuova';
85              
86             $self->{req} = HTTP::Request->new(
87             POST => $self->{uri}
88 0           );
89              
90 0           $self->{req}->content_type( 'application/x-www-form-urlencoded' );
91              
92             $self->{req}->content( ' 93 0           .'" inPassword="'. $self->{passwd} .'"/>' );
94              
95 0           my $res = $self->{ua}->request( $self->{req} );
96              
97 0 0         unless ( $res->is_success ) {
98 0           $self->{error} = 'Login failure: '.$res->status_line;
99 0           return 0
100             }
101              
102 0           $self->{parser} = XML::Simple->new;
103 0           my $xml = $self->{parser}->XMLin( $res->content );
104              
105 0 0         if ( defined $xml->{'errorCode'} ) {
106             $self->{error} = 'Login failure: '
107             . ( defined $xml->{'errorDescr'}
108 0 0         ? $xml->{'errorDescr'}
109             : 'Unspecified error'
110             );
111 0           return 0
112             }
113              
114 0           $self->{cookie} = $xml->{'outCookie'};
115              
116 0           return 1
117             }
118              
119             sub refresh {
120 0     0 1   my $self = shift;
121              
122 0           undef $self->{error};
123             $self->{req}->content( ' 124             .'" inPassword="'. $self->{passwd}
125 0           .'" inCookie="' . $self->{cookie} . '"/>'
126             );
127              
128 0           my $res = $self->{ua}->request( $self->{req} );
129              
130 0 0         unless ( $res->is_success ) {
131 0           $self->{error} = 'Refresh failed: '. $res->status_line;
132 0           return 0
133             }
134              
135 0           my $xml = $self->{parser}->XMLin( $res->content() );
136              
137 0 0         if ( defined $xml->{'errorCode'} ) {
138             $self->{error} = 'Refresh failure: '
139             . ( defined $xml->{'errorDescr'}
140 0 0         ? $xml->{'errorDescr'}
141             : 'Unspecified error'
142             );
143 0           return 0
144             }
145              
146 0           $self->{cookie} = $xml->{'outCookie'};
147              
148 0           return 1
149             }
150              
151             sub logout {
152 0     0 1   my $self = shift;
153              
154 0 0         return unless $self->{cookie};
155              
156 0           undef $self->{error};
157              
158             return ( $self->_ucsm_request( ' 159 0 0         . $self->{cookie} .'" />' ) ? 1 : 0
160             )
161             }
162              
163             sub _ucsm_request {
164 0     0     my ( $self, $content, $class_id ) = @_;
165              
166 0           undef $self->{error};
167 0           $self->{req}->content( $content );
168 0           my $res = $self->{ua}->request( $self->{req} );
169              
170 0 0         $self->error( $res->status_line ) unless $res->is_success;
171              
172             my $xml = ( $class_id
173             ? $self->{parser}->XMLin(
174             $res->content,
175             KeyAttr => $class_id
176             )
177             : $self->{parser}->XMLin(
178 0 0         $res->content,
179             KeyAttr => [ 'name', 'key', 'id', 'intId' ]
180             )
181             );
182              
183             return ( $xml->{errorCode}
184 0 0         ? do {
185             $self->{error} = ( $xml->{'errorDescr'}
186 0 0         ? $xml->{'errorDescr'}
187             : 'Unspecified error'
188             );
189             undef
190 0           }
191             : $xml
192             );
193             }
194              
195             # This private method provides an abstract factory-type constructor for resolved child
196             # objects of the specified dn. To maintain compatibility with existing methods and to
197             # provide a single method for all child objects, there are a few important design
198             # considerations that have been made.
199             #
200             # Importantly we check for a 'class_filter' argument to the method which if present is
201             # used to call the 'resolve_class_filter' method rather than the 'resolve_children' method.
202             # This is necessary due to limitations and difficulties present in resolving child objects
203             # for some objects can lead to incorrect results. For example, resolving the child objects
204             # for a chassis to retrieve the blades in the chassis is difficult, instead we can use a much
205             # more efficient and simpler method of retrieving the blades in a specified chassis by
206             # resolving all objects in the specified class (i.e. computeBlade) and restricting the
207             # results returned using a filter method.
208             #
209             # The implication of doing this is that the call to 'resolve_class_filter' returns an array
210             # which cannot be processed using the same logic as for a hash returned by the 'resolve_children'
211             # method. Therefore we perform extra processing to convert the returned array results to a
212             # hash using a nominated attribute in the object as the hash index for the objects.
213             #
214             # SYNOPSIS
215             # get_child_object ( %ARGS )
216             #
217             # PARAMETERS
218             # id The optional identifier of a specific child object. This identifier is context
219             # dependent and may be either numerical (as in the case of a chassis) or alphanumeric
220             # (as is the case with a fabric interconnect - A or B).
221             #
222             # type The desired child object type to be resolved as according to the UCSM information
223             # management hierarchy name. e.g. etherPIo is the ethernet port child object type for line cards.
224             #
225             # class The class into which the child object will be blessed.
226             #
227             # attr The pseudo-namespace in the Cisco::UCS object in which the retrieved child onjects will be cached.
228             # For example; attr => 'interconnect' will mean that Cisco::UCS::Interconnect objects retrieved in
229             # a $ucs->get_interconnects method call will be stored in $ucs->{interconnects}->{$OBJ}.
230             #
231             # self A reference to a Cisco::UCS object. If not present $self is assumed to be a Cisco::UCS object.
232             #
233             # uid Where results are returned and parsed into an array and the array index is not aligned to an identifying
234             # attribute of the object (i.e. the array index has no relation to a unique identifier for the object) then
235             # the uid may be used to refer to a unique identifying attribute of the object that should be used.
236             # For example, in resolving all blades for a Cisco::UCS object, the uid value of bladeId is used to uniquely
237             # identify all Cisco::UCS::Blade objects as the array index has no relation to a uniquely identifying feature
238             # of the blade and is not guaranteed to be consistent.
239             #
240             # class_filter (%ARGS)
241             # A class filter may be specified to filter the results to a particular subset. This is useful for
242             # operations like retrieving all blades in a particular chassis rather than retrieving all blades and
243             # manually filtering the results.
244             #
245             # Where %ARGS:
246             #
247             # classId The UCSM class which should be used for the UCSM query. For example: classId => etherPio.
248             #
249             # filter Where filter is composed of any number of valid attribute/value pairs. For example: slotId => 1, switchId => $self->{id}.
250             #
251             # eattrs A hash containing key/value pairs that should be added to the retrieved child objects as additional
252             # attributes. This can be useful where child objects need to "know" some infomration about their
253             # parent object. e.g. an interconnect switchcard needs to know which interconnect it is located in (A or B)
254             # as this information is not exposed as an attribute of the switchcard.
255             #
256              
257             sub _get_child_objects {
258 0     0     my ( $self,%args ) = @_;
259              
260             my $ucs = ( defined $self->{ucs}
261             ? $self->{ucs}
262 0 0         : $self
263             );
264              
265             my $ref = ( defined $args{self}
266             ? $args{self}
267 0 0         : $self
268             );
269              
270             my $xml = ( defined $args{class_filter}
271 0           ? $ucs->resolve_class_filter( %{ $args{class_filter} } )
272             : $ucs->resolve_children( dn => $ref->{dn} )
273 0 0         );
274              
275 0 0 0       if ( ref( $xml->{outConfigs}->{ $args{type} } ) eq 'ARRAY' ) {
    0          
276 0   0       $args{uid} ||= 'id';
277 0           my $res;
278            
279 0           foreach my $obj ( @{ $xml->{outConfigs}->{ $args{type} } } ) {
  0            
280 0           $res->{ $obj->{ $args{uid} } } = $obj
281             }
282              
283 0           $xml->{outConfigs}->{ $args{type} } = $res
284             }
285             elsif ( ( ref( $xml->{outConfigs}->{ $args{type} } ) eq 'HASH' )
286             and ( exists $xml->{outConfigs}->{ $args{type} }->{dn} ) ) {
287 0   0       $args{uid} ||= 'id';
288 0           my $res;
289             $res->{ $xml->{outConfigs}->{ $args{type} }->{ $args{uid} } }
290 0           = $xml->{outConfigs}->{ $args{type} };
291              
292 0           $xml->{outConfigs}->{ $args{type} } = $res
293             }
294              
295             return ( defined $xml->{outConfigs}->{ $args{type} }
296 0 0         ? do { my @res;
  0            
297 0           foreach my $res ( keys %{ $xml->{outConfigs}->{ $args{type} } } ) {
  0            
298             my $obj = $args{class}->new(
299             ucs => $ucs,
300             dn => $xml->{outConfigs}->{ $args{type} }->{$res}->{dn},
301 0           id => $res
302             );
303              
304 0           map { $obj->{ $_ } = $args{ eattrs }{ $_ } } keys %{ $args{ eattrs } };
  0            
  0            
305              
306 0           $ref->{ $args{attr} }->{$res} = $obj;
307 0           push @res, $obj;
308             }
309              
310 0 0         return @res unless $args{id};
311              
312             return $ref->{ $args{attr} }->{ $args{id} }
313 0 0 0       if $args{id} and $ref->{ $args{attr} }->{ $args{id} };
314              
315             return
316 0           }
317             : ()
318             );
319            
320             }
321              
322             sub get_error_id {
323 0     0 1   warn "get_error_id has been deprecated in future releases";
324 0           return get_error( @_ )
325             }
326              
327             sub error {
328 0     0 1   my ( $self, $id ) = @_;
329              
330             return (
331             defined $self->{fault}->{$id}
332 0 0         ? $self->{fault}->{$id}
333             : $self->get_error($id)
334             )
335             }
336              
337             sub get_error {
338 0     0 1   my ( $self, $id ) = @_;
339              
340 0           return $self->get_errors( $id )
341             }
342              
343             sub get_errors {
344 0     0 1   my ( $self, $id ) = @_;
345              
346 0           return $self->_get_child_objects(
347             id => $id,
348             type => 'faultInst',
349             class => 'Cisco::UCS::Fault',
350             uid => 'id',
351             attr => 'fault',
352             class_filter => {
353             classId => 'faultInst'
354             }
355             );
356             }
357              
358             sub _isInHierarchical {
359 0     0     my $inHierarchical = lc shift;
360              
361 0 0         return 'false' unless ( $inHierarchical =~ /true|false|0|1/ );
362              
363 0 0         return $inHierarchical if ( $inHierarchical =~ /^true|false$/ );
364              
365 0 0         return ( $inHierarchical == 0 ? 'false' : 'true' );
366             }
367              
368             sub _createFilter {
369 0     0     my ( $self, %args ) = @_;
370              
371 0 0         unless ( defined $args{classId} ) {
372 0           $self->{error} = 'No classId specified';
373             return
374 0           }
375              
376 0           my $filter = '';
377              
378 0           while ( my( $property,$value ) = each %args ) {
379 0 0 0       next if ( $property eq 'inHierarchical' or $property eq 'classId' );
380 0           $filter .= ' 381             . $property . '" value="' . $value . '" />';
382             }
383              
384 0           $filter .= '';
385              
386 0           return $filter;
387             }
388              
389             sub resolve_class {
390 0     0 1   my ( $self, %args ) = @_;
391              
392 0 0         unless ( defined $args{classId} ) {
393 0           $self->{error} = 'No classId specified';
394             return
395 0           }
396              
397             $args{inHierarchical} = (
398             defined $args{inHierarchical}
399             ? _isInHierarchical( $args{inHierarchical} )
400 0 0         : 'false'
401             );
402              
403             my $xml = $self->_ucsm_request( ' 404             . $args{inHierarchical} .'" cookie="'
405             . $self->{cookie} .'" classId="'
406 0 0         . $args{classId} .'" />' ) or return;
407              
408 0           return $xml
409             }
410              
411             sub resolve_classes {
412 0     0 1   my ( $self, %args ) = @_;
413              
414 0 0         unless ( defined $args{classId} ) {
415 0           $self->{error} = 'No classID specified';
416             return
417 0           }
418              
419             $args{inHierarchical} = (
420             defined $args{inHierarchical}
421             ? _isInHierarchical( $args{inHierarchical} )
422 0 0         : 'false'
423             );
424              
425             my $xml = $self->_ucsm_request( ' 426             . $args{inHierarchical}
427             . '" cookie="'. $self->{cookie} .'">'
428             . ' 429 0 0         . '" />', 'classId'
430             ) or return;
431              
432 0           return $xml
433             }
434              
435             sub resolve_dn {
436 0     0 1   my ( $self, %args ) = @_;
437              
438 0 0         unless ( defined $args{dn} ) {
439 0           $self->{error} = 'No dn specified';
440             return
441 0           }
442              
443             $args{inHierarchical} = (
444             defined $args{inHierarchical}
445             ? _isInHierarchical( $args{inHierarchical} )
446 0 0         : 'false'
447             );
448              
449             my $xml = $self->_ucsm_request( ' 450             . '" inHierarchical="'. $args{inHierarchical}
451 0 0         . '" cookie="'. $self->{cookie} .'" />'
452             ) or return;
453              
454 0           return $xml;
455             }
456              
457             sub resolve_children {
458 0     0 1   my ( $self, %args ) = @_;
459              
460 0 0         unless ( defined $args{dn} ) {
461 0           $self->{error} = 'No dn specified';
462             return
463 0           }
464              
465             $args{inHierarchical} = (
466             defined $args{inHierarchical}
467             ? _isInHierarchical( $args{inHierarchical} )
468 0 0         : 'false'
469             );
470              
471             my $xml = $self->_ucsm_request( ' 472             . $args{inHierarchical} .'" cookie="'
473             . $self->{cookie} .'" inDn="'
474 0 0         . $args{dn} .'">'
475             ) or return;
476              
477 0           return $xml
478             }
479              
480             sub resolve_class_filter {
481 0     0 1   my( $self, %args ) = @_;
482            
483             $args{inHierarchical} = (
484             defined $args{inHierarchical}
485             ? _isInHierarchical( $args{inHierarchical} )
486 0 0         : 'false'
487             );
488              
489 0 0         my $filter = $self->_createFilter( %args ) or return;
490              
491             my $xml = $self->_ucsm_request( ' 492             . $args{classId} .'" inHierarchical="'
493             . $args{inHierarchical} .'" cookie="'
494             . $self->{cookie} .'">' . $filter
495             . '', $args{classId}
496 0 0         ) or return;
497              
498 0           return $xml
499             }
500              
501             sub get_cluster_status {
502 0     0 1   my $self = shift;
503              
504 0 0         my $xml = $self->resolve_dn( dn => 'sys' ) or return;
505              
506             return (
507             defined $xml->{outConfig}->{topSystem}
508             ? $xml->{outConfig}->{topSystem}
509             : undef
510             )
511 0 0         }
512              
513             sub version {
514 0     0 1   my $self = shift;
515              
516 0 0         my $xml = $self->resolve_dn( dn => 'sys/mgmt/fw-system' ) or return;
517              
518             return (
519             defined $xml->{outConfig}->{firmwareRunning}->{version}
520             ? $xml->{outConfig}->{firmwareRunning}->{version}
521             : undef
522             )
523 0 0         }
524              
525             sub mgmt_entity {
526 0     0 1   my ( $self, $id ) = @_;
527              
528             return (
529             defined $self->{mgmt_entity}->{$id}
530 0 0         ? $self->{mgmt_entity}->{$id}
531             : $self->mgmt_entity($id)
532             )
533             }
534              
535             sub get_mgmt_entity {
536 0     0 1   my ( $self, $id ) = @_;
537              
538 0           return $self->get_mgmt_entities( $id )
539             }
540              
541             sub get_mgmt_entities {
542 0     0 1   my ( $self, $id ) = @_;
543              
544 0           return $self->_get_child_objects(
545             id => $id,
546             type => 'mgmtEntity',
547             class => 'Cisco::UCS::MgmtEntity',
548             attr => 'mgmt_entity'
549             );
550             }
551              
552             sub get_primary_mgmt_entity {
553 0     0 1   my $self = shift;
554              
555 0 0         my $xml = $self->resolve_class_filter(
556             classId => 'mgmtEntity',
557             leadership => 'primary'
558             ) or return;
559              
560             return (
561             defined $xml->{outConfigs}->{mgmtEntity}
562             ? $xml->{outConfigs}->{mgmtEntity}
563             : undef
564             )
565 0 0         }
566              
567             sub get_subordinate_mgmt_entity {
568 0     0 1   my $self = shift;
569              
570 0 0         my $xml = $self->resolve_class_filter(
571             classId => 'mgmtEntity',
572             leadership => 'subordinate'
573             ) or return;
574              
575             return (
576             defined $xml->{outConfigs}->{mgmtEntity}
577             ? $xml->{outConfigs}->{mgmtEntity}
578             : undef
579 0 0         );
580             }
581              
582             sub service_profile {
583 0     0 1   my ( $self, $id ) = @_;
584              
585             return (
586             defined $self->{service_profile}->{$id}
587 0 0         ? $self->{service_profile}->{$id}
588             : $self->get_service_profile($id)
589             )
590             }
591              
592             sub get_service_profile {
593 0     0 1   my ( $self, $id ) = @_;
594              
595 0           return $self->get_service_profiles( $id )
596             }
597              
598             sub get_service_profiles {
599 0     0 1   my ( $self, $id ) = @_;
600              
601 0           return $self->_get_child_objects(
602             id => $id,
603             type => 'lsServer',
604             class => 'Cisco::UCS::ServiceProfile',
605             uid => 'name',
606             attr => 'service_profile',
607             class_filter => {
608             classId => 'lsServer'
609             }
610             );
611             }
612              
613             sub interconnect {
614 0     0 1   my ( $self, $id ) = @_;
615              
616             return (
617             defined $self->{interconnect}->{$id}
618 0 0         ? $self->{interconnect}->{$id}
619             : $self->get_interconnect($id)
620             )
621             }
622              
623             sub get_interconnect {
624 0     0 1   my ( $self, $id ) = @_;
625              
626 0           return $self->get_interconnects( $id )
627             }
628              
629             sub get_interconnects {
630 0     0 1   my ( $self, $id ) = @_;
631              
632 0           return $self->_get_child_objects(
633             id => $id,
634             type => 'networkElement',
635             class => 'Cisco::UCS::Interconnect',
636             attr => 'interconnect'
637             );
638             }
639              
640             sub blade {
641 0     0 1   my ( $self, $id ) = @_;
642              
643             return (
644             defined $self->{blade}->{$id}
645 0 0         ? $self->{blade}->{$id}
646             : $self->get_blade($id)
647             )
648             }
649              
650             sub get_blade {
651 0     0 1   my ( $self, $id ) = @_;
652              
653 0           return $self->get_blades( $id )
654             }
655              
656             sub get_blades {
657 0     0 1   my ( $self, $id, %args ) = @_;
658              
659 0           return $self->_get_child_objects(
660             id => $id,
661             type => 'computeBlade',
662             class => 'Cisco::UCS::Blade',
663             attr => 'blade',
664             uid => 'serverId',
665             class_filter => {
666             classId => 'computeBlade'
667             }
668             );
669             }
670              
671             sub chassis {
672 0     0 1   my ( $self, $id ) = @_;
673              
674             return (
675             defined $self->{chassis}->{$id}
676 0 0         ? $self->{chassis}->{$id}
677             : $self->get_chassis($id)
678             )
679             }
680              
681             sub get_chassis {
682 0     0 1   my ( $self, $id ) = @_;
683              
684 0           return $self->get_chassiss( $id )
685             }
686              
687             sub get_chassiss {
688 0     0 1   my ( $self, $id ) = @_;
689              
690 0           return $self->_get_child_objects(
691             id => $id,
692             type => 'equipmentChassis',
693             class => 'Cisco::UCS::Chassis',
694             attr => 'chassis'
695             );
696             }
697              
698             sub full_state_backup {
699 0     0 1   my ( $self, %args ) = @_;
700              
701 0           $args{backup_type} = 'full-state';
702              
703 0           return ( $self->_backup( %args ) );
704             }
705             sub all_config_backup {
706 0     0 1   my ( $self, %args ) = @_;
707              
708 0           $args{backup_type} = 'config-all';
709              
710 0           return ( $self->_backup( %args ) );
711             }
712              
713             sub system_config_backup {
714 0     0 1   my ( $self, %args ) = @_;
715              
716 0           $args{backup_type} = 'config-system';
717              
718 0           return ( $self->_backup( %args ) );
719             }
720              
721             sub logical_config_backup {
722 0     0 1   my ( $self, %args ) = @_;
723              
724 0           $args{backup_type} = 'config-logical';
725              
726 0           return ( $self->_backup( %args ) );
727             }
728              
729             sub _backup {
730 0     0     my ( $self, %args ) = @_;
731              
732 0 0 0       unless( defined $args{backup_type} and
      0        
      0        
      0        
      0        
733             defined $args{backup_proto} and
734             defined $args{backup_host} and
735             defined $args{backup_target} and
736             defined $args{backup_passwd} and
737             defined $args{backup_username} )
738             {
739 0           $self->{error} = 'Bad argument list';
740             return
741 0           }
742              
743             $args{admin_state} = (
744             defined $args{admin_state}
745             ? $args{admin_state}
746 0 0         : 'enabled'
747             );
748              
749             $args{preserve_pooled_values} = (
750             defined $args{preserve_pooled_values}
751             ? $args{preserve_pooled_values}
752 0 0         : 'yes'
753             );
754              
755 0 0         unless ( $args{backup_type} =~ /(config-all|full-state|config-system|config-logical)/i ) {
756 0           $self->{error} = "Bad backup type ($args{backup_type})";
757             return
758 0           }
759              
760 0 0         unless ( $args{backup_proto} =~ /^((t|s)?ftp)|(scp)$/i ) {
761 0           $self->{error} = "Bad backup proto' ($args{backup_proto})";
762             return
763 0           }
764              
765 0           my $address = $self->get_cluster_status->{address};
766              
767 0           my $data = <<"XML";
768            
769            
770            
771            
772            
773             proto="$args{backup_proto}" pwd="$args{backup_passwd}" remoteFile="$args{backup_target}"
774             rn="backup-$args{backup_host}" type="$args{backup_type}"
775             user="$args{backup_username}" policyOwner="local">
776            
777            
778            
779            
780            
781             XML
782              
783 0 0         my $xml = $self->_ucsm_request( $data ) or return;
784              
785 0 0         if ( defined $xml->{'errorCode'} ) {
786             my $self->{error} = ( defined $xml->{'errorDescr'}
787 0 0         ? $xml->{'errorDescr'}
788             : "Unspecified error"
789             );
790             return
791 0           }
792              
793 0           return 1;
794             }
795              
796             1;
797              
798             __END__