2a0b6a4e5296bb93ce3ecb9fceb5fb5c4ea84194
[snaps.git] / snaps / config / router.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 from snaps.config.network import PortConfig
16 from snaps.openstack.utils import neutron_utils, keystone_utils
17
18
19 class RouterConfig(object):
20     """
21     Class representing a router configuration
22     """
23
24     def __init__(self, **kwargs):
25         """
26         Constructor - all parameters are optional
27         :param name: The router name.
28         :param project_name: The name of the project who owns the network. Only
29                              administrative users can specify a project ID
30                              other than their own. You cannot change this value
31                              through authorization policies.
32         :param external_gateway: Name of the external network to which to route
33         :param admin_state_up: The administrative status of the router.
34                                True = up / False = down (default True)
35         :param internal_subnets: List of subnet names to which to connect this
36                                  router (this way is deprecated).
37                                  *** NEW WAY ***
38                                  List of dict where the key is 'subnet' that
39                                  contains members with the following keys:
40                                  project_name, network_name, and subnet_name
41         :param port_settings: List of PortConfig objects
42         :return:
43         """
44         self.name = kwargs.get('name')
45         self.project_name = kwargs.get('project_name')
46         self.external_gateway = kwargs.get('external_gateway')
47
48         self.admin_state_up = kwargs.get('admin_state_up', True)
49         self.enable_snat = kwargs.get('enable_snat')
50         if kwargs.get('internal_subnets'):
51             self.internal_subnets = kwargs['internal_subnets']
52             if isinstance(self.internal_subnets, dict):
53                 if 'subnet' not in self.internal_subnets:
54                     raise RouterConfigError(
55                         'subnet is a required key to internal_subnets')
56                 if 'project_name' not in self.internal_subnets['subnet']:
57                     raise RouterConfigError(
58                         'subnet.project is a required key to subnet')
59                 if 'network_name' not in self.internal_subnets['subnet']:
60                     raise RouterConfigError(
61                         'network_name is a required key to subnet')
62                 if 'subnet_name' not in self.internal_subnets['subnet']:
63                     raise RouterConfigError(
64                         'subnet_name is a required key to subnet')
65         else:
66             self.internal_subnets = list()
67
68         self.port_settings = list()
69         if kwargs.get('interfaces', kwargs.get('port_settings')):
70             interfaces = kwargs.get('interfaces', kwargs.get('port_settings'))
71             for interface in interfaces:
72                 if isinstance(interface, PortConfig):
73                     self.port_settings.append(interface)
74                 else:
75                     self.port_settings.append(
76                         PortConfig(**interface['port']))
77
78         if not self.name:
79             raise RouterConfigError('Name is required')
80
81     def dict_for_neutron(self, neutron, os_creds):
82         """
83         Returns a dictionary object representing this object.
84         This is meant to be converted into JSON designed for use by the Neutron
85         API
86
87         TODO - expand automated testing to exercise all parameters
88         :param neutron: The neutron client to retrieve external network
89                         information if necessary
90         :param os_creds: The OpenStack credentials for retrieving the keystone
91                          client for looking up the project ID when the
92                          self.project_name is not None
93         :return: the dictionary object
94         """
95         out = dict()
96         ext_gw = dict()
97
98         session = keystone_utils.keystone_session(os_creds)
99         keystone = keystone_utils.keystone_client(os_creds, session)
100         try:
101             if self.name:
102                 out['name'] = self.name
103             if self.project_name:
104                 project = keystone_utils.get_project(
105                     keystone=keystone, project_name=self.project_name)
106                 if project:
107                         out['tenant_id'] = project.id
108                 else:
109                     raise RouterConfigError(
110                         'Could not find project ID for project named - ' +
111                         self.project_name)
112             if self.admin_state_up is not None:
113                 out['admin_state_up'] = self.admin_state_up
114             if self.external_gateway:
115                 ext_net = neutron_utils.get_network(
116                     neutron, keystone, network_name=self.external_gateway)
117                 if ext_net:
118                     ext_gw['network_id'] = ext_net.id
119                     out['external_gateway_info'] = ext_gw
120                 else:
121                     raise RouterConfigError(
122                         'Could not find the external network named - ' +
123                         self.external_gateway)
124         finally:
125             keystone_utils.close_session(session)
126
127         return {'router': out}
128
129
130 class RouterConfigError(Exception):
131     """
132     Exception to be thrown when router settings attributes are incorrect
133     """