Skip to content

Commit 29a3820

Browse files
committed
added validation for wwpn and iqn addresses, to block users from requesting an address that is already in use.
also added validation that the name isn't already used. a more accurate validation would be the combination of name and physical storage, but it's an overkill..
1 parent 7141f5a commit 29a3820

File tree

1 file changed

+34
-20
lines changed

1 file changed

+34
-20
lines changed

app/javascript/components/host-initiator-form/host-initiator-form.schema.js

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { componentTypes, validatorTypes } from '@@ddf';
2+
import validateName from '../../helpers/storage_manager/validate-names';
23

34
export const portTypes = [
45
{ label: __('ISCSI'), value: 'ISCSI' },
@@ -21,8 +22,9 @@ const loadStorages = (id) => API.get(`/api/providers/${id}?attributes=type,physi
2122
})));
2223

2324
const loadGroups = (id) => API.get(`/api/physical_storages/${id}?attributes=host_initiator_groups`)
25+
// eslint-disable-next-line camelcase
2426
.then(({ host_initiator_groups }) => {
25-
let groupOptions = host_initiator_groups.map(({ id, name }) => ({ label: name, value: id }));
27+
const groupOptions = host_initiator_groups.map(({ id, name }) => ({ label: name, value: id }));
2628
groupOptions.unshift({ label: `<${__('None')}>`, value: '' });
2729
return groupOptions;
2830
});
@@ -35,6 +37,16 @@ const loadWwpns = (id) => API.get(`/api/physical_storages/${id}?attributes=wwpn_
3537
label: candidate,
3638
})));
3739

40+
const validateAddress = async(addressType, address) => {
41+
const addresses = [];
42+
await API.get('/api/host_initiators?expand=resources&attributes=san_addresses')
43+
.then(({ resources }) => resources.map((resource) => resource.san_addresses))
44+
.then((addressesArrays) => addressesArrays.map((addressesArray) => addressesArray.map((address) => address[addressType])))
45+
.then((results) => (results.forEach((result) => addresses.push(...result))));
46+
47+
return addresses.includes(address) ? sprintf(__('Address %s is already in use'), address) : undefined;
48+
};
49+
3850
const createSchema = (state, setState, ems, initialValues, storageId, setStorageId) => {
3951
let emsId = state.ems_id;
4052
if (initialValues && initialValues.ems_id) {
@@ -71,6 +83,7 @@ const createSchema = (state, setState, ems, initialValues, storageId, setStorage
7183
threshold: 15,
7284
message: __('The name should have up to 15 characters.'),
7385
},
86+
async(value) => validateName('host_initiators', value, false),
7487
],
7588
},
7689
{
@@ -127,24 +140,25 @@ const createSchema = (state, setState, ems, initialValues, storageId, setStorage
127140
isRequired: true,
128141
validate: [
129142
{
130-
type: validatorTypes.REQUIRED
143+
type: validatorTypes.REQUIRED,
131144
},
132145
{
133-
type: "pattern",
146+
type: 'pattern',
134147
pattern: "iqn\\.(\\d{4}-\\d{2})\\.([^:]+)(:)([^,:\\s']+)",
135-
message: __('The IQN should have the format: iqn.yyyy-mm.naming-authority:unique name')
148+
message: __('The IQN should have the format: iqn.yyyy-mm.naming-authority:unique name'),
136149
},
137150
{
138-
type: "pattern",
139-
pattern: "^[a-z0-9:.-]*$",
140-
message: __('The IQN should contain only lower-case letters (a to z), digits (0 to 9), hyphens (-), ' +
141-
'periods (.) or colons (:)')
151+
type: 'pattern',
152+
pattern: '^[a-z0-9:.-]*$',
153+
message: __('The IQN should contain only lower-case letters (a to z), digits (0 to 9), hyphens (-), '
154+
+ 'periods (.) or colons (:)'),
142155
},
143156
{
144-
type: "max-length",
157+
type: 'max-length',
145158
threshold: 223,
146-
message: __('The IQN should have up to 223 characters.')
147-
}
159+
message: __('The IQN should have up to 223 characters.'),
160+
},
161+
async(value) => validateAddress('iqn', value),
148162
],
149163
},
150164
],
@@ -244,18 +258,19 @@ const createSchema = (state, setState, ems, initialValues, storageId, setStorage
244258
isRequired: true,
245259
validate: [
246260
{
247-
type: validatorTypes.REQUIRED
261+
type: validatorTypes.REQUIRED,
248262
},
249263
{
250-
type: "exact-length",
264+
type: 'exact-length',
251265
threshold: 16,
252-
message: __('The length of the WWPN should be exactly 16 characters.')
266+
message: __('The length of the WWPN should be exactly 16 characters.'),
253267
},
254268
{
255-
type: "pattern",
256-
pattern: "^[0-9A-Fa-f]+$",
257-
message: __('The WWPN should be a hexadecimal expression (0-9, A-F)')
258-
}
269+
type: 'pattern',
270+
pattern: '^[0-9A-Fa-f]+$',
271+
message: __('The WWPN should be a hexadecimal expression (0-9, A-F)'),
272+
},
273+
async(value) => validateAddress('wwpn', value),
259274
],
260275
},
261276
],
@@ -268,8 +283,7 @@ const createSchema = (state, setState, ems, initialValues, storageId, setStorage
268283
id: 'host_initiator_group',
269284
name: 'host_initiator_group',
270285
label: __('Host Initiator Group:'),
271-
isRequired: false,
272-
// includeEmpty: true,
286+
isRequired: true,
273287
validate: [{ type: validatorTypes.REQUIRED }],
274288
loadOptions: () => (storageId ? loadGroups(storageId) : Promise.resolve([])),
275289
isSearchable: true,

0 commit comments

Comments
 (0)