2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.policy.brmsInterface;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.Writer;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.security.GeneralSecurityException;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.List;
38 import java.util.Properties;
40 import java.util.UUID;
42 import org.apache.commons.io.FileUtils;
43 import org.apache.commons.lang.StringEscapeUtils;
44 import org.apache.maven.model.Dependency;
45 import org.apache.maven.model.DeploymentRepository;
46 import org.apache.maven.model.DistributionManagement;
47 import org.apache.maven.model.Exclusion;
48 import org.apache.maven.model.Model;
49 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
50 import org.apache.maven.shared.invoker.DefaultInvocationRequest;
51 import org.apache.maven.shared.invoker.DefaultInvoker;
52 import org.apache.maven.shared.invoker.InvocationRequest;
53 import org.apache.maven.shared.invoker.InvocationResult;
54 import org.apache.maven.shared.invoker.Invoker;
55 import org.codehaus.plexus.util.IOUtil;
56 import org.codehaus.plexus.util.WriterFactory;
57 import org.openecomp.policy.utils.BackUpHandler;
58 import org.openecomp.policy.utils.BackUpMonitor;
59 import org.openecomp.policy.utils.PolicyUtils;
60 import org.sonatype.nexus.client.NexusClient;
61 import org.sonatype.nexus.client.NexusClientException;
62 import org.sonatype.nexus.client.NexusConnectionException;
63 import org.sonatype.nexus.client.rest.NexusRestClient;
64 import org.sonatype.nexus.rest.model.NexusArtifact;
66 //import org.apache.log4j.Logger;
67 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
68 import org.openecomp.policy.common.logging.flexlogger.Logger;
69 import org.openecomp.policy.common.im.AdministrativeStateException;
70 import org.openecomp.policy.common.im.IntegrityMonitor;
71 import com.att.nsa.cambria.client.CambriaBatchingPublisher;
72 import com.att.nsa.cambria.client.CambriaClientBuilders;
73 import com.att.nsa.cambria.client.CambriaClientBuilders.PublisherBuilder;
74 import com.fasterxml.jackson.core.JsonProcessingException;
76 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
80 * BRMSPush: Application responsible to push policies to the BRMS PDP Policy Repository (PR).
81 * Mavenize and push policy to PR
85 @SuppressWarnings("deprecation")
86 public class BRMSPush {
89 private static final Logger logger = FlexLogger.getLogger(BRMSPush.class.getName());
90 private static final String projectsLocation = "RuleProjects";
91 private static final String goals[] = {"clean", "deploy"};
93 private static Map<String, String> modifiedGroups = new HashMap<String, String>();
94 private static IntegrityMonitor im;
95 private static BackUpMonitor bm;
96 private static String resourceName = null;
97 private List<String> groupIDs = null;
98 private List<String> artifactIDs= null; //"test"
99 private Map<String,Integer> names= null; // "Rules"
100 private String defaultName = null;
101 private String repID = null; // "ecomp_policy-3rd-party"
102 private String repName = null; // "d2policy-snapshots"
103 private String repURL= null;
104 private String repUserName = null;
105 private ArrayList<ControllerPOJO> controllers;
106 private HashMap<String,String> versions = new HashMap<String, String>();
107 private String repPassword = null;
108 private String policyKeyID = null;
109 private List<File> matchingList = null;
110 private boolean createFlag = false;
111 private String uebList = null;
112 private String pubTopic = null;
113 private PublisherBuilder pubBuilder = null;
114 private Long uebDelay = Long.parseLong("5000");
115 private static String brmsdependencyversion = null;
117 public BRMSPush(String propertiesFile, BackUpHandler handler) throws Exception{
118 Properties config = new Properties();
119 Path file = Paths.get(propertiesFile);
120 if(Files.notExists(file)){
121 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE+"Config File doesn't Exist in the specified Path " + file.toString());
122 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE+"Config File doesn't Exist in the specified Path " + file.toString());
124 if(file.toString().endsWith(".properties")){
126 in = new FileInputStream(file.toFile());
128 // Grab the Properties.
129 defaultName = config.getProperty("defaultName").replaceAll(" ", "");
130 if(defaultName==null){
131 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "defaultName property is missing from the property file ");
132 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "defaultName property is missing from the property file");
134 repID = config.getProperty("repositoryID").replaceAll(" ", "");
136 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "repositoryID property is missing from the property file ");
137 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "repositoryID property is missing from the property file ");
139 repName = config.getProperty("repositoryName").replaceAll(" ", "");
141 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "repositoryName property is missing from the property file ");
142 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "repositoryName property is missing from the property file ");
144 repURL = config.getProperty("repositoryURL").replaceAll(" ", "");
146 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "repositoryURL property is missing from the property file ");
147 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "repositoryURL property is missing from the property file ");
149 repUserName = config.getProperty("repositoryUsername").trim();
150 repPassword = config.getProperty("repositoryPassword").trim();
151 if(repUserName==null || repPassword==null){
152 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "repostoryUserName and respositoryPassword properties are required.");
153 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "repostoryUserName and respositoryPassword properties are required.");
155 policyKeyID = config.getProperty("policyKeyID").replaceAll(" ", "");
156 if(policyKeyID==null){
157 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "policyKeyID property is missing from the property file ");
158 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "policyKeyID property is missing from the property file ");
160 brmsdependencyversion = config.getProperty("brms.dependency.version").replaceAll(" ", "");
161 if(brmsdependencyversion==null){
162 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "brmsdependencyversion property is missing from the property file ");
163 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "brmsdependencyversion property is missing from the property file ");
166 logger.info("Trying to set up IntegrityMonitor");
168 logger.info("Trying to set up IntegrityMonitor");
169 resourceName = config.getProperty("RESOURCE_NAME").replaceAll(" ", "");;
170 if(resourceName==null){
171 logger.warn("RESOURCE_NAME is missing setting default value. ");
172 resourceName = "brmsgw_pdp01";
174 im = IntegrityMonitor.getInstance(resourceName, config);
175 } catch (Exception e) {
176 logger.error("Error starting Integerity Monitor: " + e);
178 logger.info("Trying to set up BackUpMonitor");
180 bm = BackUpMonitor.getInstance(BackUpMonitor.ResourceNode.BRMS.toString(), resourceName, config, handler);
181 } catch (Exception e) {
182 logger.error("Error starting BackUpMonitor: " + e);
184 // Setting up the Publisher for UEB
185 uebList = config.getProperty("UEB_URL").trim();
186 pubTopic = config.getProperty("UEB_TOPIC").trim();
187 String apiKey = config.getProperty("UEB_API_KEY");
188 String apiSecret = config.getProperty("UEB_API_SECRET");
189 if(uebList==null || pubTopic==null){
190 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "UEB properties are missing from the property file ");
191 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "UEB properties are missing from the property file ");
193 pubBuilder = new CambriaClientBuilders.PublisherBuilder();
194 pubBuilder.usingHosts(uebList)
196 if(apiKey!=null && !apiKey.isEmpty() &&
197 apiSecret!=null && !apiSecret.isEmpty()) {
198 apiKey= apiKey.trim();
199 apiSecret = apiSecret.trim();
200 pubBuilder.authenticatedBy(apiKey, apiSecret);
202 String uDelay = config.getProperty("UEB_DELAY");
203 if(uDelay!=null && !uDelay.isEmpty()){
204 uDelay = uDelay.trim();
206 uebDelay = Long.parseLong(uDelay);
207 }catch (NumberFormatException e){
208 logger.error("UEB_DELAY not a long format number" + e);
216 * Will Initialize the variables required for BRMSPush.
218 public void initiate() {
219 modifiedGroups = new HashMap<String, String>();
220 controllers = new ArrayList<ControllerPOJO>();
222 bm.updateNotification();
223 } catch (Exception e) {
224 logger.error("Error while updating Notification: " + e.getMessage());
229 * Will Add rules to projects. Creates necessary folders if required.
231 public void addRule(String name, String rule, Map<String, String> responseAttributes) {
232 // 1 check the response Attributes and determine if this belongs to any projects.
233 // 2 if not create folder // new File("Projects\\test").mkdirs();
236 // 5 store the groups that have been updated.
237 String kSessionName=null;
238 String selectedName = null;
240 if(!responseAttributes.isEmpty()){
241 // Pick selected Value
242 for(String key: responseAttributes.keySet()){
243 if(key.equals(policyKeyID)){
244 selectedName = responseAttributes.get(key);
246 //kmodule configurations
247 else if (key.equals("kSessionName")){
248 kSessionName=responseAttributes.get(key);
253 // If no Match then pick Default.
254 if(selectedName==null){
255 selectedName = defaultName;
257 if(names.containsKey(selectedName)){
258 //If the key is not got as parameters set by the user, setting the default value for kSessionName as closedLoop
259 if(kSessionName==null){
260 if(selectedName==defaultName){
261 kSessionName="closedloop";
263 kSessionName= selectedName;
266 // create directories if missing.
267 createProject(projectsLocation+File.separator+getArtifactID(selectedName)+File.separator+"src"+File.separator+"main"+File.separator+"resources",kSessionName);
268 copyDataToFile(projectsLocation+File.separator+getArtifactID(selectedName)+File.separator+"src"+File.separator+"main"+File.separator+"resources"+File.separator+"rules"+File.separator+name+".drl", rule);
269 addModifiedGroup(selectedName, "update"); // Will check for Create Later after generating the Pom.
274 * Will Push policies to the PolicyRepo.
276 * @param notificationType <String> type of notification Type.
278 public void pushRules(){
279 // Check how many groups have been updated.
280 // Invoke their Maven process.
282 im.startTransaction();
283 } catch (AdministrativeStateException e) {
284 logger.error("Error while starting Transaction " + e);
285 } catch (Exception e) {
286 logger.error("Error while starting Transaction " + e);
288 if(!modifiedGroups.isEmpty()){
289 Boolean flag = false;
290 for(String group: modifiedGroups.keySet()){
292 InvocationRequest request = new DefaultInvocationRequest();
294 request.setPomFile(new File(projectsLocation+File.separator+getArtifactID(group)+File.separator+"pom.xml"));
295 request.setGoals(Arrays.asList(goals));
296 Invoker invoker = new DefaultInvoker();
297 InvocationResult result = invoker.execute(request);
298 if(result.getExecutionException()!=null){
299 logger.error(result.getExecutionException());
300 }else if(result.getExitCode()!=0){
301 logger.error("Maven Invocation failure..!");
303 if(result.getExitCode()==0){
304 logger.info("Build Completed..!");
306 addNotification(group, "create");
308 addNotification(group, modifiedGroups.get(group));
313 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+"Maven Invocation issue for "+getArtifactID(group) + e.getMessage());
317 sendNotification(controllers);
324 * Removes a Rule from Rule Projects.
326 public void removeRule(String name){
327 File file = new File(projectsLocation);
328 matchingList = new ArrayList<File>();
329 searchFile(file,name);
330 for(File matchingFile: matchingList){
331 if(matchingFile.delete()){
332 logger.info("Deleted File.. " + matchingFile.getAbsolutePath());
333 String groupName = getName(matchingFile.toString());
334 String ruleFolder= projectsLocation+File.separator+getArtifactID(groupName)+File.separator+"src"+File.separator+"main"+File.separator+"resources"+File.separator+"rules";
335 if(new File(ruleFolder).listFiles().length==0){
336 removedRuleModifiedGroup(groupName);
338 addModifiedGroup(groupName, "update"); // This is an update in terms of PDPD.
344 private void addModifiedGroup(String controllerName, String operation) {
345 modifiedGroups.put(controllerName, operation);
348 private void addNotification(String controllerName, String operation) {
349 ControllerPOJO controllerPOJO = new ControllerPOJO();
350 controllerPOJO.setName(controllerName);
351 controllerPOJO.setOperation(operation);
352 HashMap<String, String> drools = new HashMap<String, String>();
353 drools.put("groupId", getGroupID(controllerName));
354 drools.put("artifactId", getArtifactID(controllerName));
355 drools.put("version", versions.get(controllerName));
356 controllerPOJO.setDrools(drools);
357 controllers.add(controllerPOJO);
359 logger.debug("Notification added: "
360 + PolicyUtils.objectToJsonString(controllerPOJO));
361 } catch (JsonProcessingException e) {
362 logger.error(XACMLErrorConstants.ERROR_SCHEMA_INVALID
363 + "Json Processing Error " + e);
367 private void removedRuleModifiedGroup(String controllerName){
368 // This will be sending Notification to PDPD directly to Lock
369 ControllerPOJO controllerPOJO = new ControllerPOJO();
370 controllerPOJO.setName(controllerName);
371 controllerPOJO.setOperation("lock");
372 List<ControllerPOJO> controllers = new ArrayList<ControllerPOJO>();
373 controllers.add(controllerPOJO);
374 sendNotification(controllers);
377 private void sendNotification(List<ControllerPOJO> controllers){
378 NotificationPOJO notification = new NotificationPOJO();
379 String requestId = UUID.randomUUID().toString();
380 logger.info("Generating notification RequestID : " + requestId);
381 notification.setRequestID(requestId);
382 notification.setEntity("controller");
383 notification.setControllers(controllers);
385 String notificationJson = PolicyUtils.objectToJsonString(notification);
386 logger.info("Sending Notification :\n" + notificationJson);
387 sendMessage(notificationJson);
388 } catch (IOException | GeneralSecurityException | InterruptedException e) {
389 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error while sending notification to PDP-D " + e.getMessage());
393 private void sendMessage(String message) throws IOException, GeneralSecurityException, InterruptedException {
394 // Sending Message through UEB interface.
395 CambriaBatchingPublisher pub = pubBuilder.build();
396 pub.send( "MyPartitionKey", message);
397 logger.debug("Message Published on UEB :" + uebList + "for Topic: " + pubTopic);
398 Thread.sleep(uebDelay);
402 private void searchFile(File file, String name) {
403 if(file.isDirectory()){
404 logger.info("Searching Directory..." + file.getAbsolutePath());
406 for(File temp: file.listFiles()){
407 if(temp.isDirectory()){
409 searchFile(temp, name);
411 if(temp.getName().equals(name+".drl")){
412 matchingList.add(temp);
420 private void createPom(String name){
421 Model model = new Model();
422 model.setModelVersion("4.0.0");
423 model.setGroupId(getGroupID(name));
424 model.setArtifactId(getArtifactID(name));
425 model.setVersion(incrementVersion(name));
427 DistributionManagement distributionManagement = new DistributionManagement();
428 DeploymentRepository repository = new DeploymentRepository();
429 repository.setId(repID);
430 repository.setName(repName);
431 repository.setUrl(repURL);
432 distributionManagement.setRepository(repository);
433 model.setDistributionManagement(distributionManagement);
434 // Depenendency Mangement goes here.
435 List<Dependency> dependencyList= new ArrayList<Dependency>();
437 String version= StringEscapeUtils.escapeJava(brmsdependencyversion);
439 Dependency demoDependency = new Dependency();
440 demoDependency.setGroupId("org.openecomp.policy.drools-applications");
441 demoDependency.setArtifactId("demo");
442 demoDependency.setVersion(version);
443 dependencyList.add(demoDependency);
445 Dependency controlloopDependency = new Dependency();
446 controlloopDependency.setGroupId("org.openecomp.policy.drools-applications");
447 controlloopDependency.setArtifactId("controlloop");
448 controlloopDependency.setVersion(version);
449 dependencyList.add(controlloopDependency);
451 Dependency restDependency = new Dependency();
452 restDependency.setGroupId("org.openecomp.policy.drools-applications");
453 restDependency.setArtifactId("rest");
454 restDependency.setVersion(version);
455 dependencyList.add(restDependency);
457 Dependency appcDependency = new Dependency();
458 appcDependency.setGroupId("org.openecomp.policy.drools-applications");
459 appcDependency.setArtifactId("appc");
460 appcDependency.setVersion(version);
461 dependencyList.add(appcDependency);
463 Dependency aaiDependency = new Dependency();
464 aaiDependency.setGroupId("org.openecomp.policy.drools-applications");
465 aaiDependency.setArtifactId("aai");
466 aaiDependency.setVersion(version);
467 dependencyList.add(aaiDependency);
469 Dependency msoDependency = new Dependency();
470 msoDependency.setGroupId("org.openecomp.policy.drools-applications");
471 msoDependency.setArtifactId("mso");
472 msoDependency.setVersion(version);
473 dependencyList.add(msoDependency);
475 Dependency trafficgeneratorDependency = new Dependency();
476 trafficgeneratorDependency.setGroupId("org.openecomp.policy.drools-applications");
477 trafficgeneratorDependency.setArtifactId("trafficgenerator");
478 trafficgeneratorDependency.setVersion(version);
479 dependencyList.add(trafficgeneratorDependency);
482 model.setDependencies(dependencyList);
484 Writer writer = null;
486 writer = WriterFactory.newXmlWriter(new File(projectsLocation+File.separator+getArtifactID(name)+File.separator+"pom.xml"));
487 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
488 pomWriter.write(writer, model);
490 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+"Error while creating POM for " + getArtifactID(name) + e.getMessage());
492 IOUtil.close(writer);
496 private void createProject(String path,String ksessionName){
497 new File(path+File.separator+"rules").mkdirs();
498 new File(path+File.separator+"META-INF").mkdirs();
499 if(!Files.exists(Paths.get(path+File.separator+"META-INF"+File.separator+"kmodule.xml"))){
500 // Hard coding XML for PDP Drools to accept our Rules.
501 String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n"+
502 "<kmodule xmlns=\"http://jboss.org/kie/6.0.0/kmodule\">" +"\n"+
503 "<kbase name=\"rules\" packages=\"rules\">" + "\n" +
504 "<ksession name=\""+ ksessionName +"\"/>"+ "\n" +
505 "</kbase></kmodule>";
506 copyDataToFile(path+File.separator+"META-INF"+File.separator+"kmodule.xml", xml);
510 private void copyDataToFile(String file, String rule) {
512 FileUtils.writeStringToFile(new File(file), rule);
513 } catch (Exception e) {
514 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW+"Error while creating Rule for " + file + e.getMessage());
518 private void readGroups(Properties config) throws Exception{
519 String[] groupNames = null;
520 if(config.getProperty("groupNames").contains(",")){
521 groupNames = config.getProperty("groupNames").replaceAll(" ", "").split(",");
523 groupNames = new String[]{config.getProperty("groupNames").replaceAll(" ", "")};
525 if(groupNames==null || groupNames.length==0){
526 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "groupNames property is missing or empty from the property file ");
527 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + "groupNames property is missing or empty from the property file ");
529 names = new HashMap<String, Integer>();
530 groupIDs = new ArrayList<String>();
531 artifactIDs = new ArrayList<String>();
532 for(int counter=0; counter < groupNames.length ;counter++){
533 String name = groupNames[counter];
534 String groupID = config.getProperty(name+".groupID");
536 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + name+".groupID property is missing from the property file ");
537 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + name+".groupID property is missing from the property file ");
539 String artifactID = config.getProperty(name+".artifactID");
540 if(artifactID==null){
541 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + name+".artifactID property is missing from the property file ");
542 throw new Exception(XACMLErrorConstants.ERROR_DATA_ISSUE + name+".artifactID property is missing from the property file ");
544 // Add to list if we got all
545 names.put(name, counter);
546 groupIDs.add(groupID);
547 artifactIDs.add(artifactID);
551 private String getGroupID(String name){
552 return groupIDs.get(names.get(name));
555 private String getArtifactID(String name){
556 return artifactIDs.get(names.get(name));
559 private String getName(String filePath){
560 filePath = filePath.replaceFirst(projectsLocation, "").substring(1);
561 String artifactName = filePath.substring(0, filePath.indexOf(File.separator));
562 for(String name : names.keySet()){
563 if(artifactName.equals(getArtifactID(name))){
567 // If not found return default
571 private String incrementVersion(String name) {
572 final NexusClient client = new NexusRestClient();
573 String newVersion = "0.1.0";
576 client.connect(repURL.substring(0, repURL.indexOf(repURL.split(":[0-9]+\\/nexus")[1])), repUserName, repPassword);
577 final NexusArtifact template = new NexusArtifact();
578 template.setGroupId(getGroupID(name));
579 template.setArtifactId(getArtifactID(name));
580 final List<NexusArtifact> artifacts = client.searchByGAV(template);
583 for(NexusArtifact artifact : artifacts){
584 String version = artifact.getVersion();
585 int majorVal = Integer.parseInt(version.substring(0, version.indexOf(".")));
586 int minorVal = Integer.parseInt(version.substring(version.indexOf(".")+1,version.lastIndexOf(".")));
587 if(majorVal > bigMajor){
590 }else if((bigMajor==majorVal) && (minorVal > bigMinor)){
595 bigMajor = bigMajor+1;
598 bigMinor = bigMinor+1;
600 if(artifacts.isEmpty()){
601 // This is new artifact.
602 newVersion = "0.1.0";
604 newVersion = bigMajor + "." + bigMinor + artifacts.get(0).getVersion().substring(artifacts.get(0).getVersion().lastIndexOf("."));
606 } catch (NexusClientException | NexusConnectionException | NullPointerException e) {
607 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "version number increment failed will be using default version " +e.getMessage());
611 } catch (NexusClientException | NexusConnectionException e) {
612 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "failed to disconnect Connection from Nexus." +e.getMessage());
615 if(newVersion.equals("0.1.0")){
618 versions.put(name, newVersion);
619 logger.info("Controller: " + name + "is on version: "+ newVersion);
623 // Return BackUpMonitor
624 public static BackUpMonitor getBackUpMonitor(){