def _update_version_control(self, name):
        if self._is_component:
            self._vc.add(FILEPATH_MANAGER.get_component_path(name))
        else:
            self._vc.add(FILEPATH_MANAGER.get_config_path(name))

        self._vc.commit("%s modified by client" % name)
Beispiel #2
0
def main():
    """
    Parse the command line arguments and run the remote IOC server.
    """
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description="Runs a remote IOC server.",
    )

    parser.add_argument("--ioc_name", required=True, type=six.text_type)

    parser.add_argument("--pv_prefix", required=True, type=six.text_type,
                        help="The PV prefix of this instrument.")

    args = parser.parse_args()

    FILEPATH_MANAGER.initialise(os.path.normpath(os.getenv("ICPCONFIGROOT")), "", "")

    print("IOC started")

    macros = get_macro_values()

    serve_forever(
        args.ioc_name,
        args.pv_prefix,
        macros
    )
    def setUp(self):
        # Find the schema directory
        dir = os.path.join(".")
        while SCHEMA_FOLDER not in os.listdir(dir):
            dir = os.path.join(dir, "..")

        self.path = os.path.abspath(CONFIG_PATH)
        FILEPATH_MANAGER.initialise(self.path, os.path.join(dir, SCHEMA_FOLDER))
    def setUp(self):
        # Find the schema directory
        dir = os.path.join(".")
        while SCHEMA_FOLDER not in os.listdir(dir):
            dir = os.path.join(dir, "..")
        self.schema_dir = os.path.join(dir, SCHEMA_FOLDER)

        FILEPATH_MANAGER.initialise(TEST_DIRECTORY, self.schema_dir)
        self.cs = ActiveConfigHolder(MACROS, ArchiverManager(None, None, MockArchiverWrapper()),
                                     MockVersionControl(), MockConfigurationFileManager(), MockIocControl(""))
    def setUp(self):
        # Make directory and fill with fake content
        FILEPATH_MANAGER.initialise(os.path.abspath(CONFIG_PATH), os.path.abspath(SCHEMA_PATH))

        # Find the schema directory
        dir = os.path.join(".")
        while SCHEMA_FOLDER not in os.listdir(dir):
            dir = os.path.join(dir, "..")

        self.bs = MockBlockServer()
        self.file_io = MockDevicesFileIO()
        self.dm = DevicesManager(self.bs, os.path.join(dir, SCHEMA_FOLDER), MockVersionControl(), self.file_io)
    def save_config(self, configuration, is_component):
        """Saves the current configuration with the specified name.

        Args:
            configuration (Configuration): The actual configuration to save
            is_component (bool): Is it a component?
        """
        if is_component:
            path = os.path.abspath(FILEPATH_MANAGER.get_component_path(configuration.get_name()))
        else:
            path = os.path.abspath(FILEPATH_MANAGER.get_config_path(configuration.get_name()))

        if not os.path.isdir(path):
            # Create the directory
            os.makedirs(path)

        blocks_xml = ConfigurationXmlConverter.blocks_to_xml(configuration.blocks, configuration.macros)
        groups_xml = ConfigurationXmlConverter.groups_to_xml(configuration.groups)
        iocs_xml = ConfigurationXmlConverter.iocs_to_xml(configuration.iocs)
        meta_xml = ConfigurationXmlConverter.meta_to_xml(configuration.meta)
        try:
            components_xml = ConfigurationXmlConverter.components_to_xml(configuration.components)
        except:
            # Is a component, so no components
            components_xml = ConfigurationXmlConverter.components_to_xml(dict())

        # Save blocks
        with open(path + "/" + FILENAME_BLOCKS, "w") as f:
            f.write(blocks_xml)

        # Save groups
        with open(path + "/" + FILENAME_GROUPS, "w") as f:
            f.write(groups_xml)

        # Save IOCs
        with open(path + "/" + FILENAME_IOCS, "w") as f:
            f.write(iocs_xml)

        # Save components
        with open(path + "/" + FILENAME_COMPONENTS, "w") as f:
            f.write(components_xml)

        # Save meta
        with open(path + "/" + FILENAME_META, "w") as f:
            f.write(meta_xml)
 def _add_to_version_control(self, synoptic_name, commit_message=None):
     # Add to version control
     try:
         self._vc.add(FILEPATH_MANAGER.get_synoptic_path(synoptic_name))
     except Exception as err:
         raise AddToVersionControlException(err)
     if commit_message is not None:
         try:
             self._vc.commit(commit_message)
         except Exception as err:
             raise CommitToVersionControlException(err)
    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 save_synoptic_xml(self, xml_data):
        """Saves the xml under the filename taken from the xml name tag.

        Args:
            xml_data (string): The XML to be saved
        """
        try:
            # Check against schema
            ConfigurationSchemaChecker.check_xml_matches_schema(os.path.join(self._schema_folder, SYNOPTIC_SCHEMA_FILE),
                                                                xml_data, "Synoptic")
            # Update PVs
            self._create_pv(xml_data)

        except Exception as err:
            print_and_log(err)
            raise

        name = self._get_synoptic_name_from_xml(xml_data)

        save_path = FILEPATH_MANAGER.get_synoptic_path(name)

        self._file_io.write_synoptic_file(name, save_path, xml_data)
        self._add_to_version_control(name, "%s modified by client" % name)
        print_and_log("Synoptic saved: " + name)
 def setUp(self):
     FILEPATH_MANAGER.initialise(TEST_DIRECTORY, SCHEMA_DIR)
     self.file_manager = MockConfigurationFileManager()
     self.config_list_manager = MagicMock()
     self.is_component = False
     self.eh = ConfigFileEventHandler(RLock(), self.config_list_manager, self.is_component)
    def __init__(self, ca_server):
        """Constructor.

        Args:
            ca_server (CAServer): The CA server used for generating PVs on the fly
        """
        super(BlockServer, self).__init__()

        # Threading stuff
        self.monitor_lock = RLock()
        self.write_lock = RLock()
        self.write_queue = list()

        FILEPATH_MANAGER.initialise(CONFIG_DIR, SCHEMA_DIR)

        self._cas = ca_server
        self._gateway = Gateway(GATEWAY_PREFIX, BLOCK_PREFIX, PVLIST_FILE, MACROS["$(MYPVPREFIX)"])
        self._active_configserver = None
        self._run_control = None
        self._block_cache = None
        self._syn = None
        self._devices = None
        self._filewatcher = None
        self.on_the_fly_handlers = list()
        self._ioc_control = IocControl(MACROS["$(MYPVPREFIX)"])
        self._db_client = DatabaseServerClient(BLOCKSERVER_PREFIX + "BLOCKSERVER:")
        self.bumpstrip = "No"
        self.block_rules = BlockRules(self)
        self.group_rules = GroupRules(self)
        self.config_desc = ConfigurationDescriptionRules(self)

        # Connect to version control
        try:
            self._vc = GitVersionControl(CONFIG_DIR, RepoFactory.get_repo(CONFIG_DIR))
            self._vc.setup()
        except NotUnderVersionControl as err:
            print_and_log("Warning: Configurations not under version control", "MINOR")
            self._vc = MockVersionControl()
        except Exception as err:
            print_and_log("Unable to start version control. Modifications to the instrument setup will not be "
                          "tracked: " + str(err), "MINOR")
            self._vc = MockVersionControl()

        # Create banner object
        self.banner = Banner(MACROS["$(MYPVPREFIX)"])

        # Import data about all configs
        try:
            self._config_list = ConfigListManager(self, SCHEMA_DIR, self._vc, ConfigurationFileManager())
        except Exception as err:
            print_and_log(
                "Error creating inactive config list. Configuration list changes will not be stored " +
                "in version control: %s " % str(err), "MINOR")
            self._config_list = ConfigListManager(self, SCHEMA_DIR, MockVersionControl(), ConfigurationFileManager())

        # Start a background thread for handling write commands
        write_thread = Thread(target=self.consume_write_queue, args=())
        write_thread.daemon = True  # Daemonise thread
        write_thread.start()

        with self.write_lock:
            self.write_queue.append((self.initialise_configserver, (FACILITY,), "INITIALISING"))

        # Starts the Web Server
        self.server = Server()
        self.server.start()
 def setUp(self):
     FILEPATH_MANAGER.initialise(TEST_DIRECTORY, SCHEMA_DIR)
     self.file_manager = MockConfigurationFileManager()
     self.synoptic_manager = MagicMock()
     self.eh = SynopticFileEventHandler(SCHEMA_DIR, RLock(), self.synoptic_manager)
 def test_synoptic_file_path_correct(self):
     synoptic = "test"
     self.assertEqual(os.path.join(self.path, SYNOPTIC_DIRECTORY, synoptic) + ".xml",
                      FILEPATH_MANAGER.get_synoptic_path(synoptic))
 def test_component_folder_path_correct(self):
     component = "test"
     self.assertEqual(os.path.join(self.path, COMPONENT_DIRECTORY, component) + os.sep,
                      FILEPATH_MANAGER.get_component_path(component))
 def test_config_folder_path_correct(self):
     config = "test"
     self.assertEqual(os.path.join(self.path, CONFIG_DIRECTORY, config) + os.sep,
                      FILEPATH_MANAGER.get_config_path(config))
    def load_config(self, name, macros, is_component):
        """Loads the configuration from the specified folder.

        Args:
            name (string): The name of the configuration
            macros (dict): The BlockServer macros
            is_component (bool): Is it a component?
        """
        configuration = Configuration(macros)

        if is_component:
            path = os.path.abspath(FILEPATH_MANAGER.get_component_path(name))
        else:
            path = os.path.abspath(FILEPATH_MANAGER.get_config_path(name))

        if not os.path.isdir(path):
            raise IOError("Configuration could not be found: " + name)

        # Create empty containers
        blocks = OrderedDict()
        groups = OrderedDict()
        components = OrderedDict()
        iocs = OrderedDict()

        # Make sure NONE group exists
        groups[GRP_NONE.lower()] = Group(GRP_NONE)

        config_files_missing = list()

        # Open the block file first
        blocks_path = os.path.join(path, FILENAME_BLOCKS)
        if os.path.isfile(blocks_path):
            root = ElementTree.parse(blocks_path).getroot()

            # Check against the schema - raises if incorrect
            self._check_againgst_schema(ElementTree.tostring(root, encoding="utf8"), FILENAME_BLOCKS)

            ConfigurationXmlConverter.blocks_from_xml(root, blocks, groups)
        else:
            config_files_missing.append(FILENAME_BLOCKS)

        # Import the groups
        groups_path = os.path.join(path, FILENAME_GROUPS)
        if os.path.isfile(groups_path):
            root = ElementTree.parse(groups_path).getroot()

            # Check against the schema - raises if incorrect
            self._check_againgst_schema(ElementTree.tostring(root, encoding="utf8"), FILENAME_GROUPS)

            ConfigurationXmlConverter.groups_from_xml(root, groups, blocks)
        else:
            config_files_missing.append(FILENAME_GROUPS)

        # Import the IOCs
        iocs_path = os.path.join(path, FILENAME_IOCS)
        if os.path.isfile(iocs_path):
            root = ElementTree.parse(iocs_path).getroot()

            # There was a historic bug where the simlevel was saved as 'None' rather than "none".
            # Correct that here
            correct_xml = ElementTree.tostring(root, encoding="utf8").replace('simlevel="None"', 'simlevel="none"')

            # Check against the schema - raises if incorrect
            self._check_againgst_schema(correct_xml, FILENAME_IOCS)

            ConfigurationXmlConverter.ioc_from_xml(root, iocs)
        else:
            config_files_missing.append(FILENAME_IOCS)

        # Import the components
        component_path = os.path.join(path, FILENAME_COMPONENTS)
        if os.path.isfile(component_path):
            root = ElementTree.parse(component_path).getroot()

            # Check against the schema - raises if incorrect
            self._check_againgst_schema(ElementTree.tostring(root, encoding="utf8"), FILENAME_COMPONENTS)

            ConfigurationXmlConverter.components_from_xml(root, components)
        elif not is_component:
            # It should be missing for a component
            config_files_missing.append(FILENAME_COMPONENTS)

        # Import the metadata
        meta = MetaData(name)
        meta_path = os.path.join(path, FILENAME_META)
        if os.path.isfile(meta_path):
            root = ElementTree.parse(meta_path).getroot()

            # Check against the schema - raises if incorrect
            self._check_againgst_schema(ElementTree.tostring(root, encoding="utf8"), FILENAME_META)

            ConfigurationXmlConverter.meta_from_xml(root, meta)
        else:
            config_files_missing.append(FILENAME_META)

        if len(config_files_missing) > 0:
            raise ConfigurationIncompleteException(
                "Files missing in " + name + " (%s)" % ",".join(list(config_files_missing))
            )

        # Set properties in the config
        configuration.blocks = blocks
        configuration.groups = groups
        configuration.iocs = iocs
        configuration.components = components
        configuration.meta = meta
        return configuration
 def _update_version_control_post_delete(self, files):
     for synoptic in files:
         self._vc.remove(FILEPATH_MANAGER.get_synoptic_path(synoptic))
     self._vc.commit("Deleted %s" % ', '.join(list(files)))