class ProjectAlice(Singleton):

    NAME = 'ProjectAlice'

    def __init__(self):
        Singleton.__init__(self, self.NAME)
        self._logger.info('Starting up project Alice core')
        self._superManager = SuperManager(self)

        self._superManager.initManagers()
        self._superManager.onStart()

        if self._superManager.configManager.getAliceConfigByName('useSLC'):
            subprocess.run(['sudo', 'systemctl', 'start', 'snipsledcontrol'])

        self._superManager.onBooted()

    @property
    def name(self) -> str:
        return self.NAME

    def onStop(self):
        self._logger.info('[ProjectAlice] Shutting down Project Alice')
        self._superManager.onStop()
        if self._superManager.configManager.getAliceConfigByName('useSLC'):
            subprocess.run(['sudo', 'systemctl', 'stop', 'snipsledcontrol'])
Example #2
0
class ProjectAlice(Singleton):

    NAME = 'ProjectAlice'

    def __init__(self):
        Singleton.__init__(self, self.NAME)
        self._logger.info('Starting up project Alice core')
        self._superManager = SuperManager(self)

        self._superManager.initManagers()
        self._superManager.onStart()

        if self._superManager.configManager.getAliceConfigByName('useSLC'):
            subprocess.run(['sudo', 'systemctl', 'start', 'snipsledcontrol'])

        self._superManager.onBooted()

    @property
    def name(self) -> str:
        return self.NAME

    def onStop(self):
        self._logger.info('[ProjectAlice] Shutting down Project Alice')
        self._superManager.onStop()

    @staticmethod
    def _startDjango():
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.gui.settings')
        django.setup()
        management.call_command('runserver', '0:8000', '--noreload')
Example #3
0
class ProjectAlice(Singleton):

    NAME = 'ProjectAlice'

    def __init__(self, restartHandler: callable):
        Singleton.__init__(self, self.NAME)
        self.logInfo('Starting up Project Alice')
        self._booted = False
        with Stopwatch() as stopWatch:
            self._restart = False
            self._restartHandler = restartHandler
            self._superManager = SuperManager(self)

            self._superManager.initManagers()
            self._superManager.onStart()

            if self._superManager.configManager.getAliceConfigByName('useSLC'):
                subprocess.run(
                    ['sudo', 'systemctl', 'start', 'snipsledcontrol'])

            self._superManager.onBooted()
        self.logInfo(f'- Started Project Alice in {stopWatch} seconds')
        self._booted = True

    @property
    def name(self) -> str:
        return self.NAME

    @property
    def isBooted(self) -> bool:
        return self._booted

    @property
    def restart(self) -> bool:
        return self._restart

    @restart.setter
    def restart(self, value: bool):
        self._restart = value

    def doRestart(self):
        self._restart = True
        self.onStop()

    def onStop(self):
        self.logInfo('Shutting down Project Alice')
        self._superManager.onStop()
        if self._superManager.configManager.getAliceConfigByName('useSLC'):
            subprocess.run(['sudo', 'systemctl', 'stop', 'snipsledcontrol'])

        self.INSTANCE = None
        self._restartHandler()
