def get_components(self):
        """Returns all of the valid components, made up of those found on startup and those subsequently created.

        Returns:
            list : A list of available components
        """
        comps = list()
        for cn, cv in self._component_metas.iteritems():
            if cn.lower() != DEFAULT_COMPONENT.lower():
                comps.append(cv.to_dict())
        return comps
 def _check_name(self, name, is_comp = False):
     # Not empty
     if name is None or name.strip() == "":
         raise Exception("Configuration name cannot be blank")
     #
     if is_comp and name.lower() == DEFAULT_COMPONENT.lower():
         raise Exception("Cannot save over default component")
     # Valid chars
     m = re.match("^[a-zA-Z][a-zA-Z0-9_]*$", name)
     if m is None:
         raise Exception("Configuration name contains invalid characters")
    def get_component_names(self, include_base=False):
        """ Get the names of the components in the configuration.

        Args:
            include_base (bool, optional): Whether to include the base in the list of names

        Returns:
            list : A list of components in the configuration
        """
        l = list()
        for cn, cv in self._components.iteritems():
            if (include_base) or (cn.lower() != DEFAULT_COMPONENT.lower()):
                l.append(cv.get_name())
        return l
    def get_ioc_names(self, include_base=False):
        """ Get the names of the IOCs in the configuration and any components.

        Args:
            include_base (bool, optional): Whether to include the IOCs in base

        Returns:
            list : The names of the IOCs
        """
        iocs = self._config.iocs.keys()
        for cn, cv in self._components.iteritems():
            if include_base:
                iocs.extend(cv.iocs)
            elif cn.lower() != DEFAULT_COMPONENT.lower():
                iocs.extend(cv.iocs)
        return iocs
    def delete(self, delete_list, are_comps=False):
        """Takes a list of configurations and removes them from the file system and any relevant PVs.

        Args:
            delete_list (list): The configurations/components to delete
            are_comps (bool): Whether they are components or not
        """
        with self._lock:
            # TODO: clean this up?
            print_and_log("Deleting: " + ", ".join(list(delete_list)), "INFO")
            lower_delete_list = set([x.lower() for x in delete_list])
            unable_to_remove_text = "Unable to remove %s from version control: %s"
            if not are_comps:
                if self.active_config_name.lower() in lower_delete_list:
                    raise InvalidDeleteException("Cannot delete currently active configuration")
                if not lower_delete_list.issubset(self._config_metas.keys()):
                    raise InvalidDeleteException("Delete list contains unknown configurations")
                for config in delete_list:
                    self._delete_pv(BlockserverPVNames.get_config_details_pv(self._config_metas[config.lower()].pv))
                    del self._config_metas[config.lower()]
                    self._remove_config_from_dependencies(config)
                try:
                    self._update_version_control_post_delete(self._conf_path, delete_list)  # Git is case sensitive
                except Exception as err:
                    print_and_log(unable_to_remove_text % ("configuration", str(err)), "MINOR")
            else:
                if DEFAULT_COMPONENT.lower() in lower_delete_list:
                    raise InvalidDeleteException("Cannot delete default component")
                # Only allow comps to be deleted if they appear in no configs
                for comp in lower_delete_list:
                    if self._comp_dependencies.get(comp):
                        raise InvalidDeleteException(
                            comp + " is in use in: " + ", ".join(self._comp_dependencies[comp])
                        )
                if not lower_delete_list.issubset(self._component_metas.keys()):
                    raise InvalidDeleteException("Delete list contains unknown components")
                for comp in lower_delete_list:
                    self._delete_pv(BlockserverPVNames.get_component_details_pv(self._component_metas[comp].pv))
                    self._delete_pv(BlockserverPVNames.get_dependencies_pv(self._component_metas[comp].pv))
                    del self._component_metas[comp]
                try:
                    self._update_version_control_post_delete(self._comp_path, delete_list)
                except Exception as err:
                    print_and_log(unable_to_remove_text % ("component", str(err)), "MINOR")

            self.update_monitors()
    def set_config(self, config, is_component=False):
        """ Replace the existing configuration with the supplied configuration.

        Args:
            config (Configuration): A configuration
            is_component (bool, optional): Whether it is a component
        """
        self.clear_config()
        self._config = config
        self._is_component = is_component
        self._components = OrderedDict()
        if not is_component:
            for n, v in config.components.iteritems():
                if n.lower() != DEFAULT_COMPONENT.lower():
                    comp = self.load_configuration(v, True)
                    self.add_component(v, comp)
            # add default component to list of components
            basecomp = self.load_configuration(DEFAULT_COMPONENT, True)
            self.add_component(DEFAULT_COMPONENT, basecomp)
    def update_a_config_in_list(self, config, is_component=False):
        """Takes a ConfigServerManager object and updates the list of meta data and the individual PVs.

        Args:
            config (ConfigHolder): The configuration holder
            is_component (bool): Whether it is a component or not
        """
        name = config.get_config_name()
        name_lower = name.lower()

        # Get pv name (create if doesn't exist)
        pv_name = self._get_pv_name(name_lower, is_component)

        # Get meta data from config
        meta = config.get_config_meta()
        meta.pv = pv_name

        # Add metas and update pvs appropriately
        if is_component:
            if name_lower is not DEFAULT_COMPONENT.lower():
                self._component_metas[name_lower] = meta
                self._update_component_pv(name_lower, config.get_config_details())
                self._update_component_dependencies_pv(name_lower.lower())
        else:
            if name_lower in self._config_metas.keys():
                # Config already exists
                self._remove_config_from_dependencies(name)

            self._config_metas[name_lower] = meta
            self._update_config_pv(name_lower, config.get_config_details())

            # Update component dependencies
            comps = config.get_component_names()
            for comp in comps:
                if comp in self._comp_dependencies:
                    self._comp_dependencies[comp.lower()].append(config.get_config_name())
                else:
                    self._comp_dependencies[comp.lower()] = [config.get_config_name()]
                self._update_component_dependencies_pv(comp.lower())
        self.update_monitors()
    def _import_configs(self, schema_folder):
        # Create the pvs and get meta data
        config_list = self._get_config_names()
        comp_list = self._get_component_names()

        # Must load components first for them all to be known in dependencies
        for comp_name in comp_list:
            try:
                path = FILEPATH_MANAGER.get_component_path(comp_name)
                # load_config checks the schema
                config = self.load_config(comp_name, True)
                self.update_a_config_in_list(config, True)
                try:
                    self._vc.add(path)
                except Exception as err:
                    print_and_log("Unable to add component to version control: " + str(err), "MINOR")
            except Exception as err:
                print_and_log("Error in loading component: " + str(err), "MINOR")

        # Create default if it does not exist
        if DEFAULT_COMPONENT.lower() not in comp_list:
            self.file_manager.copy_default(self._comp_path)

        for config_name in config_list:
            try:
                path = FILEPATH_MANAGER.get_config_path(config_name)
                # load_config checks the schema
                config = self.load_config(config_name)
                self.update_a_config_in_list(config)
                try:
                    self._vc.add(path)
                except Exception as err:
                    print_and_log("Unable to add configuration to version control: " + str(err), "MINOR")
            except Exception as err:
                print_and_log("Error in loading config: " + str(err), "MINOR")

        # Add files to version control
        self._vc.commit("Blockserver started, configs updated")
 def _comps_to_list(self):
     comps = list()
     for cn, cv in self._components.iteritems():
         if cn.lower() != DEFAULT_COMPONENT.lower():
             comps.append({'name': cv.get_name()})
     return comps