<commit_before># Copyright 2015 Mirantis, 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.

from time import sleep
import uuid
import six


from neutron.i18n import _LI, _LW
from oslo_log import log
from oslo_vmware import api
from oslo_vmware import exceptions as vmware_exceptions
from oslo_vmware import vim_util

from vmware_dvs.common import constants as dvs_const
from vmware_dvs.common import exceptions

LOG = log.getLogger(__name__)


class DVSController(object):
    """Controls one DVS."""

    def __init__(self, dvs_name, connection):
        self.connection = connection
        try:
            self.dvs_name = dvs_name
            self._dvs, self._datacenter = self._get_dvs(dvs_name, connection)
            # (SlOPS) To do release blocked port after use
            self._blocked_ports = set()
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)

    def create_network(self, network, segment):
        name = self._get_net_name(self.dvs_name, network)
        blocked = not network['admin_state_up']

        try:
            pg_spec = self._build_pg_create_spec(
                name,
                segment['segmentation_id'],
                blocked)
            pg_create_task = self.connection.invoke_api(
                self.connection.vim,
                'CreateDVPortgroup_Task',
                self._dvs, spec=pg_spec)

            result = self.connection.wait_for_task(pg_create_task)
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
        else:
            pg = result.result
            LOG.info(_LI('Network %(name)s created \n%(pg_ref)s'),
                     {'name': name, 'pg_ref': pg})
            return pg

    def update_network(self, network, original=None):
        if original:
            name = self._get_net_name(self.dvs_name, original)
        else:
            name = self._get_net_name(self.dvs_name, network)
        blocked = not network['admin_state_up']
        try:
            pg_ref = self._get_pg_by_name(name)
            pg_config_info = self._get_config_by_ref(pg_ref)

            if (pg_config_info.defaultPortConfig.blocked.value != blocked or
                    (original and original['name'] != network['name'])):
                # we upgrade only defaultPortConfig, because it is inherited
                # by all ports in PortGroup, unless they are explicite
                # overwritten on specific port.
                pg_spec = self._build_pg_update_spec(
                    pg_config_info.configVersion,
                    blocked=blocked)
                pg_spec.name = self._get_net_name(self.dvs_name, network)
                pg_update_task = self.connection.invoke_api(
                    self.connection.vim,
                    'ReconfigureDVPortgroup_Task',
                    pg_ref, spec=pg_spec)

                self.connection.wait_for_task(pg_update_task)
                LOG.info(_LI('Network %(name)s updated'), {'name': name})
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)

    def delete_network(self, network):
        name = self._get_net_name(self.dvs_name, network)
        try:
            pg_ref = self._get_pg_by_name(name)
        except exceptions.PortGroupNotFound:
            LOG.debug('Network %s not present in vcenter.' % name)
            return
        self._delete_port_group(pg_ref, name)

    def delete_networks_without_active_ports(self, pg_keys_with_active_ports):
        for pg_ref in self._get_all_port_groups():
            if pg_ref.value not in pg_keys_with_active_ports:
                # check name
                name = self.connection.invoke_api(
                    vim_util, 'get_object_property',
                    self.connection.vim, pg_ref, 'name')
                name_tokens = name.split(self.dvs_name)
                if (len(name_tokens) == 2 and not name_tokens[0] and
                        self._valid_uuid(name_tokens[1])):
                    self._delete_port_group(pg_ref, name)

    def _delete_port_group(self, pg_ref, name):
        while True:
            try:
                pg_delete_task = self.connection.invoke_api(
                    self.connection.vim,
                    'Destroy_Task',
                    pg_ref)
                self.connection.wait_for_task(pg_delete_task)
                LOG.info(_LI('Network %(name)s deleted.') % {'name': name})
                break
            except vmware_exceptions.VimException as e:
                raise exceptions.wrap_wmvare_vim_exception(e)
            except vmware_exceptions.VMwareDriverException as e:
                if dvs_const.DELETED_TEXT in e.message:
                    sleep(1)
                else:
                    raise

    def switch_port_blocked_state(self, port):
        state = not port['admin_state_up']

        port_info = self.get_port_info_by_name(port['id'])

        builder = SpecBuilder(self.connection.vim.client.factory)
        port_settings = builder.port_setting()
        port_settings.blocked = builder.blocked(state)

        update_spec = builder.port_config_spec(
            port_info.config.configVersion, port_settings)
        update_spec.key = port_info.key
        update_task = self.connection.invoke_api(
            self.connection.vim, 'ReconfigureDVPort_Task',
            self._dvs, port=[update_spec])
        self.connection.wait_for_task(update_task)

    def book_port(self, network, port_name, segment, net_name=None):
        try:
            if not net_name:
                net_name = self._get_net_name(self.dvs_name, network)
            pg = self._get_or_create_pg(net_name, network, segment)
            while True:
                try:
                    port_info = self._lookup_unbound_port(pg)
                    break
                except exceptions.UnboundPortNotFound:
                    try:
                        self._increase_ports_on_portgroup(pg)
                    except (vmware_exceptions.VMwareDriverException,
                            exceptions.VMWareDVSException) as e:
                        if dvs_const.CONCURRENT_MODIFICATION_TEXT in e.message:
                            LOG.info(_LI('Concurent modification on '
                                         'increase port group.'))
                            continue
            builder = SpecBuilder(self.connection.vim.client.factory)
            port_settings = builder.port_setting()
            port_settings.blocked = builder.blocked(False)
            update_spec = builder.port_config_spec(
                port_info.config.configVersion, port_settings, name=port_name)
            update_spec.key = port_info.key
            update_task = self.connection.invoke_api(
                self.connection.vim, 'ReconfigureDVPort_Task',
                self._dvs, port=[update_spec])
            self.connection.wait_for_task(update_task)
            return port_info.key
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)

    def release_port(self, port):
        port_info = self.get_port_info_by_name(port['id'])
        builder = SpecBuilder(self.connection.vim.client.factory)
        update_spec = builder.port_config_spec(
            port_info.config.configVersion, name='')
        update_spec.key = port_info.key
        update_task = self.connection.invoke_api(
            self.connection.vim, 'ReconfigureDVPort_Task',
            self._dvs, port=[update_spec])
        task_result = self.connection.wait_for_task(update_task)
        if task_result.state == "success":
            self._blocked_ports.discard(port_info.key)

    def _build_pg_create_spec(self, name, vlan_tag, blocked):
        builder = SpecBuilder(self.connection.vim.client.factory)
        port_setting = builder.port_setting()

        port_setting.vlan = builder.vlan(vlan_tag)
        port_setting.blocked = builder.blocked(blocked)

        port_setting.filterPolicy = builder.filter_policy([])

        pg = builder.pg_config(port_setting)
        pg.name = name<commit_msg>Improve port remove<commit_after># Copyright 2015 Mirantis, 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.