Example #4
0
class ProjectAlice(Singleton):
    NAME = 'ProjectAlice'

    def __init__(self, restartHandler: callable):
        Singleton.__init__(self, self.NAME)
        self._logger = Logger(prepend='[Project Alice]')
        self._logger.logInfo('Starting Alice main unit')
        self._booted = False
        self._isUpdating = False
        self._shuttingDown = False
        self._restart = False
        self._restartHandler = restartHandler

        if not self.checkDependencies():
            self._restart = True
            self._restartHandler()
        else:
            with Stopwatch() as stopWatch:
                self._superManager = SuperManager(self)

                self._superManager.initManagers()
                self._superManager.onStart()

                if self._superManager.configManager.getAliceConfigByName(
                        'useHLC'):
                    self._superManager.commons.runRootSystemCommand(
                        ['systemctl', 'start', 'hermesledcontrol'])

                self._superManager.onBooted()

            self._logger.logInfo(f'Started in {stopWatch} seconds')
            self._booted = True

    def checkDependencies(self) -> bool:
        """
		Compares .hash files against requirements.txt and sysrequirement.txt. Updates dependencies if necessary
		:return: boolean False if the check failed, new deps were installed (reboot maybe? :) )
		"""
        HASH_SUFFIX = '.hash'
        TXT_SUFFIX = '.txt'

        path = Path('requirements')
        savedHash = path.with_suffix(HASH_SUFFIX)
        reqHash = hashlib.blake2b(
            path.with_suffix(TXT_SUFFIX).read_bytes()).hexdigest()

        if not savedHash.exists() or savedHash.read_text() != reqHash:
            self._logger.logInfo(
                'Pip dependencies added or removed, updating virtual environment'
            )
            subprocess.run([
                './venv/bin/pip', 'install', '-r',
                str(path.with_suffix(TXT_SUFFIX))
            ])
            savedHash.write_text(reqHash)
            return False

        path = Path('sysrequirements')
        savedHash = path.with_suffix(HASH_SUFFIX)
        reqHash = hashlib.blake2b(
            path.with_suffix(TXT_SUFFIX).read_bytes()).hexdigest()

        if not savedHash.exists() or savedHash.read_text() != reqHash:
            self._logger.logInfo(
                'System dependencies added or removed, updating system')
            reqs = [
                line.rstrip('\n')
                for line in open(path.with_suffix(TXT_SUFFIX))
            ]
            subprocess.run([
                'sudo', 'apt-get', 'install', '-y', '--allow-unauthenticated'
            ] + reqs)
            savedHash.write_text(reqHash)
            return False

        path = Path('pipuninstalls')
        savedHash = path.with_suffix(HASH_SUFFIX)
        reqHash = hashlib.blake2b(
            path.with_suffix(TXT_SUFFIX).read_bytes()).hexdigest()

        if not savedHash.exists() or savedHash.read_text() != reqHash:
            self._logger.logInfo(
                'Pip conflicting dependencies added, updating virtual environment'
            )
            subprocess.run([
                './venv/bin/pip', 'uninstall', '-y', '-r',
                str(path.with_suffix(TXT_SUFFIX))
            ])
            savedHash.write_text(reqHash)
            return False

        return True

    @property
    def name(self) -> str:  # NOSONAR
        return self.NAME

    @property
    def isBooted(self) -> bool:
        return self._booted

    @property
    def restart(self) -> bool:
        return self._restart

    @restart.setter
    def restart(self, value: bool):
        self._restart = value

    def doRestart(self):
        self._restart = True
        self.onStop()

    def onStop(self, withReboot: bool = False):
        self._logger.logInfo('Shutting down')
        self._shuttingDown = True
        self._superManager.onStop()
        if self._superManager.configManager.getAliceConfigByName('useHLC'):
            self._superManager.commons.runRootSystemCommand(
                ['systemctl', 'stop', 'hermesledcontrol'])

        self._booted = False
        self.INSTANCE = None

        if withReboot:
            subprocess.run(['sudo', 'shutdown', '-r', 'now'])
        else:
            self._restartHandler()

    def wipeAll(self):
        # Set as restarting so skills don't install / update
        self._restart = True

        self._superManager.skillManager.wipeSkills()
        self._superManager.databaseManager.clearDB()
        self._superManager.assistantManager.clearAssistant()
        self._superManager.dialogTemplateManager.clearCache(False)
        self._superManager.nluManager.clearCache()

    def updateProjectAlice(self):
        self._logger.logInfo('Checking for core updates')
        STATE = 'projectalice.core.updating'
        state = self._superManager.stateManager.getState(STATE)
        if not state:
            self._superManager.stateManager.register(
                STATE, initialState=StateType.RUNNING)
        elif state.currentState == StateType.RUNNING:
            self._logger.logInfo('Update cancelled, already running')
            return

        self._superManager.stateManager.setState(STATE,
                                                 newState=StateType.RUNNING)

        self._isUpdating = True
        req = requests.get(
            url=f'{constants.GITHUB_API_URL}/ProjectAlice/branches',
            auth=SuperManager.getInstance().configManager.githubAuth)
        if req.status_code != 200:
            self._logger.logWarning('Failed checking for updates')
            self._superManager.stateManager.setState(STATE,
                                                     newState=StateType.ERROR)
            return

        userUpdatePref = SuperManager.getInstance(
        ).configManager.getAliceConfigByName('aliceUpdateChannel')

        if userUpdatePref == 'master':
            candidate = 'master'
        else:
            candidate = Version.fromString(constants.VERSION)
            for branch in req.json():
                if 'dependabot' in branch['name']:
                    continue
                repoVersion = Version.fromString(branch['name'])
                if not repoVersion.isVersionNumber:
                    continue

                releaseType = repoVersion.releaseType
                if userUpdatePref == 'rc' and releaseType in {
                        'b', 'a'
                } or userUpdatePref == 'beta' and releaseType == 'a':
                    continue

                if repoVersion > candidate:
                    candidate = repoVersion

        self._logger.logInfo(f'Checking on "{str(candidate)}" update channel')
        commons = SuperManager.getInstance().commons

        currentHash = subprocess.check_output(
            ['git', 'rev-parse', '--short HEAD'])

        commons.runSystemCommand(['git', '-C', commons.rootDir(), 'stash'])
        commons.runSystemCommand(
            ['git', '-C', commons.rootDir(), 'clean', '-df'])
        commons.runSystemCommand(
            ['git', '-C',
             commons.rootDir(), 'checkout',
             str(candidate)])
        commons.runSystemCommand(['git', '-C', commons.rootDir(), 'pull'])
        commons.runSystemCommand(
            ['git', '-C', commons.rootDir(), 'submodule', 'init'])
        commons.runSystemCommand(
            ['git', '-C',
             commons.rootDir(), 'submodule', 'update'])
        commons.runSystemCommand([
            'git', '-C',
            commons.rootDir(), 'submodule', 'foreach', 'git', 'checkout',
            f'builds_{str(candidate)}'
        ])
        commons.runSystemCommand([
            'git', '-C',
            commons.rootDir(), 'submodule', 'foreach', 'git', 'pull'
        ])

        newHash = subprocess.check_output(['git', 'rev-parse', '--short HEAD'])

        # Remove install tickets
        [
            file.unlink() for file in Path(
                commons.rootDir(), 'system/skillInstallTickets').glob('*')
            if file.is_file()
        ]

        self._superManager.stateManager.setState(STATE,
                                                 newState=StateType.FINISHED)

        if currentHash != newHash:
            self._logger.logWarning(
                'New Alice version installed, need to restart...')

            self._superManager.webUINotificationManager.newNotification(
                typ=UINotificationType.INFO, notification='aliceUpdated')
            self.doRestart()

        self._logger.logInfo('Update checks completed.')
        self._isUpdating = False

    @property
    def updating(self) -> bool:
        return self._isUpdating

    @property
    def shuttingDown(self) -> bool:
        return self._shuttingDown
