Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Samba AD provider migration checks and UI updates #108

Closed
wants to merge 9 commits into from
15 changes: 15 additions & 0 deletions api/migration/read
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,18 @@ def get_cluster_status():
modules_output, error = process.communicate()
modules = json.loads(modules_output)

# list all AD providers
command = ["/usr/sbin/ns8-action", "cluster", "list-user-domains", "null"]
process = subprocess.Popen(command, stdout=subprocess.PIPE)
domains_output, error = process.communicate()
domains = json.loads(domains_output)

# iterate over all nodes and check if mail and ejabberd are installed
for node in output["data"]["output"]["nodes"]:
node_id = node["id"]
node["mail_installed"] = False
node["ejabberd_installed"] = False
node["adProvider_installed"] = False
for module in modules['data']['output']:
if module.get("id") == "mail":
for destination in module.get("install_destinations", []):
Expand All @@ -268,6 +275,14 @@ def get_cluster_status():
for destination in module.get("install_destinations", []):
if destination["node_id"] == node_id and not destination["eligible"]:
node["ejabberd_installed"] = True
for domain in domains['data']['output']['domains']:
if domain["schema"] == "ad":
providers = domain["providers"]
for provider in providers:
provider_node_id = provider["node"]
if provider_node_id == node_id:
node["adProvider_installed"] = True
break

return simplejson.loads(json.dumps(output))

