Permalink
Browse files

XX-9415 - openacd disaster recovery

- new "resync" command in server's services list
- resync command will:
  - stop service
  - run service.onResync()
  - start service
- openacd resync will:
  - get all openacd objects from db
  - create ADD or CONFIGURE commands
  - send the commands to Mongo
- registered resync command in supervisor
- resync command will just delete the Mnesia DB
- on openacd start, Mnesia will be rebuilt and commands will be replicated from Mongo by plugin
- enhanced plugin to take into account recipes on queue creation
  • Loading branch information...
1 parent 3ff042f commit a450b8855f376b76d9783ac0b2af7e36fdf60c28 ciuc committed Nov 15, 2011
Showing with 372 additions and 8 deletions.
  1. +2 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/admin/commserver/ProcessManagerApi.java
  2. +1 −1 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/admin/commserver/SipxProcessContext.java
  3. +20 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/admin/commserver/SipxProcessContextImpl.java
  4. +5 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/FreeswitchMediaCommand.java
  5. +5 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdAgentConfigCommand.java
  6. +4 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdConfigObject.java
  7. +25 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdConfigObjectProvider.java
  8. +1 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdContext.java
  9. +17 −1 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdContextImpl.java
  10. +5 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdLogConfigCommand.java
  11. +6 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdProvisioningContext.java
  12. +28 −1 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/OpenAcdProvisioningContextImpl.java
  13. +3 −1 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/openacd/openacd.beans.xml
  14. +27 −1 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/service/SipxOpenAcdService.java
  15. +4 −0 sipXconfig/neoconf/src/org/sipfoundry/sipxconfig/service/SipxService.java
  16. +8 −1 sipXconfig/neoconf/test/org/sipfoundry/sipxconfig/openacd/OpenAcdContextTestIntegration.java
  17. +61 −0 ...fig/neoconf/test/org/sipfoundry/sipxconfig/openacd/OpenAcdProvisioningContextTestIntegration.java
  18. +3 −0 sipXconfig/web/context/WEB-INF/admin/commserver/ServicesTable.html
  19. +1 −0 sipXconfig/web/context/WEB-INF/admin/commserver/ServicesTable.properties
  20. +4 −0 sipXconfig/web/src/org/sipfoundry/sipxconfig/site/admin/commserver/ServicesTable.java
  21. +10 −0 sipXopenacd/bin/sipxopenacd.in
  22. +5 −0 sipXopenacd/etc/sipxopenacd-process.xml.in
  23. +6 −1 sipXopenacd/src/erlang/sipxplugin_poller.erl
  24. +39 −0 sipXsupervisor/src/ProcMgmtRpc.cpp
  25. +41 −1 sipXsupervisor/src/ProcMgmtRpc.h
  26. +26 −0 sipXsupervisor/src/SipxProcess.cpp
  27. +5 −0 sipXsupervisor/src/SipxProcess.h
  28. +8 −0 sipXsupervisor/src/SipxProcessFsm.cpp
  29. +1 −0 sipXsupervisor/src/SipxProcessFsm.h
  30. +1 −0 sipXsupervisor/src/SipxRpc.cpp
