示例#1
0
 def _delete_port_group(self, pg_ref, name, ignore_in_use=False):
     while True:
         try:
             pg_delete_task = pg_ref.Destroy_Task()
             wait_for_task(pg_delete_task, si=self.connection)
             LOG.info(_LI('Network %(name)s deleted.') % {'name': name})
             self._port_groups_by_name.pop(name, None)
             return True
         except vim.fault.ResourceInUse as e:
             if ignore_in_use:
                 LOG.info(
                     _LW("Could not delete port-group %(name)s. Reason: %(message)s"
                         ) % {
                             'name': name,
                             'message': e.message
                         })
                 return False
             else:
                 raise exceptions.wrap_wmvare_vim_exception(e)
         except vim.fault.VimFault as e:
             if dvs_const.DELETED_TEXT in e.message:
                 return True
             else:
                 raise exceptions.wrap_wmvare_vim_exception(e)
     return False
示例#2
0
    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)
            for iter in range(0, 4):
                try:
                    port_info = self._lookup_unbound_port_or_increase_pg(pg)

                    port_settings = self.builder.port_setting()
                    port_settings.blocked = self.builder.blocked(False)
                    update_spec = self.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:
                    sleep(0.1)
            raise exceptions.wrap_wmvare_vim_exception(e)
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#3
0
    def update_network(self, network, original=None):
        original_name = self._get_net_name(self.dvs_name, original) if original else None
        current_name = self._get_net_name(self.dvs_name, network)
        blocked = not network['admin_state_up']
        try:
            pg_ref = self._get_pg_by_name(original_name or current_name)
            pg_config_info = self._get_config_by_ref(pg_ref)

            if (pg_config_info.defaultPortConfig.blocked.value != blocked or
                    (original_name and original_name != current_name)):
                # we upgrade only defaultPortConfig, because it is inherited
                # by all ports in PortGroup, unless they are explicitly
                # overwritten on specific port.
                pg_spec = self._build_pg_update_spec(
                    pg_config_info.configVersion,
                    blocked=blocked)
                pg_spec.name = current_name
                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': current_name})
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#4
0
    def update_dvportgroup(self, pg_ref, config_version, port_config=None, name=None, retries=3):
        if retries <= 0:
            LOG.error("Maximum number of update retries reached for portgroup {}.".format(pg_ref))
            return
        try:
            pg_spec = self.builder.pg_config(port_config)
            pg_spec.configVersion = config_version
            if name:
                pg_spec.name = name

            now = timeutils.utcnow()
            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)
            delta = timeutils.utcnow() - now
            stats.timing('networking_dvs.dvportgroup.updated', delta)
            LOG.debug("Updating portgroup {} took {} seconds.".format(pg_ref, delta.seconds))
        except vmware_exceptions.VimException as e:
            if dvs_const.CONCURRENT_MODIFICATION_TEXT in str(e):
                LOG.debug("Concurrent modification detected, will retry.")
                config_version = vim_util.get_object_property(
                    self.connection.vim, pg_ref, "config.configVersion")
                return self.update_dvportgroup(pg_ref, config_version, port_config, name, retries-1)
            if dvs_const.BULK_FAULT_TEXT in str(e):
                info = get_task_info(self.connection, pg_update_task)
                self.rectifyForFault(info.error.fault)
                return
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#5
0
    def update_mtu(self, max_mtu):
        if max_mtu == self._max_mtu:
            return
        try:
            pg_config_info = self._build_dvswitch_update_spec()
            pg_config_info.maxMtu = max_mtu
            pg_config_info.configVersion = self._config_version

            pg_update_task = self._dvs.ReconfigureDvs_Task(spec=pg_config_info)

            wait_for_task(pg_update_task, si=self.connection)
            self.max_mtu = max_mtu
        except vim.fault.VimFault as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#6
0
    def switch_port_blocked_state(self, port):
        try:
            port_info = self.get_port_info(port)
            port_settings = self.builder.port_setting()
            state = not port['admin_state_up']
            port_settings.blocked = self.builder.blocked(state)

            update_spec = self.builder.port_config_spec(
                port_info.config.configVersion, port_settings)
            update_spec.key = port_info.key
            self.update_ports([update_spec])
        except exceptions.PortNotFound:
            LOG.debug("Port %s was not found. Nothing to block." % port['id'])
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#7
0
    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)
            for iter in range(0, 4):
                try:
                    port_info = self._lookup_unbound_port_or_increase_pg(pg)

                    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.submit_update_ports([update_spec])
                    wait_for_task(update_task, si=self.connection)
                    return port_info.key
                except vim.fault.VimFault as e:
                    sleep(0.1)
            raise exceptions.wrap_wmvare_vim_exception(e)
        except vim.fault.VimFault as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#8
