Skip to content

Commit

Permalink
Allow instance to adjust the memory size of the nodes (containers) of
Browse files Browse the repository at this point in the history
their cluster (only available for matomo-shared-db and dedicated-db
plans).
  • Loading branch information
pdechamboux committed Nov 4, 2019
1 parent ef718d7 commit 52adc4e
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 75 deletions.
14 changes: 13 additions & 1 deletion src/main/doc/markdown/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ cf cs matomo-service global-shared-db m -c '{"matomoTimeZone": "Europe/Paris"}'

For the `dedicated-db` plan the number of containers that run the service instance can be specified (by default, it is two of them):
```
cf cs matomo-service global-shared-db m -c '{"matomoInstances": 3}'
cf cs matomo-service dedicated-db md -c '{"matomoInstances": 3}'
```
It can be ajusted later on through an update action on the instance.

For the `matomo-shared-db` and the `dedicated-db` plans, the memory size (in MB) of the containers that run the service instance can be specified (by default, it is 512MB):
```
cf cs matomo-service matomo-shared-db ms -c '{"memorySize": 1024}'
```
Just like the number of running containers, it can be ajusted later on through an update action on the instance.

Service upgrade to new release (with higher version) is also supported by the service (see section "Update instance"). Concerning version upgrade, a policy can be specified at creation time:
```
cf cs matomo-service global-shared-db m -c '{"versionUpgradePolicy": "Explicit"}'
Expand Down Expand Up @@ -76,6 +82,12 @@ cf update-service m -c '{"matomoInstances": 6}'
```
This number is forced to stay in the interval [2..10]. This means that if a lower value than 2 is specified, then 2 is forced. In the same way, if a higher value than 10 is specified, then 10 is forced.

The fourth possibility is to adjust the memory of containers that run the instance (only in case of `matomo-shared-db` and `dedicated-db` plans):
```
cf update-service ms -c '{"memorySize": 768}'
```
This number is forced to stay in the interval [256..2048]. This means that if a lower value than 256 is specified, then 256 is forced. In the same way, if a higher value than 2048 is specified, then 2048 is forced.

## Bind to instances

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,11 @@ public Mono<Void> deployMatomoCfApp(String instid, String version, String expoho
.build());
}

