def _end(self):
        for t in self._threads:
            try:
                while not self._error and t.isAlive():
                    t.join(1)
            except KeyboardInterrupt:
                self._error = (exceptions.MaestroException,
                               exceptions.MaestroException('Manual abort'),
                               None)
            except Exception:
                self._error = sys.exc_info()
            finally:
                self._cv.acquire()
                self._cv.notifyAll()
                self._cv.release()
        self._om.end()

        # Display and raise any error that occurred
        if self._error:
            if self._auditor:
                self._auditor.error(action=self._play, what=self._containers,
                                    message=str(self._error[1]))
            exceptions.raise_with_tb(self._error)
        else:
            if self._auditor:
                self._auditor.success(level=audit.INFO, action=self._play,
                                      what=self._containers)
reads a required attribute from the node.
dataset/ETHPy150Open signalfx/maestro-ng/maestro/plays/__init__.py/BaseOrchestrationPlay._end--crossover with--dataset/ETHPy150Open esrlabs/git-repo/manifest_xml.py/XmlManifest._reqatt