def get_update_zips(self): for app in self.apps_to_update: logger().info("Starting download for {}.zip".format(app.current_version)) self.browser.get_file_at_path('UpdateRoot/{}/{}/{}.zip'.format(self.channel, app.app_name, app.current_version), '{}/zip/{}.zip'.format(app.staging_folder, app.current_version)) app.services_from_server = application_browser.get_services_from_server(self.browser, 'UpdateRoot/{}/{}'.format(self.channel, app.app_name), app.staging_folder) logger().info("Downloading {}.zip finished".format(app.current_version)) return self
def get_configured_folders_from_server(browser, path, download_folder_path): try: if os.path.isfile(os.path.join(download_folder_path, FOLDERSFILE)): os.remove(os.path.join(download_folder_path, FOLDERSFILE)) try: browser.get_file_at_path( '{}/{}'.format(path, FOLDERSFILE), os.path.join(download_folder_path, FOLDERSFILE)) except: return {} try: with open(os.path.join(download_folder_path, FOLDERSFILE), 'r') as f: return dict.fromkeys([ os.path.normcase(os.path.normpath(path)) for path in f.read().splitlines() if os.path.isdir(path) ], []) except FileNotFoundError: return {} except Exception as e: logger().error(str(e)) return {}
def self_update(self): for app in list(filter(lambda x: x.app_name == 'UPDATE', self.apps_to_update)): restarter = RestarterReplacer(app.services, app.working_folder, app.working_folder + '/staging/' + self.uuid + '/' + app.app_name) logger().info("Starting update for {}".format(app.app_name)) app.create_cver_file() restarter.update_self() return self
def update(self): for app in list(filter(lambda x: x.app_name != 'UPDATE', self.apps_to_update)): restarter = RestarterReplacer(app.services, app.working_folder, app.staging_folder) logger().info("Starting update for {} to version {}".format(app.app_name, app.current_version)) restarter.update() app.create_cver_file() logger().info("Update for {} to version {} finished successfully.".format(app.app_name, app.current_version)) return self
def get_channel(self): if os.path.isfile(os.path.join(self.working_folder, CHANNELFILE)): os.remove(os.path.join(self.working_folder, CHANNELFILE)) self.browser.get_file_at_path( 'UpdateRoot/{}'.format(CHANNELFILE), os.path.join(self.working_folder, CHANNELFILE)) config = configparser.ConfigParser(allow_no_value=True) config.read(os.path.join(self.working_folder, CHANNELFILE)) def filter_channels(v): return len( list(filter(lambda x: fnmatch.fnmatch(self.id, x), config[v]))) matches = list(filter(filter_channels, config)) logger().info("Channel matches: {}".format(matches)) if len(matches) > 0: return matches[0] else: return 'DEFAULT'
def search_paths_for_apps(services_paths_dict): for path, discovered_services in services_paths_dict.items(): path = path.strip("/\\") if not os.path.isdir(path): logger().error(path + " does not exist on machine.") continue verfiles = None verfiles = [ file for file in os.listdir(path) if file.lower().endswith('.ver') ] if len(verfiles) == 0: logger().info("No .ver-file exists in folder {}".format(path)) continue for verfile in verfiles: app_name = verfile.upper()[:-4] yield ServicedAppFactory.create( app_name=app_name, working_folder=path, discovered_services=discovered_services).parse_cver_file(path)
def delete_old_staging_folders(self, folders_to_keep = 5): staging_folders = (os.path.join(app.working_folder, 'staging') for app in self.apps if os.path.isdir(os.path.join(app.working_folder, 'staging'))) for staging_folder in staging_folders: # get all entries in the directory w/ stats entries = (os.path.join(staging_folder, fn) for fn in os.listdir(staging_folder)) entries = ((os.stat(path), path) for path in entries) # leave only regular files, insert creation date entries = ((stat[ST_CTIME], path) for stat, path in entries if S_ISREG(stat[ST_MODE]) or S_ISDIR(stat[ST_MODE])) #NOTE: on Windows `ST_CTIME` is a creation date # but on Unix it could be something else #NOTE: use `ST_MTIME` to sort by a modification date for cdate, path in sorted(entries, reverse = True)[folders_to_keep:]: logger().info('Will delete {}'.format(path)) try: delete_tree_or_file(path) except OSError as e: logger().error(str(e)) return self
def get_services_from_server(browser, path, staging_folder_path): try: if os.path.isfile(os.path.join(staging_folder_path, SERVICESFILE)): os.remove(os.path.join(staging_folder_path, SERVICESFILE)) try: browser.get_file_at_path( '{}/{}'.format(path, SERVICESFILE), os.path.join(staging_folder_path, SERVICESFILE)) except: return [] try: with open(os.path.join(staging_folder_path, SERVICESFILE), 'r') as f: return f.read().splitlines() except FileNotFoundError: return [] except Exception as e: logger().error(str(e)) return []
def check_for_updates(self): for app in self.apps: app.current_version = application_browser.get_max_version(self.browser, 'UpdateRoot/{}/{}'.format(self.channel, app.app_name)) if app.rollback_eventually_needed(): app.support_rollback = application_browser.supports_rollback(self.browser, 'UpdateRoot/{}/{}'.format(self.channel, app.app_name)) logger().info("Applications discovered: {}".format([str(app) for app in self.apps])) logger().info("Version report", {'version_report' : reduce(lambda x,y: {**x, **y}, [app.to_version_JSON() for app in self.apps], {})}) self.apps_to_update = [app for app in self.apps if app.needs_update()] if len(self.apps_to_update) > 0: logger().info("Applications that need update: {}".format([str(app) for app in self.apps_to_update])) #if we need self-update, do only self update this pass as it will cause a restart update_app_list = [x for x in self.apps_to_update if x.app_name == 'UPDATE'] if len(update_app_list) > 0: self.apps_to_update = update_app_list logger().info("Starting self update.") return self
def get_id(self): chain = 'DEFAULT' store = 'DEFAULT' chain_found = None store_found = None for folder in self.folder_list: if os.path.isfile(os.path.join(folder, CHAINFILE)) and os.stat( os.path.join(folder, CHAINFILE)).st_size > 0: with open(os.path.join(folder, CHAINFILE), 'r') as f: chain = f.read() chain_found = 'Chain ID {} found from folder {}.'.format( chain, folder) if os.path.isfile(os.path.join(folder, STOREFILE)) and os.stat( os.path.join(folder, STOREFILE)).st_size > 0: with open(os.path.join(folder, STOREFILE), 'r') as f: store = f.read() store_found = 'Store ID {} found from folder {}.'.format( store, folder) if chain == 'DEFAULT' and os.path.isfile( os.path.join(self.working_folder, 'id', CHAINFILE)) and os.stat( os.path.join(self.working_folder, 'id', CHAINFILE)).st_size > 0: with open(os.path.join(self.working_folder, 'id', CHAINFILE), 'r') as f: chain = f.read() chain_found = 'Chain ID {} found from folder {}.'.format( chain, os.path.join(self.working_folder, 'id')) if store == 'DEFAULT' and os.path.isfile( os.path.join(self.working_folder, 'id', STOREFILE)) and os.stat( os.path.join(self.working_folder, 'id', STOREFILE)).st_size > 0: with open(os.path.join(self.working_folder, 'id', STOREFILE), 'r') as f: store = f.read() store_found = 'Store ID {} found from folder {}.'.format( store, os.path.join(self.working_folder, 'id')) MyId.set_id(chain, store) if chain_found is not None: logger().info(chain_found) if store_found is not None: logger().info(store_found) logger().info('Instance ID is {}'.format(MyId.get_id())) if not os.path.isdir(os.path.join(self.working_folder, 'id')): os.mkdir(os.path.join(self.working_folder, 'id')) with open(os.path.join(self.working_folder, 'id', CHAINFILE), 'w') as f: f.write(chain) with open(os.path.join(self.working_folder, 'id', STOREFILE), 'w') as f: f.write(store) return '{}'.format(MyId.get_id())