package de.cinovo.cloudconductor.server.web.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import de.cinovo.cloudconductor.server.model.*;
import org.joda.time.DateTime;
import org.joda.time.Minutes;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import de.cinovo.cloudconductor.api.ServiceState;
import de.cinovo.cloudconductor.server.comparators.StateComparator;
import de.cinovo.cloudconductor.server.comparators.StringMapComparator;
import de.cinovo.cloudconductor.server.comparators.VersionStringComparator;
import de.cinovo.cloudconductor.server.dao.IHostDAO;
import de.cinovo.cloudconductor.server.dao.ITemplateDAO;
import de.cinovo.cloudconductor.server.web.CSViewModel;
import de.cinovo.cloudconductor.server.web.helper.AWebPage;
import de.cinovo.cloudconductor.server.web.helper.AjaxAnswer;
import de.cinovo.cloudconductor.server.web.interfaces.IHost;
import de.cinovo.cloudconductor.server.web.interfaces.IWebPath;
import de.taimos.cxf_renderer.model.RenderedUI;
import de.taimos.restutils.RESTAssert;
/**
* Copyright 2014 Cinovo AG<br>
* <br>
*
* @author psigloch
*
*/
public class HostImpl extends AWebPage implements IHost {
private DateTimeFormatter germanFmt = DateTimeFormat.forPattern("HH:mm:ss - dd.MM.yyyy");
@Autowired
protected IHostDAO dHost;
@Autowired
protected ITemplateDAO dTemplate;
private static final String HOSTS = "HOSTS";
private static final String HOST = "host";
private static final String DIFFERENCES = "DIFFERENCES";
private static final String TEMPLATES = "TEMPLATES";
@Override
protected String getTemplateFolder() {
return "hosts";
}
@Override
protected void init() {
this.navRegistry.registerMainMenu(this.getNavElementName(), IHost.ROOT);
this.addBreadCrumb(IWebPath.WEBROOT + IHost.ROOT, this.getNavElementName());
}
@Override
protected String getNavElementName() {
return "Hosts";
}
@Override
@Transactional
public RenderedUI view() {
List<EHost> eHosts = this.dHost.findList();
Map<String, String[]> reporttimes = new HashMap<>();
Map<String, List<?>> thDiff = new HashMap<>();
StateComparator comp = new StateComparator();
for (EHost h : eHosts) {
this.addSidebarElement(h.getName());
Collections.sort(h.getServices(), comp);
DateTime last = new DateTime(h.getLastSeen());
String diff = String.valueOf(Minutes.minutesBetween(last, new DateTime()).getMinutes());
reporttimes.put(h.getName(), new String[] {diff, this.germanFmt.print(last)});
thDiff.put(h.getName(), this.createHostTemplateDiff(h));
}
this.sortNamedList(eHosts);
CSViewModel view = this.createView();
view.addModel(HostImpl.HOSTS, eHosts);
view.addModel(HostImpl.DIFFERENCES, thDiff);
return view.render();
}
@Override
@Transactional
public RenderedUI view(String hname) {
EHost eHosts = this.dHost.findByName(hname);
Collections.sort(eHosts.getServices(), new StateComparator());
CSViewModel modal = this.createModal("mSingleView");
modal.addModel(HostImpl.HOST, eHosts);
modal.addModel(HostImpl.DIFFERENCES, this.createHostTemplateDiff(eHosts));
return modal.render();
}
@Override
@Transactional
public AjaxAnswer changeServiceStates(String hname, String[] start, String[] stop, String[] restart) {
RESTAssert.assertNotEmpty(hname);
if ((start.length < 1) && (stop.length < 1) && (restart.length < 1)) {
new AjaxAnswer(IWebPath.WEBROOT + IHost.ROOT);
}
EHost host = this.dHost.findByName(hname);
for (String service : start) {
for (EServiceState eservice : host.getServices()) {
if (eservice.getService().getName().equals(service)) {
eservice.setState(ServiceState.STARTING);
break;
}
}
}
for (String service : stop) {
for (EServiceState eservice : host.getServices()) {
if (eservice.getService().getName().equals(service)) {
eservice.setState(ServiceState.STOPPING);
break;
}
}
}
for (String service : restart) {
for (EServiceState eservice : host.getServices()) {
if (eservice.getService().getName().equals(service)) {
eservice.setState(ServiceState.RESTARTING_STOPPING);
break;
}
}
}
this.dHost.save(host);
return new AjaxAnswer(IWebPath.WEBROOT + IHost.ROOT);
}
@Override
@Transactional
public RenderedUI deleteHostView(String hname) {
RESTAssert.assertNotEmpty(hname);
EHost host = this.dHost.findByName(hname);
RESTAssert.assertNotNull(host);
CSViewModel modal = this.createModal("mDeleteHost");
modal.addModel(HostImpl.HOST, host);
return modal.render();
}
@Override
@Transactional
public AjaxAnswer deleteHost(String hname) {
RESTAssert.assertNotEmpty(hname);
EHost host = this.dHost.findByName(hname);
if ((host != null)) {
this.dHost.delete(host);
}
return new AjaxAnswer(IWebPath.WEBROOT + IHost.ROOT);
}
private List<Map<String, Object>> createHostTemplateDiff(EHost h) {
List<EPackageVersion> trpms = h.getTemplate().getPackageVersions();
Set<EPackageVersion> missing = new HashSet<>(trpms);
VersionStringComparator versionComp = new VersionStringComparator();
StringMapComparator mapComp = new StringMapComparator("name");
List<Map<String, Object>> notices = new ArrayList<>();
for (EPackageState ipkg : h.getPackages()) {
if (trpms.contains(ipkg.getVersion())) {
// version is ok
missing.remove(ipkg.getVersion());
continue;
}
boolean found = false;
for (EPackageVersion trpm : trpms) {
// version is not same as in template
if (trpm.getPkg().getName().equals(ipkg.getVersion().getPkg().getName())) {
Map<String, Object> wrongVersion = new HashMap<>();
wrongVersion.put("name", ipkg.getVersion().getPkg().getName());
wrongVersion.put("installed", ipkg.getVersion().getVersion());
wrongVersion.put("template", trpm.getVersion());
if (versionComp.compare(ipkg.getVersion().getVersion(), trpm.getVersion()) < 0) {
wrongVersion.put("state", "updating");
} else {
wrongVersion.put("state", "downgrading");
}
found = true;
notices.add(wrongVersion);
missing.remove(trpm);
continue;
}
for (EPackageVersion deppack : trpms) {
for(EDependency dep : deppack.getDependencies()){
if(trpm.getPkg().getName().equals(dep.getName())){
missing.remove(trpm);
found = true;
break;
}
}
}
}
// rpm is not within template
if (!found) {
Map<String, Object> wrongVersion = new HashMap<>();
wrongVersion.put("name", ipkg.getVersion().getPkg().getName());
wrongVersion.put("installed", ipkg.getVersion().getVersion());
wrongVersion.put("template", "");
wrongVersion.put("state", "uninstalling");
notices.add(wrongVersion);
}
}
for (EPackageVersion trpm : missing) {
Map<String, Object> wrongVersion = new HashMap<>();
wrongVersion.put("name", trpm.getPkg().getName());
wrongVersion.put("installed", "");
wrongVersion.put("template", trpm.getVersion());
wrongVersion.put("state", "installing");
notices.add(wrongVersion);
}
Collections.sort(notices, mapComp);
return notices;
}
@Override
@Transactional
public RenderedUI editHostTemplateView(String hostId) {
RESTAssert.assertNotNull(hostId);
EHost hostToEdit = this.dHost.findById(Long.parseLong(hostId));
CSViewModel modal = this.createModal("mModHost");
modal.addModel(HostImpl.HOST, hostToEdit);
List<ETemplate> templates = this.dTemplate.findList();
modal.addModel(HostImpl.TEMPLATES, templates);
return modal.render();
}
@Override
@Transactional
public AjaxAnswer updateHostTemplate(String hostId, String templateId) {
RESTAssert.assertNotNull(hostId);
RESTAssert.assertNotNull(templateId);
EHost hostToEdit = this.dHost.findById(Long.parseLong(hostId));
ETemplate oldTemplate = hostToEdit.getTemplate();
oldTemplate.getHosts().remove(hostToEdit);
this.dTemplate.save(oldTemplate);
ETemplate templateToAssign = this.dTemplate.findById(Long.parseLong(templateId));
templateToAssign.getHosts().add(hostToEdit);
hostToEdit.setTemplate(templateToAssign);
this.dTemplate.save(templateToAssign);
this.dHost.save(hostToEdit);
return new AjaxAnswer(IWebPath.WEBROOT + IHost.ROOT);
}
}