def __init__(self, system_bus, mainloop): # Init dbus service. dbus.service.Object.__init__(self, system_bus, DSC_SERVICE_PATH) # Init. self.mainloop = mainloop self.pkg_cache = AptCache() self.exit_flag = False self.simulate = False self.all_upgrade_pkg_names = [] self.download_dir = "/var/cache/apt/archives" self.is_upgrading = False self.in_update_list = False self.apt_action_pool = AptActionPool(self.pkg_cache) self.apt_action_pool.start() global_event.register_event('parse-download-error', self.send_parse_download_error) global_event.register_event("action-start", self.action_start) global_event.register_event("action-update", self.action_update) global_event.register_event("action-finish", self.action_finish) global_event.register_event("action-failed", self.action_failed) global_event.register_event("download-start", self.download_start) global_event.register_event("download-update", self.download_update) global_event.register_event("download-finish", self.download_finish) global_event.register_event("download-stop", self.download_stop) global_event.register_event("download-error", self.download_failed) global_event.register_event("update-list-start", self.update_list_start) global_event.register_event("update-list-finish", self.update_list_finish) global_event.register_event("update-list-failed", self.update_list_failed) global_event.register_event("update-list-update", self.update_list_update) self.packages_status = {} self.exit_manager = ExitManager(self.mainloop, self.is_update_list_running, self.is_download_action_running, self.is_apt_action_running, self.have_exit_request) self.exit_manager.start() self.set_download_dir('/var/cache/apt/archives') self.download_manager = DownloadManager(global_event, verbose=True)
def __init__(self, system_bus, mainloop): # Init dbus service. dbus.service.Object.__init__(self, system_bus, DSC_SERVICE_PATH) # Init. self.mainloop = mainloop self.pkg_cache = AptCache() self.exit_flag = False self.simulate = False self.all_upgrade_pkg_names = [] self.download_dir = "/var/cache/apt/archives" self.is_upgrading = False self.in_update_list = False self.apt_action_pool = AptActionPool(self.pkg_cache) self.apt_action_pool.start() global_event.register_event( 'parse-download-error', self.send_parse_download_error) global_event.register_event("action-start", self.action_start) global_event.register_event("action-update", self.action_update) global_event.register_event("action-finish", self.action_finish) global_event.register_event("action-failed", self.action_failed) global_event.register_event("download-start", self.download_start) global_event.register_event("download-update", self.download_update) global_event.register_event("download-finish", self.download_finish) global_event.register_event("download-stop", self.download_stop) global_event.register_event("download-error", self.download_failed) global_event.register_event( "update-list-start", self.update_list_start) global_event.register_event( "update-list-finish", self.update_list_finish) global_event.register_event( "update-list-failed", self.update_list_failed) global_event.register_event( "update-list-update", self.update_list_update) self.packages_status = {} self.exit_manager = ExitManager( self.mainloop, self.is_update_list_running, self.is_download_action_running, self.is_apt_action_running, self.have_exit_request) self.exit_manager.start() self.set_download_dir('/var/cache/apt/archives') self.download_manager = DownloadManager(global_event, verbose=True)
class PackageManager(dbus.service.Object): ''' docs ''' def __init__(self, system_bus, mainloop): log("init dbus") # Init dbus service. dbus.service.Object.__init__(self, system_bus, DSC_SERVICE_PATH) # Init. self.mainloop = mainloop self.pkg_cache = AptCache() self.exit_flag = False self.simulate = False self.all_upgrade_pkg_names = [] self.is_upgrading = False self.in_update_list = False self.apt_action_pool = AptActionPool(self.pkg_cache) self.apt_action_pool.start() global_event.register_event('parse-download-error', self.send_parse_download_error) global_event.register_event("action-start", self.action_start) global_event.register_event("action-update", self.action_update) global_event.register_event("action-finish", self.action_finish) global_event.register_event("action-failed", self.action_failed) global_event.register_event("download-start", self.download_start) global_event.register_event("download-update", self.download_update) global_event.register_event("download-finish", self.download_finish) global_event.register_event("download-stop", self.download_stop) global_event.register_event("download-error", self.download_failed) global_event.register_event("update-list-start", self.update_list_start) global_event.register_event("update-list-finish", self.update_list_finish) global_event.register_event("update-list-failed", self.update_list_failed) global_event.register_event("update-list-update", self.update_list_update) self.packages_status = {} self.exit_manager = ExitManager( self.mainloop, self.is_update_list_running, self.is_download_action_running, self.is_apt_action_running, self.have_exit_request) self.exit_manager.start() log("init finish") self.set_download_dir('/var/cache/apt/archives') self.init_download_manager(5) def download_start(self, pkg_name, action_type): utils.set_running_lock(True) self.update_signal([("download-start", (pkg_name, action_type))]) if action_type == ACTION_UPGRADE: self.is_upgrading = True def download_update(self, pkg_name, action_type, data): self.update_signal([("download-update", (pkg_name, action_type, data))]) if action_type == ACTION_UPGRADE: self.is_upgrading = True def download_stop(self, pkg_name, action_type): self.update_signal([("download-stop", (pkg_name, action_type))]) self.exit_manager.check() if action_type == ACTION_UPGRADE: self.is_upgrading = False def download_failed(self, pkg_name, action_type, e): logger.error("%s download failed with %s" % (pkg_name, e)) utils.set_running_lock(False) self.update_signal([("download-failed", (pkg_name, action_type, e))]) self.exit_manager.check() if action_type == ACTION_UPGRADE: self.is_upgrading = False def download_finish(self, action_id, action_type, all_pkg_names): utils.set_running_lock(False) self.update_signal([("download-finish", (action_id, action_type))]) if action_type == ACTION_INSTALL: self.apt_action_pool.add_install_action(all_pkg_names) elif action_type == ACTION_UPGRADE: self.start_upgrade(all_pkg_names, action_id) self.is_upgrading = False self.exit_manager.check() def action_start(self, signal_content): utils.set_running_lock(True) self.update_signal([("action-start", signal_content)]) if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = True def action_update(self, signal_content): self.update_signal([("action-update", signal_content)]) if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = True def action_finish(self, signal_content): utils.set_running_lock(False) pkg_name, action_type, pkg_info_list = signal_content if action_type == ACTION_INSTALL: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status(pkg_name, self.pkg_cache.PKG_STATUS_INSTALLED) elif action_type == ACTION_UPGRADE: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status(pkg_name, self.pkg_cache.PKG_STATUS_UPGRADED) elif action_type == ACTION_UNINSTALL: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status(pkg_name, self.pkg_cache.PKG_STATUS_UNINSTALLED) self.update_signal([("action-finish", signal_content)]) self.exit_manager.check() if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = False def action_failed(self, signal_content): utils.set_running_lock(False) self.update_signal([("action-failed", signal_content)]) self.exit_manager.check() if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = False def is_update_list_running(self): return self.in_update_list def is_download_action_running(self): return len(self.download_manager.fetch_files_dict) > 0 def is_apt_action_running(self): return len(self.apt_action_pool.active_mission_list) + len(self.apt_action_pool.wait_mission_list) > 0 def have_exit_request(self): return self.exit_flag def update_list_start(self): self.in_update_list = True self.update_signal([("update-list-start", "")]) def update_list_finish(self): self.update_signal([("update-list-merge", "")]) self.pkg_cache.open(apb.OpProgress()) db_build.BuildSoftwareDB(self.pkg_cache) self.update_signal([("update-list-finish", "")]) self.in_update_list = False self.exit_manager.check() def update_list_failed(self): self.in_update_list = False self.update_signal([("update-list-failed", "")]) self.exit_manager.check() def update_list_update(self, percent, status_message, speed_str): self.update_signal([("update-list-update", (percent, status_message, speed_str))]) def handle_dbus_reply(self, *reply): log("%s (reply): %s" % (self.module_dbus_name, str(reply))) def handle_dbus_error(self, *error): log("%s (error): %s" % (self.module_dbus_name, str(error))) def send_parse_download_error(self, pkg_name, action_type): self.update_signal([("parse-download-error", (pkg_name, action_type))]) def get_unique_id(self): return str(uuid.uuid4()) def get_real_pkg_name(self, pkg_name): if pkg_name in self.pkg_cache: return pkg_name elif (pkg_name + ":i386") in self.pkg_cache: return pkg_name + ":i386" else: return None def add_upgrade_download_with_new_policy(self, pkg_names, action_type): action_id = '%s_%s' % (self.get_unique_id(), action_type) self.update_signal([("ready-download-start", (action_id, action_type))]) real_pkg_dict, not_in_cache = parse_pkg.get_real_pkg_dict(self.pkg_cache, pkg_names) if not_in_cache: self.update_signal([("pkgs-not-in-cache", (json.dumps(not_in_cache), action_type))]) else: (all_change_pkgs, mark_failed_pkg_dict, marked_delete_sys_pkgs ) = parse_pkg.get_changes_pkgs(self.pkg_cache, real_pkg_dict) if mark_failed_pkg_dict: self.update_signal([("pkgs-mark-failed", (json.dumps(mark_failed_pkg_dict.keys()), action_type))]) elif marked_delete_sys_pkgs: self.update_signal([("marked-delete-system-pkgs", (json.dumps(marked_delete_sys_pkgs), action_type))]) else: self.update_signal([("ready-download-finish", (action_id, action_type))]) download_pkg_infos = parse_pkg.check_pkg_download_info(all_change_pkgs) if download_pkg_infos[0] == DOWNLOAD_STATUS_ERROR: self.update_signal([("pkgs-parse-download-error", (str(download_pkg_infos[1]), action_type))]) elif download_pkg_infos[0] == DOWNLOAD_STATUS_NOTNEED: self.start_upgrade(pkg_names, action_id) else: (names, download_urls, download_hash_infos, pkg_sizes) = download_pkg_infos self.all_upgrade_pkg_names = all_change_pkgs self.download_manager.add_download( action_id, action_type, download_urls, all_pkg_names=pkg_names, all_change_pkgs=all_change_pkgs, file_save_dir=self.download_dir, ) def add_download(self, pkg_name, action_type, simulate=False): pkg_infos = get_pkg_download_info(self.pkg_cache, pkg_name) self.update_signal([("ready-download-finish", (pkg_name, action_type))]) if pkg_infos[0] == DOWNLOAD_STATUS_NOTNEED: self.download_finish(pkg_name, action_type, [pkg_name,]) print "Don't need download" elif pkg_infos[0] == DOWNLOAD_STATUS_ERROR: self.update_signal([("parse-download-error", (pkg_name, action_type))]) print "Download error" else: (names, download_urls, download_hash_infos, pkg_sizes) = pkg_infos self.download_manager.add_download( pkg_name, action_type, download_urls, all_pkg_names=[pkg_name,], file_save_dir=self.download_dir) def start_upgrade(self, pkg_names, action_id): self.apt_action_pool.add_multi_upgrade_mission(pkg_names, action_id) def del_source_list_d(self): white_list_path = os.path.join(get_parent_dir(__file__), 'white_list.txt') if os.path.exists(white_list_path): with open(white_list_path) as fp: for line in fp: line = line.strip() if os.path.exists(line): os.remove(line) def get_desktops(self, pkg_name): desktops = [] try: pkg_obj = self.pkg_cache[pkg_name] for f in pkg_obj.installed_files: if f.endswith(".desktop"): desktops.append(f) except: pass return desktops @dbus.service.method(DSC_SERVICE_NAME, in_signature='', out_signature='as') def read_no_notify_config(self, no_notify_config_path): if os.path.exists(no_notify_config_path): no_notify_config_str = read_file(no_notify_config_path) try: no_notify_config = eval(no_notify_config_str) if type(no_notify_config).__name__ != "list": no_notify_config = [] except Exception: no_notify_config = [] return no_notify_config else: return [] @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def add_no_notify_pkg(self, info): pkg_name, path = info no_notify_config = self.read_no_notify_config(path) if pkg_name not in no_notify_config: pkg_name = str(pkg_name) no_notify_config.append(pkg_name) write_file(path, str(no_notify_config)) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_no_notify_pkg(self, info): pkg_name, path = info pkg_name = str(pkg_name) path = str(path) no_notify_config = self.read_no_notify_config(path) if pkg_name in no_notify_config: write_file(path, str(filter(lambda config_pkg_name: config_pkg_name != pkg_name, no_notify_config))) @dbus.service.method(DSC_SERVICE_NAME, in_signature="i", out_signature="") def init_download_manager(self, number): self.download_manager = DownloadManager(global_event, number, verbose=True) @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="") def set_download_dir(self, local_dir): apt_pkg.config.set("Dir::Cache::Archives", local_dir) self.download_dir = local_dir @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="ai") def get_download_size(self, pkg_name): total_size = 0 pkg_infos = get_pkg_download_info(self.pkg_cache, pkg_name) if pkg_infos[0] == DOWNLOAD_STATUS_NOTNEED: total_size = get_pkg_own_size(self.pkg_cache, pkg_name) size_flag = PKG_SIZE_OWN elif pkg_infos[0] == DOWNLOAD_STATUS_ERROR: total_size = -1 size_flag = PKG_SIZE_ERROR else: (names, download_urls, download_hash_infos, pkg_sizes) = pkg_infos for size in pkg_sizes: total_size += size size_flag = PKG_SIZE_DOWNLOAD return [size_flag, total_size] @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="as") def get_upgrade_download_size(self, pkg_names): real_pkg_dict, not_in_cache = parse_pkg.get_real_pkg_dict(self.pkg_cache, pkg_names) if not_in_cache: return ["-1", json.dumps([])] else: (all_change_pkgs, mark_failed_pkg_dict, marked_delete_sys_pkgs ) = parse_pkg.get_changes_pkgs(self.pkg_cache, real_pkg_dict) download_pkg_infos = parse_pkg.check_pkg_download_info(all_change_pkgs) change_pkg_names = [pkg.name for pkg in all_change_pkgs] if download_pkg_infos[0] == DOWNLOAD_STATUS_ERROR: return ["-1", json.dumps([])] elif download_pkg_infos[0] == DOWNLOAD_STATUS_NOTNEED: return ["0", json.dumps(change_pkg_names)] else: (names, download_urls, download_hash_infos, pkg_sizes) = download_pkg_infos total_size = 0 for size in pkg_sizes: total_size += size return [str(total_size), json.dumps(change_pkg_names)] @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="ai") def clean_download_cache(self): '''Clean download cache.''' # get action packages. remain_pkgs = [] for (pkg_name, info_dict) in self.download_manager.fetch_files_dict.items(): remain_pkgs.append(pkg_name) for (pkg_name, info_dict) in self.apt_action_pool.install_action_dict.items(): remain_pkgs.append(pkg_name) for (pkg_name, info_dict) in self.apt_action_pool.upgrade_action_dict.items(): remain_pkgs.append(pkg_name) # Get depend packages. remain_pkgs_paths = [] for pkg_name in remain_pkgs: result = get_pkg_dependence_file_path(self.pkg_cache, pkg_name) if not result: remain_pkgs_paths += result # Init clean size. packageNum = 0 cleanSize = 0 # Delete cache directory. cache_archive_dir = get_cache_archive_dir() if os.path.exists(cache_archive_dir): for root, folder, files in os.walk(cache_archive_dir): for file_name in files: path = os.path.join(root, file_name) if path.endswith(".deb") and (path not in remain_pkgs_paths): packageNum += 1 cleanSize += os.path.getsize(path) remove_file(path) return [packageNum, cleanSize] @dbus.service.method(DSC_SERVICE_NAME, in_signature="b", out_signature="") def say_hello(self, simulate): # Set exit_flag with False to prevent backend exit, # this just useful that frontend start again before backend exit. log("Say hello from frontend.") self.exit_flag = False self.simulate = simulate @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def request_quit(self): # Set exit flag. self.exit_flag = True self.exit_manager.check() self.update_signal([("frontend-quit", "")]) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def change_source_list(self, repo_urls): ubuntu_repo_url, deepin_repo_url = repo_urls new_source_list_content = get_source_list_contents(ubuntu_repo_url, deepin_repo_url) os.system('cp %s %s.save' % (SOURCE_LIST, SOURCE_LIST)) with open(SOURCE_LIST, 'w') as fp: fp.write(new_source_list_content) @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="(sas)") # def request_upgrade_pkgs(self): // old api name def RequestUpgradeStatus(self): """ Get upgrade status @return: Return (status_code, [json.dumps(pkg_name, pkg_version)]), status code is in below constants: - normal: no dpkg action, just return packages that need to upgrade; - upgrading: in upgrading packages; - cache-updating: in updating apt cache; """ if self.in_update_list: return ("cache-updating", []) elif self.is_upgrading: return ("upgrading", []) else: cache_upgrade_pkgs = self.pkg_cache.get_upgrade_pkgs() return ("normal", cache_upgrade_pkgs) @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="s") def request_uninstall_pkgs(self): return json.dumps(self.pkg_cache.get_uninstall_pkgs()) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="as") def request_pkgs_install_version(self, pkg_names): pkg_versions = [] for pkg_name in pkg_names: try: version = self.pkg_cache[pkg_name].versions[0].version pkg_versions.append(version) except: try: version = self.pkg_cache[pkg_name+":i386"].versions[0].version pkg_versions.append(version) except: self.update_signal([("pkg-not-in-cache", pkg_name)]) return pkg_versions @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="as") def is_pkg_in_cache(self, pkg_name): result = [] try: self.pkg_cache[pkg_name] result.append(pkg_name) except: try: pkg_name += ":i386" self.pkg_cache[pkg_name] result.append(pkg_name) except: pass return result @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="as") def request_pkgs_uninstall_version(self, pkg_names): return self.pkg_cache.get_pkgs_uninstall_version(pkg_names) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def install_pkg(self, pkg_names): for pkg_name in pkg_names: real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: ThreadMethod(self.add_download, (real_pkg_name, ACTION_INSTALL, self.simulate)).start() else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @dbus.service.method(DSC_SERVICE_NAME, in_signature="sb", out_signature="") def uninstall_pkg(self, pkg_name, purge): real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: self.apt_action_pool.add_uninstall_action(real_pkg_name, self.simulate, purge) else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @dbus.service.method(DSC_SERVICE_NAME, in_signature="sb", out_signature="") def uninstall_pkg_from_desktop(self, desktop_path, purge): ThreadMethod(self.uninstall_pkg_from_desktop_thread, (desktop_path, purge)).start() def uninstall_pkg_from_desktop_thread(self, path, purge): pkg_name = self.get_pkg_name_from_path(path) if pkg_name: self.uninstall_pkg(pkg_name, purge) else: global_event.emit("action-failed", (path, ACTION_UNINSTALL, [], "no package found for path: %s" % path)) @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="s") def get_pkg_name_from_path(self, path): result = subprocess.check_output(['dpkg', '-S', path]).strip().split(":") if len(result) == 2 and result[1].strip() == path.strip(): return result[0].strip() else: return "" @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def upgrade_pkg(self, pkg_names): for pkg_name in pkg_names: real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: self.update_signal([("ready-download-start", (real_pkg_name, ACTION_UPGRADE))]) ThreadMethod(self.add_download, (real_pkg_name, ACTION_UPGRADE, self.simulate)).start() else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def upgrade_pkgs_with_new_policy(self, pkg_names): ThreadMethod(self.add_upgrade_download_with_new_policy, (pkg_names, ACTION_UPGRADE)).start() @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def stop_download_pkg(self, pkg_names): for pkg_name in pkg_names: self.download_manager.stop_wait_download(pkg_name) @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def cancel_upgrade_download(self): if getattr(self, 'upgrade_id'): self.download_manager.stop_wait_download(self.upgrade_id) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_wait_missions(self, pkg_infos): self.apt_action_pool.remove_wait_missions(pkg_infos) @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_wait_downloads(self, pkg_names): for pkg_name in pkg_names: self.download_manager.stop_wait_download(pkg_name) @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="s") def request_pkg_short_desc(self, pkg_name): return self.pkg_cache.get_pkg_short_desc(pkg_name) @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="as") def request_status(self): download_status = { ACTION_INSTALL : [], ACTION_UPGRADE : []} for (pkg_name, info_dict) in self.download_manager.fetch_files_dict.items(): if info_dict["action_type"] == ACTION_INSTALL: download_status[ACTION_INSTALL].append((pkg_name, info_dict["status"])) elif info_dict["action_type"] == ACTION_UPGRADE: download_status[ACTION_UPGRADE].append((pkg_name, info_dict["status"])) action_status = { ACTION_INSTALL : [], ACTION_UPGRADE : [], ACTION_UNINSTALL : []} for (pkg_name, info_dict) in self.apt_action_pool.install_action_dict.items(): action_status[ACTION_INSTALL].append((pkg_name, info_dict["status"])) for (pkg_name, info_dict) in self.apt_action_pool.upgrade_action_dict.items(): action_status[ACTION_UPGRADE].append((pkg_name, info_dict["status"])) for (pkg_name, info_dict) in self.apt_action_pool.uninstall_action_dict.items(): action_status[ACTION_UNINSTALL].append((pkg_name, info_dict["status"])) return [str(download_status), str(action_status)] @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def start_update_list(self): log("start update list...") self.del_source_list_d() self.pkg_cache.open(apb.OpProgress()) self.apt_action_pool.add_update_list_mission() log("start update list done") @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="ab") def request_pkgs_install_status(self, pkg_names): _status = [] for pkg in pkg_names: _status.append(self.pkg_cache.is_pkg_installed(pkg)) return _status @dbus.service.method(DSC_SERVICE_NAME, in_signature="(si)", out_signature="") def set_pkg_status(self, pkg_status): pkg_name, status = pkg_status self.pkg_cache.set_pkg_status(pkg_name, pkg_status) @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="i") def get_pkg_installed(self, pkg_name): if self.is_pkg_in_cache(pkg_name): if self.pkg_cache.is_pkg_installed(pkg_name): return 1 else: return 0 else: return -1 @dbus.service.method(DSC_SERVICE_NAME, in_signature="ss", out_signature="s") def get_pkg_start_status(self, pkg_name, start_pkg_names): is_current_installed = self.get_pkg_installed(pkg_name) if is_current_installed == -1: return "unknown" elif is_current_installed == 0: return "uninstalled" else: desktops = self.get_desktops(pkg_name) names = start_pkg_names.split(",") for name in names: if self.get_pkg_installed(name) == 1: desktops += self.get_desktops(name) return json.dumps(desktops) @dbus.service.signal(DSC_SERVICE_NAME, signature='a(sv)') # Use below command for test: # dbus-monitor --system "type='signal', interface='com.linuxdeepin.softwarecenter'" def update_signal(self, message): # The signal is emitted when this method exits # You can have code here if you wish pass
class PackageManager(dbus.service.Object): ''' docs ''' def invoked_log(func): @functools.wraps(func) def wrapper(*args, **kw): info = "dbus method invoked: %s, arguments: %s" % (func.__name__, str(args[1:])) logger.debug(info) return func(*args, **kw) return wrapper def __init__(self, system_bus, mainloop): # Init dbus service. dbus.service.Object.__init__(self, system_bus, DSC_SERVICE_PATH) # Init. self.mainloop = mainloop self.pkg_cache = AptCache() self.exit_flag = False self.simulate = False self.all_upgrade_pkg_names = [] self.download_dir = "/var/cache/apt/archives" self.is_upgrading = False self.in_update_list = False self.apt_action_pool = AptActionPool(self.pkg_cache) self.apt_action_pool.start() global_event.register_event('parse-download-error', self.send_parse_download_error) global_event.register_event("action-start", self.action_start) global_event.register_event("action-update", self.action_update) global_event.register_event("action-finish", self.action_finish) global_event.register_event("action-failed", self.action_failed) global_event.register_event("download-start", self.download_start) global_event.register_event("download-update", self.download_update) global_event.register_event("download-finish", self.download_finish) global_event.register_event("download-stop", self.download_stop) global_event.register_event("download-error", self.download_failed) global_event.register_event("update-list-start", self.update_list_start) global_event.register_event("update-list-finish", self.update_list_finish) global_event.register_event("update-list-failed", self.update_list_failed) global_event.register_event("update-list-update", self.update_list_update) self.packages_status = {} self.exit_manager = ExitManager(self.mainloop, self.is_update_list_running, self.is_download_action_running, self.is_apt_action_running, self.have_exit_request) self.exit_manager.start() self.set_download_dir('/var/cache/apt/archives') self.download_manager = DownloadManager(global_event, verbose=True) def download_start(self, pkg_name, action_type): utils.set_running_lock(True) self.update_signal([("download-start", (pkg_name, action_type))]) if action_type == ACTION_UPGRADE: self.is_upgrading = True def download_update(self, pkg_name, action_type, data): self.update_signal([("download-update", (pkg_name, action_type, data)) ]) if action_type == ACTION_UPGRADE: self.is_upgrading = True def download_stop(self, pkg_name, action_type): self.update_signal([("download-stop", (pkg_name, action_type))]) self.exit_manager.check() if action_type == ACTION_UPGRADE: self.is_upgrading = False def download_failed(self, pkg_name, action_type, e): logger.error("%s download failed with %s" % (pkg_name, e)) utils.set_running_lock(False) self.update_signal([("download-failed", (pkg_name, action_type, e))]) self.exit_manager.check() if action_type == ACTION_UPGRADE: self.is_upgrading = False def download_finish(self, action_id, action_type, all_pkg_names): utils.set_running_lock(False) self.update_signal([("download-finish", (action_id, action_type))]) if action_type == ACTION_INSTALL: self.apt_action_pool.add_install_action(all_pkg_names) elif action_type == ACTION_UPGRADE: self.start_upgrade(all_pkg_names, action_id) self.is_upgrading = False self.exit_manager.check() def action_start(self, signal_content): utils.set_running_lock(True) self.update_signal([("action-start", signal_content)]) if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = True def action_update(self, signal_content): self.update_signal([("action-update", signal_content)]) if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = True def action_finish(self, signal_content): utils.set_running_lock(False) pkg_name, action_type, pkg_info_list = signal_content if action_type == ACTION_INSTALL: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status( pkg_name, self.pkg_cache.PKG_STATUS_INSTALLED) elif action_type == ACTION_UPGRADE: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status( pkg_name, self.pkg_cache.PKG_STATUS_UPGRADED) elif action_type == ACTION_UNINSTALL: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status( pkg_name, self.pkg_cache.PKG_STATUS_UNINSTALLED) self.update_signal([("action-finish", signal_content)]) self.exit_manager.check() if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = False def action_failed(self, signal_content): utils.set_running_lock(False) self.update_signal([("action-failed", signal_content)]) self.exit_manager.check() if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = False def is_update_list_running(self): return self.in_update_list def is_download_action_running(self): return len(self.download_manager.download_task_info) > 0 def is_apt_action_running(self): return len(self.apt_action_pool.active_mission_list) + len( self.apt_action_pool.wait_mission_list) > 0 def have_exit_request(self): return self.exit_flag def update_list_start(self): self.in_update_list = True self.update_signal([("update-list-start", "")]) def update_list_finish(self): self.update_signal([("update-list-merge", "")]) self.pkg_cache.open(apb.OpProgress()) db_build.BuildSoftwareDB(self.pkg_cache) self.update_signal([("update-list-finish", "")]) self.in_update_list = False self.exit_manager.check() def update_list_failed(self): self.in_update_list = False self.update_signal([("update-list-failed", "")]) self.exit_manager.check() def update_list_update(self, percent, status_message, speed_str): self.update_signal([("update-list-update", (percent, status_message, speed_str))]) def handle_dbus_reply(self, *reply): logger.info("%s (reply): %s" % (self.module_dbus_name, str(reply))) def handle_dbus_error(self, *error): logger.info("%s (error): %s" % (self.module_dbus_name, str(error))) def send_parse_download_error(self, pkg_name, action_type): self.update_signal([("parse-download-error", (pkg_name, action_type))]) def get_unique_id(self): return str(uuid.uuid4()) def get_real_pkg_name(self, pkg_name): if pkg_name in self.pkg_cache: return pkg_name elif (pkg_name + ":i386") in self.pkg_cache: return pkg_name + ":i386" else: return None def dist_upgrade(self): action_type = ACTION_UPGRADE action_id = '%s_%s' % (self.get_unique_id(), action_type) self.update_signal([("ready-download-start", (action_id, action_type)) ]) dist_upgrade_changes = self.pkg_cache.get_dist_upgrade_changes() # detect and prevent the system components from being uninstalled pkg_in_white_list = [] download_pkgs = [] self.all_upgrade_pkg_names = [] for pkg in dist_upgrade_changes["delete"]: name = pkg.name if name in SYS_PKG_WHITE_LIST: pkg_in_white_list.append(name) if len(pkg_in_white_list) > 0: self.update_signal([("remove-pkgs-in-white-list", (json.dumps(pkg_in_white_list), action_type)) ]) logger.error("found remove system packages: %s" % json.dumps(pkg_in_white_list)) else: for status in dist_upgrade_changes: for pkg in dist_upgrade_changes[status]: self.all_upgrade_pkg_names.append(pkg.name) if status == "delete" or status == "keep": continue if not parse_pkg.pkg_file_has_exist(pkg): download_pkgs.append(pkg) self.update_signal([("ready-download-finish", (action_id, action_type))]) if len(download_pkgs) == 0: global_event.emit("download-finish", action_id, action_type, self.all_upgrade_pkg_names) else: names = [] download_urls = [] download_hash_infos = [] pkg_sizes = [] for pkg in download_pkgs: names.append(pkg.name) download_urls.append(pkg.candidate.uri) download_hash_infos.append(pkg.candidate.md5) pkg_sizes.append(pkg.candidate.size) self.download_manager.add_download( action_id, action_type, download_urls, download_sizes=pkg_sizes, download_md5s=download_hash_infos, all_task_names=names, all_change_pkgs=self.all_upgrade_pkg_names, file_save_dir=self.download_dir) def add_download(self, pkg_name, action_type, simulate=False): installed = self.get_pkg_installed(pkg_name) if installed == 1: self.update_signal([("pkg-installed", (pkg_name, action_type))]) return elif installed == -1: self.update_signal([("pkg-not-in-cache", (pkg_name, action_type))]) return pkg_infos = get_pkg_download_info(self.pkg_cache, pkg_name) status = pkg_infos["status"] self.update_signal([("ready-download-finish", (pkg_name, action_type)) ]) if status == DOWNLOAD_STATUS_NOTNEED: self.download_finish(pkg_name, action_type, [ pkg_name, ]) elif status == DOWNLOAD_STATUS_ERROR: self.update_signal([("parse-download-error", (pkg_name, action_type))]) else: names = [] download_urls = [] download_hash_infos = [] pkg_sizes = [] for info in pkg_infos["info"]: names.append(info["name"]) download_urls.append(info["url"]) download_hash_infos.append(info["hash"]) pkg_sizes.append(info["size"]) self.download_manager.add_download( pkg_name, action_type, download_urls, download_sizes=pkg_sizes, download_md5s=download_hash_infos, all_task_names=[pkg_name], file_save_dir=self.download_dir) def start_upgrade(self, pkg_names, action_id): self.apt_action_pool.add_multi_upgrade_mission(pkg_names, action_id) def del_source_list_d(self): white_list_path = os.path.join(get_parent_dir(__file__), 'white_list.txt') if os.path.exists(white_list_path): with open(white_list_path) as fp: for line in fp: line = line.strip() if os.path.exists(line): os.remove(line) def get_desktops(self, pkg_name): desktops = [] try: pkg_obj = self.pkg_cache[pkg_name] for f in pkg_obj.installed_files: if f.endswith(".desktop"): desktops.append(f) except: pass return desktops @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature='', out_signature='as') def read_no_notify_config(self, no_notify_config_path): if os.path.exists(no_notify_config_path): no_notify_config_str = read_file(no_notify_config_path) try: no_notify_config = eval(no_notify_config_str) if type(no_notify_config).__name__ != "list": no_notify_config = [] except Exception: no_notify_config = [] return no_notify_config else: return [] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def add_no_notify_pkg(self, info): pkg_name, path = info no_notify_config = self.read_no_notify_config(path) if pkg_name not in no_notify_config: pkg_name = str(pkg_name) no_notify_config.append(pkg_name) write_file(path, str(no_notify_config)) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_no_notify_pkg(self, info): pkg_name, path = info pkg_name = str(pkg_name) path = str(path) no_notify_config = self.read_no_notify_config(path) if pkg_name in no_notify_config: write_file( path, str( filter(lambda config_pkg_name: config_pkg_name != pkg_name, no_notify_config))) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="i", out_signature="") def init_download_manager(self, number): pass @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="") def set_download_dir(self, local_dir): apt_pkg.config.set("Dir::Cache::Archives", local_dir) self.download_dir = local_dir @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="ai") def get_download_size(self, pkg_name): total_size = 0 pkg_infos = get_pkg_download_info(self.pkg_cache, pkg_name) status = pkg_infos["status"] if status == DOWNLOAD_STATUS_NOTNEED: total_size = get_pkg_own_size(self.pkg_cache, pkg_name) size_flag = PKG_SIZE_OWN elif status == DOWNLOAD_STATUS_ERROR: total_size = -1 size_flag = PKG_SIZE_ERROR else: for info in pkg_infos["info"]: total_size += info["size"] size_flag = PKG_SIZE_DOWNLOAD return [size_flag, total_size] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="ai") def clean_download_cache(self): '''Clean download cache.''' # get action packages. remain_pkgs = [] for pkg_name in self.download_manager.task_name_to_id.keys(): remain_pkgs.append(pkg_name) for pkg_name in self.apt_action_pool.install_action_dict.keys(): remain_pkgs.append(pkg_name) for pkg_name in self.apt_action_pool.upgrade_action_dict.keys(): remain_pkgs.append(pkg_name) # Get depend packages. remain_pkgs_paths = [] for pkg_name in remain_pkgs: result = get_pkg_dependence_file_path(self.pkg_cache, pkg_name) if not result: remain_pkgs_paths += result # Init clean size. packageNum = 0 cleanSize = 0 # Delete cache directory. cache_archive_dir = get_cache_archive_dir() if os.path.exists(cache_archive_dir): for root, folder, files in os.walk(cache_archive_dir): for file_name in files: path = os.path.join(root, file_name) if path.endswith(".deb") and (path not in remain_pkgs_paths): packageNum += 1 cleanSize += os.path.getsize(path) remove_file(path) return [packageNum, cleanSize] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="b", out_signature="") def say_hello(self, simulate): # Set exit_flag with False to prevent backend exit, # this just useful that frontend start again before backend exit. self.exit_flag = False self.simulate = simulate @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def request_quit(self): # Set exit flag. self.exit_flag = True self.exit_manager.check() self.update_signal([("frontend-quit", "")]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def change_source_list(self, repo_urls): ubuntu_repo_url, deepin_repo_url = repo_urls new_source_list_content = get_source_list_contents( ubuntu_repo_url, deepin_repo_url) os.system('cp %s %s.save' % (SOURCE_LIST, SOURCE_LIST)) with open(SOURCE_LIST, 'w') as fp: fp.write(new_source_list_content) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="(ss)") def RequestUpgradeStatus(self): if self.in_update_list: return ("cache-updating", json.dumps([])) elif self.is_upgrading: return ("upgrading", json.dumps([])) else: dist_upgrade_changes = self.pkg_cache.get_dist_upgrade_changes() return_infos = [] for status in dist_upgrade_changes: for pkg in dist_upgrade_changes[status]: return_infos.append( dict(status=status, name=pkg.name, version=pkg.candidate.version, size=pkg.candidate.size, downloaded=parse_pkg.pkg_file_has_exist(pkg))) return ("normal", json.dumps(return_infos)) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="a(si)", out_signature="") def RemoveWaitMissions(self, pkg_infos): self.apt_action_pool.remove_wait_missions(pkg_infos) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="s") def request_uninstall_pkgs(self): return json.dumps(self.pkg_cache.get_uninstall_pkgs()) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="as") def request_pkgs_install_version(self, pkg_names): pkg_versions = [] for pkg_name in pkg_names: try: version = self.pkg_cache[pkg_name].versions[0].version pkg_versions.append(version) except: try: version = self.pkg_cache[pkg_name + ":i386"].versions[0].version pkg_versions.append(version) except: self.update_signal([("pkg-not-in-cache", pkg_name)]) return pkg_versions @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="as") def is_pkg_in_cache(self, pkg_name): result = [] try: self.pkg_cache[pkg_name] result.append(pkg_name) except: try: pkg_name += ":i386" self.pkg_cache[pkg_name] result.append(pkg_name) except: pass return result @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="as") def request_pkgs_uninstall_version(self, pkg_names): return self.pkg_cache.get_pkgs_uninstall_version(pkg_names) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def install_pkg(self, pkg_names): for pkg_name in pkg_names: real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: ThreadMethod( self.add_download, (real_pkg_name, ACTION_INSTALL, self.simulate)).start() else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="sb", out_signature="") def uninstall_pkg(self, pkg_name, purge): real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: self.apt_action_pool.add_uninstall_action(real_pkg_name, self.simulate, purge) else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="sb", out_signature="") def uninstall_pkg_from_desktop(self, desktop_path, purge): ThreadMethod(self.uninstall_pkg_from_desktop_thread, (desktop_path, purge)).start() def uninstall_pkg_from_desktop_thread(self, path, purge): pkg_name = self.get_pkg_name_from_path(path) if pkg_name: self.uninstall_pkg(pkg_name, purge) else: global_event.emit("action-failed", (path, ACTION_UNINSTALL, [], "no package found for path: %s" % path)) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="s") def get_pkg_name_from_path(self, path): pkg_name = utils.file_path_to_package_name(path) if pkg_name == "" and path.endswith(".desktop"): desktop_name = os.path.split(path)[1] path = utils.desktop_name_to_desktop_path(desktop_name) pkg_name = utils.file_path_to_package_name(path) return pkg_name @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def upgrade_pkg(self, pkg_names): for pkg_name in pkg_names: real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: self.update_signal([("ready-download-start", (real_pkg_name, ACTION_UPGRADE))]) ThreadMethod( self.add_download, (real_pkg_name, ACTION_UPGRADE, self.simulate)).start() else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def DistUpgrade(self): ThreadMethod(self.dist_upgrade).start() @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def stop_download_pkg(self, pkg_names): for pkg_name in pkg_names: self.download_manager.stop_wait_download(pkg_name) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def cancel_upgrade_download(self): if getattr(self, 'upgrade_id'): self.download_manager.stop_wait_download(self.upgrade_id) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_wait_downloads(self, pkg_names): for pkg_name in pkg_names: self.download_manager.stop_wait_download(pkg_name) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="s") def request_pkg_short_desc(self, pkg_name): return self.pkg_cache.get_pkg_short_desc(pkg_name) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="as") def request_status(self): download_status = {ACTION_INSTALL: [], ACTION_UPGRADE: []} for info_dict in self.download_manager.download_task_info.values(): pkg_name = info_dict["task_name"] if info_dict["action_type"] == ACTION_INSTALL: download_status[ACTION_INSTALL].append( (pkg_name, info_dict["status"])) elif info_dict["action_type"] == ACTION_UPGRADE: download_status[ACTION_UPGRADE].append( (pkg_name, info_dict["status"])) action_status = { ACTION_INSTALL: [], ACTION_UPGRADE: [], ACTION_UNINSTALL: [] } for info_dict in self.apt_action_pool.install_action_dict.values(): pkg_name = info_dict["task_name"] action_status[ACTION_INSTALL].append( (pkg_name, info_dict["status"])) for info_dict in self.apt_action_pool.upgrade_action_dict.values(): pkg_name = info_dict["task_name"] action_status[ACTION_UPGRADE].append( (pkg_name, info_dict["status"])) for info_dict in self.apt_action_pool.uninstall_action_dict.values(): pkg_name = info_dict["task_name"] action_status[ACTION_UNINSTALL].append( (pkg_name, info_dict["status"])) return [str(download_status), str(action_status)] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def start_update_list(self): self.del_source_list_d() self.pkg_cache.open(apb.OpProgress()) self.apt_action_pool.add_update_list_mission() @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="ab") def request_pkgs_install_status(self, pkg_names): _status = [] for pkg in pkg_names: _status.append(self.pkg_cache.is_pkg_installed(pkg)) return _status @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="(si)", out_signature="") def set_pkg_status(self, pkg_status): pkg_name, status = pkg_status self.pkg_cache.set_pkg_status(pkg_name, pkg_status) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="i") def get_pkg_installed(self, pkg_name): if self.is_pkg_in_cache(pkg_name): if self.pkg_cache.is_pkg_installed(pkg_name): return 1 else: return 0 else: return -1 @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="ss", out_signature="s") def get_pkg_start_status(self, pkg_name, start_pkg_names): is_current_installed = self.get_pkg_installed(pkg_name) if is_current_installed == -1: return "unknown" elif is_current_installed == 0: return "uninstalled" else: desktops = self.get_desktops(pkg_name) names = start_pkg_names.split(",") for name in names: if self.get_pkg_installed(name) == 1: desktops += self.get_desktops(name) return json.dumps(desktops) @dbus.service.signal(DSC_SERVICE_NAME, signature='a(sv)') # Use below command for test: # dbus-monitor --system "type='signal', interface='com.linuxdeepin.softwarecenter'" def update_signal(self, message): # The signal is emitted when this method exits # You can have code here if you wish info = str(message) logger.debug("dbus signal emit: %s" % info)
class PackageManager(dbus.service.Object): ''' docs ''' def invoked_log(func): @functools.wraps(func) def wrapper(*args, **kw): info = "dbus method invoked: %s, arguments: %s" % ( func.__name__, str(args[1:])) logger.debug(info) return func(*args, **kw) return wrapper def __init__(self, system_bus, mainloop): # Init dbus service. dbus.service.Object.__init__(self, system_bus, DSC_SERVICE_PATH) # Init. self.mainloop = mainloop self.pkg_cache = AptCache() self.exit_flag = False self.simulate = False self.all_upgrade_pkg_names = [] self.download_dir = "/var/cache/apt/archives" self.is_upgrading = False self.in_update_list = False self.apt_action_pool = AptActionPool(self.pkg_cache) self.apt_action_pool.start() global_event.register_event( 'parse-download-error', self.send_parse_download_error) global_event.register_event("action-start", self.action_start) global_event.register_event("action-update", self.action_update) global_event.register_event("action-finish", self.action_finish) global_event.register_event("action-failed", self.action_failed) global_event.register_event("download-start", self.download_start) global_event.register_event("download-update", self.download_update) global_event.register_event("download-finish", self.download_finish) global_event.register_event("download-stop", self.download_stop) global_event.register_event("download-error", self.download_failed) global_event.register_event( "update-list-start", self.update_list_start) global_event.register_event( "update-list-finish", self.update_list_finish) global_event.register_event( "update-list-failed", self.update_list_failed) global_event.register_event( "update-list-update", self.update_list_update) self.packages_status = {} self.exit_manager = ExitManager( self.mainloop, self.is_update_list_running, self.is_download_action_running, self.is_apt_action_running, self.have_exit_request) self.exit_manager.start() self.set_download_dir('/var/cache/apt/archives') self.download_manager = DownloadManager(global_event, verbose=True) def download_start(self, pkg_name, action_type): utils.set_running_lock(True) self.update_signal([("download-start", (pkg_name, action_type))]) if action_type == ACTION_UPGRADE: self.is_upgrading = True def download_update(self, pkg_name, action_type, data): self.update_signal([("download-update", ( pkg_name, action_type, data))]) if action_type == ACTION_UPGRADE: self.is_upgrading = True def download_stop(self, pkg_name, action_type): self.update_signal([("download-stop", (pkg_name, action_type))]) self.exit_manager.check() if action_type == ACTION_UPGRADE: self.is_upgrading = False def download_failed(self, pkg_name, action_type, e): logger.error("%s download failed with %s" % (pkg_name, e)) utils.set_running_lock(False) self.update_signal([("download-failed", (pkg_name, action_type, e))]) self.exit_manager.check() if action_type == ACTION_UPGRADE: self.is_upgrading = False def download_finish(self, action_id, action_type, all_pkg_names): utils.set_running_lock(False) self.update_signal([("download-finish", (action_id, action_type))]) if action_type == ACTION_INSTALL: self.apt_action_pool.add_install_action(all_pkg_names) elif action_type == ACTION_UPGRADE: self.start_upgrade(all_pkg_names, action_id) self.is_upgrading = False self.exit_manager.check() def action_start(self, signal_content): utils.set_running_lock(True) self.update_signal([("action-start", signal_content)]) if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = True def action_update(self, signal_content): self.update_signal([("action-update", signal_content)]) if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = True def action_finish(self, signal_content): utils.set_running_lock(False) pkg_name, action_type, pkg_info_list = signal_content if action_type == ACTION_INSTALL: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status( pkg_name, self.pkg_cache.PKG_STATUS_INSTALLED) elif action_type == ACTION_UPGRADE: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status( pkg_name, self.pkg_cache.PKG_STATUS_UPGRADED) elif action_type == ACTION_UNINSTALL: for pkg_info in pkg_info_list: self.pkg_cache.set_pkg_status( pkg_name, self.pkg_cache.PKG_STATUS_UNINSTALLED) self.update_signal([("action-finish", signal_content)]) self.exit_manager.check() if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = False def action_failed(self, signal_content): utils.set_running_lock(False) self.update_signal([("action-failed", signal_content)]) self.exit_manager.check() if signal_content[1] == ACTION_UPGRADE: self.is_upgrading = False def is_update_list_running(self): return self.in_update_list def is_download_action_running(self): return len(self.download_manager.download_task_info) > 0 def is_apt_action_running(self): return len(self.apt_action_pool.active_mission_list) + len( self.apt_action_pool.wait_mission_list) > 0 def have_exit_request(self): return self.exit_flag def update_list_start(self): self.in_update_list = True self.update_signal([("update-list-start", "")]) def update_list_finish(self): self.update_signal([("update-list-merge", "")]) self.pkg_cache.open(apb.OpProgress()) db_build.BuildSoftwareDB(self.pkg_cache) self.update_signal([("update-list-finish", "")]) self.in_update_list = False self.exit_manager.check() def update_list_failed(self): self.in_update_list = False self.update_signal([("update-list-failed", "")]) self.exit_manager.check() def update_list_update(self, percent, status_message, speed_str): self.update_signal([( "update-list-update", (percent, status_message, speed_str))]) def handle_dbus_reply(self, *reply): logger.info("%s (reply): %s" % (self.module_dbus_name, str(reply))) def handle_dbus_error(self, *error): logger.info("%s (error): %s" % (self.module_dbus_name, str(error))) def send_parse_download_error(self, pkg_name, action_type): self.update_signal([("parse-download-error", (pkg_name, action_type))]) def get_unique_id(self): return str(uuid.uuid4()) def get_real_pkg_name(self, pkg_name): if pkg_name in self.pkg_cache: return pkg_name elif (pkg_name + ":i386") in self.pkg_cache: return pkg_name + ":i386" else: return None def dist_upgrade(self): action_type = ACTION_UPGRADE action_id = '%s_%s' % (self.get_unique_id(), action_type) self.update_signal([( "ready-download-start", (action_id, action_type))]) dist_upgrade_changes = self.pkg_cache.get_dist_upgrade_changes() # detect and prevent the system components from being uninstalled pkg_in_white_list = [] download_pkgs = [] self.all_upgrade_pkg_names = [] for pkg in dist_upgrade_changes["delete"]: name = pkg.name if name in SYS_PKG_WHITE_LIST: pkg_in_white_list.append(name) if len(pkg_in_white_list) > 0: self.update_signal([( "remove-pkgs-in-white-list", (json.dumps(pkg_in_white_list), action_type))]) logger.error("found remove system packages: %s" % json.dumps(pkg_in_white_list)) else: for status in dist_upgrade_changes: for pkg in dist_upgrade_changes[status]: self.all_upgrade_pkg_names.append(pkg.name) if status == "delete" or status == "keep": continue if not parse_pkg.pkg_file_has_exist(pkg): download_pkgs.append(pkg) self.update_signal([("ready-download-finish", (action_id, action_type))]) if len(download_pkgs) == 0: global_event.emit("download-finish", action_id, action_type, self.all_upgrade_pkg_names) else: names = [] download_urls = [] download_hash_infos = [] pkg_sizes = [] for pkg in download_pkgs: names.append(pkg.name) download_urls.append(pkg.candidate.uri) download_hash_infos.append(pkg.candidate.md5) pkg_sizes.append(pkg.candidate.size) self.download_manager.add_download( action_id, action_type, download_urls, download_sizes=pkg_sizes, download_md5s=download_hash_infos, all_task_names=names, all_change_pkgs=self.all_upgrade_pkg_names, file_save_dir=self.download_dir ) def add_download(self, pkg_name, action_type, simulate=False): installed = self.get_pkg_installed(pkg_name) if installed == 1: self.update_signal([("pkg-installed", (pkg_name, action_type))]) return elif installed == -1: self.update_signal([("pkg-not-in-cache", (pkg_name, action_type))]) return pkg_infos = get_pkg_download_info(self.pkg_cache, pkg_name) status = pkg_infos["status"] self.update_signal([("ready-download-finish", (pkg_name, action_type))]) if status == DOWNLOAD_STATUS_NOTNEED: self.download_finish(pkg_name, action_type, [pkg_name,]) elif status == DOWNLOAD_STATUS_ERROR: self.update_signal([("parse-download-error", (pkg_name, action_type))]) else: names = [] download_urls = [] download_hash_infos = [] pkg_sizes = [] for info in pkg_infos["info"]: names.append(info["name"]) download_urls.append(info["url"]) download_hash_infos.append(info["hash"]) pkg_sizes.append(info["size"]) self.download_manager.add_download( pkg_name, action_type, download_urls, download_sizes=pkg_sizes, download_md5s=download_hash_infos, all_task_names=[pkg_name], file_save_dir=self.download_dir ) def start_upgrade(self, pkg_names, action_id): self.apt_action_pool.add_multi_upgrade_mission(pkg_names, action_id) def del_source_list_d(self): white_list_path = os.path.join(get_parent_dir(__file__), 'white_list.txt') if os.path.exists(white_list_path): with open(white_list_path) as fp: for line in fp: line = line.strip() if os.path.exists(line): os.remove(line) def get_desktops(self, pkg_name): desktops = [] try: pkg_obj = self.pkg_cache[pkg_name] for f in pkg_obj.installed_files: if f.endswith(".desktop"): desktops.append(f) except: pass return desktops @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature='', out_signature='as') def read_no_notify_config(self, no_notify_config_path): if os.path.exists(no_notify_config_path): no_notify_config_str = read_file(no_notify_config_path) try: no_notify_config = eval(no_notify_config_str) if type(no_notify_config).__name__ != "list": no_notify_config = [] except Exception: no_notify_config = [] return no_notify_config else: return [] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def add_no_notify_pkg(self, info): pkg_name, path = info no_notify_config = self.read_no_notify_config(path) if pkg_name not in no_notify_config: pkg_name = str(pkg_name) no_notify_config.append(pkg_name) write_file(path, str(no_notify_config)) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_no_notify_pkg(self, info): pkg_name, path = info pkg_name = str(pkg_name) path = str(path) no_notify_config = self.read_no_notify_config(path) if pkg_name in no_notify_config: write_file(path, str(filter( lambda config_pkg_name: config_pkg_name != pkg_name, no_notify_config))) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="i", out_signature="") def init_download_manager(self, number): pass @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="") def set_download_dir(self, local_dir): apt_pkg.config.set("Dir::Cache::Archives", local_dir) self.download_dir = local_dir @invoked_log @dbus.service.method( DSC_SERVICE_NAME, in_signature="s", out_signature="ai") def get_download_size(self, pkg_name): total_size = 0 pkg_infos = get_pkg_download_info(self.pkg_cache, pkg_name) status = pkg_infos["status"] if status == DOWNLOAD_STATUS_NOTNEED: total_size = get_pkg_own_size(self.pkg_cache, pkg_name) size_flag = PKG_SIZE_OWN elif status == DOWNLOAD_STATUS_ERROR: total_size = -1 size_flag = PKG_SIZE_ERROR else: for info in pkg_infos["info"]: total_size += info["size"] size_flag = PKG_SIZE_DOWNLOAD return [size_flag, total_size] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="ai") def clean_download_cache(self): '''Clean download cache.''' # get action packages. remain_pkgs = [] for pkg_name in self.download_manager.task_name_to_id.keys(): remain_pkgs.append(pkg_name) for pkg_name in self.apt_action_pool.install_action_dict.keys(): remain_pkgs.append(pkg_name) for pkg_name in self.apt_action_pool.upgrade_action_dict.keys(): remain_pkgs.append(pkg_name) # Get depend packages. remain_pkgs_paths = [] for pkg_name in remain_pkgs: result = get_pkg_dependence_file_path(self.pkg_cache, pkg_name) if not result: remain_pkgs_paths += result # Init clean size. packageNum = 0 cleanSize = 0 # Delete cache directory. cache_archive_dir = get_cache_archive_dir() if os.path.exists(cache_archive_dir): for root, folder, files in os.walk(cache_archive_dir): for file_name in files: path = os.path.join(root, file_name) if path.endswith(".deb") and ( path not in remain_pkgs_paths): packageNum += 1 cleanSize += os.path.getsize(path) remove_file(path) return [packageNum, cleanSize] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="b", out_signature="") def say_hello(self, simulate): # Set exit_flag with False to prevent backend exit, # this just useful that frontend start again before backend exit. self.exit_flag = False self.simulate = simulate @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def request_quit(self): # Set exit flag. self.exit_flag = True self.exit_manager.check() self.update_signal([("frontend-quit", "")]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def change_source_list(self, repo_urls): ubuntu_repo_url, deepin_repo_url = repo_urls new_source_list_content = get_source_list_contents( ubuntu_repo_url, deepin_repo_url) os.system('cp %s %s.save' % (SOURCE_LIST, SOURCE_LIST)) with open(SOURCE_LIST, 'w') as fp: fp.write(new_source_list_content) @invoked_log @dbus.service.method( DSC_SERVICE_NAME, in_signature="", out_signature="(ss)") def RequestUpgradeStatus(self): if self.in_update_list: return ("cache-updating", json.dumps([])) elif self.is_upgrading: return ("upgrading", json.dumps([])) else: dist_upgrade_changes = self.pkg_cache.get_dist_upgrade_changes() return_infos = [] for status in dist_upgrade_changes: for pkg in dist_upgrade_changes[status]: return_infos.append(dict( status=status, name=pkg.name, version=pkg.candidate.version, size=pkg.candidate.size, downloaded=parse_pkg.pkg_file_has_exist(pkg) )) return ("normal", json.dumps(return_infos)) @invoked_log @dbus.service.method( DSC_SERVICE_NAME, in_signature="a(si)", out_signature="") def RemoveWaitMissions(self, pkg_infos): self.apt_action_pool.remove_wait_missions(pkg_infos) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="s") def request_uninstall_pkgs(self): return json.dumps(self.pkg_cache.get_uninstall_pkgs()) @invoked_log @dbus.service.method( DSC_SERVICE_NAME, in_signature="as", out_signature="as") def request_pkgs_install_version(self, pkg_names): pkg_versions = [] for pkg_name in pkg_names: try: version = self.pkg_cache[pkg_name].versions[0].version pkg_versions.append(version) except: try: version = self.pkg_cache[pkg_name+":i386"].versions[0].version pkg_versions.append(version) except: self.update_signal([("pkg-not-in-cache", pkg_name)]) return pkg_versions @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="as") def is_pkg_in_cache(self, pkg_name): result = [] try: self.pkg_cache[pkg_name] result.append(pkg_name) except: try: pkg_name += ":i386" self.pkg_cache[pkg_name] result.append(pkg_name) except: pass return result @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="as") def request_pkgs_uninstall_version(self, pkg_names): return self.pkg_cache.get_pkgs_uninstall_version(pkg_names) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def install_pkg(self, pkg_names): for pkg_name in pkg_names: real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: ThreadMethod(self.add_download, (real_pkg_name, ACTION_INSTALL, self.simulate)).start() else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="sb", out_signature="") def uninstall_pkg(self, pkg_name, purge): real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: self.apt_action_pool.add_uninstall_action(real_pkg_name, self.simulate, purge) else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="sb", out_signature="") def uninstall_pkg_from_desktop(self, desktop_path, purge): ThreadMethod(self.uninstall_pkg_from_desktop_thread, (desktop_path, purge)).start() def uninstall_pkg_from_desktop_thread(self, path, purge): pkg_name = self.get_pkg_name_from_path(path) if pkg_name: self.uninstall_pkg(pkg_name, purge) else: global_event.emit("action-failed", (path, ACTION_UNINSTALL, [], "no package found for path: %s" % path)) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="s") def get_pkg_name_from_path(self, path): pkg_name = utils.file_path_to_package_name(path) if pkg_name == "" and path.endswith(".desktop"): desktop_name = os.path.split(path)[1] path = utils.desktop_name_to_desktop_path(desktop_name) pkg_name = utils.file_path_to_package_name(path) return pkg_name @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def upgrade_pkg(self, pkg_names): for pkg_name in pkg_names: real_pkg_name = self.get_real_pkg_name(pkg_name) if real_pkg_name: self.update_signal([("ready-download-start", (real_pkg_name, ACTION_UPGRADE))]) ThreadMethod(self.add_download, (real_pkg_name, ACTION_UPGRADE, self.simulate)).start() else: self.update_signal([("pkg-not-in-cache", pkg_name)]) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def DistUpgrade(self): ThreadMethod(self.dist_upgrade).start() @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def stop_download_pkg(self, pkg_names): for pkg_name in pkg_names: self.download_manager.stop_wait_download(pkg_name) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def cancel_upgrade_download(self): if getattr(self, 'upgrade_id'): self.download_manager.stop_wait_download(self.upgrade_id) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="") def remove_wait_downloads(self, pkg_names): for pkg_name in pkg_names: self.download_manager.stop_wait_download(pkg_name) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="s") def request_pkg_short_desc(self, pkg_name): return self.pkg_cache.get_pkg_short_desc(pkg_name) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="as") def request_status(self): download_status = { ACTION_INSTALL : [], ACTION_UPGRADE : []} for info_dict in self.download_manager.download_task_info.values(): pkg_name = info_dict["task_name"] if info_dict["action_type"] == ACTION_INSTALL: download_status[ACTION_INSTALL].append((pkg_name, info_dict["status"])) elif info_dict["action_type"] == ACTION_UPGRADE: download_status[ACTION_UPGRADE].append((pkg_name, info_dict["status"])) action_status = { ACTION_INSTALL : [], ACTION_UPGRADE : [], ACTION_UNINSTALL : []} for info_dict in self.apt_action_pool.install_action_dict.values(): pkg_name = info_dict["task_name"] action_status[ACTION_INSTALL].append((pkg_name, info_dict["status"])) for info_dict in self.apt_action_pool.upgrade_action_dict.values(): pkg_name = info_dict["task_name"] action_status[ACTION_UPGRADE].append((pkg_name, info_dict["status"])) for info_dict in self.apt_action_pool.uninstall_action_dict.values(): pkg_name = info_dict["task_name"] action_status[ACTION_UNINSTALL].append((pkg_name, info_dict["status"])) return [str(download_status), str(action_status)] @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="", out_signature="") def start_update_list(self): self.del_source_list_d() self.pkg_cache.open(apb.OpProgress()) self.apt_action_pool.add_update_list_mission() @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="as", out_signature="ab") def request_pkgs_install_status(self, pkg_names): _status = [] for pkg in pkg_names: _status.append(self.pkg_cache.is_pkg_installed(pkg)) return _status @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="(si)", out_signature="") def set_pkg_status(self, pkg_status): pkg_name, status = pkg_status self.pkg_cache.set_pkg_status(pkg_name, pkg_status) @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="s", out_signature="i") def get_pkg_installed(self, pkg_name): if self.is_pkg_in_cache(pkg_name): if self.pkg_cache.is_pkg_installed(pkg_name): return 1 else: return 0 else: return -1 @invoked_log @dbus.service.method(DSC_SERVICE_NAME, in_signature="ss", out_signature="s") def get_pkg_start_status(self, pkg_name, start_pkg_names): is_current_installed = self.get_pkg_installed(pkg_name) if is_current_installed == -1: return "unknown" elif is_current_installed == 0: return "uninstalled" else: desktops = self.get_desktops(pkg_name) names = start_pkg_names.split(",") for name in names: if self.get_pkg_installed(name) == 1: desktops += self.get_desktops(name) return json.dumps(desktops) @dbus.service.signal(DSC_SERVICE_NAME, signature='a(sv)') # Use below command for test: # dbus-monitor --system "type='signal', interface='com.linuxdeepin.softwarecenter'" def update_signal(self, message): # The signal is emitted when this method exits # You can have code here if you wish info = str(message) logger.debug("dbus signal emit: %s" % info)