Example #5
0
class ProjectAlice(Singleton):
    NAME = 'ProjectAlice'

    def __init__(self, restartHandler: callable):
        Singleton.__init__(self, self.NAME)
        self._logger = Logger()
        self._logger.logInfo('Starting up Project Alice')
        self._booted = False
        with Stopwatch() as stopWatch:
            self._restart = False
            self._restartHandler = restartHandler
            self._superManager = SuperManager(self)

            self._superManager.initManagers()
            self._superManager.onStart()

            if self._superManager.configManager.getAliceConfigByName('useHLC'):
                self._superManager.commons.runRootSystemCommand(
                    ['systemctl', 'start', 'hermesledcontrol'])

            self._superManager.onBooted()
        self._logger.logInfo(f'- Started Project Alice in {stopWatch} seconds')
        self._booted = True

    @property
    def name(self) -> str:
        return self.NAME

    @property
    def isBooted(self) -> bool:
        return self._booted

    @property
    def restart(self) -> bool:
        return self._restart

    @restart.setter
    def restart(self, value: bool):
        self._restart = value

    def doRestart(self):
        self._restart = True
        self.onStop()

    def onStop(self):
        self._logger.logInfo('Shutting down Project Alice')
        self._superManager.onStop()
        if self._superManager.configManager.getAliceConfigByName('useHLC'):
            self._superManager.commons.runRootSystemCommand(
                ['systemctl', 'stop', 'hermesledcontrol'])

        self.INSTANCE = None
        self._restartHandler()

    def wipeAll(self):
        # Set as restarting so skills don't install / update
        self._restart = True

        self._superManager.skillManager.wipeSkills()
        self._superManager.databaseManager.clearDB()
        self._superManager.dialogTemplateManager.clearCache(False)
        self._superManager.nluManager.clearCache()
        self._superManager.snipsAssistantManager.clearData()

    def updateProjectAlice(self):
        self._logger.logInfo('Checking Project Alice updates')
        req = requests.get(
            url=f'{constants.GITHUB_API_URL}/ProjectAlice/branches',
            auth=SuperManager.getInstance().configManager.getGithubAuth())
        if req.status_code != 200:
            self._logger.logWarning('Failed checking for updates')
            return

        userUpdatePref = SuperManager.getInstance(
        ).configManager.getAliceConfigByName('aliceUpdateChannel')

        if userUpdatePref == 'master':
            candidate = 'master'
        else:
            candidate = Version.fromString(constants.VERSION)
            for branch in req.json():
                repoVersion = Version.fromString(branch['name'])
                if not repoVersion.isVersionNumber:
                    continue

                releaseType = repoVersion.releaseType
                if userUpdatePref == 'rc' and releaseType in {
                        'b', 'a'
                } or userUpdatePref == 'beta' and releaseType == 'a':
                    continue

                if repoVersion > candidate:
                    candidate = repoVersion

        self._logger.logInfo(f'Checking on "{str(candidate)}" update channel')
        commons = SuperManager.getInstance().commons
        commons.runSystemCommand(['git', '-C', commons.rootDir(), 'stash'])
        commons.runSystemCommand(
            ['git', '-C', commons.rootDir(), 'clean', '-df'])
        commons.runSystemCommand(
            ['git', '-C',
             commons.rootDir(), 'checkout',
             str(candidate)])
        commons.runSystemCommand(['git', '-C', commons.rootDir(), 'pull'])

        # Remove install tickets
        [
            file.unlink() for file in Path(
                commons.rootDir(), 'system/skillInstallTickets').glob('*')
            if file.is_file()
        ]