0
 def release_port(self, port):
     try:
         port_info = self.get_port_info(port)
         update_spec = builder.port_config_spec(
             port_info.config.configVersion, name='')
         update_spec.key = port_info.key
         # setting = builder.port_setting()
         # setting.filterPolicy = builder.filter_policy([])
         # update_spec.setting = setting
         update_spec.operation = 'remove'
         update_task = self.submit_update_ports([update_spec])
         wait_for_task(update_task, si=self.connection)
         self.remove_block(port_info.key)
     except exceptions.PortNotFound:
         LOG.debug("Port %s was not found. Nothing to delete." % port['id'])
     except exceptions.ResourceInUse:
         LOG.debug("Port %s in use. Nothing to delete." % port['id'])
     except vim.fault.VimFault as e:
         raise exceptions.wrap_wmvare_vim_exception(e)
示例#9
0
 def __init__(self, dvs_name, connection=None, pool=None, rectify_wait=120):
     self.connection = connection
     self.dvs_name = dvs_name
     self._uuid = None
     self.pool = pool
     self._update_spec_queue = []
     self.ports_by_key = {}
     self._blocked_ports = set()
     self._service_content = connection.vim.retrieve_service_content()
     self.builder = spec_builder.SpecBuilder(
         self.connection.vim.client.factory)
     self.hosts_to_rectify = {}
     self.rectify_wait = rectify_wait
     try:
         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)
示例#10
0
 def release_port(self, port):
     try:
         port_info = self.get_port_info(port)
         update_spec = self.builder.port_config_spec(
             port_info.config.configVersion, name='')
         update_spec.key = port_info.key
         #setting = self.builder.port_setting()
         #setting.filterPolicy = self.builder.filter_policy([])
         #update_spec.setting = setting
         update_spec.operation = 'remove'
         update_task = self.connection.invoke_api(
             self.connection.vim, 'ReconfigureDVPort_Task',
             self._dvs, port=[update_spec])
         self.connection.wait_for_task(update_task)
         self.remove_block(port_info.key)
     except exceptions.PortNotFound:
         LOG.debug("Port %s was not found. Nothing to delete." % port['id'])
     except exceptions.ResourceInUse:
         LOG.debug("Port %s in use. Nothing to delete." % port['id'])
     except vmware_exceptions.VimException as e:
         raise exceptions.wrap_wmvare_vim_exception(e)
示例#11
0
    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._dvs.CreateDVPortgroup_Task(spec=pg_spec)

            result = wait_for_task(pg_create_task, si=self.connection)
        except vim.fault.VimFault as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
        else:
            pg = result.result
            self._port_groups_by_name[name] = pg
            LOG.info(_LI('Network %(name)s created \n%(pg_ref)s'), {
                'name': name,
                'pg_ref': pg
            })
            return pg
示例#12
0
 def _delete_port_group(self, pg_ref, name, ignore_in_use=False):
     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:
             if not ignore_in_use or not re.match("The resource '\d*' is in use.", e.message):
                 raise exceptions.wrap_wmvare_vim_exception(e)
             else:
                 LOG.warn(_LW("Could not delete port-group %(name)s. Reason: %(message)s")
                          % {'name': name, 'message': e.message})
                 break
         except vmware_exceptions.VMwareDriverException as e:
             if dvs_const.DELETED_TEXT in e.message:
                 sleep(0.1)
             else:
                 raise
示例#13
0
    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
示例#14
0
    def __init__(self, dvs_name, connection=None, pool=None, rectify_wait=120):
        self.connection = connection
        self.dvs_name = dvs_name
        self.max_mtu = None
        self.pool = pool
        self._update_spec_queue = []
        self.ports_by_key = {}
        self._blocked_ports = set()
        self.hosts_to_rectify = {}
        self.rectify_wait = rectify_wait

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

        dvs_config = self._dvs.config
        self._uuid = dvs_config.uuid
        self._max_mtu = dvs_config.maxMtu
        self._config_version = dvs_config.configVersion

        self._port_groups_by_name = {}
