
New units tests that loads and runs all the admin utilities resources and operations. We do not check specific arguments and scenarios for now. Just making sure it can run. Change-Id: Iac7fcf4fc2546856ba5f3fc22e868c0ed7839443
279 lines
10 KiB
Python
279 lines
10 KiB
Python
# Copyright 2016 VMware, Inc. All rights reserved.
|
|
#
|
|
# 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 logging
|
|
import xml.etree.ElementTree as et
|
|
|
|
from neutron.callbacks import registry
|
|
from neutron import context
|
|
from neutron.db import models_v2
|
|
from neutron.db import securitygroups_db
|
|
|
|
from vmware_nsx.db import db as nsx_db
|
|
from vmware_nsx.db import nsx_models
|
|
from vmware_nsx.db import nsxv_models
|
|
from vmware_nsx import plugin
|
|
from vmware_nsx.shell.admin.plugins.common import constants
|
|
from vmware_nsx.shell.admin.plugins.common import formatters
|
|
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
|
|
from vmware_nsx.shell.admin.plugins.nsxv.resources import utils
|
|
from vmware_nsx.shell import resources as nsxadmin
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class NsxVPluginWrapper(plugin.NsxVPlugin):
|
|
def _start_rpc_listeners(self):
|
|
pass
|
|
|
|
def _validate_config(self):
|
|
pass
|
|
|
|
|
|
class NeutronSecurityGroupDB(utils.NeutronDbClient,
|
|
securitygroups_db.SecurityGroupDbMixin):
|
|
def __init__(self):
|
|
super(NeutronSecurityGroupDB, self)
|
|
# FIXME(roeyc): context is already defined in NeutrondDbClient
|
|
self.context = context.get_admin_context()
|
|
|
|
def get_security_groups_mappings(self):
|
|
q = self.context.session.query(
|
|
securitygroups_db.SecurityGroup.name,
|
|
securitygroups_db.SecurityGroup.id,
|
|
nsxv_models.NsxvSecurityGroupSectionMapping.ip_section_id,
|
|
nsx_models.NeutronNsxSecurityGroupMapping.nsx_id).join(
|
|
nsxv_models.NsxvSecurityGroupSectionMapping,
|
|
nsx_models.NeutronNsxSecurityGroupMapping).all()
|
|
sg_mappings = [{'name': mapp.name,
|
|
'id': mapp.id,
|
|
'section-uri': mapp.ip_section_id,
|
|
'nsx-securitygroup-id': mapp.nsx_id}
|
|
for mapp in q]
|
|
return sg_mappings
|
|
|
|
def get_security_group(self, sg_id):
|
|
return super(NeutronSecurityGroupDB, self).get_security_group(
|
|
self.context, sg_id)
|
|
|
|
def get_security_groups(self):
|
|
return super(NeutronSecurityGroupDB,
|
|
self).get_security_groups(self.context)
|
|
|
|
def delete_security_group_section_mapping(self, sg_id):
|
|
fw_mapping = self.context.session.query(
|
|
nsxv_models.NsxvSecurityGroupSectionMapping).filter_by(
|
|
neutron_id=sg_id).one_or_none()
|
|
if fw_mapping:
|
|
with self.context.session.begin(subtransactions=True):
|
|
self.context.session.delete(fw_mapping)
|
|
|
|
def delete_security_group_backend_mapping(self, sg_id):
|
|
sg_mapping = self.context.session.query(
|
|
nsx_models.NeutronNsxSecurityGroupMapping).filter_by(
|
|
neutron_id=sg_id).one_or_none()
|
|
if sg_mapping:
|
|
with self.context.session.begin(subtransactions=True):
|
|
self.context.session.delete(sg_mapping)
|
|
|
|
def get_vnics_in_security_group(self, security_group_id):
|
|
vnics = []
|
|
query = self.context.session.query(
|
|
models_v2.Port.id, models_v2.Port.device_id
|
|
).join(securitygroups_db.SecurityGroupPortBinding).filter_by(
|
|
security_group_id=security_group_id).all()
|
|
for p in query:
|
|
vnic_index = plugin._get_port_vnic_index(self.context, p.id)
|
|
vnic_id = plugin._get_port_vnic_id(vnic_index, p.device_id)
|
|
vnics.append(vnic_id)
|
|
return vnics
|
|
|
|
|
|
class NsxFirewallAPI(object):
|
|
def __init__(self):
|
|
self.vcns = utils.get_nsxv_client()
|
|
|
|
def list_security_groups(self):
|
|
h, secgroups = self.vcns.list_security_groups()
|
|
root = et.fromstring(secgroups)
|
|
secgroups = []
|
|
for sg in root.iter('securitygroup'):
|
|
sg_id = sg.find('objectId').text
|
|
# This specific security-group is not relevant to the plugin
|
|
if sg_id == 'securitygroup-1':
|
|
continue
|
|
secgroups.append({'name': sg.find('name').text,
|
|
'id': sg_id})
|
|
return secgroups
|
|
|
|
def list_fw_sections(self):
|
|
h, firewall_config = self.vcns.get_dfw_config()
|
|
root = et.fromstring(firewall_config)
|
|
sections = []
|
|
for sec in root.iter('section'):
|
|
sec_id = sec.attrib['id']
|
|
# Don't show NSX default sections, which are not relevant to OS.
|
|
if sec_id in ['1001', '1002', '1003']:
|
|
continue
|
|
sections.append({'name': sec.attrib['name'],
|
|
'id': sec_id})
|
|
return sections
|
|
|
|
|
|
neutron_sg = NeutronSecurityGroupDB()
|
|
nsxv_firewall = NsxFirewallAPI()
|
|
plugin = NsxVPluginWrapper()
|
|
|
|
|
|
def _log_info(resource, data, attrs=['name', 'id']):
|
|
LOG.info(formatters.output_formatter(resource, data, attrs))
|
|
|
|
|
|
def list_handler(resource):
|
|
def wrap(func):
|
|
registry.subscribe(func, resource,
|
|
nsxadmin.Operations.LIST.value)
|
|
return func
|
|
return wrap
|
|
|
|
|
|
def list_mismatches_handler(resource):
|
|
def wrap(func):
|
|
registry.subscribe(func, resource,
|
|
nsxadmin.Operations.LIST_MISMATCHES.value)
|
|
return func
|
|
return wrap
|
|
|
|
|
|
def fix_mismatches_handler(resource):
|
|
def wrap(func):
|
|
registry.subscribe(func, resource,
|
|
nsxadmin.Operations.FIX_MISMATCH.value)
|
|
return func
|
|
return wrap
|
|
|
|
|
|
@list_handler(constants.SECURITY_GROUPS)
|
|
@admin_utils.output_header
|
|
def neutron_list_security_groups_mappings(resource, event, trigger, **kwargs):
|
|
sg_mappings = neutron_sg.get_security_groups_mappings()
|
|
_log_info(constants.SECURITY_GROUPS,
|
|
sg_mappings,
|
|
attrs=['name', 'id', 'section-uri', 'nsx-securitygroup-id'])
|
|
return bool(sg_mappings)
|
|
|
|
|
|
@list_handler(constants.FIREWALL_SECTIONS)
|
|
@admin_utils.output_header
|
|
def nsx_list_dfw_sections(resource, event, trigger, **kwargs):
|
|
fw_sections = nsxv_firewall.list_fw_sections()
|
|
_log_info(constants.FIREWALL_SECTIONS, fw_sections)
|
|
return bool(fw_sections)
|
|
|
|
|
|
@list_handler(constants.FIREWALL_NSX_GROUPS)
|
|
@admin_utils.output_header
|
|
def nsx_list_security_groups(resource, event, trigger, **kwargs):
|
|
nsx_secgroups = nsxv_firewall.list_security_groups()
|
|
_log_info(constants.FIREWALL_NSX_GROUPS, nsx_secgroups)
|
|
return bool(nsx_secgroups)
|
|
|
|
|
|
def _find_missing_security_groups():
|
|
nsx_secgroups = nsxv_firewall.list_security_groups()
|
|
sg_mappings = neutron_sg.get_security_groups_mappings()
|
|
missing_secgroups = {}
|
|
for sg_db in sg_mappings:
|
|
for nsx_sg in nsx_secgroups:
|
|
if nsx_sg['id'] == sg_db['nsx-securitygroup-id']:
|
|
break
|
|
else:
|
|
missing_secgroups[sg_db['id']] = sg_db
|
|
return missing_secgroups
|
|
|
|
|
|
@list_mismatches_handler(constants.FIREWALL_NSX_GROUPS)
|
|
@admin_utils.output_header
|
|
def list_missing_security_groups(resource, event, trigger, **kwargs):
|
|
sgs_with_missing_nsx_group = _find_missing_security_groups()
|
|
missing_securitgroups_info = [
|
|
{'securitygroup-name': sg['name'],
|
|
'securitygroup-id': sg['id'],
|
|
'nsx-securitygroup-id':
|
|
sg['nsx-securitygroup-id']}
|
|
for sg in sgs_with_missing_nsx_group.values()]
|
|
_log_info(constants.FIREWALL_NSX_GROUPS, missing_securitgroups_info,
|
|
attrs=['securitygroup-name', 'securitygroup-id',
|
|
'nsx-securitygroup-id'])
|
|
return bool(missing_securitgroups_info)
|
|
|
|
|
|
def _find_missing_sections():
|
|
fw_sections = nsxv_firewall.list_fw_sections()
|
|
sg_mappings = neutron_sg.get_security_groups_mappings()
|
|
missing_sections = {}
|
|
for sg_db in sg_mappings:
|
|
for fw_section in fw_sections:
|
|
if fw_section['id'] == sg_db.get('section-uri', '').split('/')[-1]:
|
|
break
|
|
else:
|
|
missing_sections[sg_db['id']] = sg_db
|
|
return missing_sections
|
|
|
|
|
|
@list_mismatches_handler(constants.FIREWALL_SECTIONS)
|
|
@admin_utils.output_header
|
|
def list_missing_firewall_sections(resource, event, trigger, **kwargs):
|
|
sgs_with_missing_section = _find_missing_sections()
|
|
missing_sections_info = [{'securitygroup-name': sg['name'],
|
|
'securitygroup-id': sg['id'],
|
|
'section-id': sg['section-uri']}
|
|
for sg in sgs_with_missing_section.values()]
|
|
_log_info(constants.FIREWALL_SECTIONS, missing_sections_info,
|
|
attrs=['securitygroup-name', 'securitygroup-id', 'section-uri'])
|
|
return bool(missing_sections_info)
|
|
|
|
|
|
@fix_mismatches_handler(constants.SECURITY_GROUPS)
|
|
@admin_utils.output_header
|
|
def fix_security_groups(resource, event, trigger, **kwargs):
|
|
context_ = context.get_admin_context()
|
|
sgs_with_missing_section = _find_missing_sections()
|
|
sgs_with_missing_nsx_group = _find_missing_security_groups()
|
|
plugin = NsxVPluginWrapper()
|
|
# If only the fw section is missing then create it.
|
|
for sg_id in (set(sgs_with_missing_section.keys()) -
|
|
set(sgs_with_missing_nsx_group.keys())):
|
|
neutron_sg.delete_security_group_section_mapping(sg_id)
|
|
secgroup = plugin.get_security_group(context_, sg_id)
|
|
plugin._create_fw_section_for_security_group(
|
|
context_, secgroup,
|
|
sgs_with_missing_section[sg_id]['nsx-securitygroup-id'])
|
|
|
|
# If nsx security-group is missing then create both nsx security-group and
|
|
# a new fw section (remove old one).
|
|
for sg_id, sg in sgs_with_missing_nsx_group.items():
|
|
secgroup = plugin.get_security_group(context_, sg_id)
|
|
if sg_id not in sgs_with_missing_section:
|
|
plugin._delete_section(sg['section-uri'])
|
|
neutron_sg.delete_security_group_section_mapping(sg_id)
|
|
neutron_sg.delete_security_group_backend_mapping(sg_id)
|
|
plugin._process_security_group_create_backend_resources(context_,
|
|
secgroup)
|
|
nsx_id = nsx_db.get_nsx_security_group_id(context_.session, sg_id)
|
|
for vnic_id in neutron_sg.get_vnics_in_security_group(sg_id):
|
|
plugin._add_member_to_security_group(nsx_id, vnic_id)
|