|
|
|
@@ -5,37 +5,41 @@ import tarfile
|
|
|
|
import traceback
|
|
|
|
import traceback
|
|
|
|
from pathlib import Path
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
|
|
from bauh.api.abstract.download import FileDownloader
|
|
|
|
from bauh.api.abstract.download import FileDownloader
|
|
|
|
from bauh.api.abstract.handler import ProcessWatcher
|
|
|
|
from bauh.api.abstract.handler import ProcessWatcher
|
|
|
|
from bauh.api.exception import NoInternetException
|
|
|
|
from bauh.api.http import HttpClient
|
|
|
|
from bauh.commons import system
|
|
|
|
from bauh.commons import system
|
|
|
|
|
|
|
|
from bauh.commons.html import bold
|
|
|
|
from bauh.commons.system import SimpleProcess, ProcessHandler, run_cmd
|
|
|
|
from bauh.commons.system import SimpleProcess, ProcessHandler, run_cmd
|
|
|
|
from bauh.gems.web import BIN_PATH, NODE_DIR_PATH, NODE_BIN_PATH, NPM_BIN_PATH, NODE_MODULES_PATH, NATIVEFIER_BIN_PATH, \
|
|
|
|
from bauh.gems.web import BIN_PATH, NODE_DIR_PATH, NODE_BIN_PATH, NPM_BIN_PATH, NODE_MODULES_PATH, NATIVEFIER_BIN_PATH, \
|
|
|
|
ELECTRON_PATH, ELECTRON_DOWNLOAD_URL, ELECTRON_SHA256_URL, ELECTRON_VERSION
|
|
|
|
ELECTRON_PATH, ELECTRON_DOWNLOAD_URL, ELECTRON_SHA256_URL, URL_ENVIRONMENT_SETTINGS
|
|
|
|
from bauh.view.util.translation import I18n
|
|
|
|
from bauh.view.util.translation import I18n
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NodeUpdater:
|
|
|
|
class NodeUpdater:
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, logger: logging.Logger, file_downloader: FileDownloader, i18n: I18n):
|
|
|
|
def __init__(self, logger: logging.Logger, http_client: HttpClient, file_downloader: FileDownloader, i18n: I18n):
|
|
|
|
self.logger = logger
|
|
|
|
self.logger = logger
|
|
|
|
self.file_downloader = file_downloader
|
|
|
|
self.file_downloader = file_downloader
|
|
|
|
self.i18n = i18n
|
|
|
|
self.i18n = i18n
|
|
|
|
|
|
|
|
self.http_client = http_client
|
|
|
|
|
|
|
|
|
|
|
|
def _is_internet_available(self) -> bool:
|
|
|
|
def _is_internet_available(self) -> bool:
|
|
|
|
self.logger.info('Checking internet connection')
|
|
|
|
self.logger.info('Checking internet connection')
|
|
|
|
# TODO
|
|
|
|
# TODO
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def _download_and_install(self, cloud_version: str, watcher: ProcessWatcher ) -> bool:
|
|
|
|
def _download_and_install(self, version: str, version_url: str, watcher: ProcessWatcher) -> bool:
|
|
|
|
npm_dlink = 'https://nodejs.org/dist/v12.13.1/node-v12.13.1-linux-x64.tar.xz'
|
|
|
|
self.logger.info("Downloading NodeJS {}: {}".format(version, version_url))
|
|
|
|
self.logger.info("Downloading NodeJS {}: {}".format(cloud_version, npm_dlink))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tarf_path = '{}/{}'.format(BIN_PATH, npm_dlink.split('/')[-1])
|
|
|
|
tarf_path = '{}/{}'.format(BIN_PATH, version_url.split('/')[-1])
|
|
|
|
downloaded = self.file_downloader.download(npm_dlink, watcher=watcher, output_path=tarf_path, cwd=BIN_PATH)
|
|
|
|
downloaded = self.file_downloader.download(version_url, watcher=watcher, output_path=tarf_path, cwd=BIN_PATH)
|
|
|
|
|
|
|
|
|
|
|
|
if not downloaded:
|
|
|
|
if not downloaded:
|
|
|
|
self.logger.error("Could not download '{}'. Aborting...".format(npm_dlink))
|
|
|
|
self.logger.error("Could not download '{}'. Aborting...".format(version_url))
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
@@ -56,29 +60,22 @@ class NodeUpdater:
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
self.logger.error('Could not delete file {}'.format(tarf_path))
|
|
|
|
self.logger.error('Could not delete file {}'.format(tarf_path))
|
|
|
|
|
|
|
|
|
|
|
|
def update_node(self, watcher: ProcessWatcher = None) -> bool:
|
|
|
|
def update_node(self, version: str, version_url: str, watcher: ProcessWatcher = None) -> bool:
|
|
|
|
if not self._is_internet_available():
|
|
|
|
|
|
|
|
raise NoInternetException()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.logger.info('Checking Node version from bauh-files')
|
|
|
|
|
|
|
|
# TODO
|
|
|
|
|
|
|
|
cloud_version = 'v12.13.1'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Path(BIN_PATH).mkdir(parents=True, exist_ok=True)
|
|
|
|
Path(BIN_PATH).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(NODE_DIR_PATH):
|
|
|
|
if not os.path.exists(NODE_DIR_PATH):
|
|
|
|
if not self._download_and_install(cloud_version, watcher):
|
|
|
|
return self._download_and_install(version=version, version_url=version_url, watcher=watcher)
|
|
|
|
return False
|
|
|
|
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
installed_version = system.run_cmd('{} --version'.format(NODE_BIN_PATH))
|
|
|
|
installed_version = system.run_cmd('{} --version'.format(NODE_BIN_PATH))
|
|
|
|
|
|
|
|
|
|
|
|
if installed_version:
|
|
|
|
if installed_version:
|
|
|
|
installed_version = installed_version.strip()
|
|
|
|
installed_version = installed_version.strip()
|
|
|
|
|
|
|
|
|
|
|
|
self.logger.info('Node -> installed: {}. cloud: {}.'.format(installed_version, cloud_version))
|
|
|
|
self.logger.info('Node -> installed: {}. cloud: {}.'.format(installed_version, version))
|
|
|
|
|
|
|
|
|
|
|
|
if cloud_version != installed_version:
|
|
|
|
if version != installed_version:
|
|
|
|
return self._download_and_install(cloud_version, watcher)
|
|
|
|
self.logger.info("The NodeJs installed version is different from the Cloud.")
|
|
|
|
|
|
|
|
return self._download_and_install(version=version, version_url=version_url, watcher=watcher)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.logger.info("Node is already up to date")
|
|
|
|
self.logger.info("Node is already up to date")
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
@@ -87,15 +84,18 @@ class NodeUpdater:
|
|
|
|
self.logger.info("Removing {}".format(NODE_DIR_PATH))
|
|
|
|
self.logger.info("Removing {}".format(NODE_DIR_PATH))
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
shutil.rmtree(NODE_DIR_PATH)
|
|
|
|
shutil.rmtree(NODE_DIR_PATH)
|
|
|
|
return self._download_and_install(cloud_version, watcher)
|
|
|
|
return self._download_and_install(version=version, version_url=version_url, watcher=watcher)
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
self.logger.error('Could not delete the dir {}'.format(NODE_DIR_PATH))
|
|
|
|
self.logger.error('Could not delete the dir {}'.format(NODE_DIR_PATH))
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def _install_nativefier(self, handler: ProcessHandler) -> bool:
|
|
|
|
def _install_nativefier(self, version: str, handler: ProcessHandler) -> bool:
|
|
|
|
self.logger.info("Installing nativefier")
|
|
|
|
self.logger.info("Installing nativefier")
|
|
|
|
# TODO freeze specific version
|
|
|
|
|
|
|
|
proc = SimpleProcess([NPM_BIN_PATH, 'install', 'nativefier'], cwd=BIN_PATH)
|
|
|
|
if handler and handler.watcher:
|
|
|
|
|
|
|
|
handler.watcher.change_substatus(self.i18n['web.environment.install'].format(bold('nativefier')))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc = SimpleProcess([NPM_BIN_PATH, 'install', 'nativefier@{}'.format(version)], cwd=BIN_PATH)
|
|
|
|
|
|
|
|
|
|
|
|
if handler:
|
|
|
|
if handler:
|
|
|
|
return handler.handle_simple(proc)[0]
|
|
|
|
return handler.handle_simple(proc)[0]
|
|
|
|
@@ -103,22 +103,17 @@ class NodeUpdater:
|
|
|
|
proc.instance.wait()
|
|
|
|
proc.instance.wait()
|
|
|
|
|
|
|
|
|
|
|
|
if self._is_nativefier_installed():
|
|
|
|
if self._is_nativefier_installed():
|
|
|
|
self.logger.info("nativefier installed")
|
|
|
|
self.logger.info("nativefier {} installed".format(version))
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
self.logger.error("Could not install nativefier")
|
|
|
|
self.logger.error("Could not install nativefier {}".format(version))
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def _is_nativefier_installed(self) -> bool:
|
|
|
|
def _is_nativefier_installed(self) -> bool:
|
|
|
|
try:
|
|
|
|
return os.path.exists(NATIVEFIER_BIN_PATH)
|
|
|
|
return bool(system.run_cmd('{} --version'.format(NATIVEFIER_BIN_PATH)))
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
self.logger.error("Could not determine the installed nativefier version")
|
|
|
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def install_nativefier(self, remove_modules: bool = False, handler: ProcessHandler = None) -> bool:
|
|
|
|
def install_nativefier(self, version: str, remove_modules: bool = False, handler: ProcessHandler = None) -> bool:
|
|
|
|
self.logger.info("Preparing to install nativefier")
|
|
|
|
self.logger.info("Preparing to install nativefier {}".format(version))
|
|
|
|
|
|
|
|
|
|
|
|
if remove_modules and os.path.exists(NODE_MODULES_PATH):
|
|
|
|
if remove_modules and os.path.exists(NODE_MODULES_PATH):
|
|
|
|
self.logger.info('Removing old dir {}'.format(NODE_MODULES_PATH))
|
|
|
|
self.logger.info('Removing old dir {}'.format(NODE_MODULES_PATH))
|
|
|
|
@@ -128,10 +123,10 @@ class NodeUpdater:
|
|
|
|
self.logger.error('Could not remove dir {}. Aborting...'.format(NODE_MODULES_PATH))
|
|
|
|
self.logger.error('Could not remove dir {}. Aborting...'.format(NODE_MODULES_PATH))
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
return self._install_nativefier(handler)
|
|
|
|
return self._install_nativefier(version=version, handler=handler)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
if not self._is_nativefier_installed():
|
|
|
|
if not self._is_nativefier_installed():
|
|
|
|
return self._install_nativefier(handler)
|
|
|
|
return self._install_nativefier(version=version, handler=handler)
|
|
|
|
|
|
|
|
|
|
|
|
self.logger.info("Nativefier is already installed")
|
|
|
|
self.logger.info("Nativefier is already installed")
|
|
|
|
return True
|
|
|
|
return True
|
|
|
|
@@ -140,18 +135,14 @@ class NodeUpdater:
|
|
|
|
self.logger.info("Downloading Electron {}".format(version))
|
|
|
|
self.logger.info("Downloading Electron {}".format(version))
|
|
|
|
arch = 'ia32' if not is_x86_x64_arch else 'x64'
|
|
|
|
arch = 'ia32' if not is_x86_x64_arch else 'x64'
|
|
|
|
|
|
|
|
|
|
|
|
Path(ELECTRON_PATH).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
electron_url = ELECTRON_DOWNLOAD_URL.format(arch=arch, version=version)
|
|
|
|
electron_url = ELECTRON_DOWNLOAD_URL.format(arch=arch, version=version)
|
|
|
|
electron_path = '{}/{}'.format(ELECTRON_PATH, electron_url.split('/')[-1])
|
|
|
|
electron_path = '{}/{}'.format(ELECTRON_PATH, electron_url.split('/')[-1])
|
|
|
|
|
|
|
|
|
|
|
|
return self.file_downloader.download(file_url=electron_url, watcher=watcher, output_path=electron_path,cwd=ELECTRON_PATH)
|
|
|
|
return self.file_downloader.download(file_url=electron_url, watcher=watcher, output_path=electron_path, cwd=ELECTRON_PATH)
|
|
|
|
|
|
|
|
|
|
|
|
def _download_electron_sha256(self, version: str, watcher: ProcessWatcher) -> bool:
|
|
|
|
def _download_electron_sha256(self, version: str, watcher: ProcessWatcher) -> bool:
|
|
|
|
self.logger.info("Downloading Electron {} sha526".format(version))
|
|
|
|
self.logger.info("Downloading Electron {} sha526".format(version))
|
|
|
|
|
|
|
|
|
|
|
|
Path(ELECTRON_PATH).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sha256_url = ELECTRON_SHA256_URL.format(version=version)
|
|
|
|
sha256_url = ELECTRON_SHA256_URL.format(version=version)
|
|
|
|
sha256_path = '{}/{}'.format(ELECTRON_PATH, sha256_url.split('/')[-1])
|
|
|
|
sha256_path = '{}/{}'.format(ELECTRON_PATH, sha256_url.split('/')[-1])
|
|
|
|
return self.file_downloader.download(file_url=sha256_url, watcher=watcher, output_path=sha256_path, cwd=ELECTRON_PATH)
|
|
|
|
return self.file_downloader.download(file_url=sha256_url, watcher=watcher, output_path=sha256_path, cwd=ELECTRON_PATH)
|
|
|
|
@@ -161,7 +152,9 @@ class NodeUpdater:
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(ELECTRON_PATH):
|
|
|
|
if not os.path.exists(ELECTRON_PATH):
|
|
|
|
self.logger.info("Electron is not installed")
|
|
|
|
self.logger.info("Electron is not installed")
|
|
|
|
self._download_electron(version=version, is_x86_x64_arch=is_x86_x64_arch, watcher=watcher)
|
|
|
|
Path(ELECTRON_PATH).mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
if self._download_electron(version=version, is_x86_x64_arch=is_x86_x64_arch, watcher=watcher):
|
|
|
|
|
|
|
|
return self._download_electron_sha256(version=version, watcher=watcher)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
files = run_cmd('ls', print_error=False, cwd=ELECTRON_PATH)
|
|
|
|
files = run_cmd('ls', print_error=False, cwd=ELECTRON_PATH)
|
|
|
|
|
|
|
|
|
|
|
|
@@ -191,16 +184,31 @@ class NodeUpdater:
|
|
|
|
|
|
|
|
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def update_environment(self, is_x86_x64_arch: bool, handler: ProcessHandler = None):
|
|
|
|
def update_environment(self, is_x86_x64_arch: bool, handler: ProcessHandler = None) -> bool:
|
|
|
|
if not self.update_node(handler.watcher if handler else None):
|
|
|
|
try:
|
|
|
|
self.logger.warning('Could not update the environment')
|
|
|
|
res = self.http_client.get(URL_ENVIRONMENT_SETTINGS)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not res:
|
|
|
|
|
|
|
|
self.logger.warning('Could not retrieve the environments settings from the cloud')
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
if not self.install_nativefier(handler=handler):
|
|
|
|
try:
|
|
|
|
self.logger.warning('Could not update the environment')
|
|
|
|
settings = yaml.safe_load(res.content)
|
|
|
|
|
|
|
|
except yaml.YAMLError:
|
|
|
|
|
|
|
|
self.logger.error('Could not parse environment settings: {}'.format(res.text))
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
res = self.install_electron(version=ELECTRON_VERSION, is_x86_x64_arch=is_x86_x64_arch, watcher=handler.watcher if handler else None)
|
|
|
|
if not self.update_node(version=settings['nodejs']['version'], version_url=settings['nodejs']['url'],
|
|
|
|
|
|
|
|
watcher=handler.watcher if handler else None):
|
|
|
|
|
|
|
|
self.logger.warning('Could not install / update NodeJS')
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not self.install_nativefier(version=settings['nativefier']['version'], handler=handler):
|
|
|
|
|
|
|
|
self.logger.warning('Could not install / update nativefier')
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res = self.install_electron(version=settings['electron']['version'], is_x86_x64_arch=is_x86_x64_arch,
|
|
|
|
|
|
|
|
watcher=handler.watcher if handler else None)
|
|
|
|
|
|
|
|
|
|
|
|
if res:
|
|
|
|
if res:
|
|
|
|
self.logger.info('Environment updated')
|
|
|
|
self.logger.info('Environment updated')
|
|
|
|
@@ -208,3 +216,5 @@ class NodeUpdater:
|
|
|
|
self.logger.warning('Could not update the environment')
|
|
|
|
self.logger.warning('Could not update the environment')
|
|
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
return res
|
|
|
|
|
|
|
|
except requests.exceptions.ConnectionError:
|
|
|
|
|
|
|
|
return False
|
|
|
|
|