public Mono<Void> scaleMatomoCfApp(String instid, int instances) {
public Mono<Void> scaleMatomoCfApp(String instid, int instances, int memsize) {
return cfops.applications().scale(ScaleApplicationRequest.builder()
.name(getAppName(instid))
.instances(instances)
.memoryLimit(memsize)
.build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public class PMatomoInstance extends POperationStatus {
private boolean automaticVersionUpgrade;

private int instances;

private int memorySize;

@SuppressWarnings("unused")
protected PMatomoInstance() {
Expand All @@ -98,9 +100,10 @@ protected PMatomoInstance() {
this.configFileContent = null;
this.automaticVersionUpgrade = true;
this.instances = 1;
this.memorySize = 256;
}

public PMatomoInstance(String id, int idUrl, String servDefId, String name, PlatformKind pfkind, String pfapi, String planid, PPlatform pf, String version, boolean avu, int instances) {
public PMatomoInstance(String id, int idUrl, String servDefId, String name, PlatformKind pfkind, String pfapi, String planid, PPlatform pf, String version, boolean avu, int instances, int memsize) {
super(id, OpCode.CREATE.toString(), OperationState.IN_PROGRESS.getValue(), pf);
this.idUrl = idUrl;
this.serviceDefinitionId = servDefId;
Expand All @@ -114,6 +117,7 @@ public PMatomoInstance(String id, int idUrl, String servDefId, String name, Plat
this.configFileContent = null;
this.automaticVersionUpgrade = avu;
this.instances = instances;
this.memorySize = memsize;
}

public int getIdUrl() {
Expand Down Expand Up @@ -183,6 +187,15 @@ public void setIntances(int instances) {
super.touch();
}

public int getMemorySize() {
return this.memorySize;
}

public void setMemorySize(int memorysize) {
this.memorySize = memorysize;
super.touch();
}

public void setInstalledVersion(String instVers) {
this.installedVersion = instVers;
super.touch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,33 +213,33 @@ private void defineNewMatomoSite(PMatomoInstance pmi, PBinding pb, String sitena
}
}

private void deleteMatomoSite(PBinding pb) {
LOGGER.debug("SERV::deleteMatomoSite: instId={}", pb.getPMatomoInstance().getId());
RestTemplate restTemplate = new RestTemplate();
try {
URI uri = new URI("https://" + getMatomoUrl(pb.getPMatomoInstance().getId()) + "/index.php");
MultipartBodyBuilder mbb = new MultipartBodyBuilder();
mbb.part("module", "API");
mbb.part("method", "SitesManager.deleteSite");
mbb.part("idSite", Integer.toString(pb.getSiteId()));
mbb.part("format", "json");
mbb.part("token_auth", pb.getPMatomoInstance().getTokenAuth());
String res = restTemplate.postForObject(uri, mbb.build(), String.class);
LOGGER.debug("DeleteSite Response: " + res);
mbb = new MultipartBodyBuilder();
mbb.part("module", "API");
mbb.part("method", "UsersManager.deleteUser");
mbb.part("userLogin", pb.getUserName());
mbb.part("format", "json");
mbb.part("token_auth", pb.getPMatomoInstance().getTokenAuth());
res = restTemplate.postForObject(uri, mbb.build(), String.class);
LOGGER.debug("DeleteUser Response: " + res);
} catch (RestClientException e) {
throw new RuntimeException("Fail to delete a site when unbinding.", e);
} catch (URISyntaxException e) {
throw new RuntimeException("Fail to delete a site when unbinding.", e);
}
}
// private void deleteMatomoSite(PBinding pb) {
// LOGGER.debug("SERV::deleteMatomoSite: instId={}", pb.getPMatomoInstance().getId());
// RestTemplate restTemplate = new RestTemplate();
// try {
// URI uri = new URI("https://" + getMatomoUrl(pb.getPMatomoInstance().getId()) + "/index.php");
// MultipartBodyBuilder mbb = new MultipartBodyBuilder();
// mbb.part("module", "API");
// mbb.part("method", "SitesManager.deleteSite");
// mbb.part("idSite", Integer.toString(pb.getSiteId()));
// mbb.part("format", "json");
// mbb.part("token_auth", pb.getPMatomoInstance().getTokenAuth());
// String res = restTemplate.postForObject(uri, mbb.build(), String.class);
// LOGGER.debug("DeleteSite Response: " + res);
// mbb = new MultipartBodyBuilder();
// mbb.part("module", "API");
// mbb.part("method", "UsersManager.deleteUser");
// mbb.part("userLogin", pb.getUserName());
// mbb.part("format", "json");
// mbb.part("token_auth", pb.getPMatomoInstance().getTokenAuth());
// res = restTemplate.postForObject(uri, mbb.build(), String.class);
// LOGGER.debug("DeleteUser Response: " + res);
// } catch (RestClientException e) {
// throw new RuntimeException("Fail to delete a site when unbinding.", e);
// } catch (URISyntaxException e) {
// throw new RuntimeException("Fail to delete a site when unbinding.", e);
// }
// }

private String getMatomoUrl(String miid) {
return miid + "." + properties.getDomain();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -50,7 +47,6 @@
import com.orange.oss.matomocfservice.api.model.MatomoInstance;
import com.orange.oss.matomocfservice.api.model.OpCode;
import com.orange.oss.matomocfservice.cfmgr.CloudFoundryMgr;
import com.orange.oss.matomocfservice.cfmgr.CloudFoundryMgr.AppConfHolder;
import com.orange.oss.matomocfservice.cfmgr.CloudFoundryMgrProperties;
import com.orange.oss.matomocfservice.cfmgr.MatomoReleases;
import com.orange.oss.matomocfservice.config.ServiceCatalogConfiguration;
Expand All @@ -67,13 +63,17 @@
@Service
public class MatomoInstanceService extends OperationStatusService {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
private final String PARAM_VERSION = "matomoVersion";
private final String PARAM_TZ = "matomoTimeZone";
private final String PARAM_INSTANCES = "matomoInstances";
private final String PARAM_VERSIONUPGRADEPOLICY = "versionUpgradePolicy";
private final String MATOMOINSTANCE_ROOTUSER = "admin";
private final int MAX_INSTANCES = 10;
private final int DEFAULT_CLUSTERSIZE = 2;
private final static String PARAM_VERSION = "matomoVersion";
private final static String PARAM_TZ = "matomoTimeZone";
private final static String PARAM_INSTANCES = "matomoInstances";
private final static String PARAM_VERSIONUPGRADEPOLICY = "versionUpgradePolicy";
private final static String PARAM_MEMORYSIZE = "memorySize";
private final static String MATOMOINSTANCE_ROOTUSER = "admin";
private final static int MAX_INSTANCES = 10;
private final static int CLUSTERSIZE_DEFAULT = 2;
private final static int MEMSIZE_SMALL = 256;
private final static int MEMSIZE_DEFAULT = 512;
private final static int MEMSIZE_MAX = 2048;
@Autowired
private PMatomoInstanceRepository miRepo;
@Autowired
Expand Down Expand Up @@ -140,6 +140,7 @@ public MatomoInstance createMatomoInstance(MatomoInstance matomoInstance, Map<St
String tz = getTimeZone(parameters);
boolean autoversupgrade = getAutomaticVersionUpgrade(parameters);
int instances = getInstances(parameters, matomoInstance.getPlanId());
int memsize = getMemorySize(parameters, matomoInstance.getPlanId());
PPlatform ppf = getPPlatform(matomoInstance.getPlatformId());
for (PMatomoInstance pmi : miRepo.findByPlatformAndLastOperation(ppf, OpCode.DELETE.toString())) {
if (pmi.getId().equals(matomoInstance.getUuid())) {
Expand All @@ -149,7 +150,7 @@ public MatomoInstance createMatomoInstance(MatomoInstance matomoInstance, Map<St
}
PMatomoInstance pmi = new PMatomoInstance(matomoInstance.getUuid(), instanceIdMgr.allocateInstanceId(),
matomoInstance.getServiceDefinitionId(), matomoInstance.getName(), matomoInstance.getPlatformKind(),
matomoInstance.getPlatformApiLocation(), matomoInstance.getPlanId(), ppf, instversion, autoversupgrade, instances);
matomoInstance.getPlatformApiLocation(), matomoInstance.getPlanId(), ppf, instversion, autoversupgrade, instances, memsize);
savePMatomoInstance(pmi);
matomoReleases.createLinkedTree(pmi.getIdUrlStr(), instversion);
Mono<Void> createdb = (properties.getDbCreds(pmi.getPlanId()).isDedicatedDb()) ? cfMgr.createDedicatedDb(pmi.getIdUrlStr()) : Mono.empty();
Expand All @@ -160,7 +161,7 @@ public MatomoInstance createMatomoInstance(MatomoInstance matomoInstance, Map<St
})
.doOnSuccess(v -> {
LOGGER.debug("Create dedicated DB for instance \"" + pmi.getId() + "\" succeeded.");
cfMgr.deployMatomoCfApp(pmi.getIdUrlStr(), instversion, pmi.getId(), pmi.getPlanId(), tz, 256, 1)
cfMgr.deployMatomoCfApp(pmi.getIdUrlStr(), instversion, pmi.getId(), pmi.getPlanId(), tz, MEMSIZE_SMALL, 1)
.doOnError(t -> {
LOGGER.error("Async create app instance (phase 1) \"" + pmi.getId() + "\" failed.", t);
matomoReleases.deleteLinkedTree(pmi.getIdUrlStr());
Expand Down Expand Up @@ -274,6 +275,7 @@ public MatomoInstance updateMatomoInstance(MatomoInstance mi, Map<String, Object
String newversion = getVersion(parameters);
boolean autoversupgrade = getAutomaticVersionUpgrade(parameters);
int instances = getInstances(parameters, pmi.getPlanId());
int memsize = getMemorySize(parameters, pmi.getPlanId());
if (pmi.getAutomaticVersionUpgrade() != autoversupgrade) {
pmi.setAutomaticVersionUpgrade(autoversupgrade);
savePMatomoInstance(pmi);
Expand All @@ -288,12 +290,19 @@ public MatomoInstance updateMatomoInstance(MatomoInstance mi, Map<String, Object
pmi.setIntances(instances);
savePMatomoInstance(pmi);
}
if (pmi.getMemorySize() == memsize) {
memsize = -1;
} else {
LOGGER.debug("Upgrade Matomo instance nodes memory from {}MB to {}MB.", pmi.getMemorySize(), memsize);
pmi.setMemorySize(memsize);
savePMatomoInstance(pmi);
}
if (matomoReleases.isHigherVersion(newversion, pmi.getInstalledVersion())) {
LOGGER.debug("Upgrade Matomo instance from version {} to {}.", pmi.getInstalledVersion(), newversion);
updateMatomoInstanceActual(pmi, newversion);
} else if (instances != -1) {
// only scale app
cfMgr.scaleMatomoCfApp(pmi.getIdUrlStr(), pmi.getInstances())
} else if ((instances != -1) || (memsize != -1)) {
// only scale app nodes and/or memory size
cfMgr.scaleMatomoCfApp(pmi.getIdUrlStr(), pmi.getInstances(), pmi.getMemorySize())
.doOnError(t -> {
pmi.setLastOperationState(OperationState.FAILED);
savePMatomoInstance(pmi);
Expand Down Expand Up @@ -341,7 +350,7 @@ private void updateMatomoInstanceActual(PMatomoInstance pmi, String newversion)
}

private Mono<Void> settleMatomoInstance(PMatomoInstance pmi, String version, String timezone, boolean retrievetoken, CloudFoundryMgrProperties.DbCreds dbCreds) {
return cfMgr.deployMatomoCfApp(pmi.getIdUrlStr(), version, pmi.getId(), pmi.getPlanId(), timezone, pmi.getClusterMode() ? 512 : 256, pmi.getInstances())
return cfMgr.deployMatomoCfApp(pmi.getIdUrlStr(), version, pmi.getId(), pmi.getPlanId(), timezone, pmi.getMemorySize(), pmi.getInstances())
.doOnError(t -> {
LOGGER.debug("Async settle app instance (phase 2.1) \"" + pmi.getId() + "\" failed.", t);
matomoReleases.deleteLinkedTree(pmi.getIdUrlStr());
Expand Down Expand Up @@ -404,7 +413,6 @@ private MatomoInstance savePMatomoInstance(PMatomoInstance pmi) {
}

private String getVersion(Map<String, Object> parameters) {
LOGGER.debug("SERV::getVersion");
String instversion = (String) parameters.get(PARAM_VERSION);
if (instversion == null) {
instversion = matomoReleases.getDefaultReleaseName();
Expand All @@ -414,54 +422,84 @@ private String getVersion(Map<String, Object> parameters) {
LOGGER.warn("SERV::getVersion: version {} is not supported -> switch to default one.", instversion);
throw new RuntimeException("Version <" + instversion + "> is not supported by this Matomo CF Service!!");
}
LOGGER.debug("SERV::getVersion: return {}", instversion);
return instversion;
}

private boolean getAutomaticVersionUpgrade(Map<String, Object> parameters) {
LOGGER.debug("SERV::getAutomaticVersionUpgrade");
String policy = (String) parameters.get(PARAM_VERSIONUPGRADEPOLICY);
boolean bpol;
if (policy == null) {
return true;
}
policy = policy.toUpperCase();
if (policy.equals("AUTOMATIC")) {
return true;
}
if (policy.equals("EXPLICIT")) {
return false;
bpol = true;
} else {
policy = policy.toUpperCase();
if (policy.equals("AUTOMATIC")) {
bpol = true;
} else if (policy.equals("EXPLICIT")) {
bpol = false;
} else {
LOGGER.warn("SERV::getAutomaticVersionUpgrade: <{}> is a wrong value for version upgrade policy -> should be either AUTOMATIC or EXPLICIT.", policy);
throw new IllegalArgumentException("Version upgrade policy <" + policy + "> is a wrong value!!");
}
}
LOGGER.warn("SERV::getAutomaticVersionUpgrade: <{}> is a wrong value for version upgrade policy -> should be either AUTOMATIC or EXPLICIT.", policy);
throw new IllegalArgumentException("Version upgrade policy <" + policy + "> is a wrong value!!");
LOGGER.debug("SERV::getAutomaticVersionUpgrade: return {}", bpol);
return bpol;
}

private int getInstances(Map<String, Object> parameters, String planid) {
LOGGER.debug("SERV::getInstances");
Integer instances;
if (planid.equals(ServiceCatalogConfiguration.PLANGLOBSHARDB_UUID)) {
return 1;
}
instances = 1;
} else {
// then this is a cluster conf
if (planid.equals(ServiceCatalogConfiguration.PLANMATOMOSHARDB_UUID)) {
return DEFAULT_CLUSTERSIZE;
}
Integer instances = (Integer) parameters.get(PARAM_INSTANCES);
if (instances == null) {
return DEFAULT_CLUSTERSIZE;
}
if (instances < DEFAULT_CLUSTERSIZE) {
return DEFAULT_CLUSTERSIZE;
}
if (instances > MAX_INSTANCES) {
return MAX_INSTANCES;
if (planid.equals(ServiceCatalogConfiguration.PLANMATOMOSHARDB_UUID)) {
instances = CLUSTERSIZE_DEFAULT;
} else {
instances = (Integer) parameters.get(PARAM_INSTANCES);
if (instances == null) {
instances = CLUSTERSIZE_DEFAULT;
} else if (instances < CLUSTERSIZE_DEFAULT) {
instances = CLUSTERSIZE_DEFAULT;
} else if (instances > MAX_INSTANCES) {
instances = MAX_INSTANCES;
}
}
}
LOGGER.debug("SERV::getInstances: return {}", instances);
return instances;
}

/**
* Define the memory size in MB of containers that run Matomo.
* @param parameters
* @param planid
* @return
*/
private int getMemorySize(Map<String, Object> parameters, String planid) {
Integer memsize;
if (planid.equals(ServiceCatalogConfiguration.PLANGLOBSHARDB_UUID)) {
memsize = MEMSIZE_SMALL;
} else {
// then this is a cluster conf
memsize = (Integer) parameters.get(PARAM_MEMORYSIZE);
if (memsize == null) {
memsize = MEMSIZE_DEFAULT;
} else if (memsize < MEMSIZE_SMALL) {
memsize = MEMSIZE_SMALL;
} else if (memsize > MEMSIZE_MAX) {
memsize = MEMSIZE_MAX;
}
}
LOGGER.debug("SERV::getMemorySize: return {}MB", memsize);
return memsize;
}

private String getTimeZone(Map<String, Object> parameters) {
LOGGER.debug("SERV::getTimeZone");
String tz = (String) parameters.get(PARAM_TZ);
if (tz == null) {
tz = "Europe/Paris";
}
LOGGER.debug("SERV::getTimeZone: return {}", tz);
return tz;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,15 @@
<constraints nullable="false" />
</column>
</addColumn>
<addColumn tableName="matomoinstances">
<column name="memory_size" type="integer" valueNumeric="256">
<constraints nullable="false" />
</column>
</addColumn>
<rollback>
<dropColumn tableName="matomoinstances" columnName="automatic_version_upgrade"/>
<dropColumn tableName="matomoinstances" columnName="instances"/>
<dropColumn tableName="matomoinstances" columnName="memory_size"/>
</rollback>
</changeSet>
</databaseChangeLog>

0 comments on commit 52adc4e

Please sign in to comment.