1527 lines
31 KiB
ReStructuredText
1527 lines
31 KiB
ReStructuredText
===========================
|
|
Octavia HAProxy Amphora API
|
|
===========================
|
|
|
|
Introduction
|
|
============
|
|
This document describes the API interface between the reference haproxy driver
|
|
and its corresponding haproxy-based amphorae.
|
|
|
|
Octavia reference haproxy amphorae use a web service API for configuration and
|
|
control. This API should be secured through the use of TLS encryption as well
|
|
as bi-directional verification of client- and server-side certificates. (The
|
|
exact process for generating and distributing these certificates should be
|
|
covered in another document.)
|
|
|
|
In addition to the web service configuration and control interface, the
|
|
amphorae may use an HMAC-signed UDP protocol for communicating regular, less-
|
|
vital information to the controller (ex. statistics updates and health checks).
|
|
Information on this will also be covered in another document.
|
|
|
|
If a given loadbalancer is being serviced by multiple haproxy amphorae at the
|
|
same time, configuration and control actions should be made on all these
|
|
amphorae at approximately the same time. (Amphorae do not communicate directly
|
|
with each other, except in an active-standby topology, and then this
|
|
communication is limited to fail-over protocols.)
|
|
|
|
.. contents::
|
|
|
|
Versioning
|
|
----------
|
|
All Octavia APIs (including internal APIs like this one) are versioned. For the
|
|
purposes of this document, the initial version of this API shall be v0.1. (So,
|
|
any reference to a *:version* variable should be replaced with the literal
|
|
string 'v0.1'.)
|
|
|
|
Response codes
|
|
--------------
|
|
Typical response codes are:
|
|
|
|
* 200 OK - Operation was completed as requested.
|
|
* 201 Created - Operation successfully resulted in the creation / processing
|
|
of a file.
|
|
* 202 Accepted - Command was accepted but is not completed. (Note that this is
|
|
used for asynchronous processing.)
|
|
* 400 Bad Request - API handler was unable to complete request.
|
|
* 401 Unauthorized - Authentication of the client certificate failed.
|
|
* 404 Not Found - The requested file was not found.
|
|
* 500 Internal Server Error - Usually indicates a permissions problem
|
|
* 503 Service Unavailable - Usually indicates a change to a listener was
|
|
attempted during a transition of amphora topology.
|
|
|
|
A note about storing state
|
|
--------------------------
|
|
In the below API, it will become apparent that at times the amphora will need
|
|
to be aware of the state of things (topology-wise, or simply in terms running
|
|
processes on the amphora). When it comes to storing or gathering this data, we
|
|
should generally prefer to try to resolve these concerns in the following
|
|
order. Note also that not every kind of state data will use all of the steps in
|
|
this list:
|
|
|
|
1. Get state information by querying running processes (ex. parsing haproxy
|
|
status page or querying iptables counters, etc.)
|
|
2. Get state by consulting on-disk cache generated by querying running
|
|
processes. (In the case where state information is relatively expensive to
|
|
collect-- eg. package version listings.)
|
|
3. Get state by consulting stored configuration data as sent by the controller.
|
|
(ex. amphora topology, haproxy configuration or TLS certificate data)
|
|
4. Get state by querying a controller API (not described here).
|
|
|
|
In no case should the amphora assume it ever has direct access to the Octavia
|
|
database. Also, sensitive data (like TLS certificates) should be stored in
|
|
a secure way (ex. memory filesystem).
|
|
|
|
API
|
|
===
|
|
|
|
Get amphora topology
|
|
--------------------
|
|
* **URL:** /*:version*/topology
|
|
* **Method:** GET
|
|
* **URL params:** none
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: JSON formatted listing of this amphora's configured topology.
|
|
|
|
* **Error Response:**
|
|
|
|
* none
|
|
|
|
JSON Response attributes:
|
|
|
|
* *hostname* - hostname of amphora
|
|
* *uuid* - uuid of amphora
|
|
* *topology* - One of: SINGLE, ACTIVE-STANDBY, ACTIVE-ACTIVE
|
|
* *role* - One of ACTIVE, STANDBY (only applicable to ACTIVE-STANDBY)
|
|
* *ha_ip* - only applicable to ACTIVE-STANDBY topology: Highly-available
|
|
routing IP address for the ACTIVE-STANDBY pair.
|
|
|
|
**Examples**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
JSON response:
|
|
{
|
|
'hostname': 'octavia-haproxy-img-00328',
|
|
'uuid': '6e2bc8a0-2548-4fb7-a5f0-fb1ef4a696ce',
|
|
'topology': 'SINGLE',
|
|
'role': 'ACTIVE',
|
|
'ha_ip': '',
|
|
}
|
|
|
|
Set amphora topology
|
|
--------------------
|
|
* **URL:** /*:version*/topology
|
|
* **Method:** POST
|
|
* **URL params:** none
|
|
* **Data params:**
|
|
|
|
* *topology*: One of: SINGLE, ACTIVE-STANDBY, ACTIVE-ACTIVE
|
|
* *role*: One of: ACTIVE, STANDBY (only applicable to ACTIVE-STANDBY)
|
|
* *ha_ip*: (only applicable to ACTIVE-STANDBY) Highly-available IP for the
|
|
HA pair
|
|
* *secret*: (only applicable to ACTIVE-STANDBY topology) Shared secret used
|
|
for authentication with other HA pair member
|
|
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: OK
|
|
|
|
* Code: 202
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: Invalid request.
|
|
* *(Response will also include information on which parameters did not*
|
|
*pass either a syntax check or other topology logic test)*
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
|
|
**Notes:** In an ACTIVE-STANDBY configuration, the 'role' parameter might
|
|
change spontaneously due to a failure of one node. In other topologies, the
|
|
role is not used.
|
|
|
|
Also note that some topology changes can take several minutes to enact, yet
|
|
we want all API commands to return in a matter of seconds. In this case, a
|
|
topology change is initiated, and the amphora status changes from "OK" to
|
|
"TOPOLOGY-CHANGE". The controller should not try to change any resources during
|
|
this transition. (Any attempts will be met with an error.) Once the
|
|
topology change is complete, amphora status should return to "OK". (When the
|
|
UDP communication from amphorae to controller is defined, a 'transition
|
|
complete' message is probably one good candidate for this type of UDP
|
|
communication.)
|
|
|
|
**Examples**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
JSON POST parameters:
|
|
{
|
|
'topology': 'ACTIVE-STANDBY',
|
|
'role': 'ACTIVE',
|
|
'ha_ip': ' 203.0.113.2',
|
|
'secret': 'b20e06cf1abcf29c708d3b437f4a29892a0921d0',
|
|
}
|
|
|
|
Response:
|
|
OK
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Invalid request',
|
|
'details': 'Unknown topology: BAD_TEST_DATA',
|
|
}
|
|
|
|
* Error code 503:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Topology transition in progress',
|
|
}
|
|
|
|
Get amphora info
|
|
----------------
|
|
* **URL:** /info
|
|
* **Method:** GET
|
|
* **URL params:** none
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: JSON formatted listing of several basic amphora data.
|
|
|
|
* **Error Response:**
|
|
|
|
* none
|
|
|
|
JSON Response attributes:
|
|
|
|
* *hostname* - amphora hostname
|
|
* *uuid* - amphora UUID
|
|
* *haproxy_version* - Version of the haproxy installed
|
|
* *api_version* - Version of haproxy amphora API in use
|
|
|
|
**Notes:** The data in this request is used by the controller for determining
|
|
the amphora and API version numbers.
|
|
|
|
It's also worth noting that this is the only API command that doesn't have a
|
|
version string prepended to it.
|
|
|
|
**Examples:**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
{
|
|
'hostname': 'octavia-haproxy-img-00328.local',
|
|
'uuid': '6e2bc8a0-2548-4fb7-a5f0-fb1ef4a696ce',
|
|
'haproxy_version': '1.5.11',
|
|
'api_version': '0.1',
|
|
}
|
|
|
|
Get amphora details
|
|
-------------------
|
|
|
|
* **URL:** /*:version*/details
|
|
* **Method:** GET
|
|
* **URL params:** none
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: JSON formatted listing of various amphora statistics.
|
|
|
|
* **Error Response:**
|
|
|
|
* none
|
|
|
|
JSON Response attributes:
|
|
|
|
* *hostname* - amphora hostname
|
|
* *uuid* - amphora UUID
|
|
* *haproxy_version* - Version of the haproxy installed
|
|
* *api_version* - Version of haproxy amphora API/agent in use
|
|
* *network_tx* - Current total outbound bandwidth in bytes/sec (30-second
|
|
snapshot)
|
|
* *network_rx* - Current total inbound bandwidth in bytes/sec (30-second
|
|
snapshot)
|
|
* *active* - Boolean (is amphora in an "active" role?)
|
|
* *haproxy_count* - Number of running haproxy processes
|
|
* *cpu* - list of percent CPU usage broken down into:
|
|
|
|
* total
|
|
* user
|
|
* system
|
|
* soft_irq
|
|
|
|
* *memory* - memory usage in kilobytes broken down into:
|
|
|
|
* total
|
|
* free
|
|
* available
|
|
* buffers
|
|
* cached
|
|
* swap_used
|
|
* shared
|
|
* slab
|
|
* committed_as
|
|
|
|
* *disk* - disk usage in kilobytes for root filesystem, listed as:
|
|
|
|
* used
|
|
* available
|
|
|
|
* *load* - System load (list)
|
|
* *topology* - One of SINGLE, ACTIVE-STANDBY, ACTIVE-ACTIVE
|
|
* *topology_status* - One of OK, TOPOLOGY-CHANGE
|
|
* *listeners* - list of listener UUIDs being serviced by this amphora
|
|
* *packages* - list of load-balancing related packages installed with versions
|
|
(eg. OpenSSL, haproxy, nginx, etc.)
|
|
|
|
**Notes:** The data in this request is meant to provide intelligence for an
|
|
auto-scaling orchestration controller (heat) in order to determine whether
|
|
additional (or fewer) virtual amphorae are necessary to handle load. As such,
|
|
we may add additional parameters to the JSON listing above if they prove to be
|
|
useful for making these decisions.
|
|
|
|
The data in this request is also used by the controller for determining overall
|
|
health of the amphora, currently-configured topology and role, etc.
|
|
|
|
**Examples**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
{
|
|
'hostname': 'octavia-haproxy-img-00328.local',
|
|
'uuid': '6e2bc8a0-2548-4fb7-a5f0-fb1ef4a696ce',
|
|
'haproxy_version': '1.5.11',
|
|
'api_version': '0.1',
|
|
'networks': {
|
|
'eth0': {
|
|
'network_tx': 3300138,
|
|
'network_rx': 982001, }}
|
|
'active': 'TRUE',
|
|
'haproxy_count': 3,
|
|
'cpu':{
|
|
'total': 0.43,
|
|
'user': 0.30,
|
|
'system': 0.05,
|
|
'soft_irq': 0.08,
|
|
},
|
|
'memory':{
|
|
'total': 4087402,
|
|
'free': 760656,
|
|
'available': 2655901,
|
|
'buffers': 90980,
|
|
'cached': 1830143,
|
|
'swap_used': 943,
|
|
'shared': 105792,
|
|
'slab': 158819,
|
|
'committed_as': 2643480,
|
|
},
|
|
'disk':{
|
|
'used': 1234567,
|
|
'available': 5242880,
|
|
},
|
|
'load': [0.50, 0.45, 0.47],
|
|
'tolopogy': 'SINGLE',
|
|
'topology_status': 'OK',
|
|
'listeners':[
|
|
'02d0da8d-fc65-4bc4-bc46-95cadb2315d2',
|
|
'98e706a7-d22c-422f-9632-499fd83e12c0',
|
|
],
|
|
'packages':[
|
|
{'haproxy': '1.5.1'},
|
|
{'bash': '4.3.23'},
|
|
{'lighttpd': '1.4.33-1'},
|
|
{'openssl': '1.0.1f'},
|
|
<cut for brevity>
|
|
],
|
|
}
|
|
|
|
Get interface
|
|
-------------
|
|
|
|
* **URL:** /*:version*/interface/*:ip*
|
|
* **Method:** GET
|
|
* **URL params:**
|
|
|
|
* *:ip* = the ip address to find the interface name
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: OK
|
|
* Content: JSON formatted interface
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: Bad IP address version
|
|
|
|
* Code: 404
|
|
|
|
* Content: Error interface not found for IP address
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
| eth1
|
|
|
|
**Examples:**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
GET URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/interface/10.0.0.1
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK',
|
|
'interface': 'eth1'
|
|
}
|
|
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
GET URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/interface/10.5.0.1
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Error interface not found for IP address',
|
|
}
|
|
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
GET URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/interface/10.6.0.1.1
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Bad IP address version',
|
|
}
|
|
|
|
|
|
Get all listeners' statuses
|
|
---------------------------
|
|
|
|
* **URL:** /*:version*/listeners
|
|
* **Method:** GET
|
|
* **URL params:** none
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: JSON-formatted listing of each listener's status
|
|
|
|
* **Error Response:**
|
|
|
|
* none
|
|
|
|
JSON Response attributes:
|
|
|
|
Note that the command will return an array of *all* listeners' statuses. Each
|
|
listener status contains the following attributes:
|
|
|
|
* *status* - One of the operational status: ACTIVE, STOPPED, ERROR -
|
|
future versions might support provisioning status:
|
|
PENDING_CREATE, PENDING_UPDATE, PENDING_DELETE, DELETED
|
|
* *uuid* - Listener UUID
|
|
* *type* - One of: TCP, HTTP, TERMINATED_HTTPS
|
|
|
|
**Notes:** Note that this returns a status if: the pid file exists, the stats
|
|
socket exists, or an haproxy configuration is present (not just if there is
|
|
a valid haproxy configuration).
|
|
|
|
**Examples**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
[{
|
|
'status': 'ACTIVE',
|
|
'uuid': 'e2dfddc0-5b9e-11e4-8ed6-0800200c9a66',
|
|
'type': 'HTTP',
|
|
},
|
|
{
|
|
'status': 'STOPPED',
|
|
'uuid': '19d45130-5b9f-11e4-8ed6-0800200c9a66',
|
|
'type': 'TERMINATED_HTTPS',
|
|
}]
|
|
|
|
Get a listener's status
|
|
-----------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*
|
|
* **Method:** GET
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: JSON-formatted listener status
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 404
|
|
|
|
* Content: Not Found
|
|
|
|
JSON Response attributes:
|
|
|
|
* *status* - One of the operational status: ACTIVE, STOPPED, ERROR -
|
|
future versions might support provisioning status:
|
|
PENDING_CREATE, PENDING_UPDATE, PENDING_DELETE, DELETED
|
|
* *uuid* - Listener UUID
|
|
* *type* - One of: TCP, HTTP, TERMINATED_HTTPS
|
|
* *pools* - Map of pool UUIDs and their overall UP / DOWN / DEGRADED status
|
|
* *members* - Map of member UUIDs and their overall UP / DOWN status
|
|
|
|
|
|
**Notes:** Note that this returns a status if: the pid file exists,
|
|
the stats socket exists, or an haproxy configuration is present (not
|
|
just if there is a valid haproxy configuration).
|
|
|
|
**Examples**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'status': 'ACTIVE',
|
|
'uuid': 'e2dfddc0-5b9e-11e4-8ed6-0800200c9a66',
|
|
'type': 'HTTP',
|
|
'pools':[
|
|
{
|
|
'uuid': '399bbf4b-5f6c-4370-a61e-ed2ff2fc9387',
|
|
'status': 'UP',
|
|
'members':[
|
|
{'73f6d278-ae1c-4248-ad02-0bfd50d69aab': 'UP'},
|
|
{'2edca57c-5890-4bcb-ae67-4ef75776cc67': 'DOWN'},
|
|
],
|
|
},
|
|
{
|
|
'uuid': '2250eb21-16ca-44bd-9b12-0b4eb3d18140',
|
|
'status': 'DOWN',
|
|
'members':[
|
|
{'130dff11-4aab-4ba8-a39b-8d77caa7a1ad': 'DOWN'},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Listener Not Found',
|
|
'details': 'No listener with UUID: 04bff5c3-5862-4a13-b9e3-9b440d0ed50a',
|
|
}
|
|
|
|
Start or Stop a listener
|
|
------------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*/*:action*
|
|
* **Method:** PUT
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
* *:action* = One of: start, stop, reload
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 202
|
|
|
|
* Content: OK
|
|
* *(Also contains preliminary results of attempt to start / stop / soft \
|
|
restart (reload) the haproxy daemon)*
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: Invalid request
|
|
|
|
* Code: 404
|
|
|
|
* Content: Listener Not Found
|
|
|
|
* Code: 500
|
|
|
|
* Content: Error starting / stopping / reload_config haproxy
|
|
* *(Also contains error output from attempt to start / stop / soft \
|
|
restart (reload) haproxy)*
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
| Configuration file is valid
|
|
| haproxy daemon for 7e9f91eb-b3e6-4e3b-a1a7-d6f7fdc1de7c started (pid 32428)
|
|
|
|
**Examples:**
|
|
|
|
* Success code 201:
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/start
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK',
|
|
'details': 'Configuration file is valid\nhaproxy daemon for 04bff5c3-5862-4a13-b9e3-9b440d0ed50a started',
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/BAD_TEST_DATA
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Invalid Request',
|
|
'details': 'Unknown action: BAD_TEST_DATA',
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/stop
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Listener Not Found',
|
|
'details': 'No listener with UUID: 04bff5c3-5862-4a13-b9e3-9b440d0ed50a',
|
|
}
|
|
|
|
* Error code 500:
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/stop
|
|
|
|
Response:
|
|
{
|
|
'message': 'Error stopping haproxy',
|
|
'details': 'haproxy process with PID 3352 not found',
|
|
}
|
|
|
|
* Error code 503:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Topology transition in progress',
|
|
}
|
|
|
|
Delete a listener
|
|
-----------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*
|
|
* **Method:** DELETE
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 404
|
|
|
|
* Content: Not Found
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
|
|
* **Implied actions:**
|
|
|
|
* Stop listener
|
|
* Delete IPs, iptables accounting rules, etc. from this amphora if they're no
|
|
longer in use.
|
|
* Clean up listener configuration directory.
|
|
* Delete listener's SSL certificates
|
|
* Clean up logs (ship final logs to logging destination if configured)
|
|
* Clean up stats socket.
|
|
|
|
**Examples**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
DELETE URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK'
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
DELETE URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Listener Not Found',
|
|
'details': 'No listener with UUID: 04bff5c3-5862-4a13-b9e3-9b440d0ed50a',
|
|
}
|
|
|
|
* Error code 503:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Topology transition in progress',
|
|
}
|
|
|
|
Upload SSL certificate PEM file
|
|
-------------------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*/certificates/*:filename.pem*
|
|
* **Method:** PUT
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
* *:filename* = PEM filename (see notes below for naming convention)
|
|
|
|
* **Data params:** Certificate data. (PEM file should be a concatenation of
|
|
unencrypted RSA key, certificate and chain, in that order)
|
|
* **Success Response:**
|
|
|
|
* Code: 201
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: No certificate found
|
|
|
|
* Code: 400
|
|
|
|
* Content: No RSA key found
|
|
|
|
* Code: 400
|
|
|
|
* Content: Certificate and key do not match
|
|
|
|
* Code: 404
|
|
|
|
* Content: Not Found
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
|
|
**Notes:**
|
|
* filename.pem should match the primary CN for which the
|
|
certificate is valid. All-caps WILDCARD should be used to replace an asterisk
|
|
in a wildcard certificate (eg. a CN of '\*.example.com' should have a filename
|
|
of 'WILDCARD.example.com.pem'). Filenames must also have the .pem extension.
|
|
* In order for the new certificate to become effective the haproxy needs to be
|
|
explicitly restarted
|
|
|
|
**Examples:**
|
|
|
|
* Success code 201:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
(Put data should contain the certificate information, concatenated as
|
|
described above)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
(If PUT data does not contain a certificate)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'No certificate found'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
(If PUT data does not contain an RSA key)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'No RSA key found'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
(If the first certificate and the RSA key do not have the same modulus.)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Certificate and key do not match'
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Listener Not Found',
|
|
'details': 'No listener with UUID: 04bff5c3-5862-4a13-b9e3-9b440d0ed50a',
|
|
}
|
|
|
|
|
|
* Error code 503:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Topology transition in progress',
|
|
}
|
|
|
|
|
|
Get SSL certificate md5sum
|
|
--------------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*/certificates/*:filename.pem*
|
|
* **Method:** GET
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
* *:filename* = PEM filename (see notes below for naming convention)
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: PEM file md5sum
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 404
|
|
|
|
* Content: Not Found
|
|
|
|
* **Response:**
|
|
|
|
| <certificate PEM file md5 sum>
|
|
|
|
* **Implied actions:** none
|
|
|
|
**Notes:** The md5sum is the sum from the raw certificate data as stored on
|
|
the amphora (which will usually include the RSA key, certificate and chain
|
|
concatenated together). Note that we don't return any actual raw certificate
|
|
data as the controller should already know this information, and unnecessarily
|
|
disclosing it over the wire from the amphora is a security risk.
|
|
|
|
**Examples:**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
JSON response:
|
|
{
|
|
'md5sum': 'd8f6629d5e3c6852fa764fb3f04f2ffd',
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Listener Not Found',
|
|
'details': 'No listener with UUID: 04bff5c3-5862-4a13-b9e3-9b440d0ed50a',
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Certificate Not Found',
|
|
'details': 'No certificate with file name: www.example.com.pem',
|
|
}
|
|
|
|
Delete SSL certificate PEM file
|
|
-------------------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*/certificates/*:filename.pem*
|
|
* **Method:** DELETE
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
* *:filename* = PEM filename (see notes below for naming convention)
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 404
|
|
|
|
* Content: Not found
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Implied actions:**
|
|
|
|
* Clean up listener configuration directory if it's now empty.
|
|
|
|
**Examples:**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
DELETE URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK'
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
DELETE URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/certificates/www.example.com.pem
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Certificate Not Found',
|
|
'details': 'No certificate with file name: www.example.com.pem',
|
|
}
|
|
|
|
* Error code 503:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Topology transition in progress',
|
|
}
|
|
|
|
Upload listener haproxy configuration
|
|
-------------------------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:amphora_id*/*:listener*/haproxy
|
|
* **Method:** PUT
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
* *:amphora_id* = Amphora UUID
|
|
|
|
* **Data params:** haproxy configuration file for the listener
|
|
* **Success Response:**
|
|
|
|
* Code: 201
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: Invalid configuration
|
|
* *(Also includes error output from configuration check command)*
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
| Configuration file is valid
|
|
|
|
* **Implied actions:**
|
|
|
|
* Do a syntax check on haproxy configuration file prior to an attempt to
|
|
run it.
|
|
* Add resources needed for stats, logs, and connectivity
|
|
|
|
**Notes:** The uploaded configuration file should be a complete and
|
|
syntactically-correct haproxy config. The amphora does not have intelligence
|
|
to generate these itself and has only rudimentary ability to parse certain
|
|
features out of the configuration file (like bind addresses and ports for
|
|
purposes of setting up stats, and specially
|
|
formatted comments meant to indicate pools and members that will be parsed
|
|
out of the haproxy daemon status interface for tracking health and stats).
|
|
|
|
**Examples:**
|
|
|
|
* Success code 201:
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/d459b1c8-54b0-4030-9bec-4f449e73b1ef/04bff5c3-5862-4a13-b9e3-9b440d0ed50a/haproxy
|
|
(Upload PUT data should be a raw haproxy.conf file.)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Invalid request',
|
|
'details': '[ALERT] 300/013045 (28236) : parsing [haproxy.cfg:4]: unknown keyword 'BAD_LINE' out of section.\n[ALERT] 300/013045 (28236) : Error(s) found in configuration file : haproxy.cfg\n[ALERT] 300/013045 (28236) : Fatal errors found in configuration.',
|
|
}
|
|
|
|
* Error code 503:
|
|
|
|
::
|
|
|
|
Response:
|
|
{
|
|
'message': 'Topology transition in progress',
|
|
}
|
|
|
|
Get listener haproxy configuration
|
|
----------------------------------
|
|
|
|
* **URL:** /*:version*/listeners/*:listener*/haproxy
|
|
* **Method:** GET
|
|
* **URL params:**
|
|
|
|
* *:listener* = Listener UUID
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: haproxy configuration file for the listener
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 404
|
|
|
|
* Content: Not found
|
|
|
|
* **Response:**
|
|
|
|
| # Config file for 7e9f91eb-b3e6-4e3b-a1a7-d6f7fdc1de7c
|
|
| (cut for brevity)
|
|
|
|
* **Implied actions:** none
|
|
|
|
**Examples:**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
GET URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/listeners/7e9f91eb-b3e6-4e3b-a1a7-d6f7fdc1de7c/haproxy
|
|
|
|
Response is the raw haproxy.cfg:
|
|
|
|
# Config file for 7e9f91eb-b3e6-4e3b-a1a7-d6f7fdc1de7c
|
|
(cut for brevity)
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Listener Not Found',
|
|
'details': 'No listener with UUID: 04bff5c3-5862-4a13-b9e3-9b440d0ed50a',
|
|
}
|
|
|
|
|
|
Plug VIP
|
|
--------
|
|
|
|
* **URL:** /*:version*/plug/vip/*:ip*
|
|
* **Method:** Post
|
|
* **URL params:**
|
|
|
|
* *:ip* = the vip's ip address
|
|
|
|
* **Data params:**
|
|
|
|
* *subnet_cidr*: The vip subnet in cidr notation
|
|
* *gateway*: The vip subnet gateway address
|
|
* *mac_address*: The mac address of the interface to plug
|
|
|
|
* **Success Response:**
|
|
|
|
* Code: 202
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
* Code: 400
|
|
|
|
* Content: Invalid IP
|
|
* Content: Invalid subnet information
|
|
|
|
* Code: 404
|
|
|
|
* Content: No suitable network interface found
|
|
|
|
* Code: 500
|
|
|
|
* Content: Error plugging VIP
|
|
* (Also contains error output from the ip up command)
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
| VIP <vip> ip plugged on interface <interface>
|
|
|
|
* **Implied actions:**
|
|
|
|
* Look for an interface marked as down (recently added port)
|
|
* Assign VIP
|
|
* Bring that interface up
|
|
|
|
**Examples:**
|
|
|
|
* Success code 202:
|
|
|
|
::
|
|
|
|
POST URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/plug/vip/203.0.113.2
|
|
|
|
JSON POST parameters:
|
|
{
|
|
'subnet_cidr': '203.0.113.0/24',
|
|
'gateway': '203.0.113.1',
|
|
'mac_address': '78:31:c1:ce:0b:3c'
|
|
}
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK',
|
|
'details': 'VIP 203.0.113.2 plugged on interface eth1'
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Invalid VIP',
|
|
}
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'No suitable network interface found',
|
|
}
|
|
|
|
|
|
Plug Network
|
|
------------
|
|
|
|
* **URL:** /*:version*/plug/network/
|
|
* **Method:** POST
|
|
* **URL params:** none
|
|
|
|
* **Data params:**
|
|
|
|
* *mac_address*: The mac address of the interface to plug
|
|
|
|
* **Success Response:**
|
|
|
|
* Code: 202
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 404
|
|
|
|
* Content: No suitable network interface found
|
|
|
|
* Code: 500
|
|
|
|
* Content: Error plugging Port
|
|
* (Also contains error output from the ip up command)
|
|
|
|
* Code: 503
|
|
|
|
* Content: Topology transition in progress
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
| Plugged interface <interface>
|
|
|
|
**Examples:**
|
|
|
|
* Success code 202:
|
|
|
|
::
|
|
|
|
POST URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/plug/network/
|
|
|
|
JSON POST parameters:
|
|
{
|
|
'mac_address': '78:31:c1:ce:0b:3c'
|
|
}
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK',
|
|
'details': 'Plugged interface eth1'
|
|
}
|
|
|
|
|
|
* Error code 404:
|
|
|
|
::
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'No suitable network interface found',
|
|
}
|
|
|
|
|
|
Upload SSL server certificate PEM file for Controller Communication
|
|
-------------------------------------------------------------------
|
|
|
|
* **URL:** /*:version*/certificate
|
|
* **Method:** PUT
|
|
|
|
* **Data params:** Certificate data. (PEM file should be a concatenation of
|
|
unencrypted RSA key, certificate and chain, in that order)
|
|
* **Success Response:**
|
|
|
|
* Code: 202
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: No certificate found
|
|
|
|
* Code: 400
|
|
|
|
* Content: No RSA key found
|
|
|
|
* Code: 400
|
|
|
|
* Content: Certificate and key do not match
|
|
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
|
|
**Notes:**
|
|
Since certificates might be valid for a time smaller than the amphora is in
|
|
existence this add a way to rotate them. Once the certificate is uploaded the
|
|
agent is being recycled so depending on the implementation the service might
|
|
not be available for some time.
|
|
|
|
**Examples:**
|
|
|
|
* Success code 202:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/certificate
|
|
(Put data should contain the certificate information, concatenated as
|
|
described above)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/certificates
|
|
(If PUT data does not contain a certificate)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'No certificate found'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/certificate
|
|
(If PUT data does not contain an RSA key)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'No RSA key found'
|
|
}
|
|
|
|
* Error code 400:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/certificate
|
|
(If the first certificate and the RSA key do not have the same modulus.)
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Certificate and key do not match'
|
|
}
|
|
|
|
|
|
Upload keepalived configuration
|
|
-------------------------------
|
|
|
|
* **URL:** /*:version*/vrrp/upload
|
|
* **Method:** PUT
|
|
* **URL params:** none
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 200
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 500
|
|
|
|
* Content: Failed to upload keepalived configuration.
|
|
|
|
* **Response:**
|
|
|
|
OK
|
|
|
|
**Examples:**
|
|
|
|
* Success code 200:
|
|
|
|
::
|
|
|
|
PUT URI:
|
|
https://octavia-haproxy-img-00328.local/v0.1/vrrp/upload
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK'
|
|
}
|
|
|
|
|
|
Start, Stop, or Reload keepalived
|
|
---------------------------------
|
|
|
|
* **URL:** /*:version*/vrrp/*:action*
|
|
* **Method:** PUT
|
|
* **URL params:**
|
|
|
|
* *:action* = One of: start, stop, reload
|
|
|
|
* **Data params:** none
|
|
* **Success Response:**
|
|
|
|
* Code: 202
|
|
|
|
* Content: OK
|
|
|
|
* **Error Response:**
|
|
|
|
* Code: 400
|
|
|
|
* Content: Invalid Request
|
|
|
|
* Code: 500
|
|
|
|
* Content: Failed to start / stop / reload keepalived service:
|
|
* *(Also contains error output from attempt to start / stop / \
|
|
reload keepalived)*
|
|
|
|
* **Response:**
|
|
|
|
| OK
|
|
| keepalived started
|
|
|
|
**Examples:**
|
|
|
|
* Success code 202:
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/vrrp/start
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'OK',
|
|
'details': 'keepalived started',
|
|
}
|
|
|
|
* Error code: 400
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/vrrp/BAD_TEST_DATA
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Invalid Request',
|
|
'details': 'Unknown action: BAD_TEST_DATA',
|
|
}
|
|
|
|
* Error code: 500
|
|
|
|
::
|
|
|
|
PUT URL:
|
|
https://octavia-haproxy-img-00328.local/v0.1/vrrp/stop
|
|
|
|
JSON Response:
|
|
{
|
|
'message': 'Failed to stop keepalived service: keeepalived process with PID 3352 not found',
|
|
'details': 'keeepalived process with PID 3352 not found',
|
|
}
|
|
|
|
|