示例#15
0
    def create_dvportgroup(self, sg_set, port_config, update=True):
        """
        Creates an automatically-named dvportgroup on the dvswitch
        with the specified sg rules and marks it as such through the description

        Returns a dictionary with "key" and "ref" keys.

        Note, that while a portgroup's key and managed object id have
        the same string format and appear identical under normal use
        it is possible to have them diverge by the use of the backup
        and restore feature of the dvs for example.
        As such, one should not rely on any equivalence between them.
        """
        # There is a create_network method a few lines above
        # which seems to be part of a non-used call path
        # starting from the dvs_agent_rpc_api. TODO - remove it

        dvpg_name = dvportgroup_name(self.uuid, sg_set)

        portgroups = self._get_portgroups()
        if dvpg_name in portgroups:
            existing = portgroups[dvpg_name]

            if update:
                self.update_dvportgroup(existing, port_config)
            return existing

        if CONF.AGENT.dry_run:
            return

        try:
            pg_spec = builder.pg_config(port_config)
            pg_spec.name = dvpg_name
            pg_spec.numPorts = 0
            pg_spec.type = 'earlyBinding'
            pg_spec.description = sg_set

            now = timeutils.utcnow()
            pg_create_task = self._dvs.CreateDVPortgroup_Task(spec=pg_spec)

            result = wait_for_task(pg_create_task, si=self.connection)

            pg_ref = result.result

            props = util.get_object_properties_dict(self.connection, pg_ref,
                                                    ["key"])
            delta = timeutils.utcnow() - now
            stats.timing('networking_dvs.dvportgroup.created', delta)
            LOG.debug("Creating portgroup {} took {} seconds.".format(
                pg_ref.value, delta.seconds))

            pg = PortGroup(key=props["key"],
                           ref=pg_ref,
                           name=dvpg_name,
                           config_version=0,
                           description=sg_set,
                           default_port_config=port_config)
            self._port_groups_by_name[dvpg_name] = pg
            return pg
        except vim.fault.DuplicateName as dn:
            LOG.info(
                "Untagged portgroup with matching name {} found, will update and use."
                .format(dvpg_name))

            if dvpg_name not in portgroups:
                portgroups = self._get_portgroups(refresh=True)

            if dvpg_name not in portgroups:
                LOG.error(
                    "Portgroup with matching name {} not found while expected."
                    .format(dvpg_name))
                return

            existing = portgroups[dvpg_name]

            if update:
                self.update_dvportgroup(existing, port_config)

            return existing
        except vim.fault.VimFault as e:
            raise exceptions.wrap_wmvare_vim_exception(e)
示例#16
0
    def _apply_queued_update_specs(self, update_specs, callbacks, retries=5):
        if not update_specs:
            return

        failed_keys = []
        for i in range(retries):
            try:
                value = self.update_ports(update_specs)

                for spec in update_specs:
                    port = self.ports_by_key[spec.key]
                    port_desc = port.get('port_desc', None)
                    if port_desc and port_desc.config_version:
                        port_desc.config_version = str(int(port_desc.config_version) + 1)

                if callbacks:
                    succeeded_keys = [str(spec.key) for spec in update_specs]
                for callback in callbacks:
                    if callable(callback):
                        callback(self, succeeded_keys, failed_keys)

                return value
            except vmware_exceptions.VimException as e:
                if dvs_const.CONCURRENT_MODIFICATION_TEXT in e.msg:
                    for port_info in self.get_port_info_by_portkey([spec.key for spec in update_specs]):
                        port_key = str(port_info.key)
                        port = self.ports_by_key[port_key]
                        port_desc = port['port_desc']
                        update_spec_index = None
                        update_spec = None

                        for index, item in enumerate(update_specs):
                            if item.key == port_key:
                                update_spec = item
                                update_spec_index = index
                                break

                        connection_cookie = getattr(port_info, "connectionCookie", None)

                        if connection_cookie:
                            connection_cookie = str(connection_cookie)

                        if connection_cookie != port_desc.connection_cookie:
                            LOG.error("Cookie mismatch {} {} {} <> {}".format(port_desc.mac_address, port_desc.port_key,
                                                                              port_desc.connection_cookie,
                                                                              connection_cookie))
                            if update_spec_index:
                                failed_keys.append(port_key)
                                del update_specs[update_spec_index]
                        else:
                            config_version = str(port_info.config.configVersion)
                            port_desc.config_version = config_version
                            if update_spec:
                                LOG.debug("Config version {} {} from {} ({}) to {}".format(port_desc.mac_address,
                                                                                           port_desc.port_key,
                                                                                           port_desc.config_version,
                                                                                           update_spec.configVersion,
                                                                                           config_version))

                                update_spec.configVersion = config_version
                    continue

                raise exceptions.wrap_wmvare_vim_exception(e)
