Able to change monitor address and port of member

Change-Id: Ice27b281359342c99d6b5ac618feda6f24688b66
Story: 1713866
Task: 5372
This commit is contained in:
Jacky Hu 2017-11-14 16:27:24 +08:00
parent c035d81183
commit 536da0119a
20 changed files with 324 additions and 144 deletions

View File

@ -245,12 +245,15 @@ def add_member(request, **kwargs):
member = members[index]
conn = _get_sdk_connection(request)
monitor_address = member.get('monitor_address')
member = conn.load_balancer.create_member(
pool_id,
address=member['address'],
protocol_port=member['port'],
subnet_id=member['subnet'],
weight=member.get('weight'))
weight=member.get('weight'),
monitor_address=monitor_address if monitor_address else None,
monitor_port=member.get('monitor_port'))
index += 1
if kwargs.get('members_to_add'):
@ -780,8 +783,11 @@ class Member(generic.View):
"""
data = request.DATA
conn = _get_sdk_connection(request)
monitor_address = data.get('monitor_address')
member = conn.load_balancer.update_member(
member_id, pool_id, weight=data['weight'])
member_id, pool_id, weight=data.get('weight'),
monitor_address=monitor_address if monitor_address else None,
monitor_port=data.get('monitor_port'))
return _get_sdk_object_dict(member)

View File

@ -607,9 +607,6 @@ msgstr "Pool-ID"
msgid "Pool Members"
msgstr "Pool-Mitglieder"
msgid "Pool member weight has been updated."
msgstr "Pool-Mitglied Gewicht wurde aktualisiert."
msgid "Port"
msgstr "Port"
@ -822,14 +819,6 @@ msgstr "Das Zeitlimit muss eine Zahl größer oder gleich 0 sein."
msgid "The weight must be a number between 1 and 256."
msgstr "Das Gewicht muss eine Zahl zwischen 1 und 256 sein."
msgid ""
"The weight of a member determines the portion of requests or connections it "
"services compared to the other members of the pool."
msgstr ""
"Das Gewicht eines Mitglieds bestimmt die Menge an Anfragen oder "
"Verbindungen, die es bedient, verglichen mit den anderen Mitgliedern des "
"Pools."
msgid "Timeout"
msgstr "Zeitlimit"
@ -938,15 +927,9 @@ msgstr "Listener aktualisieren"
msgid "Update Load Balancer"
msgstr "Loadbalancer aktualisieren"
msgid "Update Member Weight"
msgstr "Mitglied-Gewicht aktualisieren"
msgid "Update Pool"
msgstr "Pool aktualisieren"
msgid "Update Weight"
msgstr "Gewicht aktualisieren"
msgid ""
"Use the key-manager service to create any certificate containers before "
"creating the listener.\n"

View File

@ -212,6 +212,24 @@ msgstr ""
"akan menerima lebih banyak lalu lintas. Harus dalam \n"
"   nomor 1 sampai 256."
msgid ""
"<strong>Monitor Address:</strong>\n"
" An alternate IP address used for health monitoring a backend member.\n"
" Default is null which monitors the member address."
msgstr ""
"<strong>Monitor Address:</strong>\n"
" An alternate IP address used for health monitoring a backend member.\n"
" Default is null which monitors the member address."
msgid ""
"<strong>Monitor Port:</strong>\n"
" An alternate protocol port used for health monitoring a backend member.\n"
" Default is null which monitors the member protocol port."
msgstr ""
"<strong>Monitor Port:</strong>\n"
" An alternate protocol port used for health monitoring a backend member.\n"
" Default is null which monitors the member protocol port."
msgid "A new health monitor is being created."
msgstr "Sebuah pemantauan kesehatan baru sedang dibuat."
@ -621,8 +639,8 @@ msgstr "Pool ID (ID kolam)"
msgid "Pool Members"
msgstr "Pool Members (anggota kolam)"
msgid "Pool member weight has been updated."
msgstr "Berat anggota kolam telah diperbarui."
msgid "Pool member has been updated."
msgstr "Pool member has been updated."
msgid "Port"
msgstr "Port"
@ -665,6 +683,9 @@ msgstr "Memberikan rincian untuk penyeimbang beban."
msgid "Provide the details for the pool."
msgstr "Memberikan rincian untuk kolam."
msgid "Provide the details for the member."
msgstr "Provide the details for the member."
msgid "Provider"
msgstr "Provider (penyedia)"
@ -837,12 +858,11 @@ msgstr "Timeout harus berupa angka lebih besar dari atau sama dengan 0."
msgid "The weight must be a number between 1 and 256."
msgstr "Berat harus dalam angka antara 1 dan 256."
msgid ""
"The weight of a member determines the portion of requests or connections it "
"services compared to the other members of the pool."
msgstr ""
"Berat anggota menentukan porsi dari permintaan atau koneksi layanan IT "
"dibandingkan dengan anggota lain dari kolam."
msgid "The monitor address must be a vaid IP address."
msgstr "The monitor address must be a vaid IP address."
msgid "The monitor port must be a number between 1 and 65535."
msgstr "The monitor port must be a number between 1 and 65535."
msgid "Timeout"
msgstr "Timeout (waktu habis)"
@ -952,15 +972,12 @@ msgstr "Update Listener (perbarui pendengar)"
msgid "Update Load Balancer"
msgstr "Update Load Balancer (perbarui penyeimbang beban)"
msgid "Update Member Weight"
msgstr "Update Member Weight"
msgid "Update Member"
msgstr "Update Member"
msgid "Update Pool"
msgstr "Update Pool (perbarui kolam)"
msgid "Update Weight"
msgstr "Update Weight (perbarui berat)"
msgid "Updated At"
msgstr "Updated At"
@ -1006,6 +1023,12 @@ msgstr ""
msgid "Weight"
msgstr "Weight (berat)"
msgid "Monitor Address"
msgstr "Monitor Address"
msgid "Monitor Port"
msgstr "Monitor Port"
msgid ""
"Weight\n"
" <span class=\"hz-icon-required fa fa-asterisk\"></span>"
@ -1013,6 +1036,20 @@ msgstr ""
"Weight (berat) \n"
" <span class=\"hz-icon-required fa fa-asterisk\"></span>"
msgid ""
"IP Address\n"
" <span class=\"hz-icon-required fa fa-asterisk\"></span>"
msgstr ""
"IP Address\n"
" <span class=\"hz-icon-required fa fa-asterisk\"></span>"
msgid ""
"Protocol Port\n"
" <span class=\"hz-icon-required fa fa-asterisk\"></span>"
msgstr ""
"Protocol Port\n"
" <span class=\"hz-icon-required fa fa-asterisk\"></span>"
#, python-format
msgid ""
"You are about to disassociate the floating IP address from load balancer \"%s"

View File

@ -386,9 +386,6 @@ msgstr "プール ID"
msgid "Pool Members"
msgstr "プールメンバー"
msgid "Pool member weight has been updated."
msgstr "プールメンバーのウェイトが更新されました。"
msgid "Port"
msgstr "ポート"
@ -623,15 +620,9 @@ msgstr "リスナーの更新"
msgid "Update Load Balancer"
msgstr "ロードバランサーの更新"
msgid "Update Member Weight"
msgstr "メンバーウェイトの更新"
msgid "Update Pool"
msgstr "プールの更新"
msgid "Update Weight"
msgstr "ウェイトの更新"
msgid "Weight"
msgstr "ウェイト"

View File

@ -536,9 +536,6 @@ msgstr "ИД пула"
msgid "Pool Members"
msgstr "Участники пула"
msgid "Pool member weight has been updated."
msgstr "Весь элемента пула был изменен."
msgid "Port"
msgstr "Порт"
@ -718,13 +715,6 @@ msgstr "Значение таймаута должно быть больше и
msgid "The weight must be a number between 1 and 256."
msgstr "Значение веса должно быть в диапозоне между 1 и 256."
msgid ""
"The weight of a member determines the portion of requests or connections it "
"services compared to the other members of the pool."
msgstr ""
"Вес участника определяет долю обслуживаемых запросов или соединений по "
"отношению к другим участникам пула."
msgid "Timeout"
msgstr "Таймаут"
@ -833,15 +823,9 @@ msgstr "Обновить получатель"
msgid "Update Load Balancer"
msgstr "Обновить Балансировщик Нагрузки"
msgid "Update Member Weight"
msgstr "Обновить весь участника"
msgid "Update Pool"
msgstr "Обновить пул"
msgid "Update Weight"
msgstr "Обновить вес"
msgid "Weight"
msgstr "Вес"

View File

@ -581,9 +581,6 @@ msgstr "资源池ID"
msgid "Pool Members"
msgstr "资源池成员"
msgid "Pool member weight has been updated."
msgstr "负载均衡池成员权重已经更新。"
msgid "Port"
msgstr "端口"
@ -775,11 +772,6 @@ msgstr "超时时限必须为一个大于等于0的整数。"
msgid "The weight must be a number between 1 and 256."
msgstr "权重必须为1到256的整数。"
msgid ""
"The weight of a member determines the portion of requests or connections it "
"services compared to the other members of the pool."
msgstr "成员的权重决定了它在服务中与其他池成员的请求和连接的占比。"
msgid "Timeout"
msgstr "超时时限"
@ -887,15 +879,9 @@ msgstr "更新监听器"
msgid "Update Load Balancer"
msgstr "更新负载均衡器"
msgid "Update Member Weight"
msgstr "更新成员权重"
msgid "Update Pool"
msgstr "更新资源池"
msgid "Update Weight"
msgstr "更新权重"
msgid ""
"Use the key-manager service to create any certificate containers before "
"creating the listener.\n"

View File

@ -26,6 +26,12 @@
.member-address {
width: 18em;
}
.member-monitor-port {
width: 6em;
}
.member-monitor-address {
width: 18em;
}
}
/* The IP addresses list displayed when hovering over the IP address in the

View File

@ -18,11 +18,13 @@
angular
.module('horizon.dashboard.project.lbaasv2.members')
.controller('EditWeightModalController', EditWeightModalController);
.controller('EditMemberModalController', EditMemberModalController);
EditWeightModalController.$inject = [
EditMemberModalController.$inject = [
'$uibModalInstance',
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.dashboard.project.lbaasv2.basePath',
'horizon.dashboard.project.lbaasv2.patterns',
'horizon.framework.util.i18n.gettext',
// Dependencies injected with resolve by $uibModal.open
'poolId',
@ -31,9 +33,9 @@
/**
* @ngdoc controller
* @name EditWeightModalController
* @name EditMemberModalController
* @description
* Controller used by the modal service for editing the weight of a pool member.
* Controller used by the modal service for editing a pool member.
*
* @param $uibModalInstance The angular bootstrap $uibModalInstance service.
* @param api The LBaaS v2 API service.
@ -41,22 +43,37 @@
* @param poolId The pool ID.
* @param member The pool member to update.
*
* @returns The Edit Weight modal controller.
* @returns The Edit Member modal controller.
*/
function EditWeightModalController($uibModalInstance, api, gettext, poolId, member) {
function EditMemberModalController($uibModalInstance, api, basePath,
patterns, gettext, poolId, member) {
var ctrl = this;
// IP address validation pattern
ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|');
ctrl.address = member.address;
ctrl.protocol_port = member.protocol_port;
ctrl.weight = member.weight;
ctrl.monitor_address = member.monitor_address;
ctrl.monitor_port = member.monitor_port;
ctrl.cancel = cancel;
ctrl.save = save;
ctrl.saving = false;
ctrl.weightError = gettext('The weight must be a number between 1 and 256.');
ctrl.monitorAddressError = gettext('The monitor address must be a vaid IP address.');
ctrl.monitorPortError = gettext('The monitor port must be a number between 1 and 65535.');
ctrl.helpUrl = basePath + 'workflow/members/members.help.html';
function save() {
ctrl.saving = true;
return api.editMember(poolId, member.id, { weight: ctrl.weight })
.then(onSuccess, onFailure);
return api.editMember(poolId, member.id, {
weight: ctrl.weight,
monitor_address: ctrl.monitor_address,
monitor_port: ctrl.monitor_port
}).then(onSuccess, onFailure);
}
function cancel() {

View File

@ -16,7 +16,7 @@
(function () {
'use strict';
describe('LBaaS v2 Member Edit Weight Controller', function() {
describe('LBaaS v2 Member Edit Controller', function() {
var ctrl, api, $controller, $uibModalInstance, $scope, $q;
var fail = false;
@ -37,7 +37,11 @@
$provide.value('poolId', 'pool1');
$provide.value('member', {
id: 'member1',
weight: 1
address: '3.3.3.3',
protocol_port: '443',
weight: 1,
monitor_address: '1.1.1.1',
monitor_port: 80
});
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
editMember: function() {
@ -52,24 +56,34 @@
$uibModalInstance = $injector.get('$uibModalInstance');
$scope = $injector.get('$rootScope').$new();
$q = $injector.get('$q');
ctrl = $controller('EditWeightModalController');
ctrl = $controller('EditMemberModalController');
}));
it('should define controller properties', function() {
expect(ctrl.cancel).toBeDefined();
expect(ctrl.save).toBeDefined();
expect(ctrl.saving).toBe(false);
expect(ctrl.address).toBeDefined();
expect(ctrl.protocol_port).toBeDefined();
expect(ctrl.weight).toBe(1);
expect(ctrl.ipPattern).toBeDefined();
expect(ctrl.helpUrl).toBeDefined();
expect(ctrl.weightError).toBe('The weight must be a number between 1 and 256.');
expect(ctrl.monitorAddressError).toBe('The monitor address must be a vaid IP address.');
expect(ctrl.monitorPortError).toBe('The monitor port must be a number between 1 and 65535.');
});
it('should edit member weight', function() {
it('should edit member weight, monitor address and port', function() {
spyOn(api, 'editMember').and.callThrough();
spyOn($uibModalInstance, 'close');
ctrl.save();
$scope.$apply();
expect(ctrl.saving).toBe(true);
expect(api.editMember).toHaveBeenCalledWith('pool1', 'member1', { weight: 1 });
expect(api.editMember).toHaveBeenCalledWith('pool1', 'member1', {
weight: 1,
monitor_address: '1.1.1.1',
monitor_port: 80
});
expect($uibModalInstance.close).toHaveBeenCalled();
});

View File

@ -0,0 +1,96 @@
<div class="modal-header">
<h3 class="modal-title">
<span translate>Update Member</span>
</h3>
</div>
<div class="modal-body lbaas-modal">
<div ng-form="form">
<p translate>Provide the details for the member.</p>
<div class="row">
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group"
ng-class="{ 'has-error': form.address.$invalid && form.address.$dirty }">
<label translate class="control-label" for="address">
IP Address
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<input name="address" id="address" type="text" class="form-control"
ng-model="modal.address" ng-pattern="::modal.ipPattern" ng-required="true" ng-disabled="true">
</div>
</div>
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group"
ng-class="{ 'has-error': form.protocol_port.$invalid && form.protocol_port.$dirty }">
<label translate class="control-label" for="protocol_port">
Protocol Port
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<input name="protocol_port" id="protocol_port" type="number" class="form-control"
ng-model="modal.protocol_port" ng-pattern="/^\d+$/" min="1" max="65535" ng-required="true" ng-disabled="true">
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group required"
ng-class="{ 'has-error': form.weight.$invalid && form.weight.$dirty }">
<label translate class="control-label" for="weight">
Weight
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<input name="weight" id="weight" type="number" class="form-control"
ng-model="modal.weight" ng-pattern="/^\d+$/" min="1" max="256"
ng-required="true">
<span class="help-block" ng-show="form.weight.$invalid && form.weight.$dirty">
{$ ::modal.weightError $}
</span>
</div>
</div>
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group"
ng-class="{ 'has-error': form.monitor_address.$invalid && form.monitor_address.$dirty }">
<label translate class="control-label" for="monitor_address">
Monitor Address
</label>
<input name="monitor_address" id="monitor_address" type="text" class="form-control"
ng-model="modal.monitor_address" ng-pattern="::modal.ipPattern"
>
<span class="help-block" ng-show="form.monitor_address.$invalid && form.monitor_address.$dirty">
{$ ::modal.monitorAddressError $}
</span>
</div>
</div>
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group"
ng-class="{ 'has-error': form.monitor_port.$invalid && form.monitor_port.$dirty }">
<label translate class="control-label" for="monitor_port">
Monitor Port
</label>
<input name="monitor_port" id="monitor_port" type="number" class="form-control"
ng-model="modal.monitor_port" ng-pattern="/^\d+$/" min="1" max="65535"
>
<span class="help-block" ng-show="form.monitor_port.$invalid && form.monitor_port.$dirty">
{$ ::modal.monitorPortError $}
</span>
</div>
</div>
</div>
</div>
<help-panel class="wizard-help">
<ng-include src="::modal.helpUrl"></ng-include>
</help-panel>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-default" ng-click="modal.cancel()">
<span class="fa fa-close"></span>
<span translate>Cancel</span>
</button>
<button class="btn btn-sm btn-primary"
ng-click="modal.save()"
ng-disabled="form.$invalid || modal.saving">
<span class="fa" ng-class="modal.saving ? 'fa-spinner fa-spin' : 'fa-check'"></span>
<span translate>Update</span>
</button>
</div>

View File

@ -18,7 +18,7 @@
angular
.module('horizon.dashboard.project.lbaasv2.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service',
.factory('horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service',
modalService);
modalService.$inject = [
@ -33,10 +33,10 @@
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service
* @ngname horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service
*
* @description
* Provides the service for the pool member Edit Weight action.
* Provides the service for the pool member Edit Member action.
*
* @param $q The angular service for promises.
* @param $uibModal The angular bootstrap $uibModal service.
@ -46,7 +46,7 @@
* @param toastService The horizon toast service.
* @param gettext The horizon gettext function for translation.
*
* @returns The Edit Weight modal service.
* @returns The Edit Member modal service.
*/
function modalService(
@ -99,8 +99,8 @@
function open(item) {
var spec = {
backdrop: 'static',
controller: 'EditWeightModalController as modal',
templateUrl: basePath + 'members/actions/edit-weight/modal.html',
controller: 'EditMemberModalController as modal',
templateUrl: basePath + 'members/actions/edit-member/modal.html',
resolve: {
poolId: function() {
return poolId;
@ -114,7 +114,7 @@
}
function onModalClose() {
toastService.add('success', gettext('Pool member weight has been updated.'));
toastService.add('success', gettext('Pool member has been updated.'));
$route.reload();
}

View File

@ -16,7 +16,7 @@
(function () {
'use strict';
describe('LBaaS v2 Member Edit Weight Service', function() {
describe('LBaaS v2 Member Edit Service', function() {
var service, policy, $scope, $route, $uibModal, toast;
var member = { id: 'member1' };
@ -65,7 +65,7 @@
$route = $injector.get('$route');
$uibModal = $injector.get('$uibModal');
service = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service');
'horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service');
service.init('pool1', fakePromise());
}));
@ -101,7 +101,7 @@
spyOn($route, 'reload');
service.perform(member);
$scope.$apply();
expect(toast.add).toHaveBeenCalledWith('success', 'Pool member weight has been updated.');
expect(toast.add).toHaveBeenCalledWith('success', 'Pool member has been updated.');
expect($route.reload).toHaveBeenCalled();
});

View File

@ -1,39 +0,0 @@
<div class="modal-header">
<h3 class="modal-title">
<span translate>Update Member Weight</span>
</h3>
</div>
<div class="modal-body lbaas-modal">
<p translate>The weight of a member determines the portion of requests or connections it services compared to the other members of the pool.</p>
<div ng-form="form">
<div class="row">
<div class="col-sm-12 col-md-6">
<div class="form-group required"
ng-class="{ 'has-error': form.weight.$invalid && form.weight.$dirty }">
<label translate class="control-label" for="weight">
Weight
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<input name="weight" id="weight" type="number" class="form-control"
ng-model="modal.weight" ng-pattern="/^\d+$/" min="1" max="256"
ng-required="true">
<span class="help-block" ng-show="form.weight.$invalid && form.weight.$dirty">
{$ ::modal.weightError $}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-default" ng-click="modal.cancel()">
<span class="fa fa-close"></span>
<span translate>Cancel</span>
</button>
<button class="btn btn-sm btn-primary"
ng-click="modal.save()"
ng-disabled="form.$invalid || modal.saving">
<span class="fa" ng-class="modal.saving ? 'fa-spinner fa-spin' : 'fa-check'"></span>
<span translate>Update</span>
</button>
</div>

View File

@ -23,7 +23,7 @@
rowActions.$inject = [
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
'horizon.dashboard.project.lbaasv2.members.actions.edit-weight.modal.service'
'horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service'
];
/**
@ -35,11 +35,11 @@
*
* @param gettext The horizon gettext function for translation.
* @param loadBalancersService The LBaaS v2 load balancers service.
* @param editWeight The LBaaS v2 pool member edit weight service.
* @param editMember The LBaaS v2 pool member edit service.
* @returns Members row actions service object.
*/
function rowActions(gettext, loadBalancersService, editWeight) {
function rowActions(gettext, loadBalancersService, editMember) {
var loadBalancerIsActionable, poolId;
var service = {
@ -59,9 +59,9 @@
function actions() {
return [{
service: editWeight.init(poolId, loadBalancerIsActionable),
service: editMember.init(poolId, loadBalancerIsActionable),
template: {
text: gettext('Update Weight')
text: gettext('Edit')
}
}];
}

View File

@ -36,7 +36,7 @@
it('should define correct table row actions', function() {
expect(actions.length).toBe(1);
expect(actions[0].template.text).toBe('Update Weight');
expect(actions[0].template.text).toBe('Edit');
});
it('should have the "allowed" and "perform" functions', function() {

View File

@ -33,6 +33,10 @@
<dd>{$ ctrl.member.subnet_id $}</dd>
<dt translate>Weight</dt>
<dd>{$ ctrl.member.weight $}</dd>
<dt translate>Monitor Address</dt>
<dd>{$ ::ctrl.member.monitor_address | noValue:('None' | translate) $}</dd>
<dt translate>Monitor Port</dt>
<dd>{$ ::ctrl.member.monitor_port | noValue:('None' | translate) $}</dd>
<dt translate>Created At</dt>
<dd>{$ ::ctrl.member.created_at $}</dd>
<dt translate>Updated At</dt>

View File

@ -35,6 +35,8 @@
<input type="checkbox" hz-select-all="table.items">
</th>
<th class="expander"></th>
<th class="rsp-p1" st-sort="id" st-sort-default="id" translate>ID</th>
<th class="rsp-p1" st-sort="address" translate>IP Address</th>
<th class="rsp-p1" st-sort="protocol_port" translate>Protocol Port</th>
@ -54,7 +56,7 @@
Include action-col if you want to perform actions.
rsp-p1 rsp-p2 are responsive priority as user resizes window.
-->
<tr ng-repeat="item in table.items track by item.id"
<tr ng-repeat-start="item in table.items track by item.id"
ng-class="{'st-selected': checked[item.id]}">
<td class="multi_select_column">
@ -62,6 +64,12 @@
ng-model="tCtrl.selections[item.id].checked"
hz-select="item">
</td>
<td class="expander">
<span class="fa fa-chevron-right"
hz-expand-detail
duration="200">
</span>
</td>
<td class="rsp-p1"><a ng-href="project/load_balancer/{$ ::table.loadbalancerId $}/listeners/{$ ::table.listenerId $}/pools/{$ ::table.poolId $}/members/{$ ::item.id $}">{$ ::item.id $}</a></td>
<td class="rsp-p1">{$ ::item.address $}</td>
<td class="rsp-p1">{$ ::item.protocol_port $}</td>
@ -77,7 +85,30 @@
</td>
</tr>
<tr table-status table="table" column-count="6"></tr>
<tr ng-repeat-end class="detail-row">
<!--
Detail-row:
Contains detailed information on this item.
Can be toggled using the chevron button.
Ensure colspan is greater or equal to number of column-headers.
-->
<td class="detail" colspan="9">
<div class="row">
<dl class="col-sm-2">
<dt translate>Monitor Address</dt>
<dd>{$ ::item.monitor_address | noValue:('None' | translate) $}</dd>
</dl>
<dl class="col-sm-2">
<dt translate>Monitor Port</dt>
<dd>{$ ::item.monitor_port | noValue:('None' | translate) $}</dd>
</dl>
</div>
</td>
</tr>
<tr table-status table="table" column-count="9"></tr>
</tbody>
<!--

View File

@ -26,3 +26,13 @@
to the other members of the pool. A higher weight means it will receive more traffic. Must be
a number from 1 to 256.
</p>
<p translate>
<strong>Monitor Address:</strong>
An alternate IP address used for health monitoring a backend member.
Default is null which monitors the member address.
</p>
<p translate>
<strong>Monitor Port:</strong>
An alternate protocol port used for health monitoring a backend member.
Default is null which monitors the member protocol port.
</p>

View File

@ -11,6 +11,8 @@
class="table table-striped table-rsp table-detail">
<thead>
<tr>
<th class="expander"></th>
<th class="rsp-p1" translate>
IP Address
<span class="hz-icon-required fa fa-asterisk" ng-show="ctrl.tableData.displayedAllocated.length > 0">
@ -35,7 +37,13 @@
</div>
</td>
</tr>
<tr ng-repeat="row in ctrl.tableData.displayedAllocated track by row.id">
<tr ng-repeat-start="row in ctrl.tableData.displayedAllocated track by row.id">
<td class="expander">
<span class="fa fa-chevron-right"
hz-expand-detail
duration="200">
</span>
</td>
<td class="rsp-p1">
<div ng-if="!row.addresses"
class="form-group required member-address"
@ -97,6 +105,48 @@
</action-list>
</td>
</tr>
<tr ng-repeat-end class="detail-row">
<!--
Detail-row:
Contains detailed information on this item.
Can be toggled using the chevron button.
Ensure colspan is greater or equal to number of column-headers.
-->
<td class="detail" colspan="7">
<div class="row">
<dl class="col-lg-5 col-md-5 col-sm-5">
<dt translate>Monitor Address</dt>
<dd
class="form-group member-monitor-address"
ng-class="{ 'has-error': memberDetailsForm['{$ ::row.id $}-monitor-address'].$invalid && memberDetailsForm['{$ ::row.id $}-monitor-address'].$dirty }">
<input name="{$ ::row.id $}-monitor-address" type="text" class="form-control"
ng-model="row.monitor_address" ng-pattern="::ctrl.ipPattern"
ng-disabled="row.allocatedMember"
popover-placement="top" popover-append-to-body="true"
popover-trigger="focus"
ng-attr-popover="{$ memberDetailsForm[row.id + '-monitor-address'].$invalid && memberDetailsForm[row.id + '-monitor-address'].$dirty ? ctrl.ipError : '' $}">
</dd>
</dl>
<dl class="col-lg-5 col-md-5 col-sm-5">
<dt translate>Monitor Port</dt>
<dd class="form-group member-monitor-port"
ng-class="{ 'has-error': memberDetailsForm['{$ ::row.id $}-monitor-port'].$invalid && memberDetailsForm['{$ ::row.id $}-monitor-port'].$dirty }">
<input name="{$ ::row.id $}-monitor-port" type="number" class="form-control"
ng-model="row.monitor_port" ng-pattern="/^\d+$/" min="1" max="65535"
ng-disabled="row.allocatedMember"
popover-placement="top" popover-append-to-body="true"
popover-trigger="focus"
ng-attr-popover="{$ memberDetailsForm[row.id + '-monitor-port'].$invalid && memberDetailsForm[row.id + '-monitor-port'].$dirty ? ctrl.portError : '' $}">
</dd>
</dl>
</div>
</td>
</tr>
<tr table-status table="table" column-count="7"></tr>
<tr>
<td colspan="5">
<action-list class="pull-right">

View File

@ -501,7 +501,9 @@
members.push({
id: server.id,
name: server.name,
weight: 1
weight: 1,
monitor_address: null,
monitor_port: null
});
}
});
@ -661,6 +663,8 @@
subnet: mapSubnetObj(member.subnet_id),
port: member.protocol_port,
weight: member.weight,
monitor_address: member.monitor_address,
monitor_port: member.monitor_port,
allocatedMember: true
});
});