1package VM::EC2::REST::instance;
2
3use VM::EC2 '';  # important not to import anything!
4package VM::EC2;  # add methods to VM::EC2
5use strict;
6
7VM::EC2::Dispatch->register(
8    ConfirmProductInstance      => 'boolean',
9    DescribeInstances => sub { VM::EC2::Dispatch::load_module('VM::EC2::ReservationSet');
10			       my $r = VM::EC2::ReservationSet->new(@_) or return;
11						       return $r->instances;
12    },
13    DescribeInstanceStatus => 'fetch_items_iterator,instanceStatusSet,VM::EC2::Instance::StatusItem,instance_status',
14    ModifyInstanceAttribute => 'boolean',
15    RebootInstances      => 'boolean',
16    ResetInstanceAttribute => 'boolean',
17    RunInstances      => sub { VM::EC2::Dispatch::load_module('VM::EC2::Instance::Set');
18						       my $s = VM::EC2::Instance::Set->new(@_) or return;
19						       return $s->instances;
20			    },
21    StartInstances       => 'fetch_items,instancesSet,VM::EC2::Instance::State::Change',
22    StopInstances        => 'fetch_items,instancesSet,VM::EC2::Instance::State::Change',
23    TerminateInstances   => 'fetch_items,instancesSet,VM::EC2::Instance::State::Change',
24    );
25
26my $VEP = 'VM::EC2::ParmParser';
27
28=head1 NAME
29
30VM::EC2::REST::instance - VM::EC2 methods for controlling instances
31
32=head1 SYNOPSIS
33
34 use VM::EC2 ':standard';
35
36=head1 METHODS
37
38The methods in this section allow you to retrieve information about
39EC2 instances, launch new instances, control the instance lifecycle
40(e.g. starting and stopping them), and fetching the console output
41from instances.
42
43Implemented:
44 ConfirmProductInstance
45 DescribeInstanceAttribute
46 DescribeInstances
47 DescribeInstanceStatus
48 ModifyInstanceAttribute
49 RebootInstances
50 ResetInstanceAttribute
51 RunInstances
52 StartInstances
53 StopInstances
54 TerminateInstances
55
56Unimplemented:
57 (none)
58
59The primary object manipulated by these methods is
60L<VM::EC2::Instance>. Please see the L<VM::EC2::Instance> manual page
61for additional methods that allow you to attach and detach volumes,
62modify an instance's attributes, and convert instances into images.
63
64=head2 @instances = $ec2->describe_instances(@instance_ids)
65
66=head2 @instances = $ec2->describe_instances(\%filters)
67
68=head2 @instances = $ec2->describe_instances(-instance_id=>\@ids,-filter=>\%filters)
69
70Return a series of VM::EC2::Instance objects. Optional arguments are:
71
72 -instance_id     ID of the instance(s) to return information on.
73                  This can be a string scalar, or an arrayref.
74
75 -filter          Tags and other filters to apply.
76
77The filter argument is a hashreference in which the keys are the
78filter names, and the values are the match strings. Some filters
79accept wildcards.
80
81A typical filter example:
82
83  $ec2->describe_instances(
84    -filter        => {'block-device-mapping.device-name'=>'/dev/sdh',
85                       'architecture'                    => 'i386',
86                       'tag:Role'                        => 'Server'
87                      });
88
89You may omit the -filter argument name if there are no other arguments:
90
91  $ec2->describe_instances({'block-device-mapping.device-name'=>'/dev/sdh',
92                            'architecture'                    => 'i386',
93                             'tag:Role'                        => 'Server'});
94
95There are a large number of filters, which are listed in full at
96http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html.
97
98Here is a alpha-sorted list of filter names: architecture,
99availability-zone, block-device-mapping.attach-time,
100block-device-mapping.delete-on-termination,
101block-device-mapping.device-name, block-device-mapping.status,
102block-device-mapping.volume-id, client-token, dns-name, group-id,
103group-name, hypervisor, image-id, instance-id, instance-lifecycle,
104instance-state-code, instance-state-name, instance-type,
105instance.group-id, instance.group-name, ip-address, kernel-id,
106key-name, launch-index, launch-time, monitoring-state, owner-id,
107placement-group-name, platform, private-dns-name, private-ip-address,
108product-code, ramdisk-id, reason, requester-id, reservation-id,
109root-device-name, root-device-type, source-dest-check,
110spot-instance-request-id, state-reason-code, state-reason-message,
111subnet-id, tag-key, tag-value, tag:key, virtualization-type, vpc-id.
112
113Note that the objects returned from this method are the instances
114themselves, and not a reservation set. The reservation ID can be
115retrieved from each instance by calling its reservationId() method.
116
117=cut
118
119sub describe_instances {
120    my $self = shift;
121    my %args = $VEP->args(-instance_id,@_);
122    my @params = $VEP->format_parms(\%args,
123				    {
124					list_parm   => 'InstanceId',
125					filter_parm => 'Filter'
126				    });
127    return $self->call('DescribeInstances',@params);
128}
129
130=head2 @i = $ec2->run_instances($ami_id)
131
132=head2 @i = $ec2->run_instances(-image_id=>$id,%other_args)
133
134This method will provision and launch one or more instances given an
135AMI ID. If successful, the method returns a series of
136VM::EC2::Instance objects.
137
138If called with a single argument this will be interpreted as the AMI
139to launch, and all other arguments will take their
140defaults. Otherwise, the arguments will be taken as a
141-parameter=>$argument list.
142
143=over 4
144
145=item Required arguments:
146
147  -image_id       ID of an AMI to launch
148
149=item Optional arguments:
150
151  -min_count         Minimum number of instances to launch [1]
152
153  -max_count         Maximum number of instances to launch [1]
154
155  -key_name          Name of the keypair to use
156
157  -security_group_id Security group ID to use for this instance.
158                     Use an arrayref for multiple group IDs
159
160  -security_group    Security group name to use for this instance.
161                     Use an arrayref for multiple values.
162
163  -user_data         User data to pass to the instances. Do NOT base64
164                     encode this. It will be done for you.
165
166  -instance_type     Type of the instance to use. See below for a
167                     list.
168
169  -availability_zone The availability zone you want to launch the
170                     instance into. Call $ec2->regions for a list.
171
172  -zone              Short version of -availability_aone.
173
174  -placement_zone    Deprecated version of -availability_zone.
175
176  -placement_group   An existing placement group to launch the
177                     instance into. Applicable to cluster instances
178                     only.
179
180  -tenancy           Specify 'dedicated' to launch the instance on a
181                     dedicated server. Only applicable for VPC
182                     instances.
183
184  -kernel_id         ID of the kernel to use for the instances,
185                     overriding the kernel specified in the image.
186
187  -ramdisk_id        ID of the ramdisk to use for the instances,
188                     overriding the ramdisk specified in the image.
189
190  -block_devices     Specify block devices to map onto the instances,
191                     overriding the values specified in the image.
192                     See below for the syntax of this argument.
193
194  -block_device_mapping  Alias for -block_devices.
195
196  -monitoring        Pass a true value to enable detailed monitoring.
197
198  -subnet_id         ID of the subnet to launch the instance
199                     into. Only applicable for VPC instances.
200
201  -termination_protection  Pass true to lock the instance so that it
202                     cannot be terminated using the API. Use
203                     modify_instance() to unset this if youu wish to
204                     terminate the instance later.
205
206  -disable_api_termination -- Same as above.
207
208  -shutdown_behavior Pass "stop" (the default) to stop the instance
209                     and save its disk state when "shutdown" is called
210                     from within the instance. Stopped instances can
211                     be restarted later. Pass "terminate" to
212                     instead terminate the instance and discard its
213                     state completely.
214
215  -instance_initiated_shutdown_behavior -- Same as above.
216
217  -private_ip_address Assign the instance to a specific IP address
218                     from a VPC subnet (VPC only).
219
220  -client_token      Unique identifier that you can provide to ensure
221                     idempotency of the request. You can use
222                     $ec2->token() to generate a suitable identifier.
223                     See http://docs.amazonwebservices.com/AWSEC2/
224                         latest/UserGuide/Run_Instance_Idempotency.html
225
226  -network_interfaces  A single network interface specification string
227                     or a list of them as an array reference (VPC only).
228                     These are described in more detail below.
229
230  -iam_arn           The Amazon resource name (ARN) of the IAM Instance Profile (IIP)
231                       to associate with the instances.
232
233  -iam_name          The name of the IAM instance profile (IIP) to associate with the
234                       instances.
235
236  -ebs_optimized     Boolean. If true, create an EBS-optimized instance
237                     (valid only for certain instance types.
238
239=item Instance types
240
241The following is the list of instance types currently allowed by
242Amazon:
243
244   m1.small   c1.medium  m2.xlarge   cc1.4xlarge  cg1.4xlarge  t1.micro
245   m1.large   c1.xlarge  m2.2xlarge
246   m1.xlarge             m2.4xlarge
247
248=item Block device syntax
249
250The syntax of -block_devices is identical to what is used by the
251ec2-run-instances command-line tool. Borrowing from the manual page of
252that tool:
253
254The format is '<device>=<block-device>', where 'block-device' can be one of the
255following:
256
257    - 'none': indicates that a block device that would be exposed at the
258       specified device should be suppressed. For example: '/dev/sdb=none'
259
260     - 'ephemeral[0-3]': indicates that the Amazon EC2 ephemeral store
261       (instance local storage) should be exposed at the specified device.
262       For example: '/dev/sdc=ephemeral0'.
263
264     - 'vol-12345678': A volume ID will attempt to attach the given volume to the
265       instance, contingent on volume state and availability zone.
266
267     - 'none': Suppress this block device, even if it is mapped in the AMI.
268
269     - '[<snapshot-id>][:<size>[:<delete-on-termination>[:<volume-type>[:<iops>]]]]':
270       indicates that an Amazon EBS volume, created from the specified Amazon EBS
271       snapshot, should be exposed at the specified device. The following
272       combinations are supported:
273
274         - '<snapshot-id>': the ID of an Amazon EBS snapshot, which must
275           be owned by or restorable by the caller. May be left out if a
276           <size> is specified, creating an empty Amazon EBS volume of
277           the specified size.
278
279         - '<size>': the size (GiBs) of the Amazon EBS volume to be
280           created. If a snapshot was specified, this may not be smaller
281           than the size of the snapshot itself.
282
283         - '<delete-on-termination>': indicates whether the Amazon EBS
284            volume should be deleted on instance termination. If not
285            specified, this will default to 'true' and the volume will be
286            deleted.
287
288         - '<volume-type>': The volume type. One of "standard", "gp2" or "io1".
289            "gp2" is the new general purpose SSD type.
290
291         - '<iops>': The number of I/O operations per second (IOPS) that
292           the volume suports. A number between 100 to 4000. Only valid
293           for volumes of type "io1".
294
295         Examples: -block_devices => '/dev/sdb=snap-7eb96d16'
296                   -block_devices => '/dev/sdc=snap-7eb96d16:80:false'
297                   -block_devices => '/dev/sdd=:120'
298                   -block_devices => '/dev/sdc=:120:true:io1:500'
299
300To provide multiple mappings, use an array reference. In this example,
301we launch two 'm1.small' instance in which /dev/sdb is mapped to
302ephemeral storage and /dev/sdc is mapped to a new 100 G EBS volume:
303
304 @i=$ec2->run_instances(-image_id  => 'ami-12345',
305                        -min_count => 2,
306                        -block_devices => ['/dev/sdb=ephemeral0',
307                                           '/dev/sdc=:100:true']
308    )
309
310=item Network interface syntax
311
312Each instance has a single primary network interface and private IP
313address that is ordinarily automatically assigned by Amazon. When you
314are running VPC instances, however, you can add additional elastic
315network interfaces (ENIs) to the instance and add secondary private IP
316addresses to one or more of these ENIs. ENIs can exist independently
317of instances, and be detached and reattached in much the same way as
318EBS volumes. This is explained in detail at
319http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/using-instance-addressing.html.
320
321The network configuration can be specified using the
322-network_interface parameter:
323
324 -network_interfaces => ['eth0=10.10.0.12:subnet-1234567:sg-1234567:true:My Custom Eth0',
325                         'eth1=10.10.1.12,10.10.1.13:subnet-999999:sg-1234567:true:My Custom Eth1']
326
327 or
328
329 -network_interfaces => ['eth0=10.10.0.12:subnet-1234567:sg-1234567:true:My Custom Eth0:true']
330
331The format is '<device>=<specification>'. The device is an ethernet
332interface name such as eth0, eth1, eth2, etc. The specification has up
333to five fields, each separated by the ":" character. All fields are
334optional and can be left blank. If missing, AWS will choose a default.
335
336  10.10.1.12,10.10.1.13:subnet-999999:sg-1234567:true:My Custom Eth1
337
338B<1. IP address(es)>: A single IP address in standard dot form, or a
339list of IP addresses separated by commas. The first address in the
340list will become the primary private IP address for the
341interface. Subsequent addresses will become secondary private
342addresses. You may specify "auto" or leave the field blank to have AWS
343choose an address automatically from within the subnetwork. To
344allocate several secondary IP addresses and have AWS pick the
345addresses automatically, give the count of secondary addresses you
346wish to allocate as an integer following the primary IP address. For
347example, "auto,3" will allocate an automatic primary IP address and
348three automatic secondary addresses, while "10.10.1.12,3" will force
349the primary address to be 10.10.1.12 and create three automatic
350secondary addresses.
351
352B<2. Subnetwork ID>: The ID of the VPC subnetwork in which the ENI
353resides. An instance may have several ENIs associated with it, and
354each ENI may be attached to a different subnetwork.
355
356B<3. Security group IDs>: A comma-delimited list of the security group
357IDs to associate with this ENI.
358
359B<4. DeleteOnTerminate>: True if this ENI should be automatically
360deleted when the instance terminates.
361
362B<5. Description>: A human-readable description of the ENI.
363
364B<6. Associate Public Address>: Indicates whether to assign a public
365IP address to the ENI on an instance in a VPC.  Can only be specified
366as true when a single network interface of device index 0 is created.
367Defaults to true when launching in a Default VPC.
368
369As an alternative syntax, you may specify the ID of an existing ENI in
370lieu of the primary IP address and other fields. The ENI will be
371attached to the instance if its permissions allow:
372
373 -network_interfaces => 'eth0=eni-123456'
374
375=item Return value
376
377On success, this method returns a list of VM::EC2::Instance
378objects. If called in a scalar context AND only one instance was
379requested, it will return a single instance object (rather than
380returning a list of size one which is then converted into numeric "1",
381as would be the usual Perl behavior).
382
383Note that this behavior is different from the Amazon API, which
384returns a ReservationSet. In this API, ask the instances for the
385the reservation, owner, requester, and group information using
386reservationId(), ownerId(), requesterId() and groups() methods.
387
388=item Tips
389
3901. If you have a VM::EC2::Image object returned from
391   Describe_images(), you may run it using run_instances():
392
393 my $image = $ec2->describe_images(-image_id  => 'ami-12345');
394 $image->run_instances( -min_count => 10,
395                        -block_devices => ['/dev/sdb=ephemeral0',
396                                           '/dev/sdc=:100:true']
397    )
398
3992. It may take a short while for a newly-launched instance to be
400    returned by describe_instances(). You may need to sleep for 1-2 seconds
401    before current_status() returns the correct value.
402
4033. Each instance object has a current_status() method which will
404   return the current run state of the instance. You may poll this
405   method to wait until the instance is running:
406
407   my $instance = $ec2->run_instances(...);
408   sleep 1;
409   while ($instance->current_status ne 'running') {
410      sleep 5;
411   }
412
4134. The utility method wait_for_instances() will wait until all
414   passed instances are in the 'running' or other terminal state.
415
416   my @instances = $ec2->run_instances(...);
417   $ec2->wait_for_instances(@instances);
418
419=back
420
421=cut
422
423sub run_instances {
424    my $self = shift;
425    my %args = $VEP->args('-image_id',@_);
426    $args{-image_id}  or croak "run_instances(): -image_id argument missing";
427
428    # the following define argument aliases
429    $args{-min_count} ||= 1;
430    $args{-max_count} ||= $args{-min_count};
431    $args{-availability_zone}  ||= $args{-zone};
432    $args{-availability_zone}  ||= $args{-placement_zone};
433    $args{-group_name} = $args{-placement_group};
434    $args{-monitoring_enabled} ||= $args{-monitoring};
435    $args{-instance_initiated_shutdown_behavior} ||= $args{-shutdown_behavior};
436    $args{-block_device_mapping} ||= $args{-block_devices};
437    $args{-network_interface}    ||= $args{-network_interfaces};
438    $args{-iam_instance_profile_arn}  ||= $args{-iam_arn};
439    $args{-iam_instance_profile_name} ||= $args{-iam_name};
440
441    my (@param) = $VEP->format_parms(\%args,{
442	single_parm => [qw(ImageId MinCount MaxCount KeyName KernelId RamdiskId PrivateIpAddress
443                           InstanceInitiatedShutdownBehavior ClientToken SubnetId InstanceType
444                           IamInstanceProfile.Arn IamInstanceProfile.Name
445                           )],
446	list_parm   => [qw(SecurityGroup SecurityGroupId)],
447        'Placement.single_parm'   => [qw(AvailabilityZone GroupName Tenancy)],
448	base64_parm => 'UserData',
449	boolean_parm=> [qw(DisableApiTermination EbsOptimized Monitoring.Enabled)],
450	block_device_parm         => 'BlockDeviceMapping',
451	network_interface_parm    => 'NetworkInterface',
452							   });
453    return $self->call('RunInstances',@param);
454}
455
456=head2 @s = $ec2->start_instances(@instance_ids)
457
458=head2 @s = $ec2->start_instances(-instance_id=>\@instance_ids)
459
460Start the instances named by @instance_ids and return one or more
461VM::EC2::Instance::State::Change objects.
462
463To wait for the all the instance ids to reach their final state
464("running" unless an error occurs), call wait_for_instances().
465
466Example:
467
468    # find all stopped instances
469    @instances = $ec2->describe_instances(-filter=>{'instance-state-name'=>'stopped'});
470
471    # start them
472    $ec2->start_instances(@instances)
473
474    # pause till they are running (or crashed)
475    $ec2->wait_for_instances(@instances)
476
477You can also start an instance by calling the object's start() method:
478
479    $instances[0]->start('wait');  # start instance and wait for it to
480				   # be running
481
482The objects returned by calling start_instances() indicate the current
483and previous states of the instance. The previous state is typically
484"stopped" and the current state is usually "pending." This information
485is only current to the time that the start_instances() method was called.
486To get the current run state of the instance, call its status()
487method:
488
489  die "ouch!" unless $instances[0]->current_status eq 'running';
490
491=cut
492
493sub start_instances {
494    my $self = shift;
495    my (@param) = $VEP->simple_arglist('InstanceId' => @_);
496    return $self->call('StartInstances',@param);
497}
498
499=head2 @s = $ec2->stop_instances(@instance_ids)
500
501=head2 @s = $ec2->stop_instances(-instance_id=>\@instance_ids,-force=>1)
502
503Stop the instances named by @instance_ids and return one or more
504VM::EC2::Instance::State::Change objects. In the named parameter
505version of this method, you may optionally provide a -force argument,
506which if true, forces the instance to halt without giving it a chance
507to run its shutdown procedure (the equivalent of pulling a physical
508machine's plug).
509
510To wait for instances to reach their final state, call
511wait_for_instances().
512
513Example:
514
515    # find all running instances
516    @instances = $ec2->describe_instances(-filter=>{'instance-state-name'=>'running'});
517
518    # stop them immediately and wait for confirmation
519    $ec2->stop_instances(-instance_id=>\@instances,-force=>1);
520    $ec2->wait_for_instances(@instances);
521
522You can also stop an instance by calling the object's start() method:
523
524    $instances[0]->stop('wait');  # stop first instance and wait for it to
525			          # stop completely
526
527=cut
528
529sub stop_instances {
530    my $self = shift;
531
532    my %args = $VEP->args('-instance_id' => @_);
533    $args{-instance_id} or croak "usage: stop_instances(\@instance_ids)";
534
535    my @params = $VEP->format_parms(\%args,{
536	single_parm => 'Force',
537	list_parm   => 'InstanceId'});
538
539    return $self->call('StopInstances',@params);
540}
541
542=head2 @s = $ec2->terminate_instances(@instance_ids)
543
544=head2 @s = $ec2->terminate_instances(-instance_id=>\@instance_ids)
545
546Terminate the instances named by @instance_ids and return one or more
547VM::EC2::Instance::State::Change objects. This method will fail
548for any instances whose termination protection field is set.
549
550To wait for the all the instances to reach their final state, call
551wait_for_instances().
552
553Example:
554
555    # find all instances tagged as "Version 0.5"
556    @instances = $ec2->describe_instances({'tag:Version'=>'0.5'});
557
558    # terminate them
559    $ec2->terminate_instances(@instances);
560
561You can also terminate an instance by calling its terminate() method:
562
563    $instances[0]->terminate;
564
565=cut
566
567sub terminate_instances {
568    my $self = shift;
569    my @params = $VEP->simple_arglist('InstanceId'=>@_);
570    @params or croak 'Usage: terminate_instances(\@instance_ids)';
571    return $self->call('TerminateInstances',@params);
572}
573
574=head2 @s = $ec2->reboot_instances(@instance_ids)
575
576=head2 @s = $ec2->reboot_instances(-instance_id=>\@instance_ids)
577
578Reboot the instances named by @instance_ids and return one or more
579VM::EC2::Instance::State::Change objects.
580
581To wait for the all the instances to reach their final state, call
582wait_for_instances().
583
584You can also reboot an instance by calling its terminate() method:
585
586    $instances[0]->reboot;
587
588=cut
589
590sub reboot_instances {
591    my $self = shift;
592    my @params = $VEP->simple_arglist('InstanceId'=>@_);
593    return $self->call('RebootInstances',@params);
594}
595
596=head2 $boolean = $ec2->confirm_product_instance($instance_id,$product_code,$callback)
597
598=head2 $boolean = $ec2->confirm_product_instance(-instance_id=>$instance_id,-product_code=>$product_code,-cb=>$callback)
599
600Return "true" if the instance indicated by $instance_id is associated
601with the given product code.
602
603=cut
604
605sub confirm_product_instance {
606    my $self = shift;
607    @_ >= 2 or croak "Usage: confirm_product_instance(\$instance_id,\$product_code)";
608    my %args = $_[0] =~ /^-/ ? @_ : (-instance_id=>$_[0],-product_code=>$_[1],-cb=>$_[2]);
609    my @params = $VEP->format_parms(\%args,{
610	single_parm => [qw(InstanceId ProductCode)]}
611	);
612    return $self->call('ConfirmProductInstance',@params);
613}
614
615=head2 $meta = VM::EC2->instance_metadata
616
617=head2 $meta = $ec2->instance_metadata
618
619B<For use on running EC2 instances only:> This method returns a
620VM::EC2::Instance::Metadata object that will return information about
621the currently running instance using the HTTP:// metadata fields
622described at
623http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?instancedata-data-categories.html. This
624is usually fastest way to get runtime information on the current
625instance.
626
627Note that this method can be called as either an instance or a class
628method.
629
630=cut
631
632sub instance_metadata {
633    VM::EC2::Dispatch::load_module('VM::EC2::Instance::Metadata');
634    return VM::EC2::Instance::Metadata->new();
635}
636
637=head2 @data = $ec2->describe_instance_attribute($instance_id,$attribute,$callback)
638
639This method returns instance attributes. Only one attribute can be
640retrieved at a time. The following is the list of attributes that can be
641retrieved:
642
643 instanceType                      -- scalar
644 kernel                            -- scalar
645 ramdisk                           -- scalar
646 userData                          -- scalar
647 disableApiTermination             -- scalar
648 instanceInitiatedShutdownBehavior -- scalar
649 rootDeviceName                    -- scalar
650 blockDeviceMapping                -- list of hashref
651 sourceDestCheck                   -- scalar
652 groupSet                          -- list of scalar
653 productCodes                      -- list of hashref
654 ebsOptimized                      -- scalar
655 sriovNetSupport                   -- scalar
656
657All of these values can be retrieved more conveniently from the
658L<VM::EC2::Instance> object returned from describe_instances(), so
659there is no attempt to parse the results of this call into Perl
660objects. Therefore, some of the attributes, in particular
661'blockDeviceMapping' will be returned as raw hashrefs.
662
663=cut
664
665sub describe_instance_attribute {
666    my $self = shift;
667    @_ >= 2 or croak "Usage: describe_instance_attribute(\$instance_id,\$attribute_name)";
668    my %args = $_[0]=~/^-/ ? @_ : (-instance_id=>$_[0],-attribute=>$_[1],-cb=>$_[2]);
669    my (@param)  = $VEP->format_parms(\%args,
670					     {single_parm => [qw(InstanceId Attribute)]});
671    my $result = $self->call('DescribeInstanceAttribute',@param);
672    return $result && $result->attribute($args{-attribute});
673}
674
675=head2 $boolean = $ec2->modify_instance_attribute($instance_id,-$attribute_name=>$value)
676
677This method changes instance attributes. It can only be applied to stopped instances.
678The following is the list of attributes that can be set:
679
680 -instance_type           -- type of instance, e.g. "m1.small"
681 -kernel                  -- kernel id
682 -ramdisk                 -- ramdisk id
683 -user_data               -- user data
684 -termination_protection  -- true to prevent termination from the console
685 -disable_api_termination -- same as the above
686 -shutdown_behavior       -- "stop" or "terminate"
687 -instance_initiated_shutdown_behavior -- same as above
688 -root_device_name        -- root device name
689 -source_dest_check       -- enable NAT (VPC only)
690 -group_id                -- VPC security group
691 -block_devices           -- Specify block devices to change
692                             deleteOnTermination flag
693 -block_device_mapping    -- Alias for -block_devices
694 -ebs_optimization        -- EBS Optmization
695 -sriov_net_support       -- Enhanced networking support
696
697Only one attribute can be changed in a single request. For example:
698
699  $ec2->modify_instance_attribute('i-12345',-kernel=>'aki-f70657b2');
700
701The result code is true if the attribute was successfully modified,
702false otherwise. In the latter case, $ec2->error() will provide the
703error message.
704
705The ability to change the deleteOnTermination flag for attached block devices
706is not documented in the official Amazon API documentation, but appears to work.
707The syntax is:
708
709# turn on deleteOnTermination
710 $ec2->modify_instance_attribute(-block_devices=>'/dev/sdf=v-12345')
711# turn off deleteOnTermination
712 $ec2->modify_instance_attribute(-block_devices=>'/dev/sdf=v-12345')
713
714The syntax is slightly different from what is used by -block_devices
715in run_instances(), and is "device=volumeId:boolean". Multiple block
716devices can be specified using an arrayref.
717
718=cut
719
720sub modify_instance_attribute {
721    my $self = shift;
722    my $instance_id = shift or croak "Usage: modify_instance_attribute(\$instanceId,%param)";
723    my %args   = @_;
724    $args{-instance_id}             =                $instance_id;
725    $args{-block_device_mapping}  ||=                $args{-block_devices};
726    $args{-disable_api_termination} = 'true'      if $args{-termination_protection};
727    $args{-instance_initiated_shutdown_behavior} ||= $args{-shutdown_behavior};
728
729    my (@param) = $VEP->format_parms(\%args,{
730	single_parm => 'InstanceId',
731	value_parm  => [qw(InstanceType Kernel Ramdisk UserData DisableApiTermination
732                           InstanceInitiatedShutdownBehavior SourceDestCheck
733                           SriovNetSupport)],
734	list_parm   => 'GroupId',
735	block_device_parm => 'BlockDeviceMapping',
736        boolean_parm => 'ebsOptimized',
737					   });
738    return $self->call('ModifyInstanceAttribute',@param);
739}
740
741=head2 $boolean = $ec2->reset_instance_attribute($instance_id,$attribute [,$callback])
742
743This method resets an attribute of the given instance to its default
744value. Valid attributes are "kernel", "ramdisk" and
745"sourceDestCheck". The result code is true if the reset was
746successful.
747
748=cut
749
750sub reset_instance_attribute {
751    my $self = shift;
752    @_      >= 2 or croak "Usage: reset_instance_attribute(\$instanceId,\$attribute_name)";
753    my ($instance_id,$attribute) = @_;
754    my %valid = map {$_=>1} qw(kernel ramdisk sourceDestCheck);
755    $valid{$attribute} or croak "attribute to reset must be one of 'kernel', 'ramdisk', or 'sourceDestCheck'";
756    return $self->call('ResetInstanceAttribute',InstanceId=>$instance_id,Attribute=>$attribute);
757}
758
759=head2 @status_list = $ec2->describe_instance_status(@instance_ids);
760
761=head2 @status_list = $ec2->describe_instance_status(-instance_id=>\@ids,-filter=>\%filters,%other_args);
762
763=head2 @status_list = $ec2->describe_instance_status(\%filters);
764
765This method returns a list of VM::EC2::Instance::Status objects
766corresponding to status checks and scheduled maintenance events on the
767instances of interest. You may provide a list of instances to return
768information on, a set of filters, or both.
769
770The filters are described at
771http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstanceStatus.html. The
772brief list is:
773
774availability-zone, event.code, event.description, event.not-after,
775event.not-before, instance-state-name, instance-state-code,
776system-status.status, system-status.reachability,
777instance-status.status, instance-status.reachability.
778
779Request arguments are:
780
781  -instance_id            Scalar or array ref containing the instance ID(s) to return
782                           information about (optional).
783
784  -filter                 Filters to apply (optional).
785
786  -include_all_instances  If true, include all instances, including those that are
787                           stopped, pending and shutting down. Otherwise, returns
788                           the status of running instances only.
789
790 -max_results             An integer corresponding to the number of instance items
791                           per response (must be greater than 5).
792
793If -max_results is specified, then the call will return at most the
794number of instances you requested. You may see whether there are additional
795results by calling more_instance_status(), and then retrieve the next set of
796results with additional call(s) to describe_instance_status():
797
798 my @results = $ec2->describe_instance_status(-max_results => 10);
799 do_something(\@results);
800 while ($ec2->more_instance_status) {
801    @results = $ec2->describe_instance_status;
802    do_something(\@results);
803 }
804
805NOTE: As of 29 July 2012, passing -include_all_instances causes an EC2
806"unknown parameter" error, indicating some mismatch between the
807documented API and the actual one.
808
809=cut
810
811sub more_instance_status {
812    my $self = shift;
813    return $self->{instance_status_token} &&
814           !$self->{instance_status_stop};
815}
816
817sub describe_instance_status {
818    my $self = shift;
819    my @parms;
820
821    if (!@_ && $self->{instance_status_token} && $self->{instance_status_args}) {
822	@parms = (@{$self->{instance_status_args}},NextToken=>$self->{instance_status_token});
823    }
824
825    else {
826	my %args = $VEP->args('InstanceId',@_);
827	(@parms) = $VEP->format_parms(\%args,{
828	    list_parm   => 'InstanceId',
829	    filter_parm => 'Filter',
830	    boolean_parm=> 'IncludeAllInstances',
831	    single_parm => 'MaxResults'});
832
833	if ($args{-max_results}) {
834	    $self->{instance_status_token} = 'xyzzy'; # dummy value
835	    $self->{instance_status_args}  = \@parms;
836	}
837
838    }
839    return $self->call('DescribeInstanceStatus',@parms);
840}
841
842=head2 $t = $ec2->token
843
844Return a client token for use with start_instances().
845
846=cut
847
848sub token {
849    my $self = shift;
850    my $seed = $self->{idempotent_seed};
851    $self->{idempotent_seed} = sha1_hex($seed);
852    $seed =~ s/(.{6})/$1-/g;
853    return $seed;
854}
855
856=head2 $ec2->wait_for_instances(@instances)
857
858Wait for all members of the provided list of instances to reach some
859terminal state ("running", "stopped" or "terminated"), and then return
860a hash reference that maps each instance ID to its final state.
861
862Typical usage:
863
864 my @instances = $image->run_instances(-key_name      =>'My_key',
865                                       -security_group=>'default',
866                                       -min_count     =>2,
867                                       -instance_type => 't1.micro')
868           or die $ec2->error_str;
869 my $status = $ec2->wait_for_instances(@instances);
870 my @failed = grep {$status->{$_} ne 'running'} @instances;
871 print "The following failed: @failed\n";
872
873If no terminal state is reached within a set timeout, then this method
874returns undef and sets $ec2->error_str() to a suitable message. The
875timeout, which defaults to 10 minutes (600 seconds), can be get or set
876with $ec2->wait_for_timeout().
877
878=cut
879
880sub wait_for_instances {
881    my $self = shift;
882    $self->wait_for_terminal_state(\@_,
883				   ['running','stopped','terminated'],
884				   $self->wait_for_timeout);
885}
886
887
888=head1 SEE ALSO
889
890L<VM::EC2>
891
892=head1 AUTHOR
893
894Lincoln Stein E<lt>lincoln.stein@gmail.comE<gt>.
895
896Copyright (c) 2011 Ontario Institute for Cancer Research
897
898This package and its accompanying libraries is free software; you can
899redistribute it and/or modify it under the terms of the GPL (either
900version 1, or at your option, any later version) or the Artistic
901License 2.0.  Refer to LICENSE for the full license text. In addition,
902please see DISCLAIMER.txt for disclaimers of warranty.
903
904=cut
905
906
9071;
908