@@ -23,5 +23,7 @@
Map<String, String> restart(String host, String[] processes, boolean block);
+ Map<String, String> resync(String host, String[] processes, boolean block);
+
boolean setConfigVersion(String host, String service, String version);
}
@@ -17,7 +17,7 @@
public interface SipxProcessContext {
enum Command {
- START, STOP, RESTART, RELOAD;
+ START, STOP, RESTART, RELOAD, RESYNC;
}
/**
@@ -286,6 +286,26 @@ public void manageServices(Location location, Collection< ? extends SipxService>
}
break;
+ case RESYNC:
+ api.stop(getHost(), processNames, true);
+ logProcessStateChange(processNames, location, PROCESS_STATE_CHANGE.STOPPED);
+
+ for (SipxService process : processes) {
+ process.onStop();
+ }
+
+ api.resync(getHost(), processNames, false);
+ for (SipxService process : processes) {
+ process.onResync();
+ }
+
+ api.start(getHost(), processNames, true);
+ logProcessStateChange(processNames, location, PROCESS_STATE_CHANGE.STARTED);
+ for (SipxService process : processes) {
+ process.onStart();
+ }
+
+ break;
default:
break;
}
@@ -68,4 +68,9 @@ public String getDialString() {
public String getType() {
return "freeswitch_media_manager";
}
+
+ @Override
+ public boolean isConfigCommand() {
+ return true;
+ }
}
@@ -46,4 +46,9 @@ public void setListenerEnabled(boolean enabled) {
public String getType() {
return "agent_configuration";
}
+
+ @Override
+ public boolean isConfigCommand() {
+ return true;
+ }
}
@@ -26,4 +26,8 @@
public abstract List<String> getProperties();
+ public boolean isConfigCommand() {
+ return false;
+ }
+
}
@@ -0,0 +1,25 @@
+/**
+ *
+ *
+ * Copyright (c) 2010 / 2011 eZuce, Inc. All rights reserved.
+ * Contributed to SIPfoundry under a Contributor Agreement
+ *
+ * This software is free software; you can redistribute it and/or modify it under
+ * the terms of the Affero General Public License (AGPL) as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+ * details.
+ */
+package org.sipfoundry.sipxconfig.openacd;
+
+import java.util.List;
+
+public interface OpenAcdConfigObjectProvider {
+
+ public List<OpenAcdConfigObject> getConfigObjects();
+
+}
@@ -136,4 +136,5 @@
public OpenAcdLine newOpenAcdLine();
public OpenAcdCommand newOpenAcdCommand();
public void replicateConfig();
+ public void resync();
}
@@ -47,7 +47,8 @@
import org.sipfoundry.sipxconfig.service.SipxServiceManager;
import org.springframework.dao.support.DataAccessUtils;
-public abstract class OpenAcdContextImpl extends SipxHibernateDaoSupport implements OpenAcdContext, DaoEventListener {
+public abstract class OpenAcdContextImpl extends SipxHibernateDaoSupport implements OpenAcdContext,
+ DaoEventListener, OpenAcdConfigObjectProvider {
private static final String VALUE = "value";
private static final String OPEN_ACD_EXTENSION_WITH_NAME = "openAcdExtensionWithName";
@@ -332,6 +333,10 @@ public void addAgentsToGroup(OpenAcdAgentGroup agentGroup, Collection<OpenAcdAge
return getHibernateTemplate().loadAll(OpenAcdAgent.class);
}
+ public List<OpenAcdRecipeAction> getRecipeActions() {
+ return getHibernateTemplate().loadAll(OpenAcdRecipeAction.class);
+ }
+
public OpenAcdAgent getAgentById(Integer agentId) {
return getHibernateTemplate().load(OpenAcdAgent.class, agentId);
}
@@ -959,6 +964,17 @@ public void onDelete(Object entity) {
}
}
+ public List<OpenAcdConfigObject> getConfigObjects() {
+ List<OpenAcdConfigObject> objects = new ArrayList<OpenAcdConfigObject>();
+ objects.addAll(getSkills());
+ objects.addAll(getClients());
+ objects.addAll(getAgentGroups());
+ objects.addAll(getAgents());
+ objects.addAll(getQueueGroups());
+ objects.addAll(getQueues());
+ return objects;
+ }
+
public void setSipxServiceManager(SipxServiceManager manager) {
m_serviceManager = manager;
}
@@ -49,4 +49,9 @@ public String getLogDir() {
public String getType() {
return "log_configuration";
}
+
+ @Override
+ public boolean isConfigCommand() {
+ return true;
+ }
}
@@ -18,6 +18,8 @@
import java.util.List;
+import org.sipfoundry.commons.mongo.MongoDbTemplate;
+
public interface OpenAcdProvisioningContext {
void addObjects(List< ? extends OpenAcdConfigObject> objects);
@@ -27,4 +29,8 @@
void updateObjects(List< ? extends OpenAcdConfigObject> objects);
void configure(List< ? extends OpenAcdConfigObject> objects);
+
+ void resync();
+
+ public MongoDbTemplate getDb();
}
@@ -21,12 +21,17 @@
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import org.sipfoundry.commons.mongo.MongoDbTemplate;
import org.sipfoundry.sipxconfig.common.UserChangeEvent;
import org.sipfoundry.sipxconfig.common.UserException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
@@ -36,7 +41,8 @@
import com.mongodb.DBCollection;
import com.mongodb.WriteResult;
-public class OpenAcdProvisioningContextImpl implements OpenAcdProvisioningContext, ApplicationListener {
+public class OpenAcdProvisioningContextImpl implements OpenAcdProvisioningContext, ApplicationListener,
+ BeanFactoryAware {
enum Command {
ADD {
public String toString() {
@@ -64,6 +70,7 @@ public String toString() {
}
private OpenAcdContext m_openAcdContext;
+ private ListableBeanFactory m_beanFactory;
private MongoDbTemplate m_db;
public void onApplicationEvent(ApplicationEvent event) {
@@ -156,6 +163,25 @@ private static String getDataValue(Object bean, String name) {
}
}
+ public void resync() {
+ Map<String, OpenAcdConfigObjectProvider> beanMap = m_beanFactory
+ .getBeansOfType(OpenAcdConfigObjectProvider.class);
+ for (OpenAcdConfigObjectProvider bean : beanMap.values()) {
+ for (OpenAcdConfigObject configObj : bean.getConfigObjects()) {
+ if (!configObj.isConfigCommand()) {
+ addObjects(Collections.singletonList(configObj));
+ } else {
+ configure(Collections.singletonList(configObj));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) {
+ m_beanFactory = (ListableBeanFactory) beanFactory;
+ }
+
@Required
public void setOpenAcdContext(OpenAcdContext openAcdContext) {
m_openAcdContext = openAcdContext;
@@ -168,4 +194,5 @@ public MongoDbTemplate getDb() {
public void setDb(MongoDbTemplate db) {
m_db = db;
}
+
}
@@ -7,11 +7,13 @@
<bean id="openAcdCommand" class="org.sipfoundry.sipxconfig.openacd.OpenAcdCommand" scope="prototype">
</bean>
+ <bean id="freeswitchMediaCommand" class="org.sipfoundry.sipxconfig.openacd.FreeswitchMediaCommand" scope="prototype">
+ </bean>
+
<bean id="openAcdContextImpl" class="org.sipfoundry.sipxconfig.openacd.OpenAcdContextImpl">
<lookup-method name="newOpenAcdLine" bean="openAcdLine"/>
<lookup-method name="newOpenAcdCommand" bean="openAcdCommand"/>
<property name="sessionFactory" ref="sessionFactory" />
- <property name="sipxServiceManager" ref="sipxServiceManager" />
<property name="aliasManager" ref="aliasManager" />
<property name="provisioningContext" ref="openAcdProvisioningContext" />
<property name="locationsManager" ref="locationsManager" />
@@ -16,16 +16,20 @@
*/
package org.sipfoundry.sipxconfig.service;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import org.sipfoundry.sipxconfig.admin.commserver.Location;
import org.sipfoundry.sipxconfig.openacd.FreeswitchMediaCommand;
import org.sipfoundry.sipxconfig.openacd.OpenAcdAgentConfigCommand;
+import org.sipfoundry.sipxconfig.openacd.OpenAcdConfigObject;
+import org.sipfoundry.sipxconfig.openacd.OpenAcdConfigObjectProvider;
import org.sipfoundry.sipxconfig.openacd.OpenAcdLogConfigCommand;
import org.sipfoundry.sipxconfig.openacd.OpenAcdProvisioningContext;
import org.sipfoundry.sipxconfig.setting.SettingEntry;
-public class SipxOpenAcdService extends SipxService implements LoggingEntity {
+public class SipxOpenAcdService extends SipxService implements LoggingEntity, OpenAcdConfigObjectProvider {
public static final String BEAN_ID = "sipxOpenAcdService";
public static final String FS_ENABLED = "freeswitch_media_manager/FREESWITCH_ENABLED";
public static final String C_NODE = "freeswitch_media_manager/C_NODE";
@@ -101,6 +105,11 @@ public void onConfigChange() {
}
@Override
+ public void onResync() {
+ m_provisioningContext.resync();
+ }
+
+ @Override
public void afterReplication(Location location) {
m_provisioningContext.configure(Collections.singletonList(new OpenAcdLogConfigCommand(getOpenAcdLogLevel(),
m_logDirectory)));
@@ -138,4 +147,21 @@ public String getDialString() {
m_domainName);
}
}
+
+ @Override
+ public List<OpenAcdConfigObject> getConfigObjects() {
+ Boolean enabled = (Boolean) getSettingTypedValue(FS_ENABLED);
+ String cNode = getSettingValue(C_NODE);
+ String dialString = getSettingValue(DIAL_STRING);
+ List<OpenAcdConfigObject> objects = new ArrayList<OpenAcdConfigObject>();
+ objects.add(new FreeswitchMediaCommand(enabled, cNode,
+ dialString));
+
+ Boolean dialPlanListener = (Boolean) getSettingTypedValue(DIALPLAN_LISTENER);
+ objects.add(new OpenAcdAgentConfigCommand(dialPlanListener));
+
+ objects.add(new OpenAcdLogConfigCommand(getOpenAcdLogLevel(),
+ m_logDirectory));
+ return objects;
+ }
}
@@ -443,6 +443,10 @@ public void onStop() {
// intentionally empty
}
+ public void onResync() {
+ // intentionally empty
+ }
+
public void onRestart() {
// intentionally empty
}
@@ -43,6 +43,8 @@
import org.sipfoundry.sipxconfig.service.SipxFreeswitchService;
import org.sipfoundry.sipxconfig.service.SipxServiceManager;
import org.sipfoundry.sipxconfig.service.freeswitch.DefaultContextConfigurationTest;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.dao.support.DataAccessUtils;
public class OpenAcdContextTestIntegration extends IntegrationTestCase {
@@ -389,6 +391,7 @@ public void testOpenAcdAgentGroupCrud() throws Exception {
public void testOpenAcdAgentCrud() throws Exception {
loadDataSet("common/SampleUsersSeed.xml");
loadDataSetXml("admin/commserver/seedLocations.xml");
+ loadDataSetXml("domain/DomainSeed.xml");
User charlie = m_coreContext.loadUser(1003);
OpenAcdAgentGroup group = new OpenAcdAgentGroup();
@@ -1000,6 +1003,11 @@ public void testGroupedSkills() throws Exception {
assertTrue(queueSkills.contains(all));
}
+ public void testRetrieveOpenacdConfigObject() {
+ List<OpenAcdConfigObject> objs = m_openAcdContextImpl.getConfigObjects();
+ assertTrue(!objs.isEmpty());
+ }
+
public void setOpenAcdContextImpl(OpenAcdContextImpl openAcdContext) {
m_openAcdContextImpl = openAcdContext;
OpenAcdProvisioningContext provisioning = EasyMock.createNiceMock(OpenAcdProvisioningContext.class);
@@ -1024,5 +1032,4 @@ public int getFreeswitchSipPort() {
return 50;
}
}
-
}
Oops, something went wrong.

0 comments on commit a450b88

Please sign in to comment.