1# Copyright (c) 2013 Amazon.com, Inc. or its affiliates.  All Rights Reserved
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
23import boto
24from boto.connection import AWSQueryConnection
25from boto.regioninfo import RegionInfo
26from boto.exception import JSONResponseError
27from boto.directconnect import exceptions
28from boto.compat import json
29
30
31class DirectConnectConnection(AWSQueryConnection):
32    """
33    AWS Direct Connect makes it easy to establish a dedicated network
34    connection from your premises to Amazon Web Services (AWS). Using
35    AWS Direct Connect, you can establish private connectivity between
36    AWS and your data center, office, or colocation environment, which
37    in many cases can reduce your network costs, increase bandwidth
38    throughput, and provide a more consistent network experience than
39    Internet-based connections.
40
41    The AWS Direct Connect API Reference provides descriptions,
42    syntax, and usage examples for each of the actions and data types
43    for AWS Direct Connect. Use the following links to get started
44    using the AWS Direct Connect API Reference :
45
46
47    + `Actions`_: An alphabetical list of all AWS Direct Connect
48      actions.
49    + `Data Types`_: An alphabetical list of all AWS Direct Connect
50      data types.
51    + `Common Query Parameters`_: Parameters that all Query actions
52      can use.
53    + `Common Errors`_: Client and server errors that all actions can
54      return.
55    """
56    APIVersion = "2012-10-25"
57    DefaultRegionName = "us-east-1"
58    DefaultRegionEndpoint = "directconnect.us-east-1.amazonaws.com"
59    ServiceName = "DirectConnect"
60    TargetPrefix = "OvertureService"
61    ResponseError = JSONResponseError
62
63    _faults = {
64        "DirectConnectClientException": exceptions.DirectConnectClientException,
65        "DirectConnectServerException": exceptions.DirectConnectServerException,
66    }
67
68    def __init__(self, **kwargs):
69        region = kwargs.pop('region', None)
70        if not region:
71            region = RegionInfo(self, self.DefaultRegionName,
72                                self.DefaultRegionEndpoint)
73
74        if 'host' not in kwargs:
75            kwargs['host'] = region.endpoint
76
77        super(DirectConnectConnection, self).__init__(**kwargs)
78        self.region = region
79
80    def _required_auth_capability(self):
81        return ['hmac-v4']
82
83    def allocate_connection_on_interconnect(self, bandwidth, connection_name,
84                                            owner_account, interconnect_id,
85                                            vlan):
86        """
87        Creates a hosted connection on an interconnect.
88
89        Allocates a VLAN number and a specified amount of bandwidth
90        for use by a hosted connection on the given interconnect.
91
92        :type bandwidth: string
93        :param bandwidth: Bandwidth of the connection.
94        Example: " 500Mbps "
95
96        Default: None
97
98        :type connection_name: string
99        :param connection_name: Name of the provisioned connection.
100        Example: " 500M Connection to AWS "
101
102        Default: None
103
104        :type owner_account: string
105        :param owner_account: Numeric account Id of the customer for whom the
106            connection will be provisioned.
107        Example: 123443215678
108
109        Default: None
110
111        :type interconnect_id: string
112        :param interconnect_id: ID of the interconnect on which the connection
113            will be provisioned.
114        Example: dxcon-456abc78
115
116        Default: None
117
118        :type vlan: integer
119        :param vlan: The dedicated VLAN provisioned to the connection.
120        Example: 101
121
122        Default: None
123
124        """
125        params = {
126            'bandwidth': bandwidth,
127            'connectionName': connection_name,
128            'ownerAccount': owner_account,
129            'interconnectId': interconnect_id,
130            'vlan': vlan,
131        }
132        return self.make_request(action='AllocateConnectionOnInterconnect',
133                                 body=json.dumps(params))
134
135    def allocate_private_virtual_interface(self, connection_id,
136                                           owner_account,
137                                           new_private_virtual_interface_allocation):
138        """
139        Provisions a private virtual interface to be owned by a
140        different customer.
141
142        The owner of a connection calls this function to provision a
143        private virtual interface which will be owned by another AWS
144        customer.
145
146        Virtual interfaces created using this function must be
147        confirmed by the virtual interface owner by calling
148        ConfirmPrivateVirtualInterface. Until this step has been
149        completed, the virtual interface will be in 'Confirming'
150        state, and will not be available for handling traffic.
151
152        :type connection_id: string
153        :param connection_id: The connection ID on which the private virtual
154            interface is provisioned.
155        Default: None
156
157        :type owner_account: string
158        :param owner_account: The AWS account that will own the new private
159            virtual interface.
160        Default: None
161
162        :type new_private_virtual_interface_allocation: dict
163        :param new_private_virtual_interface_allocation: Detailed information
164            for the private virtual interface to be provisioned.
165        Default: None
166
167        """
168        params = {
169            'connectionId': connection_id,
170            'ownerAccount': owner_account,
171            'newPrivateVirtualInterfaceAllocation': new_private_virtual_interface_allocation,
172        }
173        return self.make_request(action='AllocatePrivateVirtualInterface',
174                                 body=json.dumps(params))
175
176    def allocate_public_virtual_interface(self, connection_id, owner_account,
177                                          new_public_virtual_interface_allocation):
178        """
179        Provisions a public virtual interface to be owned by a
180        different customer.
181
182        The owner of a connection calls this function to provision a
183        public virtual interface which will be owned by another AWS
184        customer.
185
186        Virtual interfaces created using this function must be
187        confirmed by the virtual interface owner by calling
188        ConfirmPublicVirtualInterface. Until this step has been
189        completed, the virtual interface will be in 'Confirming'
190        state, and will not be available for handling traffic.
191
192        :type connection_id: string
193        :param connection_id: The connection ID on which the public virtual
194            interface is provisioned.
195        Default: None
196
197        :type owner_account: string
198        :param owner_account: The AWS account that will own the new public
199            virtual interface.
200        Default: None
201
202        :type new_public_virtual_interface_allocation: dict
203        :param new_public_virtual_interface_allocation: Detailed information
204            for the public virtual interface to be provisioned.
205        Default: None
206
207        """
208        params = {
209            'connectionId': connection_id,
210            'ownerAccount': owner_account,
211            'newPublicVirtualInterfaceAllocation': new_public_virtual_interface_allocation,
212        }
213        return self.make_request(action='AllocatePublicVirtualInterface',
214                                 body=json.dumps(params))
215
216    def confirm_connection(self, connection_id):
217        """
218        Confirm the creation of a hosted connection on an
219        interconnect.
220
221        Upon creation, the hosted connection is initially in the
222        'Ordering' state, and will remain in this state until the
223        owner calls ConfirmConnection to confirm creation of the
224        hosted connection.
225
226        :type connection_id: string
227        :param connection_id: ID of the connection.
228        Example: dxcon-fg5678gh
229
230        Default: None
231
232        """
233        params = {'connectionId': connection_id, }
234        return self.make_request(action='ConfirmConnection',
235                                 body=json.dumps(params))
236
237    def confirm_private_virtual_interface(self, virtual_interface_id,
238                                          virtual_gateway_id):
239        """
240        Accept ownership of a private virtual interface created by
241        another customer.
242
243        After the virtual interface owner calls this function, the
244        virtual interface will be created and attached to the given
245        virtual private gateway, and will be available for handling
246        traffic.
247
248        :type virtual_interface_id: string
249        :param virtual_interface_id: ID of the virtual interface.
250        Example: dxvif-123dfg56
251
252        Default: None
253
254        :type virtual_gateway_id: string
255        :param virtual_gateway_id: ID of the virtual private gateway that will
256            be attached to the virtual interface.
257        A virtual private gateway can be managed via the Amazon Virtual Private
258            Cloud (VPC) console or the `EC2 CreateVpnGateway`_ action.
259
260        Default: None
261
262        """
263        params = {
264            'virtualInterfaceId': virtual_interface_id,
265            'virtualGatewayId': virtual_gateway_id,
266        }
267        return self.make_request(action='ConfirmPrivateVirtualInterface',
268                                 body=json.dumps(params))
269
270    def confirm_public_virtual_interface(self, virtual_interface_id):
271        """
272        Accept ownership of a public virtual interface created by
273        another customer.
274
275        After the virtual interface owner calls this function, the
276        specified virtual interface will be created and made available
277        for handling traffic.
278
279        :type virtual_interface_id: string
280        :param virtual_interface_id: ID of the virtual interface.
281        Example: dxvif-123dfg56
282
283        Default: None
284
285        """
286        params = {'virtualInterfaceId': virtual_interface_id, }
287        return self.make_request(action='ConfirmPublicVirtualInterface',
288                                 body=json.dumps(params))
289
290    def create_connection(self, location, bandwidth, connection_name):
291        """
292        Creates a new connection between the customer network and a
293        specific AWS Direct Connect location.
294
295        A connection links your internal network to an AWS Direct
296        Connect location over a standard 1 gigabit or 10 gigabit
297        Ethernet fiber-optic cable. One end of the cable is connected
298        to your router, the other to an AWS Direct Connect router. An
299        AWS Direct Connect location provides access to Amazon Web
300        Services in the region it is associated with. You can
301        establish connections with AWS Direct Connect locations in
302        multiple regions, but a connection in one region does not
303        provide connectivity to other regions.
304
305        :type location: string
306        :param location: Where the connection is located.
307        Example: EqSV5
308
309        Default: None
310
311        :type bandwidth: string
312        :param bandwidth: Bandwidth of the connection.
313        Example: 1Gbps
314
315        Default: None
316
317        :type connection_name: string
318        :param connection_name: The name of the connection.
319        Example: " My Connection to AWS "
320
321        Default: None
322
323        """
324        params = {
325            'location': location,
326            'bandwidth': bandwidth,
327            'connectionName': connection_name,
328        }
329        return self.make_request(action='CreateConnection',
330                                 body=json.dumps(params))
331
332    def create_interconnect(self, interconnect_name, bandwidth, location):
333        """
334        Creates a new interconnect between a AWS Direct Connect
335        partner's network and a specific AWS Direct Connect location.
336
337        An interconnect is a connection which is capable of hosting
338        other connections. The AWS Direct Connect partner can use an
339        interconnect to provide sub-1Gbps AWS Direct Connect service
340        to tier 2 customers who do not have their own connections.
341        Like a standard connection, an interconnect links the AWS
342        Direct Connect partner's network to an AWS Direct Connect
343        location over a standard 1 Gbps or 10 Gbps Ethernet fiber-
344        optic cable. One end is connected to the partner's router, the
345        other to an AWS Direct Connect router.
346
347        For each end customer, the AWS Direct Connect partner
348        provisions a connection on their interconnect by calling
349        AllocateConnectionOnInterconnect. The end customer can then
350        connect to AWS resources by creating a virtual interface on
351        their connection, using the VLAN assigned to them by the AWS
352        Direct Connect partner.
353
354        :type interconnect_name: string
355        :param interconnect_name: The name of the interconnect.
356        Example: " 1G Interconnect to AWS "
357
358        Default: None
359
360        :type bandwidth: string
361        :param bandwidth: The port bandwidth
362        Example: 1Gbps
363
364        Default: None
365
366        Available values: 1Gbps,10Gbps
367
368        :type location: string
369        :param location: Where the interconnect is located
370        Example: EqSV5
371
372        Default: None
373
374        """
375        params = {
376            'interconnectName': interconnect_name,
377            'bandwidth': bandwidth,
378            'location': location,
379        }
380        return self.make_request(action='CreateInterconnect',
381                                 body=json.dumps(params))
382
383    def create_private_virtual_interface(self, connection_id,
384                                         new_private_virtual_interface):
385        """
386        Creates a new private virtual interface. A virtual interface
387        is the VLAN that transports AWS Direct Connect traffic. A
388        private virtual interface supports sending traffic to a single
389        virtual private cloud (VPC).
390
391        :type connection_id: string
392        :param connection_id: ID of the connection.
393        Example: dxcon-fg5678gh
394
395        Default: None
396
397        :type new_private_virtual_interface: dict
398        :param new_private_virtual_interface: Detailed information for the
399            private virtual interface to be created.
400        Default: None
401
402        """
403        params = {
404            'connectionId': connection_id,
405            'newPrivateVirtualInterface': new_private_virtual_interface,
406        }
407        return self.make_request(action='CreatePrivateVirtualInterface',
408                                 body=json.dumps(params))
409
410    def create_public_virtual_interface(self, connection_id,
411                                        new_public_virtual_interface):
412        """
413        Creates a new public virtual interface. A virtual interface is
414        the VLAN that transports AWS Direct Connect traffic. A public
415        virtual interface supports sending traffic to public services
416        of AWS such as Amazon Simple Storage Service (Amazon S3).
417
418        :type connection_id: string
419        :param connection_id: ID of the connection.
420        Example: dxcon-fg5678gh
421
422        Default: None
423
424        :type new_public_virtual_interface: dict
425        :param new_public_virtual_interface: Detailed information for the
426            public virtual interface to be created.
427        Default: None
428
429        """
430        params = {
431            'connectionId': connection_id,
432            'newPublicVirtualInterface': new_public_virtual_interface,
433        }
434        return self.make_request(action='CreatePublicVirtualInterface',
435                                 body=json.dumps(params))
436
437    def delete_connection(self, connection_id):
438        """
439        Deletes the connection.
440
441        Deleting a connection only stops the AWS Direct Connect port
442        hour and data transfer charges. You need to cancel separately
443        with the providers any services or charges for cross-connects
444        or network circuits that connect you to the AWS Direct Connect
445        location.
446
447        :type connection_id: string
448        :param connection_id: ID of the connection.
449        Example: dxcon-fg5678gh
450
451        Default: None
452
453        """
454        params = {'connectionId': connection_id, }
455        return self.make_request(action='DeleteConnection',
456                                 body=json.dumps(params))
457
458    def delete_interconnect(self, interconnect_id):
459        """
460        Deletes the specified interconnect.
461
462        :type interconnect_id: string
463        :param interconnect_id: The ID of the interconnect.
464        Example: dxcon-abc123
465
466        """
467        params = {'interconnectId': interconnect_id, }
468        return self.make_request(action='DeleteInterconnect',
469                                 body=json.dumps(params))
470
471    def delete_virtual_interface(self, virtual_interface_id):
472        """
473        Deletes a virtual interface.
474
475        :type virtual_interface_id: string
476        :param virtual_interface_id: ID of the virtual interface.
477        Example: dxvif-123dfg56
478
479        Default: None
480
481        """
482        params = {'virtualInterfaceId': virtual_interface_id, }
483        return self.make_request(action='DeleteVirtualInterface',
484                                 body=json.dumps(params))
485
486    def describe_connections(self, connection_id=None):
487        """
488        Displays all connections in this region.
489
490        If a connection ID is provided, the call returns only that
491        particular connection.
492
493        :type connection_id: string
494        :param connection_id: ID of the connection.
495        Example: dxcon-fg5678gh
496
497        Default: None
498
499        """
500        params = {}
501        if connection_id is not None:
502            params['connectionId'] = connection_id
503        return self.make_request(action='DescribeConnections',
504                                 body=json.dumps(params))
505
506    def describe_connections_on_interconnect(self, interconnect_id):
507        """
508        Return a list of connections that have been provisioned on the
509        given interconnect.
510
511        :type interconnect_id: string
512        :param interconnect_id: ID of the interconnect on which a list of
513            connection is provisioned.
514        Example: dxcon-abc123
515
516        Default: None
517
518        """
519        params = {'interconnectId': interconnect_id, }
520        return self.make_request(action='DescribeConnectionsOnInterconnect',
521                                 body=json.dumps(params))
522
523    def describe_interconnects(self, interconnect_id=None):
524        """
525        Returns a list of interconnects owned by the AWS account.
526
527        If an interconnect ID is provided, it will only return this
528        particular interconnect.
529
530        :type interconnect_id: string
531        :param interconnect_id: The ID of the interconnect.
532        Example: dxcon-abc123
533
534        """
535        params = {}
536        if interconnect_id is not None:
537            params['interconnectId'] = interconnect_id
538        return self.make_request(action='DescribeInterconnects',
539                                 body=json.dumps(params))
540
541    def describe_locations(self):
542        """
543        Returns the list of AWS Direct Connect locations in the
544        current AWS region. These are the locations that may be
545        selected when calling CreateConnection or CreateInterconnect.
546        """
547        params = {}
548        return self.make_request(action='DescribeLocations',
549                                 body=json.dumps(params))
550
551    def describe_virtual_gateways(self):
552        """
553        Returns a list of virtual private gateways owned by the AWS
554        account.
555
556        You can create one or more AWS Direct Connect private virtual
557        interfaces linking to a virtual private gateway. A virtual
558        private gateway can be managed via Amazon Virtual Private
559        Cloud (VPC) console or the `EC2 CreateVpnGateway`_ action.
560        """
561        params = {}
562        return self.make_request(action='DescribeVirtualGateways',
563                                 body=json.dumps(params))
564
565    def describe_virtual_interfaces(self, connection_id=None,
566                                    virtual_interface_id=None):
567        """
568        Displays all virtual interfaces for an AWS account. Virtual
569        interfaces deleted fewer than 15 minutes before
570        DescribeVirtualInterfaces is called are also returned. If a
571        connection ID is included then only virtual interfaces
572        associated with this connection will be returned. If a virtual
573        interface ID is included then only a single virtual interface
574        will be returned.
575
576        A virtual interface (VLAN) transmits the traffic between the
577        AWS Direct Connect location and the customer.
578
579        If a connection ID is provided, only virtual interfaces
580        provisioned on the specified connection will be returned. If a
581        virtual interface ID is provided, only this particular virtual
582        interface will be returned.
583
584        :type connection_id: string
585        :param connection_id: ID of the connection.
586        Example: dxcon-fg5678gh
587
588        Default: None
589
590        :type virtual_interface_id: string
591        :param virtual_interface_id: ID of the virtual interface.
592        Example: dxvif-123dfg56
593
594        Default: None
595
596        """
597        params = {}
598        if connection_id is not None:
599            params['connectionId'] = connection_id
600        if virtual_interface_id is not None:
601            params['virtualInterfaceId'] = virtual_interface_id
602        return self.make_request(action='DescribeVirtualInterfaces',
603                                 body=json.dumps(params))
604
605    def make_request(self, action, body):
606        headers = {
607            'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action),
608            'Host': self.region.endpoint,
609            'Content-Type': 'application/x-amz-json-1.1',
610            'Content-Length': str(len(body)),
611        }
612        http_request = self.build_base_http_request(
613            method='POST', path='/', auth_path='/', params={},
614            headers=headers, data=body)
615        response = self._mexe(http_request, sender=None,
616                              override_num_retries=10)
617        response_body = response.read().decode('utf-8')
618        boto.log.debug(response_body)
619        if response.status == 200:
620            if response_body:
621                return json.loads(response_body)
622        else:
623            json_body = json.loads(response_body)
624            fault_name = json_body.get('__type', None)
625            exception_class = self._faults.get(fault_name, self.ResponseError)
626            raise exception_class(response.status, response.reason,
627                                  body=json_body)
628