openvidu-server: refactor Media Node selection

pull/553/head
pabloFuente 2020-10-23 20:00:01 +02:00
parent e32b1f01b4
commit d358562033
3 changed files with 118 additions and 106 deletions

View File

@ -46,7 +46,6 @@ import io.openvidu.client.OpenViduException;
import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.OpenViduException.Code;
import io.openvidu.client.internal.ProtocolElements; import io.openvidu.client.internal.ProtocolElements;
import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionProperties;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.Recording; import io.openvidu.java.client.Recording;
@ -307,8 +306,8 @@ public abstract class SessionManager {
log.error("Data invalid format"); log.error("Data invalid format");
throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format");
} }
Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), serverMetadata, Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), serverMetadata, record, role,
record, role, kurentoOptions); kurentoOptions);
session.storeToken(tokenObj); session.storeToken(tokenObj);
session.showTokens("Token created"); session.showTokens("Token created");
return tokenObj; return tokenObj;

View File

@ -78,13 +78,13 @@ public class KurentoSessionManager extends SessionManager {
private static final Logger log = LoggerFactory.getLogger(KurentoSessionManager.class); private static final Logger log = LoggerFactory.getLogger(KurentoSessionManager.class);
@Autowired @Autowired
private KmsManager kmsManager; protected KmsManager kmsManager;
@Autowired @Autowired
private KurentoSessionEventsHandler kurentoSessionEventsHandler; protected KurentoSessionEventsHandler kurentoSessionEventsHandler;
@Autowired @Autowired
private KurentoParticipantEndpointConfig kurentoEndpointConfig; protected KurentoParticipantEndpointConfig kurentoEndpointConfig;
@Override @Override
/* Protected by Session.closingLock.readLock */ /* Protected by Session.closingLock.readLock */
@ -110,23 +110,10 @@ public class KurentoSessionManager extends SessionManager {
if (KmsManager.selectAndRemoveKmsLock.tryLock(KmsManager.MAX_SECONDS_LOCK_WAIT, TimeUnit.SECONDS)) { if (KmsManager.selectAndRemoveKmsLock.tryLock(KmsManager.MAX_SECONDS_LOCK_WAIT, TimeUnit.SECONDS)) {
try { try {
kSession = (KurentoSession) sessions.get(sessionId); kSession = (KurentoSession) sessions.get(sessionId);
if (kSession == null) { if (kSession == null) {
// Session still null. It was not created by other thread while waiting for lock // Session still null. It was not created by other thread while waiting for lock
Kms lessLoadedKms = null; Kms selectedMediaNode = this.selectMediaNode(sessionNotActive);
try { kSession = createSession(sessionNotActive, selectedMediaNode);
lessLoadedKms = this.kmsManager.getLessLoadedConnectedAndRunningKms();
} catch (NoSuchElementException e) {
// Restore session not active
this.cleanCollections(sessionId);
this.storeSessionNotActive(sessionNotActive);
throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
"There is no available Media Node where to initialize session '" + sessionId
+ "'");
}
log.info("KMS less loaded is {} with a load of {}", lessLoadedKms.getUri(),
lessLoadedKms.getLoad());
kSession = createSession(sessionNotActive, lessLoadedKms);
} }
} finally { } finally {
KmsManager.selectAndRemoveKmsLock.unlock(); KmsManager.selectAndRemoveKmsLock.unlock();
@ -992,8 +979,8 @@ public class KurentoSessionManager extends SessionManager {
@Override @Override
/* Protected by Session.closingLock.readLock */ /* Protected by Session.closingLock.readLock */
public Participant publishIpcam(Session session, MediaOptions mediaOptions, ConnectionProperties connectionProperties) public Participant publishIpcam(Session session, MediaOptions mediaOptions,
throws Exception { ConnectionProperties connectionProperties) throws Exception {
final String sessionId = session.getSessionId(); final String sessionId = session.getSessionId();
final KurentoMediaOptions kMediaOptions = (KurentoMediaOptions) mediaOptions; final KurentoMediaOptions kMediaOptions = (KurentoMediaOptions) mediaOptions;
@ -1119,7 +1106,7 @@ public class KurentoSessionManager extends SessionManager {
sessionEventsHandler.onVideoData(participant, transactionId, height, width, videoActive, audioActive); sessionEventsHandler.onVideoData(participant, transactionId, height, width, videoActive, audioActive);
} }
private void applyFilterInPublisher(KurentoParticipant kParticipant, KurentoFilter filter) protected void applyFilterInPublisher(KurentoParticipant kParticipant, KurentoFilter filter)
throws OpenViduException { throws OpenViduException {
GenericMediaElement.Builder builder = new GenericMediaElement.Builder(kParticipant.getPipeline(), GenericMediaElement.Builder builder = new GenericMediaElement.Builder(kParticipant.getPipeline(),
filter.getType()); filter.getType());
@ -1131,13 +1118,13 @@ public class KurentoSessionManager extends SessionManager {
kParticipant.getPublisher().getMediaOptions().setFilter(filter); kParticipant.getPublisher().getMediaOptions().setFilter(filter);
} }
private void removeFilterInPublisher(KurentoParticipant kParticipant) { protected void removeFilterInPublisher(KurentoParticipant kParticipant) {
kParticipant.getPublisher().cleanAllFilterListeners(); kParticipant.getPublisher().cleanAllFilterListeners();
kParticipant.getPublisher().revert(kParticipant.getPublisher().getFilter()); kParticipant.getPublisher().revert(kParticipant.getPublisher().getFilter());
kParticipant.getPublisher().getMediaOptions().setFilter(null); kParticipant.getPublisher().getMediaOptions().setFilter(null);
} }
private KurentoFilter execFilterMethodInPublisher(KurentoParticipant kParticipant, String method, protected KurentoFilter execFilterMethodInPublisher(KurentoParticipant kParticipant, String method,
JsonObject params) { JsonObject params) {
kParticipant.getPublisher().execMethod(method, params); kParticipant.getPublisher().execMethod(method, params);
KurentoFilter filter = kParticipant.getPublisher().getMediaOptions().getFilter(); KurentoFilter filter = kParticipant.getPublisher().getMediaOptions().getFilter();
@ -1146,7 +1133,7 @@ public class KurentoSessionManager extends SessionManager {
return updatedFilter; return updatedFilter;
} }
private void addFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) protected void addFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType)
throws OpenViduException { throws OpenViduException {
PublisherEndpoint pub = kParticipant.getPublisher(); PublisherEndpoint pub = kParticipant.getPublisher();
if (!pub.isListenerAddedToFilterEvent(eventType)) { if (!pub.isListenerAddedToFilterEvent(eventType)) {
@ -1170,7 +1157,7 @@ public class KurentoSessionManager extends SessionManager {
} }
} }
private void removeFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) { protected void removeFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) {
PublisherEndpoint pub = kParticipant.getPublisher(); PublisherEndpoint pub = kParticipant.getPublisher();
if (pub.isListenerAddedToFilterEvent(eventType)) { if (pub.isListenerAddedToFilterEvent(eventType)) {
GenericMediaElement filter = kParticipant.getPublisher().getFilter(); GenericMediaElement filter = kParticipant.getPublisher().getFilter();
@ -1178,4 +1165,19 @@ public class KurentoSessionManager extends SessionManager {
} }
} }
protected Kms selectMediaNode(Session session) throws OpenViduException {
Kms lessLoadedKms = null;
try {
lessLoadedKms = this.kmsManager.getLessLoadedConnectedAndRunningKms();
} catch (NoSuchElementException e) {
// Restore session not active
this.cleanCollections(session.getSessionId());
this.storeSessionNotActive(session);
throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
"There is no available Media Node where to initialize session '" + session + "'");
}
log.info("KMS less loaded is {} with a load of {}", lessLoadedKms.getUri(), lessLoadedKms.getLoad());
return lessLoadedKms;
}
} }

View File

@ -99,80 +99,19 @@ public class SessionRestController {
log.info("REST API: POST {}/sessions {}", RequestMappings.API, params != null ? params.toString() : "{}"); log.info("REST API: POST {}/sessions {}", RequestMappings.API, params != null ? params.toString() : "{}");
SessionProperties.Builder builder = new SessionProperties.Builder(); SessionProperties sessionProperties;
String customSessionId = null; try {
sessionProperties = getSessionPropertiesFromParams(params).build();
if (params != null) { } catch (Exception e) {
return this.generateErrorResponse(e.getMessage(), "/sessions", HttpStatus.BAD_REQUEST);
String mediaModeString;
String recordingModeString;
String defaultOutputModeString;
String defaultRecordingLayoutString;
String defaultCustomLayout;
try {
mediaModeString = (String) params.get("mediaMode");
recordingModeString = (String) params.get("recordingMode");
defaultOutputModeString = (String) params.get("defaultOutputMode");
defaultRecordingLayoutString = (String) params.get("defaultRecordingLayout");
defaultCustomLayout = (String) params.get("defaultCustomLayout");
customSessionId = (String) params.get("customSessionId");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", "/sessions", HttpStatus.BAD_REQUEST);
}
try {
// Safe parameter retrieval. Default values if not defined
if (recordingModeString != null) {
RecordingMode recordingMode = RecordingMode.valueOf(recordingModeString);
builder = builder.recordingMode(recordingMode);
} else {
builder = builder.recordingMode(RecordingMode.MANUAL);
}
if (defaultOutputModeString != null) {
OutputMode defaultOutputMode = OutputMode.valueOf(defaultOutputModeString);
builder = builder.defaultOutputMode(defaultOutputMode);
} else {
builder.defaultOutputMode(OutputMode.COMPOSED);
}
if (defaultRecordingLayoutString != null) {
RecordingLayout defaultRecordingLayout = RecordingLayout.valueOf(defaultRecordingLayoutString);
builder = builder.defaultRecordingLayout(defaultRecordingLayout);
} else {
builder.defaultRecordingLayout(RecordingLayout.BEST_FIT);
}
if (mediaModeString != null) {
MediaMode mediaMode = MediaMode.valueOf(mediaModeString);
builder = builder.mediaMode(mediaMode);
} else {
builder = builder.mediaMode(MediaMode.ROUTED);
}
if (customSessionId != null && !customSessionId.isEmpty()) {
if (!sessionManager.formatChecker.isValidCustomSessionId(customSessionId)) {
return this.generateErrorResponse(
"Parameter 'customSessionId' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]",
"/sessions", HttpStatus.BAD_REQUEST);
}
builder = builder.customSessionId(customSessionId);
}
builder = builder.defaultCustomLayout((defaultCustomLayout != null) ? defaultCustomLayout : "");
} catch (IllegalArgumentException e) {
return this.generateErrorResponse("RecordingMode " + params.get("recordingMode") + " | "
+ "Default OutputMode " + params.get("defaultOutputMode") + " | " + "Default RecordingLayout "
+ params.get("defaultRecordingLayout") + " | " + "MediaMode " + params.get("mediaMode")
+ ". Some parameter is not defined", "/sessions", HttpStatus.BAD_REQUEST);
}
} }
SessionProperties sessionProperties = builder.build();
String sessionId; String sessionId;
if (customSessionId != null && !customSessionId.isEmpty()) { if (sessionProperties.customSessionId() != null && !sessionProperties.customSessionId().isEmpty()) {
if (sessionManager.getSessionWithNotActive(customSessionId) != null) { if (sessionManager.getSessionWithNotActive(sessionProperties.customSessionId()) != null) {
return new ResponseEntity<>(HttpStatus.CONFLICT); return new ResponseEntity<>(HttpStatus.CONFLICT);
} }
sessionId = customSessionId; sessionId = sessionProperties.customSessionId();
} else { } else {
sessionId = IdentifierPrefixes.SESSION_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() sessionId = IdentifierPrefixes.SESSION_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
+ RandomStringUtils.randomAlphanumeric(9); + RandomStringUtils.randomAlphanumeric(9);
@ -846,17 +785,76 @@ public class SessionRestController {
} }
} }
protected Token getTokenFromConnectionId(String connectionId, Iterator<Entry<String, Token>> iterator) { protected SessionProperties.Builder getSessionPropertiesFromParams(Map<?, ?> params) throws Exception {
boolean found = false;
Token token = null; SessionProperties.Builder builder = new SessionProperties.Builder();
while (iterator.hasNext() && !found) { String customSessionId = null;
Token tAux = iterator.next().getValue();
found = tAux.getConnectionId().equals(connectionId); if (params != null) {
if (found) {
token = tAux; String mediaModeString;
String recordingModeString;
String defaultOutputModeString;
String defaultRecordingLayoutString;
String defaultCustomLayout;
try {
mediaModeString = (String) params.get("mediaMode");
recordingModeString = (String) params.get("recordingMode");
defaultOutputModeString = (String) params.get("defaultOutputMode");
defaultRecordingLayoutString = (String) params.get("defaultRecordingLayout");
defaultCustomLayout = (String) params.get("defaultCustomLayout");
customSessionId = (String) params.get("customSessionId");
} catch (ClassCastException e) {
throw new Exception("Type error in some parameter: " + e.getMessage());
}
try {
// Safe parameter retrieval. Default values if not defined
if (recordingModeString != null) {
RecordingMode recordingMode = RecordingMode.valueOf(recordingModeString);
builder = builder.recordingMode(recordingMode);
} else {
builder = builder.recordingMode(RecordingMode.MANUAL);
}
if (defaultOutputModeString != null) {
OutputMode defaultOutputMode = OutputMode.valueOf(defaultOutputModeString);
builder = builder.defaultOutputMode(defaultOutputMode);
} else {
builder.defaultOutputMode(OutputMode.COMPOSED);
}
if (defaultRecordingLayoutString != null) {
RecordingLayout defaultRecordingLayout = RecordingLayout.valueOf(defaultRecordingLayoutString);
builder = builder.defaultRecordingLayout(defaultRecordingLayout);
} else {
builder.defaultRecordingLayout(RecordingLayout.BEST_FIT);
}
if (defaultCustomLayout != null) {
builder.defaultCustomLayout(defaultCustomLayout);
} else {
builder.defaultCustomLayout("");
}
if (mediaModeString != null) {
MediaMode mediaMode = MediaMode.valueOf(mediaModeString);
builder = builder.mediaMode(mediaMode);
} else {
builder = builder.mediaMode(MediaMode.ROUTED);
}
if (customSessionId != null && !customSessionId.isEmpty()) {
if (!sessionManager.formatChecker.isValidCustomSessionId(customSessionId)) {
throw new Exception(
"Parameter 'customSessionId' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]");
}
builder = builder.customSessionId(customSessionId);
}
} catch (IllegalArgumentException e) {
throw new Exception("RecordingMode " + params.get("recordingMode") + " | " + "Default OutputMode "
+ params.get("defaultOutputMode") + " | " + "Default RecordingLayout "
+ params.get("defaultRecordingLayout") + " | " + "MediaMode " + params.get("mediaMode")
+ ". Some parameter is not defined");
} }
} }
return token; return builder;
} }
protected ConnectionProperties.Builder getConnectionPropertiesFromParams(Map<?, ?> params) throws Exception { protected ConnectionProperties.Builder getConnectionPropertiesFromParams(Map<?, ?> params) throws Exception {
@ -975,6 +973,19 @@ public class SessionRestController {
return builder; return builder;
} }
protected Token getTokenFromConnectionId(String connectionId, Iterator<Entry<String, Token>> iterator) {
boolean found = false;
Token token = null;
while (iterator.hasNext() && !found) {
Token tAux = iterator.next().getValue();
found = tAux.getConnectionId().equals(connectionId);
if (found) {
token = tAux;
}
}
return token;
}
protected ResponseEntity<String> generateErrorResponse(String errorMessage, String path, HttpStatus status) { protected ResponseEntity<String> generateErrorResponse(String errorMessage, String path, HttpStatus status) {
JsonObject responseJson = new JsonObject(); JsonObject responseJson = new JsonObject();
responseJson.addProperty("timestamp", System.currentTimeMillis()); responseJson.addProperty("timestamp", System.currentTimeMillis());