From 33c1c9cf415397421a676bf24bdb40c45776e110 Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Thu, 9 Apr 2020 00:00:45 +0200
Subject: [PATCH] OO-4626: support enable/disable, add panel with statistics of
 servers

---
 .../bigbluebutton/BigBlueButtonManager.java   |  3 +
 .../manager/BigBlueButtonManagerImpl.java     | 60 ++++++++++++++-----
 .../manager/BigBlueButtonMeetingDAO.java      | 13 ++++
 .../manager/BigBlueButtonUtils.java           |  3 +
 .../model/BigBlueButtonErrorCodes.java        |  1 +
 .../BigBlueButtonAdminServersController.java  | 16 ++++-
 .../BigBlueButtonAdminServersTableModel.java  | 42 +++++++++----
 .../ui/BigBlueButtonMeetingController.java    | 10 +++-
 .../ui/BigBlueButtonServerRow.java            | 49 +++++----------
 .../ui/EditBigBlueButtonServerController.java |  4 +-
 .../bigbluebutton/ui/_content/meeting.html    |  5 +-
 .../ui/_i18n/LocalStrings_de.properties       |  3 +
 .../ui/_i18n/LocalStrings_en.properties       |  3 +
 13 files changed, 147 insertions(+), 65 deletions(-)

diff --git a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonManager.java b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonManager.java
index 4547dcc8c36..4d38e4f6a62 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonManager.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/BigBlueButtonManager.java
@@ -48,6 +48,9 @@ public interface BigBlueButtonManager {
 	
 	public List<BigBlueButtonServerInfos> getServersInfos();
 	
+	public List<BigBlueButtonServerInfos> filterServersInfos(List<BigBlueButtonServerInfos> infos);
+	
+	
 	public void deleteServer(BigBlueButtonServer server, BigBlueButtonErrors errors);
 	
 	
diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java
index 43d08f1e58f..14ce098f809 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonManagerImpl.java
@@ -21,10 +21,13 @@ package org.olat.modules.bigbluebutton.manager;
 
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -233,6 +236,28 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 		return getServersInfos(servers);
 	}
 
+	@Override
+	public List<BigBlueButtonServerInfos> filterServersInfos(List<BigBlueButtonServerInfos> infos) {
+		Calendar cal = Calendar.getInstance();
+		cal.add(Calendar.DATE, -5);
+		Date from = cal.getTime();
+		cal.add(Calendar.DATE, 10);
+		Date to = cal.getTime();
+		
+		List<String> meetingsIds = this.bigBlueButtonMeetingDao.getMeetingsIds(from, to);
+		Set<String> instanceMeetingsIds = new HashSet<>(meetingsIds);
+		List<BigBlueButtonServerInfos> instanceInfos = new ArrayList<>();
+		for(BigBlueButtonServerInfos info:infos) {
+			List<BigBlueButtonMeetingInfos> meetings = info.getMeetingsInfos();
+			List<BigBlueButtonMeetingInfos> instanceMeetings = meetings.stream()
+					.filter(meeting -> instanceMeetingsIds.contains(meeting.getMeetingId()))
+					.collect(Collectors.toList());
+			double load = this.calculateLoad(info.getServer(), instanceMeetings);
+			instanceInfos.add(new BigBlueButtonServerInfos(info.getServer(), instanceMeetings, load));
+		}
+		return instanceInfos;
+	}
+
 	@Override
 	public void deleteServer(BigBlueButtonServer server, BigBlueButtonErrors errors) {
 		List<BigBlueButtonMeeting> meetings = bigBlueButtonMeetingDao.getMeetings(server);
@@ -405,6 +430,11 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 	}
 	
 	private List<BigBlueButtonMeetingInfos> getMeetingInfos(BigBlueButtonServer server, BigBlueButtonErrors errors) {
+		if(!server.isEnabled()) {
+			errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.serverDisabled));
+			return new ArrayList<>();
+		}
+		
 		BigBlueButtonUriBuilder uriBuilder = getUriBuilder(server);
 		uriBuilder
 			.operation("getMeetings");
