1
# Copyright 2014 VMware, Inc.
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5
# not use this file except in compliance with the License. You may obtain
6
# a copy of the License at
8
# http://www.apache.org/licenses/LICENSE-2.0
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
# License for the specific language governing permissions and limitations
17
from oslo.serialization import jsonutils
19
from neutron.openstack.common import log
20
from neutron.plugins.vmware.api_client import exception as api_exc
21
from neutron.plugins.vmware.common import exceptions as nsx_exc
22
from neutron.plugins.vmware.common import utils
23
from neutron.plugins.vmware import nsxlib
24
from neutron.plugins.vmware.nsxlib import switch
28
HTTP_DELETE = "DELETE"
31
GWSERVICE_RESOURCE = "gateway-service"
32
TRANSPORTNODE_RESOURCE = "transport-node"
34
LOG = log.getLogger(__name__)
37
def create_l2_gw_service(cluster, tenant_id, display_name, devices):
38
"""Create a NSX Layer-2 Network Gateway Service.
40
:param cluster: The target NSX cluster
41
:param tenant_id: Identifier of the Openstack tenant for which
43
:param display_name: Descriptive name of this gateway service
44
:param devices: List of transport node uuids (and network
45
interfaces on them) to use for the network gateway service
46
:raise NsxApiException: if there is a problem while communicating
47
with the NSX controller
49
# NOTE(salvatore-orlando): This is a little confusing, but device_id in
50
# NSX is actually the identifier a physical interface on the gateway
51
# device, which in the Neutron API is referred as interface_name
52
gateways = [{"transport_node_uuid": device['id'],
53
"device_id": device['interface_name'],
54
"type": "L2Gateway"} for device in devices]
56
"display_name": utils.check_and_truncate(display_name),
57
"tags": utils.get_tags(os_tid=tenant_id),
59
"type": "L2GatewayServiceConfig"
61
return nsxlib.do_request(
62
HTTP_POST, nsxlib._build_uri_path(GWSERVICE_RESOURCE),
63
jsonutils.dumps(gwservice_obj), cluster=cluster)
66
def plug_l2_gw_service(cluster, lswitch_id, lport_id,
67
gateway_id, vlan_id=None):
68
"""Plug a Layer-2 Gateway Attachment object in a logical port."""
69
att_obj = {'type': 'L2GatewayAttachment',
70
'l2_gateway_service_uuid': gateway_id}
72
att_obj['vlan_id'] = vlan_id
73
return switch.plug_interface(cluster, lswitch_id, lport_id, att_obj)
76
def get_l2_gw_service(cluster, gateway_id):
77
return nsxlib.do_request(
78
HTTP_GET, nsxlib._build_uri_path(GWSERVICE_RESOURCE,
79
resource_id=gateway_id),
83
def get_l2_gw_services(cluster, tenant_id=None,
84
fields=None, filters=None):
85
actual_filters = dict(filters or {})
87
actual_filters['tag'] = tenant_id
88
actual_filters['tag_scope'] = 'os_tid'
89
return nsxlib.get_all_query_pages(
90
nsxlib._build_uri_path(GWSERVICE_RESOURCE,
91
filters=actual_filters),
95
def update_l2_gw_service(cluster, gateway_id, display_name):
96
# TODO(salvatore-orlando): Allow updates for gateways too
97
gwservice_obj = get_l2_gw_service(cluster, gateway_id)
101
gwservice_obj["display_name"] = utils.check_and_truncate(display_name)
102
return nsxlib.do_request(HTTP_PUT,
103
nsxlib._build_uri_path(GWSERVICE_RESOURCE,
104
resource_id=gateway_id),
105
jsonutils.dumps(gwservice_obj), cluster=cluster)
108
def delete_l2_gw_service(cluster, gateway_id):
109
nsxlib.do_request(HTTP_DELETE,
110
nsxlib._build_uri_path(GWSERVICE_RESOURCE,
111
resource_id=gateway_id),
115
def _build_gateway_device_body(tenant_id, display_name, neutron_id,
116
connector_type, connector_ip,
117
client_certificate, tz_uuid):
119
connector_type_mappings = {
120
utils.NetworkTypes.STT: "STTConnector",
121
utils.NetworkTypes.GRE: "GREConnector",
122
utils.NetworkTypes.BRIDGE: "BridgeConnector",
123
'ipsec%s' % utils.NetworkTypes.STT: "IPsecSTT",
124
'ipsec%s' % utils.NetworkTypes.GRE: "IPsecGRE"}
125
nsx_connector_type = connector_type_mappings.get(connector_type)
126
body = {"display_name": utils.check_and_truncate(display_name),
127
"tags": utils.get_tags(os_tid=tenant_id,
128
q_gw_dev_id=neutron_id),
129
"admin_status_enabled": True}
131
if connector_ip and nsx_connector_type:
132
body["transport_connectors"] = [
133
{"transport_zone_uuid": tz_uuid,
134
"ip_address": connector_ip,
135
"type": nsx_connector_type}]
137
if client_certificate:
138
body["credential"] = {"client_certificate":
139
{"pem_encoded": client_certificate},
140
"type": "SecurityCertificateCredential"}
144
def create_gateway_device(cluster, tenant_id, display_name, neutron_id,
145
tz_uuid, connector_type, connector_ip,
147
body = _build_gateway_device_body(tenant_id, display_name, neutron_id,
148
connector_type, connector_ip,
149
client_certificate, tz_uuid)
151
return nsxlib.do_request(
152
HTTP_POST, nsxlib._build_uri_path(TRANSPORTNODE_RESOURCE),
153
jsonutils.dumps(body, sort_keys=True), cluster=cluster)
154
except api_exc.InvalidSecurityCertificate:
155
raise nsx_exc.InvalidSecurityCertificate()
158
def update_gateway_device(cluster, gateway_id, tenant_id,
159
display_name, neutron_id,
160
tz_uuid, connector_type, connector_ip,
162
body = _build_gateway_device_body(tenant_id, display_name, neutron_id,
163
connector_type, connector_ip,
164
client_certificate, tz_uuid)
166
return nsxlib.do_request(
168
nsxlib._build_uri_path(TRANSPORTNODE_RESOURCE,
169
resource_id=gateway_id),
170
jsonutils.dumps(body, sort_keys=True), cluster=cluster)
171
except api_exc.InvalidSecurityCertificate:
172
raise nsx_exc.InvalidSecurityCertificate()
175
def delete_gateway_device(cluster, device_uuid):
176
return nsxlib.do_request(HTTP_DELETE,
177
nsxlib._build_uri_path(TRANSPORTNODE_RESOURCE,
182
def get_gateway_device_status(cluster, device_uuid):
183
status_res = nsxlib.do_request(HTTP_GET,
184
nsxlib._build_uri_path(
185
TRANSPORTNODE_RESOURCE,
187
extra_action='status'),
189
# Returns the connection status
190
return status_res['connection']['connected']
193
def get_gateway_devices_status(cluster, tenant_id=None):
195
gw_device_query_path = nsxlib._build_uri_path(
196
TRANSPORTNODE_RESOURCE,
198
relations="TransportNodeStatus",
199
filters={'tag': tenant_id,
200
'tag_scope': 'os_tid'})
202
gw_device_query_path = nsxlib._build_uri_path(
203
TRANSPORTNODE_RESOURCE,
205
relations="TransportNodeStatus")
207
response = nsxlib.get_all_query_pages(gw_device_query_path, cluster)
209
for item in response:
210
results[item['uuid']] = (item['_relations']['TransportNodeStatus']
211
['connection']['connected'])