def get_package_info(cls):
     """
     Retrieve the package information related to the ASD Manager
     This must return a dictionary with keys: 'names', 'edition', 'binaries', 'non_blocking', 'version_commands' and 'mutually_exclusive'
         Names: These are the names of the packages split up per component related to this repository (alba-asdmanager)
             * Alba
                 * PKG_MGR_SDM        --> The code itself to deploy and run the ASD Manager
                 * PKG_ALBA(_EE)      --> ASDs and maintenance agents rely on the ALBA Binary
                 * PKG_OVS_EXTENSIONS --> Extensions code is used by the alba-asdmanager
         Edition: Used for different purposes
         Binaries: The names of the packages that come with a binary (also split up per component)
         Non Blocking: Packages which are potentially not yet available on all releases. These should be removed once every release contains these packages by default
         Version Commands: The commandos used to determine which binary version is currently active
         Mutually Exclusive: Packages which are not allowed to be installed depending on the edition. Eg: ALBA_EE cannot be installed on a 'community' edition
     :return: A dictionary containing information about the expected packages to be installed
     :rtype: dict
     """
     edition = Configuration.get_edition()
     if edition == cls.EDITION_COMMUNITY:
         return {
             'names': {
                 cls.COMP_ALBA:
                 {cls.PKG_MGR_SDM, cls.PKG_ALBA, cls.PKG_OVS_EXTENSIONS}
             },
             'edition': edition,
             'binaries': {
                 cls.COMP_ALBA: {cls.PKG_ALBA}
             },
             'non_blocking': {cls.PKG_OVS_EXTENSIONS},
             'version_commands': {
                 cls.PKG_ALBA: cls.VERSION_CMD_ALBA
             },
             'mutually_exclusive': {cls.PKG_ALBA_EE}
         }
     elif edition == cls.EDITION_ENTERPRISE:
         return {
             'names': {
                 cls.COMP_ALBA:
                 {cls.PKG_MGR_SDM, cls.PKG_ALBA_EE, cls.PKG_OVS_EXTENSIONS}
             },
             'edition': edition,
             'binaries': {
                 cls.COMP_ALBA: {cls.PKG_ALBA_EE}
             },
             'non_blocking': {cls.PKG_OVS_EXTENSIONS},
             'version_commands': {
                 cls.PKG_ALBA_EE: cls.VERSION_CMD_ALBA
             },
             'mutually_exclusive': {cls.PKG_ALBA}
         }
     else:
         raise ValueError(
             'Unsupported edition found: "{0}"'.format(edition))
    def execute_migration_code(cls):
        # type: () -> None
        """
        Run some migration code after an update has been done
        :return: None
        :rtype: NoneType
        """
        cls._logger.info('Starting out of band migrations for SDM nodes')

        ###########################
        # Start crucial migration #
        ###########################

        # Removal of bootstrap file and store API IP, API port and node ID in SQLite DB
        try:
            if cls._local_client.file_exists(BOOTSTRAP_FILE):
                cls._logger.info('Bootstrap file still exists. Retrieving node ID')
                with open(BOOTSTRAP_FILE) as bstr_file:
                    node_id = json.load(bstr_file)['node_id']
            else:
                node_id = SettingList.get_setting_by_code(code='node_id').value
        except Exception:
            cls._logger.exception('Unable to determine the node ID, cannot migrate')
            raise

        try:
            api_settings_map = {'api_ip': 'ip', 'api_port': 'port'}  # Map settings code to keys in the Config management
            required_settings = ['node_id', 'migration_version'] + api_settings_map.keys()
            for settings_code in required_settings:
                try:
                    _ = SettingList.get_setting_by_code(settings_code)
                except ObjectNotFoundException:
                    cls._logger.info('Missing required settings: {0}'.format(settings_code))
                    if settings_code == 'node_id':
                        value = node_id
                    elif settings_code in api_settings_map.keys():
                        # Information must be extracted from Configuration
                        main_config = Configuration.get(ASD_NODE_CONFIG_MAIN_LOCATION.format(node_id))
                        value = main_config[api_settings_map[settings_code]]
                    elif settings_code == 'migration_version':
                        # Introduce version for ASD Manager migration code
                        value = 0
                    else:
                        raise NotImplementedError('No action implemented for setting {0}'.format(settings_code))

                    cls._logger.info('Modeling Setting with code {0} and value {1}'.format(settings_code, value))
                    setting = Setting()
                    setting.code = settings_code
                    setting.value = value
                    setting.save()

            if cls._local_client.file_exists(BOOTSTRAP_FILE):
                cls._logger.info('Removing the bootstrap file')
                cls._local_client.file_delete(BOOTSTRAP_FILE)
        except Exception:
            cls._logger.exception('Error during migration of code settings. Unable to proceed')
            raise

        ###############################
        # Start non-crucial migration #
        ###############################

        errors = []
        migration_setting = SettingList.get_setting_by_code(code='migration_version')
        # Add installed package_name in version files and additional string replacements in service files
        try:
            if migration_setting.value < 1:
                cls._logger.info('Adding additional information to service files')
                edition = Configuration.get_edition()
                if edition == PackageFactory.EDITION_ENTERPRISE:
                    for version_file_name in cls._local_client.file_list(directory=ServiceFactory.RUN_FILE_DIR):
                        version_file_path = '{0}/{1}'.format(ServiceFactory.RUN_FILE_DIR, version_file_name)
                        contents = cls._local_client.file_read(filename=version_file_path)
                        if '{0}='.format(PackageFactory.PKG_ALBA) in contents:
                            contents = contents.replace(PackageFactory.PKG_ALBA, PackageFactory.PKG_ALBA_EE)
                            cls._local_client.file_write(filename=version_file_path, contents=contents)

                    node_id = SettingList.get_setting_by_code(code='node_id').value
                    asd_services = list(ASDController.list_asd_services())
                    maint_services = list(MaintenanceController.get_services())
                    for service_name in asd_services + maint_services:
                        config_key = ServiceFactory.SERVICE_CONFIG_KEY.format(node_id, service_name)
                        if Configuration.exists(key=config_key):
                            config = Configuration.get(key=config_key)
                            if 'RUN_FILE_DIR' in config:
                                continue
                            config['RUN_FILE_DIR'] = ServiceFactory.RUN_FILE_DIR
                            config['ALBA_PKG_NAME'] = PackageFactory.PKG_ALBA_EE
                            config['ALBA_VERSION_CMD'] = PackageFactory.VERSION_CMD_ALBA
                            Configuration.set(key=config_key, value=config)
                            cls._service_manager.regenerate_service(name=ASDController.ASD_PREFIX if service_name in asd_services else MaintenanceController.MAINTENANCE_PREFIX,
                                                                    client=cls._local_client,
                                                                    target_name=service_name)
        except Exception as ex:
            cls._logger.exception('Failed to regenerate the ASD and Maintenance services')
            errors.append(ex)

        try:
            if migration_setting.value < 2:
                if System.get_component_identifier() not in Configuration.get(Configuration.get_registration_key(), default=[]):
                    Configuration.register_usage(System.get_component_identifier())
        except Exception as ex:
            cls._logger.exception('Failed to register the asd-manager')
            errors.append(ex)

        if len(errors) == 0:
            cls._logger.info('No errors during non-crucial migration. Saving the migration setting')
            # Save migration settings when no errors occurred
            migration_setting = SettingList.get_setting_by_code(code='migration_version')
            migration_setting.value = 2
            migration_setting.save()

        cls._logger.info('Finished out of band migrations for SDM nodes')