diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index 999d6777f4..4c9ceeced6 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -507,6 +507,22 @@ healthmonitor-delay-optional: in: body required: false type: integer +healthmonitor-domain_name: + description: | + The domain name, which be injected into the HTTP Host Header to the backend + server for HTTP health check. + in: body + min_version: 2.10 + required: true + type: string +healthmonitor-domain_name-optional: + description: | + The domain name, which be injected into the HTTP Host Header to the backend + server for HTTP health check. + in: body + min_version: 2.10 + required: false + type: string healthmonitor-expected_codes: description: | The list of HTTP status codes expected in response from the member to @@ -547,6 +563,20 @@ healthmonitor-http_method-optional: in: body required: false type: string +healthmonitor-http_version: + description: | + The HTTP version. One of ``1.0`` or ``1.1``. The default is ``1.0``. + in: body + min_version: 2.10 + required: true + type: float +healthmonitor-http_version-optional: + description: | + The HTTP version. One of ``1.0`` or ``1.1``. The default is ``1.0``. + in: body + min_version: 2.10 + required: false + type: float healthmonitor-id: description: | The associated health monitor ID. diff --git a/api-ref/source/v2/examples/healthmonitor-create-curl b/api-ref/source/v2/examples/healthmonitor-create-curl index ec77df0002..d2003d1e0e 100644 --- a/api-ref/source/v2/examples/healthmonitor-create-curl +++ b/api-ref/source/v2/examples/healthmonitor-create-curl @@ -1 +1 @@ -curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: " -d '{"healthmonitor":{"name":"super-pool-health-monitor","admin_state_up":true,"pool_id":"4029d267-3983-4224-a3d0-afb3fe16a2cd","delay":"10","expected_codes":"200","max_retries":"1","http_method":"GET","timeout":"5","url_path":"/","type":"HTTP","max_retries_down":3,"tags":["test_tag"]}}' http://198.51.100.10:9876/v2/lbaas/healthmonitors +curl -X POST -H "Content-Type: application/json" -H "X-Auth-Token: " -d '{"healthmonitor":{"name":"super-pool-health-monitor","admin_state_up":true,"pool_id":"4029d267-3983-4224-a3d0-afb3fe16a2cd","delay":"10","expected_codes":"200","max_retries":"1","http_method":"GET","timeout":"5","url_path":"/","type":"HTTP","max_retries_down":3,"tags":["test_tag"],"http_version":1.1,"domain_name":"testlab.com"}}' http://198.51.100.10:9876/v2/lbaas/healthmonitors diff --git a/api-ref/source/v2/examples/healthmonitor-create-request.json b/api-ref/source/v2/examples/healthmonitor-create-request.json index ef38d6a065..9859835e72 100644 --- a/api-ref/source/v2/examples/healthmonitor-create-request.json +++ b/api-ref/source/v2/examples/healthmonitor-create-request.json @@ -11,6 +11,8 @@ "url_path": "/", "type": "HTTP", "max_retries_down": 3, - "tags": ["test_tag"] + "tags": ["test_tag"], + "http_version": 1.1, + "domain_name": "testlab.com" } } diff --git a/api-ref/source/v2/examples/healthmonitor-create-response.json b/api-ref/source/v2/examples/healthmonitor-create-response.json index 3888d746eb..b2d95722b5 100644 --- a/api-ref/source/v2/examples/healthmonitor-create-response.json +++ b/api-ref/source/v2/examples/healthmonitor-create-response.json @@ -21,6 +21,8 @@ "type": "HTTP", "id": "8ed3c5ac-6efa-420c-bedb-99ba14e58db5", "operating_status": "ONLINE", - "tags": ["test_tag"] + "tags": ["test_tag"], + "http_version": 1.1, + "domain_name": "testlab.com" } } diff --git a/api-ref/source/v2/examples/healthmonitor-show-response.json b/api-ref/source/v2/examples/healthmonitor-show-response.json index 3888d746eb..f8c4c40009 100644 --- a/api-ref/source/v2/examples/healthmonitor-show-response.json +++ b/api-ref/source/v2/examples/healthmonitor-show-response.json @@ -21,6 +21,8 @@ "type": "HTTP", "id": "8ed3c5ac-6efa-420c-bedb-99ba14e58db5", "operating_status": "ONLINE", - "tags": ["test_tag"] + "tags": ["test_tag"], + "http_version": 1.0, + "domain_name": null } } diff --git a/api-ref/source/v2/examples/healthmonitor-update-curl b/api-ref/source/v2/examples/healthmonitor-update-curl index d7551fda05..7b9aef3004 100644 --- a/api-ref/source/v2/examples/healthmonitor-update-curl +++ b/api-ref/source/v2/examples/healthmonitor-update-curl @@ -1 +1 @@ -curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: " -d '{"healthmonitor":{"name":"super-pool-health-monitor-updated","admin_state_up":true,"delay":5,"expected_codes":"200","http_method":"HEAD","timeout":2,"url_path":"/index.html","max_retries":2,"max_retries_down":2,"tags":["updated_tag"]}}' http://198.51.100.10:9876/v2/lbaas/healthmonitors/8ed3c5ac-6efa-420c-bedb-99ba14e58db5 +curl -X PUT -H "Content-Type: application/json" -H "X-Auth-Token: " -d '{"healthmonitor":{"name":"super-pool-health-monitor-updated","admin_state_up":true,"delay":5,"expected_codes":"200","http_method":"HEAD","timeout":2,"url_path":"/index.html","max_retries":2,"max_retries_down":2,"tags":["updated_tag"],"http_version":1.1}}' http://198.51.100.10:9876/v2/lbaas/healthmonitors/8ed3c5ac-6efa-420c-bedb-99ba14e58db5 diff --git a/api-ref/source/v2/examples/healthmonitor-update-request.json b/api-ref/source/v2/examples/healthmonitor-update-request.json index e65b53f7b0..73b8d1bed3 100644 --- a/api-ref/source/v2/examples/healthmonitor-update-request.json +++ b/api-ref/source/v2/examples/healthmonitor-update-request.json @@ -9,6 +9,7 @@ "url_path": "/index.html", "max_retries": 2, "max_retries_down": 2, - "tags": ["updated_tag"] + "tags": ["updated_tag"], + "http_version": 1.1 } } diff --git a/api-ref/source/v2/examples/healthmonitor-update-response.json b/api-ref/source/v2/examples/healthmonitor-update-response.json index 72b62ff8b0..416eb15dfe 100644 --- a/api-ref/source/v2/examples/healthmonitor-update-response.json +++ b/api-ref/source/v2/examples/healthmonitor-update-response.json @@ -21,6 +21,8 @@ "type": "HTTP", "id": "8ed3c5ac-6efa-420c-bedb-99ba14e58db5", "operating_status": "ONLINE", - "tags": ["updated_tag"] + "tags": ["updated_tag"], + "http_version": 1.1, + "domain_name": null } } diff --git a/api-ref/source/v2/examples/healthmonitors-list-response.json b/api-ref/source/v2/examples/healthmonitors-list-response.json index db6d0c6197..444790a4e4 100644 --- a/api-ref/source/v2/examples/healthmonitors-list-response.json +++ b/api-ref/source/v2/examples/healthmonitors-list-response.json @@ -22,7 +22,9 @@ "type": "HTTP", "id": "8ed3c5ac-6efa-420c-bedb-99ba14e58db5", "operating_status": "ONLINE", - "tags": ["test_tag"] + "tags": ["test_tag"], + "http_vesion": 1.0, + "domain_name": null } ] } diff --git a/api-ref/source/v2/healthmonitor.inc b/api-ref/source/v2/healthmonitor.inc index f9928f6da3..c4941d0810 100644 --- a/api-ref/source/v2/healthmonitor.inc +++ b/api-ref/source/v2/healthmonitor.inc @@ -48,8 +48,10 @@ Response Parameters - admin_state_up: admin_state_up - created_at: created_at - delay: healthmonitor-delay + - domain_name: healthmonitor-domain_name - expected_codes: healthmonitor-expected_codes - http_method: healthmonitor-http_method + - http_version: healthmonitor-http_version - id: healthmonitor-id - max_retries: healthmonitor-max-retries - max_retries_down: healthmonitor-max-retries-down @@ -127,6 +129,8 @@ Some attributes receive default values if you omit them from the request: - ``http_method`` The default is ``GET``. +- ``http_version`` The default is ``1.0``. + - ``max_retries_down`` The default is ``3``. - ``url_path`` The default is ``/``. @@ -155,8 +159,10 @@ Request - admin_state_up: admin_state_up-default-optional - delay: healthmonitor-delay + - domain_name: healthmonitor-domain_name-optional - expected_codes: healthmonitor-expected_codes-optional - http_method: healthmonitor-http_method-optional + - http_version: healthmonitor-http_version-optional - name: name-optional - max_retries: healthmonitor-max-retries - max_retries_down: healthmonitor-max-retries-down-optional @@ -187,8 +193,10 @@ Response Parameters - admin_state_up: admin_state_up - created_at: created_at - delay: healthmonitor-delay + - domain_name: healthmonitor-domain_name - expected_codes: healthmonitor-expected_codes - http_method: healthmonitor-http_method + - http_version: healthmonitor-http_version - id: healthmonitor-id - max_retries: healthmonitor-max-retries - max_retries_down: healthmonitor-max-retries-down @@ -255,8 +263,10 @@ Response Parameters - admin_state_up: admin_state_up - created_at: created_at - delay: healthmonitor-delay + - domain_name: healthmonitor-domain_name - expected_codes: healthmonitor-expected_codes - http_method: healthmonitor-http_method + - http_version: healthmonitor-http_version - id: healthmonitor-id - max_retries: healthmonitor-max-retries - max_retries_down: healthmonitor-max-retries-down @@ -312,9 +322,11 @@ Request - admin_state_up: admin_state_up-default-optional - delay: healthmonitor-delay-optional + - domain_name: healthmonitor-domain_name-optional - expected_codes: healthmonitor-expected_codes-optional - healthmonitor_id: path-healthmonitor-id - http_method: healthmonitor-http_method-optional + - http_version: healthmonitor-http_version-optional - max_retries: healthmonitor-max-retries-optional - max_retries_down: healthmonitor-max-retries-down-optional - name: name-optional @@ -342,8 +354,10 @@ Response Parameters - admin_state_up: admin_state_up - created_at: created_at - delay: healthmonitor-delay + - domain_name: healthmonitor-domain_name - expected_codes: healthmonitor-expected_codes - http_method: healthmonitor-http_method + - http_version: healthmonitor-http_version - id: healthmonitor-id - max_retries: healthmonitor-max-retries - max_retries_down: healthmonitor-max-retries-down diff --git a/octavia/api/drivers/data_models.py b/octavia/api/drivers/data_models.py index 65aabf4ea5..ce88b851aa 100644 --- a/octavia/api/drivers/data_models.py +++ b/octavia/api/drivers/data_models.py @@ -218,7 +218,8 @@ class HealthMonitor(BaseDataModel): def __init__(self, admin_state_up=Unset, delay=Unset, expected_codes=Unset, healthmonitor_id=Unset, http_method=Unset, max_retries=Unset, max_retries_down=Unset, name=Unset, pool_id=Unset, - timeout=Unset, type=Unset, url_path=Unset): + timeout=Unset, type=Unset, url_path=Unset, http_version=Unset, + domain_name=Unset): self.admin_state_up = admin_state_up self.delay = delay @@ -232,6 +233,8 @@ class HealthMonitor(BaseDataModel): self.timeout = timeout self.type = type self.url_path = url_path + self.http_version = http_version + self.domain_name = domain_name class L7Policy(BaseDataModel): diff --git a/octavia/api/root_controller.py b/octavia/api/root_controller.py index e0f8b8a5ec..1ac839e6f8 100644 --- a/octavia/api/root_controller.py +++ b/octavia/api/root_controller.py @@ -95,6 +95,9 @@ class RootController(rest.RestController): self._add_a_version(versions, 'v2.8', 'v2', 'SUPPORTED', '2019-02-12T00:00:00Z', host_url) # HTTP Redirect code - self._add_a_version(versions, 'v2.9', 'v2', 'CURRENT', + self._add_a_version(versions, 'v2.9', 'v2', 'SUPPORTED', '2019-03-04T00:00:00Z', host_url) + # Healthmonitor host header + self._add_a_version(versions, 'v2.10', 'v2', 'CURRENT', + '2019-03-05T00:00:00Z', host_url) return {'versions': versions} diff --git a/octavia/api/v2/controllers/health_monitor.py b/octavia/api/v2/controllers/health_monitor.py index 2f50b59a32..b90c873913 100644 --- a/octavia/api/v2/controllers/health_monitor.py +++ b/octavia/api/v2/controllers/health_monitor.py @@ -139,6 +139,17 @@ class HealthMonitorController(base.BaseController): hm_dict[consts.EXPECTED_CODES] = ( consts.HEALTH_MONITOR_DEFAULT_EXPECTED_CODES) + if hm_dict.get('domain_name') and not hm_dict.get('http_version'): + raise exceptions.ValidationException( + detail=_("'http_version' must be specified when 'domain_name' " + "is provided.")) + + if hm_dict.get('http_version') and hm_dict.get('domain_name'): + if hm_dict['http_version'] < 1.1: + raise exceptions.InvalidOption( + value='http_version %s' % hm_dict['http_version'], + option='health monitors HTTP 1.1 domain name health check') + try: return self.repositories.health_monitor.create( lock_session, **hm_dict) @@ -280,6 +291,20 @@ class HealthMonitorController(base.BaseController): if health_monitor.expected_codes is None: health_monitor.expected_codes = wtypes.Unset + if health_monitor.domain_name and not ( + db_hm.http_version or health_monitor.http_version): + raise exceptions.ValidationException( + detail=_("'http_version' must be specified when 'domain_name' " + "is provided.")) + + if ((db_hm.http_version or health_monitor.http_version) and + (db_hm.domain_name or health_monitor.domain_name)): + http_version = health_monitor.http_version or db_hm.http_version + if http_version < 1.1: + raise exceptions.InvalidOption( + value='http_version %s' % http_version, + option='health monitors HTTP 1.1 domain name health check') + @wsme_pecan.wsexpose(hm_types.HealthMonitorRootResponse, wtypes.text, body=hm_types.HealthMonitorRootPUT, status_code=200) def put(self, id, health_monitor_): diff --git a/octavia/api/v2/types/health_monitor.py b/octavia/api/v2/types/health_monitor.py index 9450d094f1..57237cebbd 100644 --- a/octavia/api/v2/types/health_monitor.py +++ b/octavia/api/v2/types/health_monitor.py @@ -45,6 +45,8 @@ class HealthMonitorResponse(BaseHealthMonitorType): created_at = wtypes.wsattr(wtypes.datetime.datetime) updated_at = wtypes.wsattr(wtypes.datetime.datetime) tags = wtypes.wsattr(wtypes.ArrayType(wtypes.StringType())) + http_version = wtypes.wsattr(float) + domain_name = wtypes.wsattr(wtypes.StringType()) @classmethod def from_data_model(cls, data_model, children=False): @@ -100,6 +102,11 @@ class HealthMonitorPOST(BaseHealthMonitorType): project_id = wtypes.wsattr(wtypes.StringType(max_length=36)) pool_id = wtypes.wsattr(wtypes.UuidType(), mandatory=True) tags = wtypes.wsattr(wtypes.ArrayType(wtypes.StringType(max_length=255))) + http_version = wtypes.wsattr( + wtypes.Enum(float, *constants.SUPPORTED_HTTP_VERSIONS)) + domain_name = wtypes.wsattr( + wtypes.StringType(min_length=1, max_length=255, + pattern=constants.DOMAIN_NAME_REGEX)) class HealthMonitorRootPOST(types.BaseType): @@ -124,6 +131,11 @@ class HealthMonitorPUT(BaseHealthMonitorType): wtypes.StringType(pattern=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$')) admin_state_up = wtypes.wsattr(bool) tags = wtypes.wsattr(wtypes.ArrayType(wtypes.StringType(max_length=255))) + http_version = wtypes.wsattr( + wtypes.Enum(float, *constants.SUPPORTED_HTTP_VERSIONS)) + domain_name = wtypes.wsattr( + wtypes.StringType(min_length=1, max_length=255, + pattern=constants.DOMAIN_NAME_REGEX)) class HealthMonitorRootPUT(types.BaseType): @@ -152,6 +164,11 @@ class HealthMonitorSingleCreate(BaseHealthMonitorType): wtypes.StringType(pattern=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$')) admin_state_up = wtypes.wsattr(bool, default=True) tags = wtypes.wsattr(wtypes.ArrayType(wtypes.StringType(max_length=255))) + http_version = wtypes.wsattr( + wtypes.Enum(float, *constants.SUPPORTED_HTTP_VERSIONS)) + domain_name = wtypes.wsattr( + wtypes.StringType(min_length=1, max_length=255, + pattern=constants.DOMAIN_NAME_REGEX)) class HealthMonitorStatusResponse(BaseHealthMonitorType): diff --git a/octavia/common/constants.py b/octavia/common/constants.py index c0cdc9ed0c..1b48721364 100644 --- a/octavia/common/constants.py +++ b/octavia/common/constants.py @@ -52,6 +52,7 @@ SUPPORTED_HEALTH_MONITOR_HTTP_METHODS = ( HEALTH_MONITOR_HTTP_METHOD_DELETE, HEALTH_MONITOR_HTTP_METHOD_TRACE, HEALTH_MONITOR_HTTP_METHOD_OPTIONS, HEALTH_MONITOR_HTTP_METHOD_CONNECT, HEALTH_MONITOR_HTTP_METHOD_PATCH) +SUPPORTED_HTTP_VERSIONS = [1.0, 1.1] HEALTH_MONITOR_DEFAULT_EXPECTED_CODES = '200' HEALTH_MONITOR_DEFAULT_URL_PATH = '/' TYPE = 'type' @@ -203,6 +204,9 @@ HTTP_HEADER_VALUE_REGEX = (r'\A[a-zA-Z0-9' HTTP_QUOTED_HEADER_VALUE_REGEX = (r'\A"[a-zA-Z0-9 \t' r'!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~\\]*"\Z') +DOMAIN_NAME_REGEX = ( + r'^(?=.{1,253}\.?$)(?:(?!-|[^.]+_)[A-Za-z0-9-_]{1,63}(?