Skip to content

Add a Service to the Exoscale Marketplace

This runbook describes everything that has to be done to make an existing Servala service available through the Exoscale Marketplace integration, so that Exoscale customers can enable it and get billed for it.

It touches three systems:

  1. Exoscale: the product listing, the OSB identifiers, and the billing product
  2. Servala Portal: the OSB service and plan identifiers
  3. Odoo (VSHN Central): the billing product mapping

Prerequisite: the service already exists in the catalog

This runbook only covers the Exoscale-specific wiring. The service itself (its definition, control plane CRD, compute plans, and offering) must already exist in the Servala service catalog. See Service Catalog for how a service is onboarded in general. If the service does not run on the Exoscale control plane in Geneva (CH-GVA-2) yet, that has to be set up first.

Overview

flowchart LR
    exo["Exoscale<br/>(product + billing)"]
    portal["Servala Portal<br/>(osb_service_id,<br/>osb_plan_id)"]
    odoo["Odoo<br/>(product mapping)"]

    exo-- agreed IDs --> portal
    exo-- product slug --> odoo

The Exoscale service_id and plan_id must match between Exoscale and the portal. The Exoscale product slug must match between Exoscale and Odoo. Agree on all three identifiers with Exoscale before you start.

Step 1: Coordinate with Exoscale

Exoscale lists every product manually in their marketplace database. There is no catalog endpoint and no backchannel from the portal to Exoscale, so the product has to be set up on the Exoscale side first.

Agree with Exoscale on:

  • The product slug (for example servala-postgresql). This is used both in the Exoscale marketplace listing and in the usage reporting.
  • The OSB service_id: the identifier Exoscale will send in the OSB API call when a customer enables the service.
  • The OSB plan_id: the identifier for the published plan. Servala uses one plan per service (the default plan). The technical suspend plan is shared and does not need to be created per service.
  • The billing product on the Exoscale side.

How Exoscale must configure billing for the product

Servala reports the already-priced CHF amount as the metering quantity, using a single billing dimension named service. Exoscale must configure the product with the service dimension priced at exactly 1 CHF per unit (unit u). With a per-unit price of 1, the amount Exoscale charges the customer equals the amount Servala reports. Any other price would produce a wrong invoice. See Exoscale Marketplace Billing.

Exoscale then publishes the product page on the marketplace.

Step 2: Configure the OSB identifiers in the portal

In the Servala Portal Django admin:

  1. Open the Service and set its osb_service_id ("Open Service Broker service ID for API matching") to the service_id agreed with Exoscale.
  2. Open the Service Offering for the Exoscale provider and set its osb_plan_id ("Open Service Broker plan ID for API matching") to the plan_id agreed with Exoscale. There must be exactly one offering with this osb_plan_id for the service, because the OSB API resolves an incoming (service_id, plan_id) pair to one service offering.

When Exoscale later sends an OSB PUT to enable the service, the portal matches service_id against osb_service_id and plan_id against osb_plan_id. If either does not match, the call is rejected. The matched service is then added to the organization's enabled services (limit_osb_services), which makes it visible and provisionable in the portal for that organization.

Origin

Organizations created through the Exoscale Marketplace use the exoscale-marketplace origin, which is created automatically on the first onboarding. You do not need to create it per service.

Step 3: Add the billing product mapping in Odoo

In Odoo (VSHN Central), add a product mapping so the service's usage is reported to Exoscale under the correct product slug.

Create an Exoscale product mapping entry with:

  • Match: a string that matches the service description on the sale order line (for example PostgreSQL or Forgejo). Matching is case-insensitive and the first matching entry by sequence wins.
  • Exoscale product: the product slug agreed with Exoscale (for example servala-postgresql).
  • Variable: the billing dimension, service by default.

Without a mapping, usage is not billed

If a billable service has no product mapping, its usage is silently not reported to Exoscale and the customer is not charged for it. The metering job flags unmapped usage groups, but it does not invent a product. Always add the mapping as part of onboarding a new service.

See Exoscale Marketplace Billing for how the mapping is used during reporting.

Step 4: Verify

  1. Enablement: Ask Exoscale to enable the new service for a test organization, or simulate the OSB PUT call against the portal OSB API. Confirm a 201 (new) or 200 (already enabled) response, that the organization sees the service, and that the welcome E-Mail is sent.
  2. Provisioning: Provision an instance in the portal and confirm it comes up on the Exoscale Geneva control plane.
  3. Billing: Confirm the service description on the resulting Odoo sale order line matches the product mapping, and build a metering report in dry-run mode to confirm the usage is grouped under the correct Exoscale product slug before any real report is sent.

Checklist

  • Product slug, service_id, and plan_id agreed with Exoscale
  • Exoscale billing product configured with the service dimension at 1 CHF/unit
  • Exoscale marketplace product page published
  • osb_service_id set on the Service in the portal
  • osb_plan_id set on the Exoscale Service Offering in the portal
  • Product mapping added in Odoo (match, product slug, variable)
  • Enablement, provisioning, and billing verified end to end