1# Copyright (c) 2009-2010 Mitch Garnaat http://garnaat.org/
2#
3# Permission is hereby granted, free of charge, to any person obtaining a
4# copy of this software and associated documentation files (the
5# "Software"), to deal in the Software without restriction, including
6# without limitation the rights to use, copy, modify, merge, publish, dis-
7# tribute, sublicense, and/or sell copies of the Software, and to permit
8# persons to whom the Software is furnished to do so, subject to the fol-
9# lowing conditions:
10#
11# The above copyright notice and this permission notice shall be included
12# in all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20# IN THE SOFTWARE.
21
22"""
23Represents a Virtual Private Cloud.
24"""
25
26from boto.ec2.ec2object import TaggedEC2Object
27
28class VPC(TaggedEC2Object):
29
30    def __init__(self, connection=None):
31        """
32        Represents a VPC.
33
34        :ivar id: The unique ID of the VPC.
35        :ivar dhcp_options_id: The ID of the set of DHCP options you've associated with the VPC
36                                (or default if the default options are associated with the VPC).
37        :ivar state: The current state of the VPC.
38        :ivar cidr_block: The CIDR block for the VPC.
39        :ivar is_default: Indicates whether the VPC is the default VPC.
40        :ivar instance_tenancy: The allowed tenancy of instances launched into the VPC.
41        :ivar classic_link_enabled: Indicates whether ClassicLink is enabled.
42        """
43        super(VPC, self).__init__(connection)
44        self.id = None
45        self.dhcp_options_id = None
46        self.state = None
47        self.cidr_block = None
48        self.is_default = None
49        self.instance_tenancy = None
50        self.classic_link_enabled = None
51
52    def __repr__(self):
53        return 'VPC:%s' % self.id
54
55    def endElement(self, name, value, connection):
56        if name == 'vpcId':
57            self.id = value
58        elif name == 'dhcpOptionsId':
59            self.dhcp_options_id = value
60        elif name == 'state':
61            self.state = value
62        elif name == 'cidrBlock':
63            self.cidr_block = value
64        elif name == 'isDefault':
65            self.is_default = True if value == 'true' else False
66        elif name == 'instanceTenancy':
67            self.instance_tenancy = value
68        elif name == 'classicLinkEnabled':
69            self.classic_link_enabled = value
70        else:
71            setattr(self, name, value)
72
73    def delete(self):
74        return self.connection.delete_vpc(self.id)
75
76    def _update(self, updated):
77        self.__dict__.update(updated.__dict__)
78
79    def _get_status_then_update_vpc(self, get_status_method, validate=False,
80                                    dry_run=False):
81        vpc_list = get_status_method(
82            [self.id],
83            dry_run=dry_run
84        )
85        if len(vpc_list):
86            updated_vpc = vpc_list[0]
87            self._update(updated_vpc)
88        elif validate:
89            raise ValueError('%s is not a valid VPC ID' % (self.id,))
90
91    def update(self, validate=False, dry_run=False):
92        self._get_status_then_update_vpc(
93            self.connection.get_all_vpcs,
94            validate=validate,
95            dry_run=dry_run
96        )
97        return self.state
98
99    def update_classic_link_enabled(self, validate=False, dry_run=False):
100        """
101        Updates instance's classic_link_enabled attribute
102
103        :rtype: bool
104        :return: self.classic_link_enabled after update has occurred.
105        """
106        self._get_status_then_update_vpc(
107            self.connection.get_all_classic_link_vpcs,
108            validate=validate,
109            dry_run=dry_run
110        )
111        return self.classic_link_enabled
112
113    def disable_classic_link(self, dry_run=False):
114        """
115        Disables  ClassicLink  for  a VPC. You cannot disable ClassicLink for a
116        VPC that has EC2-Classic instances linked to it.
117
118        :type dry_run: bool
119        :param dry_run: Set to True if the operation should not actually run.
120
121        :rtype: bool
122        :return: True if successful
123        """
124        return self.connection.disable_vpc_classic_link(self.id,
125                                                        dry_run=dry_run)
126
127    def enable_classic_link(self, dry_run=False):
128        """
129        Enables a VPC for ClassicLink. You can then link EC2-Classic instances
130        to your ClassicLink-enabled VPC to allow communication over private IP
131        addresses. You cannot enable your VPC for ClassicLink if any of your
132        VPC's route tables have existing routes for address ranges within the
133        10.0.0.0/8 IP address range, excluding local routes for VPCs in the
134        10.0.0.0/16 and 10.1.0.0/16 IP address ranges.
135
136        :type dry_run: bool
137        :param dry_run: Set to True if the operation should not actually run.
138
139        :rtype: bool
140        :return: True if successful
141        """
142        return self.connection.enable_vpc_classic_link(self.id,
143                                                       dry_run=dry_run)
144
145    def attach_classic_instance(self, instance_id, groups, dry_run=False):
146        """
147        Links  an EC2-Classic instance to a ClassicLink-enabled VPC through one
148        or more of the VPC's security groups. You cannot link an EC2-Classic
149        instance to more than one VPC at a time. You can only link an instance
150        that's in the running state. An instance is automatically unlinked from
151        a VPC when it's stopped. You can link it to the VPC again when you
152        restart it.
153
154        After you've linked an instance, you cannot  change  the VPC security
155        groups  that are associated with it. To change the security groups, you
156        must first unlink the instance, and then link it again.
157
158        Linking your instance to a VPC is sometimes referred  to  as  attaching
159        your instance.
160
161        :type intance_id: str
162        :param instance_is: The ID of a ClassicLink-enabled VPC.
163
164        :tye groups: list
165        :param groups: The ID of one or more of the VPC's security groups.
166            You cannot specify security groups from a different VPC. The
167            members of the list can be
168            :class:`boto.ec2.securitygroup.SecurityGroup` objects or
169            strings of the id's of the security groups.
170
171        :type dry_run: bool
172        :param dry_run: Set to True if the operation should not actually run.
173
174        :rtype: bool
175        :return: True if successful
176        """
177        return self.connection.attach_classic_link_vpc(
178            vpc_id=self.id,
179            instance_id=instance_id,
180            groups=groups,
181            dry_run=dry_run
182        )
183
184    def detach_classic_instance(self, instance_id, dry_run=False):
185        """
186        Unlinks a linked EC2-Classic instance from a VPC. After the instance
187        has been unlinked, the VPC security groups are no longer associated
188        with it. An instance is automatically unlinked from a VPC when
189        it's stopped.
190
191        :type intance_id: str
192        :param instance_is: The ID of the VPC to which the instance is linked.
193
194        :type dry_run: bool
195        :param dry_run: Set to True if the operation should not actually run.
196
197        :rtype: bool
198        :return: True if successful
199        """
200        return self.connection.detach_classic_link_vpc(
201            vpc_id=self.id,
202            instance_id=instance_id,
203            dry_run=dry_run
204        )
205