class ProjectAlice(Singleton):
	NAME = 'ProjectAlice'


	def __init__(self, restartHandler: callable):
		Singleton.__init__(self, self.NAME)
		self._logger = Logger(prepend='[Project Alice]')
		self._logger.logInfo('Starting Alice satellite unit')
		self._booted = False
		with Stopwatch() as stopWatch:
			self._restart = False
			self._restartHandler = restartHandler
			self._superManager = SuperManager(self)

			self._superManager.initManagers()
			self._superManager.onStart()

			if self._superManager.configManager.getAliceConfigByName('useHLC'):
				self._superManager.commons.runRootSystemCommand(['systemctl', 'start', 'hermesledcontrol'])

			self._superManager.onBooted()

		self._logger.logInfo(f'Started in {stopWatch} seconds')
		self._booted = True


	@property
	def name(self) -> str:
		return self.NAME


	@property
	def isBooted(self) -> bool:
		return self._booted


	@property
	def restart(self) -> bool:
		return self._restart


	@restart.setter
	def restart(self, value: bool):
		self._restart = value


	def doRestart(self):
		self._restart = True
		self.onStop()


	def onStop(self):
		self._logger.logInfo('Shutting down')
		self._superManager.onStop()
		if self._superManager.configManager.getAliceConfigByName('useHLC'):
			self._superManager.commons.runRootSystemCommand(['systemctl', 'stop', 'hermesledcontrol'])

		self.INSTANCE = None
		self._restartHandler()


	def updateProjectAlice(self):
		self._logger.logInfo('Checking for satellite updates')
		req = requests.get(url=f'{constants.GITHUB_API_URL}/ProjectAliceSatellite/branches', auth=SuperManager.getInstance().configManager.getGithubAuth())
		if req.status_code != 200:
			self._logger.logWarning('Failed checking for updates')
			return

		userUpdatePref = SuperManager.getInstance().configManager.getAliceConfigByName('aliceUpdateChannel')

		if userUpdatePref == 'master':
			candidate = 'master'
		else:
			candidate = Version.fromString(constants.VERSION)
			for branch in req.json():
				repoVersion = Version.fromString(branch['name'])
				if not repoVersion.isVersionNumber:
					continue

				releaseType = repoVersion.releaseType
				if userUpdatePref == 'rc' and releaseType in {'b', 'a'} or userUpdatePref == 'beta' and releaseType == 'a':
					continue

				if repoVersion > candidate:
					candidate = repoVersion

		self._logger.logInfo(f'Checking on "{str(candidate)}" update channel')
		commons = SuperManager.getInstance().commons
		commons.runSystemCommand(['git', '-C', commons.rootDir(), 'stash'])
		commons.runSystemCommand(['git', '-C', commons.rootDir(), 'clean', '-df'])
		commons.runSystemCommand(['git', '-C', commons.rootDir(), 'checkout', str(candidate)])
		commons.runSystemCommand(['git', '-C', commons.rootDir(), 'pull'])