from time import sleep
import uuid
import six


from neutron.i18n import _LI, _LW
from oslo_log import log
from oslo_vmware import api
from oslo_vmware import exceptions as vmware_exceptions
from oslo_vmware import vim_util

from vmware_dvs.common import constants as dvs_const
from vmware_dvs.common import exceptions

LOG = log.getLogger(__name__)


class DVSController(object):
    """Controls one DVS."""

    def __init__(self, dvs_name, connection):
        self.connection = connection
        try:
            self.dvs_name = dvs_name
            self._dvs, self._datacenter = self._get_dvs(dvs_name, connection)
            # (SlOPS) To do release blocked port after use
            self._blocked_ports = set()
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)

    def create_network(self, network, segment):
        name = self._get_net_name(self.dvs_name, network)
        blocked = not network['admin_state_up']

        try:
            pg_spec = self._build_pg_create_spec(
                name,
                segment['segmentation_id'],
                blocked)
            pg_create_task = self.connection.invoke_api(
                self.connection.vim,
                'CreateDVPortgroup_Task',
                self._dvs, spec=pg_spec)

            result = self.connection.wait_for_task(pg_create_task)
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
        else:
            pg = result.result
            LOG.info(_LI('Network %(name)s created \n%(pg_ref)s'),
                     {'name': name, 'pg_ref': pg})
            return pg

    def update_network(self, network, original=None):
        if original:
            name = self._get_net_name(self.dvs_name, original)
        else:
            name = self._get_net_name(self.dvs_name, network)
        blocked = not network['admin_state_up']
        try:
            pg_ref = self._get_pg_by_name(name)
            pg_config_info = self._get_config_by_ref(pg_ref)

            if (pg_config_info.defaultPortConfig.blocked.value != blocked or
                    (original and original['name'] != network['name'])):
                # we upgrade only defaultPortConfig, because it is inherited
                # by all ports in PortGroup, unless they are explicite
                # overwritten on specific port.
                pg_spec = self._build_pg_update_spec(
                    pg_config_info.configVersion,
                    blocked=blocked)
                pg_spec.name = self._get_net_name(self.dvs_name, network)
                pg_update_task = self.connection.invoke_api(
                    self.connection.vim,
                    'ReconfigureDVPortgroup_Task',
                    pg_ref, spec=pg_spec)

                self.connection.wait_for_task(pg_update_task)
                LOG.info(_LI('Network %(name)s updated'), {'name': name})
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)

    def delete_network(self, network):
        name = self._get_net_name(self.dvs_name, network)
        try:
            pg_ref = self._get_pg_by_name(name)
        except exceptions.PortGroupNotFound:
            LOG.debug('Network %s not present in vcenter.' % name)
            return
        self._delete_port_group(pg_ref, name)

    def delete_networks_without_active_ports(self, pg_keys_with_active_ports):
        for pg_ref in self._get_all_port_groups():
            if pg_ref.value not in pg_keys_with_active_ports:
                # check name
                name = self.connection.invoke_api(
                    vim_util, 'get_object_property',
                    self.connection.vim, pg_ref, 'name')
                name_tokens = name.split(self.dvs_name)
                if (len(name_tokens) == 2 and not name_tokens[0] and
                        self._valid_uuid(name_tokens[1])):
                    self._delete_port_group(pg_ref, name)

    def _delete_port_group(self, pg_ref, name):
        while True:
            try:
                pg_delete_task = self.connection.invoke_api(
                    self.connection.vim,
                    'Destroy_Task',
                    pg_ref)
                self.connection.wait_for_task(pg_delete_task)
                LOG.info(_LI('Network %(name)s deleted.') % {'name': name})
                break
            except vmware_exceptions.VimException as e:
                raise exceptions.wrap_wmvare_vim_exception(e)
            except vmware_exceptions.VMwareDriverException as e:
                if dvs_const.DELETED_TEXT in e.message:
                    sleep(1)
                else:
                    raise

    def switch_port_blocked_state(self, port):
        state = not port['admin_state_up']

        port_info = self.get_port_info_by_name(port['id'])

        builder = SpecBuilder(self.connection.vim.client.factory)
        port_settings = builder.port_setting()
        port_settings.blocked = builder.blocked(state)

        update_spec = builder.port_config_spec(
            port_info.config.configVersion, port_settings)
        update_spec.key = port_info.key
        update_task = self.connection.invoke_api(
            self.connection.vim, 'ReconfigureDVPort_Task',
            self._dvs, port=[update_spec])
        self.connection.wait_for_task(update_task)

    def book_port(self, network, port_name, segment, net_name=None):
        try:
            if not net_name:
                net_name = self._get_net_name(self.dvs_name, network)
            pg = self._get_or_create_pg(net_name, network, segment)
            while True:
                try:
                    port_info = self._lookup_unbound_port(pg)
                    break
                except exceptions.UnboundPortNotFound:
                    try:
                        self._increase_ports_on_portgroup(pg)
                    except (vmware_exceptions.VMwareDriverException,
                            exceptions.VMWareDVSException) as e:
                        if dvs_const.CONCURRENT_MODIFICATION_TEXT in e.message:
                            LOG.info(_LI('Concurent modification on '
                                         'increase port group.'))
                            continue
            builder = SpecBuilder(self.connection.vim.client.factory)
            port_settings = builder.port_setting()
            port_settings.blocked = builder.blocked(False)
            update_spec = builder.port_config_spec(
                port_info.config.configVersion, port_settings, name=port_name)
            update_spec.key = port_info.key
            update_task = self.connection.invoke_api(
                self.connection.vim, 'ReconfigureDVPort_Task',
                self._dvs, port=[update_spec])
            self.connection.wait_for_task(update_task)
            return port_info.key
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)

    def release_port(self, port):
        vif_details = port.get('binding:vif_details')
        key = None
        if vif_details:
            key = vif_details.get('dvs_port_key')
            port_info = self._get_port_info_by_portkey(key)
        if not key:
            port_info = self.get_port_info_by_name(port['id'])
            key = port_info.key
        builder = SpecBuilder(self.connection.vim.client.factory)
        update_spec = builder.port_config_spec(
            port_info.config.configVersion, name='')
        update_spec.key = key
        update_task = self.connection.invoke_api(
            self.connection.vim, 'ReconfigureDVPort_Task',
            self._dvs, port=[update_spec])
        task_result = self.connection.wait_for_task(update_task)
        if task_result.state == "success":
            self._blocked_ports.discard(port_info.key)

    def _build_pg_create_spec(self, name, vlan_tag, blocked):
        builder = SpecBuilder(self.connection.vim.client.factory)
        port_setting = builder.port_setting()

        port_setting.vlan = builder.vlan(vlan_tag)
        port_setting.blocked = builder.blocked(blocked)

        port_setting.filterPolicy = builder.filter_policy([])

        pg = builder.pg_config(port_setting)
        pg.name = name
{'fraction_non_alphanumeric': 0.07856296881168574, 'fraction_numerical': 0.0015791551519936833, 'mean_word_length': 2.0870473537604455, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5602783', 'n_tokens_mistral': 5092, 'n_tokens_neox': 4884, 'n_words': 1042}