Expand Down
5 changes: 4 additions & 1 deletion ui/public/i18n/language.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"account_provider_migration_in_progress": "Account provider migration in progress",
"account_provider_migration_in_progress_description": "NS8 apps are currently using NS7 account provider",
"start_account_provider_migration_explanation": "Do not shutdown or disconnect the leader node {leaderNode} until the migration has finished",
"ad_provider_cannot_be_migrated_to_node": "This samba ad provider cannot be migrated to the leader node {leaderNode}, because it is already installed. We need one more node to migrate the samba ad provider",
"ad_ip_address_explanation": "Select an IP address to configure Active Directory",
"ad_ip_address": "Active Directory IP address",
"disconnect_successful": "Disconnected from NS8 cluster",
Expand Down Expand Up @@ -110,7 +111,9 @@
"error_certificate_verify_failed": "Certificate verification failed. You can deselect 'TLS validation' to skip this check, if necessary",
"error_no_route_to_host": "Connection to NS8 cluster failed. Please check the IP address or the fully qualified domain name",
"error_port_connection_error": "NS8 cannot connect to the NS7 LDAP service. Ensure that LDAP ports (e.g. 389, 636 of slapd service) are open and accessible from the green zone.",
"already_installed_on_this_node": "Already installed on this node"
"already_installed_on_this_node": "Already installed on this node",
"no_available_node_for_samba_provider": "No available node for Samba Active Directory provider, you have to add a new node to migrate the Samba Active Directory provider",
"read_cluster_status": "Read cluster status"
},
"validation": {
"leader_node_empty": "Leader node is required",
Expand Down
153 changes: 118 additions & 35 deletions ui/src/views/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
loading.connectionRead ||
loading.migrationRead ||
loading.accountProviderInfo ||
loading.abortAction
loading.abortAction ||
loading.getClusterStatus
"
class="spinner spinner-lg"
></div>
Expand Down Expand Up @@ -219,7 +220,20 @@
</a>
</span>
</div>

<!-- account provider samba ad node limit banner-->
<div v-if="!isAvailableNodeForSambaProvider && config.isConnected">
<div class="alert alert-info alert-dismissable">
<button
@click="connectionRead()"
:disabled="loading.migrationUpdate"
class="btn btn-default cluster-status"
>
{{ $t("dashboard.read_cluster_status") }}
</button>
<span class="pficon pficon-info"></span>
{{ $t("dashboard.no_available_node_for_samba_provider") }}
</div>
</div>
<div
v-if="accountProviderMigrationStarted"
class="alert alert-info alert-dismissable"
Expand Down Expand Up @@ -250,7 +264,9 @@
"
@click="showStartMigrationModal(app)"
:disabled="
loading.migrationUpdate || !canStartAccountProviderMigration
loading.migrationUpdate ||
!canStartAccountProviderMigration ||
!isAvailableNodeForSambaProvider
"
class="btn btn-default"
>
Expand Down Expand Up @@ -279,7 +295,10 @@
>
<button
@click="showStartMigrationModal(app)"
:disabled="isStartMigrationButtonDisabled(app)"
:disabled="
isStartMigrationButtonDisabled(app) ||
!isAvailableNodeForSambaProvider
"
v-if="!isMailChild(app) && !isAdChild(app)"
class="btn btn-default"
>
Expand Down Expand Up @@ -447,15 +466,21 @@
<span class="pficon pficon-error-circle-o"></span>
{{ error.getClusterStatus }}
</div>
<template v-if="currentApp.id === 'account-provider'">
<div class="mg-bottom-20">
{{
$t(
"dashboard.start_account_provider_migration_explanation",
{ leaderNode: config.leaderNode }
)
}}
</div>
<template v-if="!loading.getClusterStatus">
<template
v-if="
currentApp.id === 'account-provider' && !isSaveDisabled
"
>
<div class="mg-bottom-20">
{{
$t(
"dashboard.start_account_provider_migration_explanation",
{ leaderNode: config.leaderNode }
)
}}
</div>
</template>
</template>
<template v-else>
<div v-if="!loading.getClusterStatus" class="mg-bottom-20">
Expand All @@ -468,27 +493,28 @@
}}
</div>
<div v-else>
{{
$t("dashboard.app_cannot_be_migrated_to_node", {
appName: currentApp.name,
leaderNode: config.leaderNode
})
}}
<div
class="mg-top-10"
v-if="currentApp.id === 'nethserver-mail' && !sogoApp && !isSaveDisabled"
>
{{ $t("dashboard.roundcube_webtop_migration") }}
</div>
<div
class="mg-top-10"
v-if="currentApp.id === 'nethserver-mail' && sogoApp && !isSaveDisabled"
>
{{ $t("dashboard.roundcube_webtop_sogo_migration") }}
</div>
<div class="mg-top-10" v-if="sogoApp && !isSaveDisabled">
{{ $t("dashboard.enable_forge_sogo") }}
</div>
{{
$t("dashboard.app_cannot_be_migrated_to_node", {
appName: currentApp.name,
leaderNode: config.leaderNode
})
}}
<div
class="mg-top-10"
v-if="currentApp.id === 'nethserver-mail' && !sogoApp && !isSaveDisabled"
>
{{ $t("dashboard.roundcube_webtop_migration") }}
</div>
<div
class="mg-top-10"
v-if="currentApp.id === 'nethserver-mail' && sogoApp && !isSaveDisabled"
>
{{ $t("dashboard.roundcube_webtop_sogo_migration") }}
</div>
<div class="mg-top-10" v-if="sogoApp && !isSaveDisabled">
{{ $t("dashboard.enable_forge_sogo") }}
</div>
</div>
</div>
</template>
<!-- loading nodes -->
Expand Down Expand Up @@ -644,7 +670,7 @@
</div>
</template>
<template v-else-if="currentApp.id === 'nethserver-ejabberd'">
<!-- node selection for email apps -->
<!-- node selection for ejabberd apps -->
<div class="form-group">
<label class="col-sm-5 control-label" for="ejabberd-node">
{{
Expand Down Expand Up @@ -677,6 +703,40 @@
</div>
</div>
</template>
<template v-else-if="currentApp.provider === 'ad'">
<!-- node selection for AD apps -->
<div class="form-group">
<label class="col-sm-5 control-label" for="adprovider-node">
{{
$t("dashboard.destination_node", {
app: currentApp.name
})
}}
</label>
<div class="col-sm-6">
<select
v-model="appNode"
class="combobox form-control"
id="adprovider-node"
>
<option
v-for="node in clusterNodes"
v-bind:key="node.id"
:value="node.id"
:disabled="!node.online || node.adProvider_installed"
>
<span v-if="node.adProvider_installed"
>{{ getNodeLabel(node) }}
{{
$t("dashboard.already_installed_on_this_node")
}}</span
>
<span v-else>{{ getNodeLabel(node) }}</span>
</option>
</select>
</div>
</div>
</template>
<template v-else>
<!-- node selection for app-->
<div class="form-group">
Expand Down Expand Up @@ -1260,9 +1320,27 @@ export default {
(node) => node.id === this.appNode
);
return selectedNode ? selectedNode.ejabberd_installed : false;
} else if (
this.currentApp &&
this.currentApp.provider === 'ad') {
const selectedNode = this.clusterNodes.find(
(node) => node.id === this.appNode
);
return selectedNode ? selectedNode.adProvider_installed : false;
}
return false;
},
isAvailableNodeForSambaProvider() {
// check if there is a node available for samba provider, return true if there is
if ( this.accountProviderConfig.type === "ad" && this.accountProviderConfig.location === 'local') {
return this.clusterNodes.some(
(node) => node.online && !node.adProvider_installed
);
} else {
// if account provider is not ad or is remote, return true
return true;
}
},
accountProviderApp() {
return this.apps.find((app) => app.id === "account-provider");
},
Expand Down Expand Up @@ -1595,6 +1673,7 @@ export default {
this.loading.connectionRead = false;
this.isLdapEnabled = slapd.status === "enabled";
if (this.config.isConnected) {
this.migrationReadClusterStatus();
this.listApplications();
} else {
this.$nextTick(() => {
Expand Down Expand Up @@ -2179,6 +2258,10 @@ export default {
justify-content: flex-end;
}

.cluster-status {
margin-right: 0px !important;
float: right;
}
.node-spinner {
margin-left: 20px;
}
Expand Down