@@ -412,7 +442,6 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 		Document doc = sendRequest(uriBuilder, errors);
 		BigBlueButtonUtils.print(doc);
 		if(BigBlueButtonUtils.checkSuccess(doc, errors)) {
-			BigBlueButtonUtils.print(doc);
 			return BigBlueButtonUtils.getMeetings(doc);
 		}
 		return new ArrayList<>();
@@ -438,6 +467,11 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 	}
 	
 	private void deleteRecording(String recordId, BigBlueButtonServer server, BigBlueButtonErrors errors) {
+		if(!server.isEnabled()) {
+			log.error("Try deleting a recording of a disabled server: {}", server.getUrl());
+			errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.serverDisabled));
+			return;
+		}
 		BigBlueButtonUriBuilder uriBuilder = getUriBuilder(server);
 		uriBuilder
 			.operation("deleteRecordings")
@@ -546,7 +580,7 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 	@Override
 	public boolean isMeetingRunning(BigBlueButtonMeeting meeting) {
 		BigBlueButtonServer server = meeting.getServer();
-		if(server == null) {
+		if(server == null || !server.isEnabled()) {
 			return false;
 		}
 		
@@ -653,6 +687,10 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 	private boolean createBigBlueButtonMeeting(BigBlueButtonMeeting meeting, BigBlueButtonErrors errors) {
 		BigBlueButtonMeetingTemplate template = meeting.getTemplate();
 		BigBlueButtonServer server = meeting.getServer();
+		if(!server.isEnabled()) {
+			errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.serverDisabled));
+			return false;
+		}
 		
 		BigBlueButtonUriBuilder uriBuilder = getUriBuilder(server);
 		uriBuilder
@@ -704,7 +742,7 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 
 	@Override
 	public List<BigBlueButtonRecording> getRecordings(BigBlueButtonMeeting meeting, BigBlueButtonErrors errors) {
-		if(meeting.getServer() == null) {
+		if(meeting.getServer() == null || !meeting.getServer().isEnabled()) {
 			return new ArrayList<>();
 		}
 		
@@ -714,23 +752,12 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 			.parameter("meetingID", meeting.getMeetingId());
 		
 		Document doc = sendRequest(uriBuilder, errors);
-		BigBlueButtonUtils.print(doc);
 		if(BigBlueButtonUtils.checkSuccess(doc, errors)) {
 			return BigBlueButtonUtils.getRecordings(doc);
 		}
 		return Collections.emptyList();
 	}
 	
-	public void getBigBlueButtonDefaultConfigXml(BigBlueButtonServer server) {
-		BigBlueButtonUriBuilder uriBuilder = getUriBuilder(server);
-		uriBuilder
-			.operation("getDefaultConfigXML");
-		BigBlueButtonErrors errors = new BigBlueButtonErrors();
-		Document doc = sendRequest(uriBuilder, errors);
-		BigBlueButtonUtils.print(doc);
-		BigBlueButtonUtils.checkSuccess(doc, errors);	
-	}
-	
 	@Override
 	public boolean checkConnection(String url, String sharedSecret, BigBlueButtonErrors errors) {
 		BigBlueButtonUriBuilder uriBuilder = BigBlueButtonUriBuilder.fromUri(URI.create(url), sharedSecret);
@@ -750,14 +777,15 @@ public class BigBlueButtonManagerImpl implements BigBlueButtonManager, Initializ
 	protected Document sendRequest(BigBlueButtonUriBuilder builder, BigBlueButtonErrors errors) {
 		URI uri = builder.build();
 		HttpGet get = new HttpGet(uri);
-		try(CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+		try(CloseableHttpClient httpClient = HttpClientBuilder.create()
+				.disableAutomaticRetries().build();
 				CloseableHttpResponse response = httpClient.execute(get)) {
 			int statusCode = response.getStatusLine().getStatusCode();
 			log.debug("Status code of: {} {}", uri, statusCode);
 			return BigBlueButtonUtils.getDocumentFromEntity(response.getEntity());
 		} catch(Exception e) {
 			errors.append(new BigBlueButtonError(BigBlueButtonErrorCodes.unkown));
-			log.error("", e);
+			log.error("Cannot send: {}", uri, e);
 			return null;
 		}
 	}
diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java
index e23bea5fcc9..abe4aa8ac96 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonMeetingDAO.java
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.UUID;
 
 import javax.persistence.LockModeType;
+import javax.persistence.TemporalType;
 import javax.persistence.TypedQuery;
 
 import org.olat.core.commons.persistence.DB;
@@ -86,6 +87,18 @@ public class BigBlueButtonMeetingDAO {
 		return meetings == null || meetings.isEmpty() ? null : meetings.get(0);
 	}
 	
+	public List<String> getMeetingsIds(Date from, Date to ) {
+		QueryBuilder sb = new QueryBuilder();
+		sb.append("select meeting.meetingId from bigbluebuttonmeeting as meeting")
+		  .append(" where meeting.permanent=true or (meeting.startDate>:from and meeting.startDate<:to)");
+		
+		return dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), String.class)
+				.setParameter("from", from, TemporalType.TIMESTAMP)
+				.setParameter("to", to, TemporalType.TIMESTAMP)
+				.getResultList();
+	}
+	
 	public BigBlueButtonMeeting loadForUpdate(BigBlueButtonMeeting meeting) {
 		//first remove it from caches
 		dbInstance.getCurrentEntityManager().detach(meeting);
diff --git a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonUtils.java b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonUtils.java
index e8c854043ba..fa4579b9f1f 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonUtils.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/manager/BigBlueButtonUtils.java
@@ -90,6 +90,9 @@ public class BigBlueButtonUtils {
     }
     
     protected static boolean checkSuccess(Document document, BigBlueButtonErrors errors) {
+    	if(document == null) {
+    		return false;
+    	}
     	String returnCode = getFirstElementValue(document.getDocumentElement(), "returncode");
     	print(document);
     	if(SUCCESS.equals(returnCode)) {
diff --git a/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonErrorCodes.java b/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonErrorCodes.java
index b72a057433a..f40b7471488 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonErrorCodes.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/model/BigBlueButtonErrorCodes.java
@@ -30,6 +30,7 @@ public enum BigBlueButtonErrorCodes {
 	sharedSecretDenied,
 	deletedObject,
 	serverNotAvailable,
+	serverDisabled,
 	unkown
 	;
 
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersController.java
index 62285767ad8..04baceada2c 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersController.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.bigbluebutton.ui;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -26,6 +27,7 @@ import java.util.stream.Collectors;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
@@ -81,6 +83,11 @@ public class BigBlueButtonAdminServersController extends FormBasicController {
 		serversTableEl = uifactory.addTableElement(getWindowControl(), "servers", serversTableModel, 10, false, getTranslator(), formLayout);
 		serversTableEl.setCustomizeColumns(true);
 		serversTableEl.setEmtpyTableMessageKey("bigbluebutton.servers.empty");
+		
+		List<FlexiTableFilter> filters = new ArrayList<>();
+		filters.add(new FlexiTableFilter(translate("filter.all.instances"), "all"));
+		filters.add(new FlexiTableFilter(translate("filter.this.instance"), "this"));
+		serversTableEl.setFilters("", filters, false);
 	}
 
 	@Override
@@ -90,12 +97,19 @@ public class BigBlueButtonAdminServersController extends FormBasicController {
 	
 	private void loadModel() {
 		List<BigBlueButtonServer> servers = bigBlueButtonManager.getServers();
+		
 		List<BigBlueButtonServerInfos> serversInfos = bigBlueButtonManager.getServersInfos();
 		Map<BigBlueButtonServer, BigBlueButtonServerInfos> serversToInfos = serversInfos.stream()
 				.collect(Collectors.toMap(BigBlueButtonServerInfos::getServer, infos -> infos, (u, v) -> u));
+		
+		List<BigBlueButtonServerInfos> instanceServersInfos = bigBlueButtonManager.filterServersInfos(serversInfos);
+		Map<BigBlueButtonServer, BigBlueButtonServerInfos> instanceServersToInfos = instanceServersInfos.stream()
+				.collect(Collectors.toMap(BigBlueButtonServerInfos::getServer, infos -> infos, (u, v) -> u));
+		
 		List<BigBlueButtonServerRow> rows = servers.stream()
-				.map(server -> new BigBlueButtonServerRow(server, serversToInfos.get(server)))
+				.map(server -> new BigBlueButtonServerRow(server, serversToInfos.get(server), instanceServersToInfos.get(server)))
 				.collect(Collectors.toList());
+		
 		serversTableModel.setObjects(rows);
 		serversTableEl.reset(true, true, true);
 	}
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersTableModel.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersTableModel.java
index 3abcef753e2..dbe5e31e462 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersTableModel.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonAdminServersTableModel.java
@@ -19,10 +19,13 @@
  */
 package org.olat.modules.bigbluebutton.ui;
 
+import java.util.List;
 import java.util.Locale;
 
 import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FilterableFlexiTableModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel;
@@ -34,11 +37,12 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFl
  *
  */
 public class BigBlueButtonAdminServersTableModel extends DefaultFlexiTableDataModel<BigBlueButtonServerRow>
-implements SortableFlexiTableDataModel<BigBlueButtonServerRow> {
+implements SortableFlexiTableDataModel<BigBlueButtonServerRow>, FilterableFlexiTableModel {
 	
 	private static final ServersCols[] COLS = ServersCols.values();
 
 	private final Locale locale;
+	private boolean allInstances = true;
 	
 	public BigBlueButtonAdminServersTableModel(FlexiTableColumnModel columnsModel, Locale locale) {
 		super(columnsModel);
@@ -50,6 +54,15 @@ implements SortableFlexiTableDataModel<BigBlueButtonServerRow> {
 		//
 	}
 
+	@Override
+	public void filter(String searchString, List<FlexiTableFilter> filters) {
+		if(filters != null && !filters.isEmpty() && "this".equals(filters.get(0).getFilter())) {
+			allInstances = false;
+		} else {
+			allInstances = true;
+		}
+	}
+
 	@Override
 	public Object getValueAt(int row, int col) {
 		BigBlueButtonServerRow server = getObject(row);
@@ -62,15 +75,24 @@ implements SortableFlexiTableDataModel<BigBlueButtonServerRow> {
 			case url: return row.getUrl();
 			case enabled: return row.isEnabled();
 			case capacityFactor: return row.getCapacityFactor();
-			case moderatorCount: return row.getModeratorCount();
-			case participantCount: return row.getParticipantCount();
-			case listenerCount: return row.getListenerCount();
-			case voiceParticipantCount: return row.getVoiceParticipantCount();
-			case videoCount: return row.getVideoCount();
-			case maxUsers: return row.getMaxUsers();
-			case recordingMeetings: return row.getRecordingMeetings();
-			case breakoutRecordingMeetings: return row.getBreakoutRecordingMeetings();
-			case load: return row.getLoad();
+			case moderatorCount: return allInstances
+					? row.getAllInstancesServerInfos().getModeratorCount() : row.getServerInfos().getModeratorCount();
+			case participantCount: return allInstances
+					?  row.getAllInstancesServerInfos().getParticipantCount() : row.getServerInfos().getParticipantCount();
+			case listenerCount: return allInstances
+					?  row.getAllInstancesServerInfos().getListenerCount() : row.getServerInfos().getListenerCount();
+			case voiceParticipantCount: return allInstances
+					?  row.getAllInstancesServerInfos().getVoiceParticipantCount() : row.getServerInfos().getVoiceParticipantCount();
+			case videoCount: return allInstances
+					?  row.getAllInstancesServerInfos().getVideoCount() : row.getServerInfos().getVideoCount();
+			case maxUsers: return allInstances
+					?  row.getAllInstancesServerInfos().getMaxUsers() : row.getServerInfos().getMaxUsers();
+			case recordingMeetings: return allInstances
+					?  row.getAllInstancesServerInfos().getRecordingMeetings() : row.getServerInfos().getRecordingMeetings();
+			case breakoutRecordingMeetings: return allInstances
+					?  row.getAllInstancesServerInfos().getBreakoutRecordingMeetings() : row.getServerInfos().getBreakoutRecordingMeetings();
+			case load: return allInstances
+					?   row.getAllInstancesServerInfos().getLoad() : row.getServerInfos().getLoad();
 			default: return "ERROR";
 		}
 	}
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java
index 4b3f6fe33c9..205018093ca 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonMeetingController.java
@@ -166,15 +166,21 @@ public class BigBlueButtonMeetingController extends FormBasicController implemen
 		updateButtonsAndStatus();
 	}
 	
+	private boolean isDisabled() {
+		return meeting.getServer() != null && !meeting.getServer().isEnabled();
+	}
+	
 	private void updateButtonsAndStatus() {
 		boolean isEnded = isEnded();
 		boolean accessible = isAccessible();
+		boolean disabled = isDisabled();
+		flc.contextPut("disabled", Boolean.valueOf(disabled));
 		flc.contextPut("ended", Boolean.valueOf(isEnded));
 		flc.contextPut("notStarted", Boolean.TRUE);
-		joinButton.setVisible(accessible);
+		joinButton.setVisible(accessible && !disabled);
 		joinButton.setEnabled(!readOnly);
 			
-		if(accessible) {
+		if(accessible && !disabled) {
 			boolean running = bigBlueButtonManager.isMeetingRunning(meeting);
 			if(moderator || administrator) {
 				flc.contextPut("notStarted", Boolean.FALSE);
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonServerRow.java b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonServerRow.java
index e2f3cf0517e..62506b318c3 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonServerRow.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/BigBlueButtonServerRow.java
@@ -19,6 +19,8 @@
  */
 package org.olat.modules.bigbluebutton.ui;
 
+import java.util.ArrayList;
+
 import org.olat.modules.bigbluebutton.BigBlueButtonServer;
 import org.olat.modules.bigbluebutton.model.BigBlueButtonServerInfos;
 
@@ -32,10 +34,16 @@ public class BigBlueButtonServerRow {
 	
 	private final BigBlueButtonServer server;
 	private final BigBlueButtonServerInfos serverInfos;
+	private final BigBlueButtonServerInfos allInstanceServerInfos;
 	
-	public BigBlueButtonServerRow(BigBlueButtonServer server, BigBlueButtonServerInfos serverInfos) {
+	public BigBlueButtonServerRow(BigBlueButtonServer server,
+			BigBlueButtonServerInfos allInstanceServerInfos,
+			BigBlueButtonServerInfos serverInfos) {
 		this.server = server;
-		this.serverInfos = serverInfos;
+		this.serverInfos = serverInfos == null
+				? new BigBlueButtonServerInfos(server, new ArrayList<>(), 0.0d) : serverInfos;
+		this.allInstanceServerInfos = allInstanceServerInfos == null
+				? new BigBlueButtonServerInfos(server, new ArrayList<>(), 0.0d) : allInstanceServerInfos;
 	}
 	
 	public String getUrl() {
@@ -50,40 +58,15 @@ public class BigBlueButtonServerRow {
 		return server.getCapacityFactory();
 	}
 	
-	public double getLoad() {
-		return serverInfos.getLoad();
-	}
-	
-	public Long getModeratorCount() {
-		return serverInfos.getModeratorCount();
+	public BigBlueButtonServer getServer() {
+		return server;
 	}
 	
-	public Long getParticipantCount() {
-		return serverInfos.getParticipantCount();
+	public BigBlueButtonServerInfos getAllInstancesServerInfos() {
+		return allInstanceServerInfos;
 	}
 
-	public Long getListenerCount() {
-		return serverInfos.getListenerCount();
-	}
-	
-	public Long getVoiceParticipantCount() {
-		return serverInfos.getVoiceParticipantCount();
-	}
-	
-	public Long getVideoCount() {
-		return serverInfos.getVideoCount();
+	public BigBlueButtonServerInfos getServerInfos() {
+		return serverInfos;
 	}
-	
-	public Long getMaxUsers() {
-		return serverInfos.getMaxUsers();
-	}
-	
-	public Long getRecordingMeetings() {
-		return serverInfos.getRecordingMeetings();
-	}
-	
-	public Long getBreakoutRecordingMeetings() {
-		return serverInfos.getBreakoutRecordingMeetings();
-	}
-
 }
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonServerController.java b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonServerController.java
index a0acc91b713..8cd040c71b3 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonServerController.java
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/EditBigBlueButtonServerController.java
@@ -126,7 +126,9 @@ public class EditBigBlueButtonServerController extends FormBasicController {
 
 		allOk &= validateUrlFields();
 		if(allOk) {
-			allOk &= validateConnection();
+			if(enabledEl.isAtLeastSelected(1)) {
+				allOk &= validateConnection();
+			}
 			
 			if((server == null || server.getKey() == null)
 					&& bigBlueButtonManager.hasServer(urlEl.getValue())) {
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_content/meeting.html b/src/main/java/org/olat/modules/bigbluebutton/ui/_content/meeting.html
index 5e3781462cd..8a37526ef54 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/_content/meeting.html
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_content/meeting.html
@@ -11,8 +11,9 @@
 #if($r.isTrue($ended))
 	<div class="o_block_large o_warning">$r.translate("meeting.ended")</div>
 #end
-
-#if($r.isTrue($notStarted))
+#if($r.isTrue($disabled))
+	<div class="o_block_large o_error" role="alert">$r.translate("error.serverDisabled")</div>
+#elseif($r.isTrue($notStarted))
 <div class="o_block_large o_info">$r.translate("meeting.create.intro")</div>
 #end
 
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties
index 7049cc84d66..003e7c980fd 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_de.properties
@@ -44,9 +44,12 @@ error.prefix=Ein Fehler ist aufgetreten\:
 error.same.day=Sie haben schon ein Meeting an diesem Tag geplant.
 error.server.exists=Ein Server mit diesem URL existiert schon.
 error.server.raw={1} <small>Schl\u00FCssel\: {0}</small>
+error.serverDisabled=Server ist momentan nicht verf\u00FCgbar.
 error.start.after.end=Das Enddatum darf nicht vor dem Beginndatum sein.
 error.too.long.time=Zeit ist zu lang. Es sind maximal {0} Minuten erlaubt.
 error.url.invalid=Ung\u00FCltige Serveradresse
+filter.all.instances=Alle OpenOlats
+filter.this.instance=Dieses OpenOlat
 meeting.create.intro=Der Online-Termin wurde vom Betreuer noch nicht er\u00F6ffnet. Teilnehmer k\u00F6nnen den Raum f\u00FCr noch nicht betreten.
 meeting.day=Datum des Meetings
 meeting.deleted=Das Meeting wurde erfolgreich gel\u00F6scht.
diff --git a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties
index 0a56e87a859..c2a39241c04 100644
--- a/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/bigbluebutton/ui/_i18n/LocalStrings_en.properties
@@ -44,9 +44,12 @@ error.prefix=An error happened\:
 error.same.day=You already have a meeting planed at this date.
 error.server.exists=A server with this URL already exists.
 error.server.raw={1} <small>Key {0}</small>
+error.serverDisabled=Server is currently not available.
 error.start.after.end=The end date must not be before the start date.
 error.too.long.time=Time is too long. It is limited to {0} minutes.
 error.url.invalid=Invalid server URL
+filter.all.instances=All OpenOlats
+filter.this.instance=This OpenOlat
 meeting.create.intro=The meeting has not yet been started by the coach. Participants are not able to enter the classroom.
 meeting.day=Date of the meeting
 meeting.deleted=The meeting was successfully deleted.
-- 
GitLab