Files
ec2-api/ec2api/api/dhcp_options.py
alevine eb1725aa29 Added filtering by tags
Change-Id: I0b4a005a5b4585478e32fb84b50b379a32f09d48
2014-12-24 21:45:35 +04:00

180 lines
6.7 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 ec2api.api import clients
from ec2api.api import common
from ec2api.api import ec2utils
from ec2api.api import utils
from ec2api.db import api as db_api
from ec2api import exception
from ec2api.openstack.common.gettextutils import _
from ec2api.openstack.common import log as logging
LOG = logging.getLogger(__name__)
ec2_opts = [
cfg.StrOpt('network_device_mtu',
default=1500,
help='MTU size to set by DHCP for instances. Corresponds '
'with the network_device_mtu in nova.conf.')
]
CONF = cfg.CONF
CONF.register_opts(ec2_opts)
"""DHCP options related API implementation
"""
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, 'dopt',
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']}
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', 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, 'dopt', 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, 'dopt', rollback_dhcp_options_id)
if dhcp_options_id is not None else
None)
with utils.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)