1cdaf9fe00
Change-Id: I3e5de1b5bd3a0fe238d78c32b627609e1ef886ae
187 lines
6.8 KiB
Python
187 lines
6.8 KiB
Python
# Copyright 2014
|
|
# The Cloudscaling Group, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
|
|
import netaddr
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
from ec2api.api import clients
|
|
from ec2api.api import common
|
|
from ec2api.api import ec2utils
|
|
from ec2api.db import api as db_api
|
|
from ec2api import exception
|
|
from ec2api.i18n import _
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
ec2_opts = [
|
|
cfg.IntOpt('network_device_mtu',
|
|
default=1500,
|
|
help='MTU size to set by DHCP for instances. Corresponds '
|
|
'with the network_device_mtu in ec2api.conf.')
|
|
]
|
|
|
|
CONF = cfg.CONF
|
|
CONF.register_opts(ec2_opts)
|
|
|
|
|
|
"""DHCP options related API implementation
|
|
"""
|
|
|
|
|
|
class Validator(common.Validator):
|
|
|
|
def dopt_id_or_default(self, id):
|
|
if id == 'default':
|
|
return
|
|
self.ec2_id(id, ['dopt'])
|
|
|
|
|
|
DHCP_OPTIONS_MAP = {'domain-name-servers': 'dns-server',
|
|
'domain-name': 'domain-name',
|
|
'ntp-servers': 'ntp-server',
|
|
'netbios-name-servers': 'netbios-ns',
|
|
'netbios-node-type': 'netbios-nodetype'}
|
|
|
|
|
|
def create_dhcp_options(context, dhcp_configuration):
|
|
dhcp_options = {}
|
|
for dhcp_option in dhcp_configuration:
|
|
key = dhcp_option['key']
|
|
values = dhcp_option['value']
|
|
if key not in DHCP_OPTIONS_MAP:
|
|
raise exception.InvalidParameterValue(
|
|
value=values,
|
|
parameter=key,
|
|
reason='Unrecognized key is specified')
|
|
if not type(values) is list:
|
|
raise exception.InvalidParameterValue(
|
|
value=values,
|
|
parameter=key,
|
|
reason='List of values is expected')
|
|
if key not in ['domain-name', 'netbios-node-type']:
|
|
ips = []
|
|
for ip in values:
|
|
ip_address = netaddr.IPAddress(ip)
|
|
if not ip_address:
|
|
raise exception.InvalidParameterValue(
|
|
value=ip,
|
|
parameter=key,
|
|
reason='Invalid list of IPs is specified')
|
|
ips.append(ip)
|
|
dhcp_options[key] = ips
|
|
else:
|
|
dhcp_options[key] = values
|
|
dhcp_options = db_api.add_item(context, 'dopt',
|
|
{'dhcp_configuration': dhcp_options})
|
|
return {'dhcpOptions': _format_dhcp_options(context, dhcp_options)}
|
|
|
|
|
|
def delete_dhcp_options(context, dhcp_options_id):
|
|
if not dhcp_options_id:
|
|
raise exception.MissingParameter(
|
|
_('DHCP options ID must be specified'))
|
|
dhcp_options = ec2utils.get_db_item(context, dhcp_options_id)
|
|
vpcs = db_api.get_items(context, 'vpc')
|
|
for vpc in vpcs:
|
|
if dhcp_options['id'] == vpc.get('dhcp_options_id'):
|
|
raise exception.DependencyViolation(
|
|
obj1_id=dhcp_options['id'],
|
|
obj2_id=vpc['id'])
|
|
db_api.delete_item(context, dhcp_options['id'])
|
|
return True
|
|
|
|
|
|
class DhcpOptionsDescriber(common.TaggableItemsDescriber,
|
|
common.NonOpenstackItemsDescriber):
|
|
|
|
KIND = 'dopt'
|
|
FILTER_MAP = {'dhcp_options_id': 'dhcpOptionsId',
|
|
'key': ['dhcpConfigurationSet', 'key'],
|
|
'value': ['dhcpConfigurationSet', ['valueSet', 'value']]}
|
|
|
|
def format(self, dhcp_options):
|
|
return _format_dhcp_options(self.context, dhcp_options)
|
|
|
|
|
|
def describe_dhcp_options(context, dhcp_options_id=None,
|
|
filter=None):
|
|
formatted_dhcp_options = DhcpOptionsDescriber().describe(
|
|
context, ids=dhcp_options_id, filter=filter)
|
|
return {'dhcpOptionsSet': formatted_dhcp_options}
|
|
|
|
|
|
def associate_dhcp_options(context, dhcp_options_id, vpc_id):
|
|
vpc = ec2utils.get_db_item(context, vpc_id)
|
|
rollback_dhcp_options_id = vpc.get('dhcp_options_id')
|
|
if dhcp_options_id == 'default':
|
|
dhcp_options_id = None
|
|
dhcp_options = None
|
|
else:
|
|
dhcp_options = ec2utils.get_db_item(context, dhcp_options_id)
|
|
dhcp_options_id = dhcp_options['id']
|
|
neutron = clients.neutron(context)
|
|
os_ports = neutron.list_ports()['ports']
|
|
network_interfaces = db_api.get_items(context, 'eni')
|
|
rollback_dhcp_options_object = (
|
|
db_api.get_item_by_id(context, rollback_dhcp_options_id)
|
|
if dhcp_options_id is not None else
|
|
None)
|
|
with common.OnCrashCleaner() as cleaner:
|
|
_associate_vpc_item(context, vpc, dhcp_options_id)
|
|
cleaner.addCleanup(_associate_vpc_item, context, vpc,
|
|
rollback_dhcp_options_id)
|
|
for network_interface in network_interfaces:
|
|
os_port = next((p for p in os_ports
|
|
if p['id'] == network_interface['os_id']), None)
|
|
if not os_port:
|
|
continue
|
|
_add_dhcp_opts_to_port(context, dhcp_options,
|
|
network_interface, os_port, neutron)
|
|
cleaner.addCleanup(_add_dhcp_opts_to_port, context,
|
|
rollback_dhcp_options_object, network_interface,
|
|
os_port, neutron)
|
|
return True
|
|
|
|
|
|
def _add_dhcp_opts_to_port(context, dhcp_options, network_interface, os_port,
|
|
neutron=None):
|
|
dhcp_opts = [{'opt_name': 'mtu',
|
|
'opt_value': str(CONF.network_device_mtu)}]
|
|
if dhcp_options is not None:
|
|
for key, values in dhcp_options['dhcp_configuration'].items():
|
|
strvalues = [str(v) for v in values]
|
|
dhcp_opts.append({'opt_name': DHCP_OPTIONS_MAP[key],
|
|
'opt_value': ','.join(strvalues)})
|
|
if not neutron:
|
|
neutron = clients.neutron(context)
|
|
neutron.update_port(os_port['id'],
|
|
{'port': {'extra_dhcp_opts': dhcp_opts}})
|
|
|
|
|
|
def _format_dhcp_options(context, dhcp_options):
|
|
dhcp_configuration = []
|
|
for key, values in dhcp_options['dhcp_configuration'].items():
|
|
items = [{'value': v} for v in values]
|
|
dhcp_configuration.append({'key': key, 'valueSet': items})
|
|
return {'dhcpOptionsId': dhcp_options['id'],
|
|
'dhcpConfigurationSet': dhcp_configuration}
|
|
|
|
|
|
def _associate_vpc_item(context, vpc, dhcp_options_id):
|
|
vpc['dhcp_options_id'] = dhcp_options_id
|
|
db_api.update_item(context, vpc)
|