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 installation checks for mail and ejabberd on nodes #102

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
28 changes: 26 additions & 2 deletions api/migration/read
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import sys
import subprocess
import simplejson
import json
import os
import fcntl, errno

Expand Down Expand Up @@ -240,12 +241,35 @@ def list_apps():
apps.append(get_account_provider_info())
return apps


def get_cluster_status():
bash_command = "/usr/sbin/ns8-action cluster get-cluster-status null"
process = subprocess.Popen(bash_command.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
return simplejson.loads(output)

output = json.loads(output.decode('utf-8'))

# list all modules
command = ["/usr/sbin/ns8-action", "cluster", "list-modules", "null"]
process = subprocess.Popen(command, stdout=subprocess.PIPE)
modules_output, error = process.communicate()
modules = json.loads(modules_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
for module in modules['data']['output']:
if module.get("id") == "mail":
for destination in module.get("install_destinations", []):
if destination["node_id"] == node_id and not destination["eligible"]:
node["mail_installed"] = True
if module.get("id") == "ejabberd":
for destination in module.get("install_destinations", []):
if destination["node_id"] == node_id and not destination["eligible"]:
node["ejabberd_installed"] = True

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

def check_user_domains():
dump = subprocess.Popen(('echo \'{"action": "dump"}\' | /usr/libexec/nethserver/api/system-accounts-provider/read'), stdout=subprocess.PIPE, shell = True)
Expand Down
4 changes: 3 additions & 1 deletion ui/public/i18n/language.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"error_listing_packages_to_remove": "Error listing packages to remove",
"error_removing_app": "Error removing app",
"error_retrieving_account_provider_info": "Error retrieving account provider info",
"app_cannot_be_migrated_to_node": "{appName} cannot be migrated to NethServer 8 cluster {leaderNode}. An instance is already installed.",
"app_will_be_migrated": "{appName} will be migrated to NethServer 8 cluster {leaderNode}.",
"disconnect_not_allowed_explanation": "Some apps have already been migrated: it is not possible to disconnect at this point.",
"destination_node": "Destination node for {app}",
Expand Down Expand Up @@ -108,7 +109,8 @@
"error_unauthorized": "Access denied. Please verify your credentials.",
"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."
"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"
},
"validation": {
"leader_node_empty": "Leader node is required",
Expand Down
109 changes: 89 additions & 20 deletions ui/src/views/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -458,30 +458,38 @@
</div>
</template>
<template v-else>
<div class="mg-bottom-20">
<div>
<div v-if="!loading.getClusterStatus" class="mg-bottom-20">
<div v-if="!isSaveDisabled">
{{
$t("dashboard.app_will_be_migrated", {
appName: currentApp.name,
leaderNode: config.leaderNode
})
}}
</div>
<div
class="mg-top-10"
v-if="currentApp.id === 'nethserver-mail' && !sogoApp"
>
{{ $t("dashboard.roundcube_webtop_migration") }}
</div>
<div
class="mg-top-10"
v-if="currentApp.id === 'nethserver-mail' && sogoApp"
>
{{ $t("dashboard.roundcube_webtop_sogo_migration") }}
</div>
<div class="mg-top-10" v-if="sogoApp">
{{ $t("dashboard.enable_forge_sogo") }}
</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>
</div>
</div>
</template>
<!-- loading nodes -->
Expand Down Expand Up @@ -511,9 +519,15 @@
v-for="node in clusterNodes"
v-bind:key="node.id"
:value="node.id"
:disabled="!node.online"
:disabled="!node.online || node.mail_installed"
>
{{ getNodeLabel(node) }}
<span v-if="node.mail_installed"
>{{ getNodeLabel(node) }}
{{
$t("dashboard.already_installed_on_this_node")
}}</span
>
<span v-else>{{ getNodeLabel(node) }}</span>
</option>
</select>
</div>
Expand Down Expand Up @@ -630,6 +644,40 @@
</div>
</div>
</template>
<template v-else-if="currentApp.id === 'nethserver-ejabberd'">
<!-- node selection for ejabberd apps -->
<div class="form-group">
<label class="col-sm-5 control-label" for="ejabberd-node">
{{
$t("dashboard.destination_node", {
app: currentApp.name
})
}}
</label>
<div class="col-sm-6">
<select
v-model="appNode"
class="combobox form-control"
id="ejabberd-node"
>
<option
v-for="node in clusterNodes"
v-bind:key="node.id"
:value="node.id"
:disabled="!node.online || node.ejabberd_installed"
>
<span v-if="node.ejabberd_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 @@ -677,7 +725,11 @@
type="button"
class="btn btn-primary"
@click="startMigrationFromModal"
:disabled="loading.getClusterStatus || !!error.getClusterStatus"
:disabled="
loading.getClusterStatus ||
!!error.getClusterStatus ||
isSaveDisabled
"
>
{{ $t("dashboard.start_migration") }}
</button>
Expand Down Expand Up @@ -1195,6 +1247,23 @@ export default {
};
},
computed: {
isSaveDisabled() {
if (this.currentApp && this.currentApp.id === "nethserver-mail") {
const selectedNode = this.clusterNodes.find(
(node) => node.id === this.emailNode
);
return selectedNode ? selectedNode.mail_installed : false;
} else if (
this.currentApp &&
this.currentApp.id === "nethserver-ejabberd"
) {
const selectedNode = this.clusterNodes.find(
(node) => node.id === this.appNode
);
return selectedNode ? selectedNode.ejabberd_installed : false;
}
return false;
},
accountProviderApp() {
return this.apps.find((app) => app.id === "account-provider");
},
Expand Down