示例#17
0
    def update_dvportgroup(self, pg, port_config=None, name=None, retries=3):
        for ntry in six.moves.xrange(retries):
            pg_ref = pg.ref

            if not pg.name:
                LOG.debug("Missing name for %s", pg_ref.value)

            if pg.async_fetch:
                LOG.warning("Blocking on port-group %s", pg.name)
                pg.async_fetch.wait()

            default_port_config = pg.default_port_config

            if (name == pg.name or not name) \
                    and (default_port_config or not port_config) \
                    and not _config_differs(default_port_config, port_config):
                LOG.debug("Skipping update: No changes to known config on %s",
                          pg.name)
                return

            try:
                pg_spec = builder.pg_config(port_config)
                pg_spec.configVersion = str(pg.config_version)

                if name and name != pg.name:
                    pg_spec.name = name

                now = timeutils.utcnow()
                if not CONF.AGENT.dry_run:
                    pg_update_task = pg_ref.ReconfigureDVPortgroup_Task(
                        spec=pg_spec)
                else:
                    LOG.debug(pg_spec)

                pg.config_version = str(int(pg.config_version) + 1)
                pg.default_port_config = port_config

                if not CONF.AGENT.dry_run:
                    wait_for_task(pg_update_task, si=self.connection)

                delta = timeutils.utcnow() - now
                stats.timing('networking_dvs.dvportgroup.updated', delta)

                LOG.debug("Updating portgroup {} took {} seconds.".format(
                    pg_ref.value, delta.seconds))
                return
            except vim.fault.DvsOperationBulkFault as e:
                self.rectify_for_fault(e)
            except vim.fault.VimFault as e:
                if dvs_const.CONCURRENT_MODIFICATION_TEXT in str(e) \
                        and ntry != retries - 1:
                    LOG.debug("Concurrent modification detected, will retry.")
                    ## TODO A proper read-out of the current config
                    props = util.get_object_properties_dict(
                        self.connection, pg_ref,
                        ["config.configVersion", "config.defaultPortConfig"])
                    pg.config_version = props["config.configVersion"]
                    pg.default_port_config = props["config.defaultPortConfig"]

                    continue
                raise exceptions.wrap_wmvare_vim_exception(e)
示例#18
0
    def create_dvportgroup(self, sg_attr_key, sg_set, port_config):
        """
        Creates an automatically-named dvportgroup on the dvswitch
        with the specified sg rules and marks it as such through a custom attribute

        Returns a dictionary with "key" and "ref" keys.

        Note, that while a portgroup's key and managed object id have
        the same string format and appear identical under normal use
        it is possible to have them diverge by the use of the backup
        and restore feature of the dvs for example.
        As such, one should not rely on any equivalence between them.
        """
        # There is a create_network method a few lines above
        # which seems to be part of a non-used call path
        # starting from the dvs_agent_rpc_api. TODO - remove it

        dvpg_name = self.dvportgroup_name(sg_set)

        try:
            pg_spec = self.builder.pg_config(port_config)
            pg_spec.name = dvpg_name
            pg_spec.numPorts = 0
            pg_spec.type = 'earlyBinding'
            pg_spec.description = sg_set

            now = timeutils.utcnow()
            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)

            pg_ref = result.result

            # Tag the portgroup for the specific security group set
            self.connection.invoke_api(
                self.connection.vim,
                "SetField",
                self._service_content.customFieldsManager,
                entity=pg_ref,
                key=sg_attr_key,
                value=sg_set)

            props = vim_util.get_object_properties_dict(self.connection.vim, pg_ref, ["key"])
            delta = timeutils.utcnow() - now
            stats.timing('networking_dvs.dvportgroup.created', delta)
            LOG.debug("Creating portgroup {} took {} seconds.".format(pg_ref, delta.seconds))
            return {"key": props["key"], "ref": pg_ref}
        except vmware_exceptions.DuplicateName as dn:
            LOG.info("Untagged portgroup with matching name {} found, will update and use.".format(dvpg_name))
            portgroups = self._get_portgroups()
            for existing in portgroups:
                if existing['name'] != dvpg_name:
                    continue
                break # found it
            else:
                LOG.error("Portgroup with matching name {} not found while expected.".format(dvpg_name))
                return

            self.update_dvportgroup(existing["ref"], existing["config.configVersion"], port_config)

            # Tag the portgroup for the specific security group set
            self.connection.invoke_api(
                self.connection.vim,
                "SetField",
                self._service_content.customFieldsManager,
                entity=existing["ref"],
                key=sg_attr_key,
                value=sg_set)

            return existing
        except vmware_exceptions.VimException as e:
            raise exceptions.wrap_wmvare_vim_exception(e)