Repository index service
Introduction
Repository Index Service (RIS) is a client-server protocol for package repository management. Based on information provided by the client via URI, the server responds with an XML repository index. The client then uses this information to manage the service's repositories on the system.
Repository Index Service is an extension of Novell Update Service employed in update management of SUSE Linux Enterprise. Compared to NU services, RIS does not require authentication. The repository index can be generated based on any information contained in the URI, like URI parameters, path, as well as user credentials. Another extension allows to use whole URI in the index, while NU services only allow a path relative to the URI of the service.
Specification
Server
The main task of the server is to provide the repoindex.xml which is expected at <RIS-URI>/repo/repoindex.xml, where RIS-URI is the base URI of the service (it should be noted here that the base URI can already contain non-empty path).
RNC schema of the repoindex.xml file is maintained in libzypp's repository. The URIs of <repo> tags should point to common software repositories (like rpmmd, yast, or other); they must not point to another services.
The repoindex.xml can be static, as well as dynamically generated based on various URI component data, like user credentials, parameters, or path. Administrators of the site providing the service publish URIs to be used by clients to access the service.
Client
The client is responsible for managing the services defined on the system, managing the collection of repositories belonging to a service, and, most importantly, for retrieving of the repository index from the specified URI and updating the repository definitions on the system according to it. The following subsections describe the client's responsibilities in more detail.
Adding Service
The client should create and save a .service file based on user provided data, containg at least the required attributes. Once done, the service must be known to the client. The client can (but is not required to) automatically refresh the service.
Removing Service
Removing a service means removing all of its repositories from the system. The client does not need to read the repository index to complete this task.
Refreshing Service
For each enabled service on the system, the task of the client is to read the repository index pointed to by the service URI and update the system repositories according to it.
- Repositories relevant for the target system (matching the target distribution) and not found in it must be added. To prevent repository alias conflicts, the client should some disambiguation method, like prepending the on-system repository alias with the service alias, or similar. All the repository attributes found in the index should be filled in the newly added repository.
- Repositories found in the system but not in the index must be removed.
- The index and system repositories are associated with each other using the repository alias and target distribution.
- Enabled status of existing on-system repositories must not be touched. Responsibility for enabling or disabling desired repositories should be left to user. The exception is if the repository alias is listed in repostoenable or repostodisable attributes of the .service file, in which case the client should enable/disable the corresponding repositories. Newly added repositories should be added as disabled.
- URI of matching existing on-system repositories must be updated according to the index.
- Other attributes can be optionally updated, too, but if the client chooses to do so, it should warn users that any changes in service's repositories will be lost on the next refresh.
Disabled services must be ignored.
Disabling Service
Disabling a service means disabling all of its repositories on the system and disabling the service itself. Disabled service is still known to the client, but must be ignored when refreshing services.
The client does not need to read the repository index to complete this task.
Enabling Service
Enabling a service means enabling the service itself (thus making it not to be ignored during refresh). Repositories of the service should not be enabled, unless the client implements some mechanism of storing the enabled status of the repositories before disabling the service and restoring the status when enabling the service again.
Authentication
If the URI requires authentication, the client must ask user to provide the credentials or retrieve previously saved ones. These credentials should then be used for all repositories of the service, in case they require authentication, too.
.service File
Serves for storing information about the service on the system. The file is in INI format with one section having the service alias as its name and the following attributes:
name | description | value | required | default |
name | Descriptive name of the service. | string | no | <empty> |
url | URL of the service | URL | yes | <N/A> |
type | Service type | ris (for Repository Index Service) or NONE | no (should be detected) | NONE |
enabled | Enabled status | 1 or 0 | no | 0 |
autorefresh | Whether the service should be refreshed automatically when used. | 1 or 0 | no | 0 |
repostoenable | List of repositories which should get enabled during service refresh. The client should remove this attribute from the .service file after the refresh. | comma-separated list of repository aliases | no | <empty> |
repostodisable | List of repositories which should get disabled during service refresh. The client should remove this attribute from the .service file after the refresh. | comma-separated list of repository aliases | no | <empty> |
If an attribute is not present in the .service file, the listed default value should be used. If the type is not present or is NONE, it should be detected whenever needed and eventually saved back to the .service file. Once type is present and known, the client should issue an error messages if other type of service is detected when accessing the service URL.
Examples
repoindex.xml
Let's have a service providing main repositories for current openSUSE release at http://somesoftwaresite.org/current/opensuse. The repoindex.xml file might look like this:
<?xml version="1.0"?> <repoindex> <repo alias="os11-main" name="openSUSE 11.0 Main" description="Main openSUSE 11.0 i386 repository" url="http://download.opensuse.org/distribution/11.0/repo/oss/" distro_target="opensuse-11-i386" priority="50"/> <repo alias="os11-main" name="openSUSE 11.0 Main" description="Main openSUSE 11.0 x86_64 repository" url="http://download.opensuse.org/distribution/11.0/repo/oss/" distro_target="opensuse-11-x86_64" priority="50"/> <repo alias="os11-main" name="openSUSE 11.0 Main" description="Main openSUSE 11.0 ppc repository" url="http://download.opensuse.org/distribution/11.0/repo/oss/" distro_target="opensuse-11-ppc" priority="50"/> <repo alias="os11-nos" name="openSUSE 11.0 Non-OSS" description="Non Open Source Software for openSUSE 11.0 i386" url="http://download.opensuse.org/distribution/11.0/repo/non-oss/" distro_target="opensuse-11-i386" priority="70"/> <repo alias="os11-nos" name="openSUSE 11.0 Non-OSS" description="Non Open Source Software for openSUSE 11.0 x86_64" url="http://download.opensuse.org/distribution/11.0/repo/non-oss/" distro_target="opensuse-11-x86_64" priority="70"/> <repo alias="os11-nos" name="openSUSE 11.0 Non-OSS" description="Non Open Source Software for openSUSE 11.0 ppc" url="http://download.opensuse.org/distribution/11.0/repo/non-oss/" distro_target="opensuse-11-ppc" priority="70"/> <repo alias="os11-upd" name="openSUSE 11.0 Updates" description="Official update repository for openSUSE 11.0 i386" url="http://download.opensuse.org/update/11.0/" distro_target="opensuse-11-i386" priority="20"/> <repo alias="os11-upd" name="openSUSE 11.0 Updates" description="Official update repository for openSUSE 11.0 x86_64" url="http://download.opensuse.org/update/11.0/" distro_target="opensuse-11-x86_64" priority="20"/> <repo alias="os11-upd" name="openSUSE 11.0 Updates" description="Official update repository for openSUSE 11.0 ppc" url="http://download.opensuse.org/update/11.0/" distro_target="opensuse-11-ppc" priority="20"/> </repoindex>
The client would take the service URI, fetch the index and add os11-main, os11-nos, and os11-upd repositories to the system, making them ready for installation. Right after the release of 11.1, the service administrators would update the index with the current repositories. The client would remove the old ones and add the ones upon refresh.
Another example might be a restricted access service for customers of a proprietary software vendor. The repoindex.xml can be generated dynamically based on authentication and purchased products database. The repositories themselves should require authentication in this case.
<repoindex> <repo alias="company-foo" name="Company's Foo" path="products/foo" distro_target="sle-11-i386" priority="20"/> <repo alias="company-bar" name="Company's Bar" path="products/bar" distro_target="sle-11-i386" priority="20"/> <repo alias="company-foo-upd" name="Company's Foo Updates" path="products/foo/updates" distro_target="sle-11-i386" priority="1"/> </repoindex>
The client would take the service URI, authenticate, fetch the index and add the repositories to the system. The vendor would update the index based on customer's purchases. The client would synchronize with the index upon refresh.
.service
[best] name=The Best Opensource Software enabled=1 autorefresh=0 url=http://somesite.org/repos/ type=ris