Implement Cloud Foundry Service Broker API

https://blueprints.launchpad.net/murano/+spec/cloudfoundry-api-support

Cloud Foundry is PaaS which supports full lifecycle from initial development, through all testing stages, to deployment. Most well known Cloud Foundry flavours is Cloud Foundry OSS, Pivotal Cloud Foundry and Pivotal Web Services.

If we implement Cloud Foundry Service Broker API in murano, murano apps will be available at Cloud Foundry as services. So Cloud Foundry users will be granted an ability to operate murano applications.

Problem description

Typical scenario of Cloud Foundry and murano collaboration will look like:

  1. While configuring murano enable murano service broker in config file. Provide host and port for it.

  2. Add murano Service Broker in Cloud Foundry and grant access to murano apps for Cloud Foundry organization.

  3. Provision murano app as Cloud Foundry service instance using Cloud Foundry tools.

Proposed change

We need to write Cloud Foundry Service Broker implementation for murano. One of the parts of this implementation should be some mapping function between Cloud Foundry and OpenStack resources. Now it’s planned to map Cloud Foundry Organizations to OpenStack tenants and Cloud Foundry spaces to murano environments. So, all tenant users will be granted with the privileges based on their existing roles in OpenStack tenant. Each Cloud Foundry space will be linked wih murano environment. The parameters which is needed to murano for successful application deployment will store in service object section parameters. The Service Broker itself will parse them as soon as Cloud Foundry can’t do it. It will be parsed during Provision request. The request body will look like that:

{
  "service_id":        "service-guid-here",
  "plan_id":           "plan-guid-here",
  "organization_guid": "org-guid-here",
  "space_guid":        "space-guid-here",
  "parameters":{

                "parameter1": 1,
                "parameter2": "value"

               }

}

It’s planned to setup a Service Broker as a separate service. Additional options should be added to the configs. Also we want to use Cloud Foundry experimental asynchronous operations[3].

Alternatives

None

Data model impact

None

REST API impact

No existing API of murano service is going to be changed. New service will be created implementing the standard Cloud Foundry Service Broker API. Its API methods are as follows:

GET /v2/catalog

Request

Method

URI

Description

GET

/v2/catalog

List all available apps

Parameters:

  • None

Response

Code

Description

200

OK. The expected resource body as below

{
 "services": [{
    "id": "service-guid-here",
    "name": "mysql",
    "description": "A MySQL-compatible relational database",
    "bindable": true,
    "plans": [{
      "id": "plan1-guid-here",
      "name": "small",
      "description": "A small shared database with 100mb storage quota and 10 connections"
    },{
      "id": "plan2-guid-here",
      "name": "large",
      "description": "A large dedicated database with 10GB storage quota, 512MB of RAM, and 100 connections",
      "free": false
    }],
    "dashboard_client": {
      "id": "client-id-1",
      "secret": "secret-1",
      "redirect_uri": "https://dashboard.service.com"
    }
  }]
}

PUT /v2/service_instances/:instance_id?accepts_incomplete=true

Request

Method

URI

Description

PUT

/v2/service_instances/:instance_id?accepts_incomplete=true

Create new service resources for developer

{
  "service_id":        "service-guid-here",
  "plan_id":           "plan-guid-here",
  "organization_guid": "org-guid-here",
  "space_guid":        "space-guid-here"
}

Response

Code

Description

200

OK. May be returned if the service instance already exists and the requested parameters are identical to the existing service instance.

202

Accepted. Service instance creation is in progress.

409

Conflict. Should be returned if the requested service instance already exists. The expected response body is “{}”

422

Should be returned if the request did not include ?accepts_incomplete=true

{
 "dashboard_url": "http://example-dashboard.com/9189kdfsk0vfnku"
}

PATCH /v2/service_instances/:instance_id?accepts_incomplete=true

Request

Method

URI

Description

PATCH

/v2/service_instances/:instance_id?accepts_incomplete=true

Update existing service instance

{
 "plan_id": "plan_guid_here"
}

Response

Code

Description

200

Return if only the new plan matches the old one completely

202

Accepted. Service instance update is in progress.

422

Should be returned if the request did not include ?accepts_incomplete=true

DELETE /v2/service_instances/:instance_id?accepts_incomplete=true

Method

URI

Description

DELETE

/v2/service_instances/:instance_id?accepts_incomplete=true

Delete all resources create during the provision.

Response

Code

Description

202

Accepted. Service instance deletion in progress.

410

Returned if service does not exist

422

Should be returned if the request did not include ?accepts_incomplete=true

PUT /v2/service_instances/:instance_id/service_bindings/:binding_id

Request

Method

URI

Description

PUT

/v2/service_instances/:instance_id/service_bindings/:binding_id

Bind service

{
 "plan_id": "plan_guid_here",
 "service_id": "service_guid_here",
 "app_guid": "app_guid_here"
}

Response

Code

Description

201

Binding has been created. The expected response body is below.

200

May be returned if the binding already exists and the requested parameters are identical to the existing binding. The expected response body is below.

409

Should be returned if the requested binding already exists. The expected response. body is {}, though the description field can be used to return a user-factorin error message.

{
  "credentials": {
    "uri": "mysql://mysqluser:pass@mysqlhost:3306/dbname",
    "username": "mysqluser",
    "password": "pass",
    "host": "mysqlhost",
    "port": 3306,
    "database": "dbname"
  }
}

DELETE /v2/service_instances/:instance_id/service_bindings/:binding_id

Request

Method

URI

Description

DELETE

/v2/service_instances/:instance_id/service_bindings/:binding_id

Unbind service

Response

Code

Description

200

Binding was deleted

410

Returned if binding does not exist

GET /v2/service_instances/:instance_id/last_operation

Request

Method

URI

Description

GET

/v2/service_instances/:instance_id/last_operation

Polling status of the last 202 operation

Response

Code

Description

200

OK

410

GONE. Appropriate only for asynchronous delete requests Cloud Foundry will consider this response a success and remove the resource from its database.

{
  "state": "in progress",
  "description": "Creating service (10% complete)."
}

Versioning impact

None

Other end user impact

None

Deployer impact

Service Broker should be deployed and enabled in the murano config.

Developer impact

None

Murano-dashboard / Horizon impact

None

Implementation

Assignee(s)

Primary assignee:

starodubcevna

Work Items

Changes can be split to this parts:

  • Implement the stub of Service Broker itself. Add needed config opts and starting point.

  • Implement basic Cloud Foundry API calls such as list and provision. Also on this step we should add murano specific API calls.

  • Series of extensions for Cloud Foundry API support:
    • Add update and deprovision API calls

    • Add bind/unbind API calls

Dependencies

None

Testing

Unit tests should cover new API calls.

Documentation Impact

Document “Murano and Cloud Foundry HowTo”. It should be step by step guide for Cloud Foundry and murano cooperation.

References

[1] https://youtu.be/ezq9P1WN2LY [2] http://docs.cloudfoundry.org/services/api.html [3] https://docs.cloudfoundry.org/services/asynchronous-operations.html