Skip to content

Commit

Permalink
feat(nutanix): add install node popin
Browse files Browse the repository at this point in the history
ref: MANAGER-15712

Signed-off-by: Thibault Barske <[email protected]>
  • Loading branch information
tibs245 committed Jan 5, 2025
1 parent 2658390 commit 94faa2d
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import template from './template.html';
import controller from './controller';

export default {
bindings: {
goBack: '<',
availableVersions: '<',
installNode: '<',
handleSuccess: '<',
handleError: '<',
},
template,
controller,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { isValidIPv4, isPrivateIp } from '../../../utils';

export default class {
/* @ngInject */
constructor(NutanixService, $translate) {
this.NutanixService = NutanixService;
this.$translate = $translate;
this.errorIpMessage = {
notValidIp: $translate.instant(
'nutanix_dashboard_install_form_not_valid_ip_error',
),
notPrivateIp: $translate.instant(
'nutanix_dashboard_install_form_not_private_ip_error',
),
};
}

validPrivateIP(inputName) {
this.installNodeForm[inputName].$setValidity(
'notValidIp',
!this[inputName] || isValidIPv4(this[inputName]),
);

this.installNodeForm[inputName].$setValidity(
'notPrivateIp',
!this[inputName] || isPrivateIp(this[inputName]),
);

return null;
}

onSubmit() {
if (this.installNodeForm.$invalid) {
return;
}

this.isLoading = true;

this.installNode({
ahvIp: this.ahvIp,
cvmIp: this.cvmIp,
version: this.version,
})
.then(() => {
this.handleSuccess(
`${this.$translate.instant(
'nutanix_dashboard_install_node_success_banner',
)}`,
);
})
.catch((error) => {
this.handleError(
`${this.$translate.instant(
'nutanix_dashboard_install_node_error_banner',
)} ${error.message}`,
);
})
.finally(() => {
this.isLoading = false;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import angular from 'angular';
import '@ovh-ux/manager-core';
import '@uirouter/angularjs';
import 'angular-translate';
import '@ovh-ux/ui-kit';

import component from './component';

const moduleName = 'ovhManagerNutanixNutanixInstallNodeModal';

angular
.module(moduleName, [
'oui',
'ovhManagerCore',
'pascalprecht.translate',
'ui.router',
])
.component('installNutanixNodeModal', component)
.run(/* @ngTranslationsInject:json ./translations */);

export default moduleName;
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<oui-modal
data-on-dismiss="$ctrl.goBack()"
data-primary-action="$ctrl.onSubmit()"
data-primary-label="{{:: 'nutanix_dashboard_install_node_confirm' | translate }}"
data-primary-disabled="$ctrl.installNodeForm.$invalid"
data-loading="$ctrl.isLoading"
data-secondary-action="$ctrl.goBack()"
data-secondary-label="{{:: 'nutanix_dashboard_install_node_cancel' | translate }}"
data-heading="{{:: 'nutanix_dashboard_install_node_title' | translate }}"
>
<div>
<p data-translate="nutanix_dashboard_install_node_description"></p>

<oui-message type="info"
><span data-translate="nutanix_dashboard_install_node_tips"></span
></oui-message>

<form class="mt-4" name="$ctrl.installNodeForm" novalidate>
<oui-field
label="{{ 'nutanix_dashboard_install_node_label_ahv_ip' | translate }}"
data-error-messages="$ctrl.errorIpMessage"
>
<div class="oui-input-overlay">
<input
class="oui-input"
type="text"
name="ahvIp"
data-ng-change="$ctrl.validPrivateIP('ahvIp')"
data-ng-model="$ctrl.ahvIp"
required
/>
<span
class="oui-icon oui-icon-help-circle"
title="{{:: 'nutanix_dashboard_install_ip_tooltip' | translate }}"
oui-tooltip
>
</span>
</div>
</oui-field>
<oui-field
label="{{ 'nutanix_dashboard_install_node_label_cvm_ip' | translate }}"
data-error-messages="$ctrl.errorIpMessage"
>
<div class="oui-input-overlay">
<input
class="oui-input"
type="text"
name="cvmIp"
data-ng-change="$ctrl.validPrivateIP('cvmIp')"
data-ng-model="$ctrl.cvmIp"
required
/>
<span
class="oui-icon oui-icon-help-circle"
title="{{:: 'nutanix_dashboard_install_ip_tooltip' | translate }}"
oui-tooltip
>
</span>
</div>
</oui-field>
<oui-field
label="{{:: 'nutanix_dashboard_install_node_label_version_aos' | translate }}"
>
<oui-select
name="version"
data-model="$ctrl.version"
data-items=":: $ctrl.availableVersions"
/>
</oui-field>
</form>
</div>
</oui-modal>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"nutanix_dashboard_install_node_title": "Installer le noeud",
"nutanix_dashboard_install_node_description": "Vous allez installer AOS et AHV sur votre noeud. Indiquez des adresses IP inutilisées dans le réseau de votre cluster.",
"nutanix_dashboard_install_node_tips": "Pour une installation simultanée sur plusieurs noeuds, veuillez utiliser l'API",
"nutanix_dashboard_install_node_label_ahv_ip": "IP du noeud",
"nutanix_dashboard_install_node_label_cvm_ip": "IP CVM",
"nutanix_dashboard_install_node_label_version_aos": "Version AOS",
"nutanix_dashboard_install_node_confirm": "Installer",
"nutanix_dashboard_install_node_cancel": "Annuler",
"nutanix_dashboard_install_node_success_banner": "Votre demande d'installation a été prise en compte. Cette opération peut prendre jusqu'à 1h",
"nutanix_dashboard_install_node_error_banner": "Votre demande d'installation n'a pas été prise en compte : ",
"nutanix_dashboard_install_form_not_valid_ip_error": "Adresse IPv4 invalide",
"nutanix_dashboard_install_form_not_private_ip_error": "Ce champ accepte uniquement les adresses IPv4 privées",
"nutanix_dashboard_install_ip_tooltip": "L'adresse IP doit être incluse dans le sous-réseau du cluster."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import angular from 'angular';

import '@uirouter/angularjs';
import 'oclazyload';

const moduleName = 'ovhManagerNutanixNodeInstallLazyLoading';

angular.module(moduleName, ['ui.router', 'oc.lazyLoad']).config(
/* @ngInject */ ($stateProvider) => {
$stateProvider.state('nutanix.dashboard.nodes.all.install-node.**', {
url: '/install/:node',
lazyLoad: ($transition$) => {
const $ocLazyLoad = $transition$.injector().get('$ocLazyLoad');
return import('./install-node.module').then((mod) =>
$ocLazyLoad.inject(mod.default || mod),
);
},
});
},
);

export default moduleName;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import atInternet from '@ovh-ux/ng-at-internet';
import angular from 'angular';
import installModal from '../../../component/install-node-modal/module';

import '@ovh-ux/ng-translate-async-loader';
import '@uirouter/angularjs';
import 'angular-translate';
import '@ovh-ux/ui-kit';

import routing from './install-node.routing';

const moduleName = 'ovhManagerNutanixNodeInstall';

angular
.module(moduleName, [
atInternet,
'oui',
'pascalprecht.translate',
'ui.router',
installModal,
])
.config(routing);

export default moduleName;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export default /* @ngInject */ ($stateProvider) => {
$stateProvider.state('nutanix.dashboard.nodes.all.install-node', {
url: '/install/:node',
views: {
modal: {
component: 'installNutanixNodeModal',
},
},
layout: 'modal',
resolve: {
nodeId: /* @ngInject */ ($transition$) => $transition$.params().node,
goBack: /* @ngInject */ ($state) => () =>
$state.go('nutanix.dashboard.nodes.all'),
handleSuccess: /* @ngInject */ (Alerter, goBack) => (message) => {
Alerter.success(message, 'nutanix_dashboard_alert');
goBack();
},
handleError: /* @ngInject */ (Alerter, goBack) => (message) => {
Alerter.error(message, 'nutanix_dashboard_alert');
goBack();
},
installNode: /* ngInject */ (NutanixService, serviceName, nodeId) => (
params,
) => NutanixService.installClusterNode(serviceName, nodeId, params),
availableVersions: /* ngInject */ (cluster) => cluster.availableVersions,
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import nodeOsDatagrid from '../../component/service-status/module';
import addNodes from './add-nodes';
import poweronNode from './poweron-node';
import poweroffNode from './poweroff-node';
import installNode from './install-node';
import uninstallNode from './uninstall-node';
import resiliateNode from './resiliate-node';

Expand All @@ -29,6 +30,7 @@ angular
addNodes,
poweronNode,
poweroffNode,
installNode,
uninstallNode,
resiliateNode,
])
Expand Down
7 changes: 7 additions & 0 deletions packages/manager/modules/nutanix/src/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,13 @@ export default class NutanixService {
return this.$http.post(`/dedicated/server/${nodeId}/reboot`);
}

installClusterNode(clusterId, nodeId, options) {
return this.$http.put(
`/nutanix/${clusterId}/nodes/${nodeId}/deploy`,
options,
);
}

uninstallClusterNode(clusterId, nodeId) {
return this.$http.post(`/nutanix/${clusterId}/nodes/${nodeId}/terminate`);
}
Expand Down
31 changes: 31 additions & 0 deletions packages/manager/modules/nutanix/src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export function isValidIPv4(ip) {
const octets = ip.split('.');
if (octets.length !== 4) return false;
return octets.every((octet) => {
const num = Number(octet);
return num >= 0 && num <= 255 && /^\d{1,3}$/.test(octet);
});
}

export function isPrivateIp(ip) {
const octets = ip.split('.').map(Number);

// Vérifier la plage 10.0.0.0 - 10.255.255.255
if (octets[0] === 10) {
return true;
}

// Vérifier la plage 172.16.0.0 - 172.31.255.255
if (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31) {
return true;
}

// Vérifier la plage 192.168.0.0 - 192.168.255.255
if (octets[0] === 192 && octets[1] === 168) {
return true;
}

return false;
}

export default { isValidIPv4, isPrivateIp };

0 comments on commit 94faa2d

Please sign in to comment.