diff --git a/cps/admin.py b/cps/admin.py index ac82bc8e..f201efc8 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -1671,7 +1671,8 @@ def get_updater_status(): "9": _(u'Update failed:') + u' ' + _(u'Connection error'), "10": _(u'Update failed:') + u' ' + _(u'Timeout while establishing connection'), "11": _(u'Update failed:') + u' ' + _(u'General error'), - "12": _(u'Update failed:') + u' ' + _(u'Update File Could Not be Saved in Temp Dir') + "12": _(u'Update failed:') + u' ' + _(u'Update file could not be saved in temp dir'), + "13": _(u'Update failed:') + u' ' + _(u'Files could not be replaced during update') } status['text'] = text updater_thread.status = 0 diff --git a/cps/static/js/main.js b/cps/static/js/main.js index ce930cc3..2f7dc172 100644 --- a/cps/static/js/main.js +++ b/cps/static/js/main.js @@ -239,14 +239,13 @@ $(function() { dataType: "json", url: window.location.pathname + "/../../get_updater_status", success: function success(data) { - // console.log(data.status); $("#DialogContent").html(updateText[data.status]); if (data.status > 6) { cleanUp(); } }, error: function error() { - $("#DialogContent").html(updateText[7]); + $("#DialogContent").html(updateText[11]); cleanUp(); }, timeout: 2000 @@ -442,7 +441,6 @@ $(function() { success: function success(data) { updateText = data.text; $("#DialogContent").html(updateText[data.status]); - // console.log(data.status); updateTimerID = setInterval(updateTimer, 2000); } }); diff --git a/cps/updater.py b/cps/updater.py index fb5219b6..94cb0453 100644 --- a/cps/updater.py +++ b/cps/updater.py @@ -94,14 +94,17 @@ class Updater(threading.Thread): return False self.status = 4 log.debug(u'Replacing files') - self.update_source(foldername, constants.BASE_DIR) - self.status = 6 - log.debug(u'Preparing restart of server') - time.sleep(2) - web_server.stop(True) - self.status = 7 - time.sleep(2) - return True + if self.update_source(foldername, constants.BASE_DIR): + self.status = 6 + log.debug(u'Preparing restart of server') + time.sleep(2) + web_server.stop(True) + self.status = 7 + time.sleep(2) + return True + else: + self.status = 13 + except requests.exceptions.HTTPError as ex: log.error(u'HTTP Error %s', ex) self.status = 8 @@ -181,6 +184,28 @@ class Updater(threading.Thread): rf.append(item) return rf + @classmethod + def check_permissions(cls, root_src_dir, root_dst_dir): + access = True + remove_path = len(root_src_dir) + 1 + for src_dir, __, files in os.walk(root_src_dir): + root_dir = os.path.join(root_dst_dir, src_dir[remove_path:]) + # Skip non existing folders on check + if not os.path.isdir(root_dir): # root_dir.lstrip(os.sep).startswith('.') or + continue + if not os.access(root_dir, os.R_OK|os.W_OK): + log.debug("Missing permissions for {}".format(root_dir)) + access = False + for file_ in files: + curr_file = os.path.join(root_dir, file_) + # Skip non existing files on check + if not os.path.isfile(curr_file): # or curr_file.startswith('.'): + continue + if not os.access(curr_file, os.R_OK|os.W_OK): + log.debug("Missing permissions for {}".format(curr_file)) + access = False + return access + @classmethod def moveallfiles(cls, root_src_dir, root_dst_dir): new_permissions = os.stat(root_dst_dir) @@ -269,20 +294,25 @@ class Updater(threading.Thread): remove_items = self.reduce_dirs(rf, new_list) - self.moveallfiles(source, destination) + if self.check_permissions(source, destination): + self.moveallfiles(source, destination) - for item in remove_items: - item_path = os.path.join(destination, item[1:]) - if os.path.isdir(item_path): - log.debug("Delete dir %s", item_path) - shutil.rmtree(item_path, ignore_errors=True) - else: - try: - os.remove(item_path) - log.debug("Delete file %s", item_path) - except OSError: - log.debug("Could not remove: %s", item_path) - shutil.rmtree(source, ignore_errors=True) + for item in remove_items: + item_path = os.path.join(destination, item[1:]) + if os.path.isdir(item_path): + log.debug("Delete dir %s", item_path) + shutil.rmtree(item_path, ignore_errors=True) + else: + try: + os.remove(item_path) + log.debug("Delete file %s", item_path) + except OSError: + log.debug("Could not remove: %s", item_path) + shutil.rmtree(source, ignore_errors=True) + return True + else: + log.debug("Permissions missing for update") + return False @staticmethod def is_venv(): @@ -572,5 +602,5 @@ class Updater(threading.Thread): status['message'] = _(u'Timeout while establishing connection') except (requests.exceptions.RequestException, ValueError): status['message'] = _(u'General error') - log.debug('Updater status: %s', status['message']) + log.debug('Updater status: {}'.format(status['message'] or "OK")) return status, commit