def test_inventory(): """ Test the inventory function """ instance = Action() status = instance.inventory(choices=[]) assert type(status) == tuple assert status[0] == True assert type(status[1]) == dict status = instance.inventory(choices=[ 'repos', 'core', 'tools', 'images', 'built', 'running', 'enabled', 'foo' ]) assert type(status) == tuple assert status[0] == True assert type(status[1]) == dict
def while_waiting(self): """ Update with current tools that are not cores """ if not self.triggered: i = 4 api_action = Action() response = api_action.inventory(choices=['repos', 'tools', 'core']) if response[0]: inventory = response[1] for repo in inventory['repos']: repo_name = repo.rsplit("/", 2)[1:] self.tools_tc[repo] = {} title_text = self.add(npyscreen.TitleText, name='Plugin: '+repo, editable=False, rely=i, relx=5) title_text.display() i += 1 for tool in inventory['tools']: r_name = tool[0].split(":") if repo_name[0] == r_name[0] and repo_name[1] == r_name[1]: core = False for item in inventory['core']: if tool[0] == item[0]: core = True t = tool[1] if t == "": t = "/" if core: t += ":" + ":".join(tool[0].split(":")[-2:]) self.tools_tc[repo][t] = self.add(npyscreen.CheckBox, name=t, value=True, relx=10) self.tools_tc[repo][t].display() i += 1 i += 2 self.triggered = 1 return
class InventoryForm(npyscreen.FormBaseNew): """ Inventory form for the Vent CLI """ action = None def while_waiting(self): """ Update the text with the plugins in the inventory when nothing is happening """ if self.action is None: self.action = Action() # don't include core tools in this inventory response = self.action.inventory(choices=['repos', 'core', 'tools', 'images', 'built', 'running', 'enabled']) if response[0]: inventory = response[1] value = "Tools for each plugin found:\n" for repo in inventory['repos']: if repo != "https://github.com/cyberreboot/vent": value += "\n Plugin: "+repo+"\n" repo_name = repo.rsplit("/", 2)[1:] for tool in inventory['tools']: is_core = False for core in inventory['core']: if core[0] == tool[0]: is_core = True if not is_core: r_name = tool[0].split(":") if repo_name[0] == r_name[0] and repo_name[1] == r_name[1]: value += " "+tool[1]+"\n" for built in inventory['built']: if built[0] == tool[0]: value += " Built: "+built[2]+"\n" for enabled in inventory['enabled']: if enabled[0] == tool[0]: value += " Enabled: "+enabled[2]+"\n" for image in inventory['images']: if image[0] == tool[0]: value += " Image name: "+image[2]+"\n" for running in inventory['running']: if running[0] == tool[0]: value += " Status: "+running[2]+"\n" else: value = "There was an issue with inventory retrieval:\n"+str(response[1])+"\nPlease see vent.log for more details." self.inventory_mle.values=value.split("\n") self.inventory_mle.display() return def create(self): """ Override method for creating FormBaseNew form """ self.add_handlers({"^T": self.change_forms,"^Q": self.exit}) self.add(npyscreen.TitleFixedText, name='Inventory items:', value='') self.inventory_mle = self.add(npyscreen.Pager, values=['Checking for plugins in the inventory, please wait...']) def exit(self, *args, **keywords): self.parentApp.switchForm("MAIN") def change_forms(self, *args, **keywords): """ Toggles back to main """ change_to = "MAIN" # Tell the VentApp object to change forms. self.parentApp.change_form(change_to)
def while_waiting(self): """ Update with current tools that are not cores """ if not self.triggered: i = 4 api_action = Action() response = api_action.inventory(choices=[ 'repos', 'tools', 'built', 'enabled', 'running', 'core' ]) if response[0]: inventory = response[1] for repo in inventory['repos']: if repo != 'https://github.com/cyberreboot/vent': repo_name = repo.rsplit("/", 2)[1:] self.tools_tc[repo] = {} title_text = self.add(npyscreen.TitleText, name='Plugin: ' + repo, editable=False, rely=i, relx=5) title_text.display() i += 1 for tool in inventory['tools']: r_name = tool[0].split(":") if repo_name[0] == r_name[0] and repo_name[ 1] == r_name[1]: core = False running = False built = False enabled = False for item in inventory['core']: if tool[0] == item[0]: core = True for item in inventory['running']: if tool[0] == item[0] and item[ 2] == 'running': running = True for item in inventory['built']: if tool[0] == item[0] and item[2] == 'yes': built = True for item in inventory['enabled']: if tool[0] == item[0] and item[2] == 'yes': enabled = True t = tool[1] if t == "": t = "/" if not core and not running and built and enabled: t += ":" + ":".join( tool[0].split(":")[-2:]) self.tools_tc[repo][t] = self.add( npyscreen.CheckBox, name=t, value=True, relx=10) self.tools_tc[repo][t].display() i += 1 i += 2 self.triggered = 1 return
def while_waiting(self): """ Update with current tools that are not cores """ if not self.triggered: i = 4 api_action = Action() response = api_action.inventory(choices=['repos', 'tools', 'built', 'enabled', 'running', 'core']) if response[0]: inventory = response[1] for repo in inventory['repos']: if repo != 'https://github.com/cyberreboot/vent': repo_name = repo.rsplit("/", 2)[1:] self.tools_tc[repo] = {} title_text = self.add(npyscreen.TitleText, name='Plugin: '+repo, editable=False, rely=i, relx=5) title_text.display() i += 1 for tool in inventory['tools']: r_name = tool[0].split(":") if repo_name[0] == r_name[0] and repo_name[1] == r_name[1]: core = False running = False built = False enabled = False for item in inventory['core']: if tool[0] == item[0]: core = True for item in inventory['running']: if tool[0] == item[0] and item[2] == 'running': running = True for item in inventory['built']: if tool[0] == item[0] and item[2] == 'yes': built = True for item in inventory['enabled']: if tool[0] == item[0] and item[2] == 'yes': enabled = True t = tool[1] if t == "": t = "/" if not core and not running and built and enabled: t += ":" + ":".join(tool[0].split(":")[-2:]) self.tools_tc[repo][t] = self.add(npyscreen.CheckBox, name=t, value=True, relx=10) self.tools_tc[repo][t].display() i += 1 i += 2 self.triggered = 1 return
class ToolForm(npyscreen.ActionForm): """ Tools form for the Vent CLI """ def __init__(self, *args, **keywords): """ Initialize tool form objects """ self.logger = Logger(__name__) self.logger.info(str(keywords['names'])) self.api_action = Action() self.m_helper = MenuHelper() action = {'api_action': self.api_action} self.tools_tc = {} self.repo_widgets = {} if keywords['action_dict']: action.update(keywords['action_dict']) if keywords['names']: i = 1 for name in keywords['names']: action['action_object' + str(i)] = getattr( self.api_action, name) i += 1 self.action = action # get list of all possible group views to display self.views = deque() possible_groups = set() manifest = Template(self.api_action.plugin.manifest) if self.action['cores']: tools = self.api_action.inventory(choices=['core'])[1]['core'] else: tools = self.api_action.inventory(choices=['tools'])[1]['tools'] for tool in tools: groups = manifest.option(tool, 'groups')[1].split(',') for group in groups: # don't do core because that's the purpose of all in views if group != '' and group != 'core': possible_groups.add(group) self.manifest = manifest self.views += possible_groups self.views.append('all groups') self.no_instance = ['build', 'remove'] super(ToolForm, self).__init__(*args, **keywords) def quit(self, *args, **kwargs): """ Overridden to switch back to MAIN form """ self.parentApp.switchForm('MAIN') def toggle_view(self, *args, **kwargs): """ Toggles the view between different groups """ group_to_display = self.views.popleft() self.cur_view.value = group_to_display for repo in self.tools_tc: for tool in self.tools_tc[repo]: t_groups = self.manifest.option(tool, 'groups')[1] if group_to_display not in t_groups and \ group_to_display != 'all groups': self.tools_tc[repo][tool].value = False self.tools_tc[repo][tool].hidden = True else: self.tools_tc[repo][tool].value = True self.tools_tc[repo][tool].hidden = False # redraw elements self.display() # add view back to queue self.views.append(group_to_display) def create(self, group_view=False): """ Update with current tools """ self.add_handlers({"^T": self.quit, "^Q": self.quit}) self.add(npyscreen.TitleText, name='Select which tools to ' + self.action['action'] + ':', editable=False) togglable = ['remove', 'enable', 'disable', 'build'] if self.action['action_name'] in togglable: self.cur_view = self.add(npyscreen.TitleText, name='Group view:', value='all groups', editable=False, rely=3) self.add_handlers({"^V": self.toggle_view}) i = 5 else: i = 4 if self.action['action_name'] == 'start': response = self.action['api_action'].inventory(choices=[ 'repos', 'tools', 'built', 'enabled', 'running', 'core' ]) else: response = self.action['api_action'].inventory( choices=['core', 'repos', 'tools']) if response[0]: inventory = response[1] repos = inventory['repos'] # dict has repo as key and list of core/non-core tools as values has_core = {} has_non_core = {} # find all tools that are in this repo # and list them if they are core for repo in repos: core_list = [] ncore_list = [] # splice the repo names for processing if (repo.startswith("http")): repo_name = repo.rsplit("/", 2)[1:] else: repo_name = repo.split("/") # determine if enabled or disabled tools should be shown show_disabled = False if 'action_name' in self.action: if self.action['action_name'] == 'enable': show_disabled = True for tool in inventory['tools']: tool_repo_name = tool.split(":") # cross reference repo names if (repo_name[0] == tool_repo_name[0] and repo_name[1] == tool_repo_name[1]): # check to ensure tool not set to locally active = no # in vent.cfg externally_active = False vent_cfg_file = self.action['api_action'].vent_config vent_cfg = Template(vent_cfg_file) tool_pairs = vent_cfg.section('external-services')[1] for ext_tool in tool_pairs: if ext_tool[0].lower() == inventory['tools'][tool]: try: ext_tool_options = json.loads(ext_tool[1]) loc = 'locally_active' if (loc in ext_tool_options and ext_tool_options[loc] == 'no'): externally_active = True except Exception as e: self.logger.error("Couldn't check ext" " because: " + str(e)) externally_active = False # check to ensure not disabled disabled = False manifest = Template(self.api_action.plugin.manifest) if manifest.option(tool, 'enabled')[1] == 'no': disabled = True if (not externally_active and not disabled and not show_disabled): instance_num = re.search( r'\d+$', manifest.option(tool, 'name')[1]) if not instance_num: ncore_list.append(tool) # multiple instances share same image elif self.action[ 'action_name'] not in self.no_instance: ncore_list.append(tool) elif (not externally_active and disabled and show_disabled): instance_num = re.search( r'\d+$', manifest.option(tool, 'name')[1]) if not instance_num: ncore_list.append(tool) # multiple instances share same image elif self.action[ 'action_name'] not in self.no_instance: ncore_list.append(tool) for tool in inventory['core']: tool_repo_name = tool.split(":") # cross reference repo names if (repo_name[0] == tool_repo_name[0] and repo_name[1] == tool_repo_name[1]): # check to ensure tool not set to locally active = no # in vent.cfg externally_active = False vent_cfg_file = self.action['api_action'].vent_config vent_cfg = Template(vent_cfg_file) tool_pairs = vent_cfg.section('external-services')[1] for ext_tool in tool_pairs: if ext_tool[0].lower() == inventory['core'][tool]: try: ext_tool_options = json.loads(ext_tool[1]) loc = 'locally_active' if (loc in ext_tool_options and ext_tool_options[loc] == 'no'): externally_active = True except Exception as e: self.logger.error("Couldn't check ext" " because: " + str(e)) externally_active = False # check to ensure not disabled disabled = False manifest = Template(self.api_action.plugin.manifest) if manifest.option(tool, 'enabled')[1] == 'no': disabled = True if (not externally_active and not disabled and not show_disabled): instance_num = re.search( r'\d+$', manifest.option(tool, 'name')[1]) if not instance_num: core_list.append(tool) # multiple instances share same image elif self.action[ 'action_name'] not in self.no_instance: core_list.append(tool) elif (not externally_active and disabled and show_disabled): instance_num = re.search( r'\d+$', manifest.option(tool, 'name')[1]) if not instance_num: core_list.append(tool) # multiple instances share same image elif self.action[ 'action_name'] not in self.no_instance: core_list.append(tool) has_core[repo] = core_list has_non_core[repo] = ncore_list for repo in repos: self.tools_tc[repo] = {} if self.action['cores']: # make sure only repos with core tools are displayed if has_core.get(repo): self.repo_widgets[repo] = self.add(npyscreen.TitleText, name='Plugin: ' + repo, editable=False, rely=i, relx=5) for tool in has_core[repo]: tool_name = tool.split(":", 2)[2].split("/")[-1] if tool_name == "": tool_name = "/" self.tools_tc[repo][tool] = self.add( npyscreen.CheckBox, name=tool_name, value=True, relx=10) i += 1 i += 3 else: # make sure only repos with non-core tools are displayed if has_non_core.get(repo): self.repo_widgets[repo] = self.add(npyscreen.TitleText, name='Plugin: ' + repo, editable=False, rely=i, relx=5) for tool in has_non_core[repo]: tool_name = tool.split(":", 2)[2].split("/")[-1] if tool_name == "": tool_name = "/" self.tools_tc[repo][tool] = self.add( npyscreen.CheckBox, name=tool_name, value=True, relx=10) i += 1 i += 3 return def on_ok(self): """ Take the tool selections and perform the provided action on them """ def diff(first, second): """ Get the elements that exist in the first list and not in the second """ second = set(second) return [item for item in first if item not in second] def popup(original, orig_type, thr, title): """ Start the thread and display a popup of info until the thread is finished """ thr.start() info_str = "" while thr.is_alive(): if orig_type == 'containers': info = diff(Containers(), original) elif orig_type == 'images': info = diff(Images(), original) if info: info_str = "" for entry in info: info_str = entry[0] + ": " + entry[1] + "\n" + info_str if self.action['action_name'] != 'configure': npyscreen.notify_wait(info_str, title=title) time.sleep(1) thr.join() try: result = self.api_action.queue.get(False) if isinstance(result, tuple) and isinstance(result[1], tuple): running, failed = result[1] r_str = '' for container in running: r_str += container + ": successful\n" for container in failed: r_str += container + ": failed\n" npyscreen.notify_confirm(r_str) except Exception as e: # pragma: no cover pass return if self.action['type'] == 'images': originals = Images() else: originals = Containers() tool_d = {} if self.action['action_name'] in ['clean', 'remove', 'stop', 'update']: reconfirmation_str = "" if self.action['cores']: reconfirmation_str = "Are you sure you want to " reconfirmation_str += self.action['action_name'] reconfirmation_str += " core containers?" else: reconfirmation_str = "Are you sure you want to " reconfirmation_str += self.action['action_name'] reconfirmation_str += " plugin containers?" perform = npyscreen.notify_ok_cancel(reconfirmation_str, title="Confirm command") if not perform: return tools_to_configure = [] for repo in self.tools_tc: for tool in self.tools_tc[repo]: self.logger.info(tool) if self.tools_tc[repo][tool].value: t = tool.split(":", 2)[2].split("/")[-1] if t.startswith('/:'): t = " " + t[1:] t = t.split(":") if self.action['action_name'] == 'start': status = self.action['action_object2'](name=t[0], branch=t[1], version=t[2]) if status[0]: tool_d.update(status[1]) elif self.action['action_name'] == 'configure': constraints = { 'name': t[0], 'branch': t[1], 'version': t[2], 'repo': repo } options = ['type'] action = self.action['api_action'] tool = action.p_helper.constraint_options( constraints, options)[0] # only one tool should be returned name = tool.keys()[0] if tool[name]['type'] == 'registry': registry_image = True else: registry_image = False kargs = { 'name': 'Configure ' + t[0], 'tool_name': t[0], 'branch': t[1], 'version': t[2], 'repo': repo, 'next_tool': None, 'get_configure': action.get_configure, 'save_configure': action.save_configure, 'restart_tools': action.restart_tools, 'clean': action.clean, 'prep_start': action.prep_start, 'start_tools': action.start, 'from_registry': registry_image } if tools_to_configure: kargs['next_tool'] = tools_to_configure[-1] self.parentApp.addForm("EDITOR" + t[0], EditorForm, **kargs) tools_to_configure.append("EDITOR" + t[0]) else: kargs = {'name': t[0], 'branch': t[1], 'version': t[2]} # add core recognition if self.action['cores']: kargs.update({'groups': 'core'}) # use latest version for update, not necessarily # version in manifest if self.action['action_name'] == 'update': if t[2] != 'HEAD': repo_commits = self.m_helper.repo_commits( repo)[1] for branch in repo_commits: if branch[0] == t[1]: kargs.update( {'new_version': branch[1][0]}) else: kargs.update({'new_version': 'HEAD'}) thr = Thread(target=self.action['action_object1'], args=(), kwargs=kargs) popup( originals, self.action['type'], thr, 'Please wait, ' + self.action['present_t'] + '...') if self.action['action_name'] == 'start': thr = Thread(target=self.action['action_object1'], args=(), kwargs={'tool_d': tool_d}) popup(originals, self.action['type'], thr, 'Please wait, ' + self.action['present_t'] + '...') if self.action['action_name'] != 'configure': npyscreen.notify_confirm('Done ' + self.action['present_t'] + '.', title=self.action['past_t']) self.quit() else: if len(tools_to_configure) > 0: self.parentApp.change_form(tools_to_configure[-1]) else: npyscreen.notify_confirm( "No tools selected, returning to" " main menu", title="No action taken") self.quit() def on_cancel(self): """ When user clicks cancel, will return to MAIN """ self.quit()
class CoreInventoryForm(npyscreen.FormBaseNew): """ Core Inventory form for the Vent CLI """ action = None def while_waiting(self): """ Update the text with the core tools in the inventory when nothing is happening """ if self.action is None: self.action = Action() # include only core tools in this inventory response = self.action.inventory(choices=[ 'repos', 'core', 'tools', 'images', 'built', 'running', 'enabled' ]) if response[0]: inventory = response[1] value = "Tools for each plugin found:\n" for repo in inventory['repos']: value += "\n Plugin: " + repo + "\n" repo_name = repo.rsplit("/", 2)[1:] for tool in inventory['tools']: is_core = False for core in inventory['core']: if core[0] == tool[0]: is_core = True if is_core: r_name = tool[0].split(":") if repo_name[0] == r_name[0] and repo_name[ 1] == r_name[1]: value += " " + tool[1] + "\n" for built in inventory['built']: if built[0] == tool[0]: value += " Built: " + built[2] + "\n" for enabled in inventory['enabled']: if enabled[0] == tool[0]: value += " Enabled: " + enabled[ 2] + "\n" for image in inventory['images']: if image[0] == tool[0]: value += " Image name: " + image[ 2] + "\n" for running in inventory['running']: if running[0] == tool[0]: value += " Status: " + running[ 2] + "\n" tmp_value = value.split("\n") if "Plugin: " in tmp_value[-2]: value = "\n".join(value.split("\n")[:-2]) else: value = "There was an issue with core inventory retrieval:\n" + str( response[1]) + "\nPlease see vent.log for more details." self.inventory_mle.values = value.split("\n") self.inventory_mle.display() return def create(self): """ Override method for creating FormBaseNew form """ self.add_handlers({"^T": self.change_forms, '^Q': self.exit}) self.add(npyscreen.TitleFixedText, name='Core inventory items:', value='') self.inventory_mle = self.add( npyscreen.Pager, values=[ 'Checking for core plugins in the inventory, please wait...' ]) def exit(self, *args, **keywords): self.parentApp.switchForm("MAIN") def change_forms(self, *args, **keywords): """ Toggles back to main """ change_to = "MAIN" # Tell the VentApp object to change forms. self.parentApp.change_form(change_to)