Explorar el Código

allow standalone bubbles to upgrade from jenkins

tags/v1.4.6
Jonathan Cobb hace 4 años
padre
commit
6a23b1abd4
Se han modificado 8 ficheros con 151 adiciones y 28 borrados
  1. +3
    -2
      bubble-server/src/main/java/bubble/resources/account/MeResource.java
  2. +2
    -0
      bubble-server/src/main/java/bubble/server/BubbleConfiguration.java
  3. +12
    -0
      bubble-server/src/main/java/bubble/service/boot/JarUpgradeMonitor.java
  4. +80
    -0
      bubble-server/src/main/java/bubble/service/boot/PublicUpgradeMonitorService.java
  5. +36
    -2
      bubble-server/src/main/java/bubble/service/boot/SageHelloService.java
  6. +12
    -3
      bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java
  7. +5
    -20
      bubble-server/src/main/java/bubble/service/upgrade/BubbleJarUpgradeService.java
  8. +1
    -1
      bubble-server/src/main/resources/packer/roles/bubble/tasks/main.yml

+ 3
- 2
bubble-server/src/main/java/bubble/resources/account/MeResource.java Ver fichero

@@ -30,6 +30,7 @@ import bubble.service.account.StandardAuthenticatorService;
import bubble.service.account.download.AccountDownloadService;
import bubble.service.boot.BubbleModelSetupService;
import bubble.service.boot.SageHelloService;
import bubble.service.boot.StandardSelfNodeService;
import bubble.service.cloud.NodeLaunchMonitor;
import bubble.service.upgrade.BubbleJarUpgradeService;
import com.fasterxml.jackson.databind.JsonNode;
@@ -426,7 +427,7 @@ public class MeResource {
return ok(model);
}

@Autowired private SageHelloService sageHelloService;
@Autowired private StandardSelfNodeService selfNodeService;
@Autowired private BubbleJarUpgradeService jarUpgradeService;

private final AtomicLong lastUpgradeCheck = new AtomicLong(0);
@@ -442,7 +443,7 @@ public class MeResource {
synchronized (lastUpgradeCheck) {
if (now() - lastUpgradeCheck.get() > UPGRADE_CHECK_INTERVAL) {
lastUpgradeCheck.set(now());
sageHelloService.interrupt();
selfNodeService.getJarUpgradeMonitorBean().interrupt();
}
}
return ok_empty();


+ 2
- 0
bubble-server/src/main/java/bubble/server/BubbleConfiguration.java Ver fichero

@@ -274,6 +274,8 @@ public class BubbleConfiguration extends PgRestServerConfiguration
}
public String getShortVersion () { return getVersionInfo().getShortVersion(); }

// For a Bubble node with a sage, this will be set in the hello_from_sage notification handler
// For a Bubble without a sage, this will be set in NodeInitializerListener
@Getter private BubbleVersionInfo sageVersion;
public void setSageVersion(BubbleVersionInfo version) {
sageVersion = version;


+ 12
- 0
bubble-server/src/main/java/bubble/service/boot/JarUpgradeMonitor.java Ver fichero

@@ -0,0 +1,12 @@
package bubble.service.boot;

import bubble.model.cloud.BubbleVersionInfo;
import org.cobbzilla.util.daemon.SimpleDaemon;

import java.io.File;

public abstract class JarUpgradeMonitor extends SimpleDaemon {

public abstract void downloadJar(File upgradeJar, BubbleVersionInfo sageVersion);

}

+ 80
- 0
bubble-server/src/main/java/bubble/service/boot/PublicUpgradeMonitorService.java Ver fichero

@@ -0,0 +1,80 @@
package bubble.service.boot;

import bubble.model.cloud.BubbleVersionInfo;
import bubble.server.BubbleConfiguration;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.daemon.SimpleDaemon;
import org.cobbzilla.util.io.Decompressors;
import org.cobbzilla.util.io.FileUtil;
import org.cobbzilla.util.io.TempDir;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;

import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.shortError;
import static org.cobbzilla.util.http.HttpUtil.url2file;
import static org.cobbzilla.util.http.HttpUtil.url2string;
import static org.cobbzilla.util.io.FileUtil.abs;
import static org.cobbzilla.wizard.model.SemanticVersion.isNewerVersion;

@Service @Slf4j
public class PublicUpgradeMonitorService extends JarUpgradeMonitor {

public static final long MONITOR_INTERVAL = HOURS.toMillis(6);
public static final long MONITOR_START_DELAY = SECONDS.toMillis(30);

@Override protected long getStartupDelay() { return MONITOR_START_DELAY; }
@Override protected long getSleepTime() { return MONITOR_INTERVAL; }
@Override protected boolean canInterruptSleep() { return true; }

public static final String BUBBLE_BASE_URI = "https://jenkins.bubblev.org/public/releases/bubble/";
public static final String RELEASE_VERSION_URL = BUBBLE_BASE_URI + "latest.txt";

public static final String VERSION_TOKEN = "@@VERSION@@";
public static final String RELEASE_JAR_URL = BUBBLE_BASE_URI + VERSION_TOKEN + "/bubble.zip";
public static final String RELEASE_SHA_URL = BUBBLE_BASE_URI + VERSION_TOKEN + "/bubble.zip.sha256";

@Autowired private BubbleConfiguration configuration;

@Override protected void process() {
try {
final String fullVersion = url2string(RELEASE_VERSION_URL).replace("_", " ");
String currentVersion = configuration.getVersionInfo().getVersion();
// only update our sage version if the new public version is both
// -- newer than ourselves
// -- newer than the current sageVersion (or the current sageVersion is null)
if (isNewerVersion(fullVersion, currentVersion)
&& (configuration.getSageVersion() == null || isNewerVersion(fullVersion, configuration.getSageVersion().getVersion()))) {
log.info("process: found newer version: "+fullVersion+" (current version "+currentVersion+"), setting sage version on BubbleConfiguration");
configuration.setSageVersion(new BubbleVersionInfo()
.setVersion(fullVersion)
.setShortVersion(fullVersion.substring(fullVersion.indexOf(" ")+1))
.setSha256(url2string(RELEASE_SHA_URL.replace(VERSION_TOKEN, fullVersion))));
}
} catch (Exception e) {
log.warn("process: error: "+shortError(e));
}
}

@Override public void downloadJar(File upgradeJar, BubbleVersionInfo sageVersion) {
try {
@Cleanup final TempDir temp = new TempDir();
final File bubbleZip = new File(temp, "bubble.zip");
url2file(RELEASE_JAR_URL.replace(VERSION_TOKEN, sageVersion.getVersion()), bubbleZip);
Decompressors.extract(bubbleZip, temp);
final File jarFile = new File(abs(temp) + "/bubble-" + sageVersion.getVersion() + "/bubble.jar");
if (!jarFile.exists()) {
die("downloadJar: jar file not found in zip file: "+abs(jarFile));
}
FileUtil.copyFile(jarFile, upgradeJar);
} catch (Exception e) {
die("downloadJar: "+shortError(e));
}
}

}

+ 36
- 2
bubble-server/src/main/java/bubble/service/boot/SageHelloService.java Ver fichero

@@ -8,26 +8,37 @@ import bubble.dao.account.message.AccountMessageDAO;
import bubble.dao.cloud.BubbleNodeDAO;
import bubble.model.account.message.AccountMessage;
import bubble.model.cloud.BubbleNode;
import bubble.model.cloud.BubbleVersionInfo;
import bubble.model.cloud.notify.NotificationReceipt;
import bubble.notify.upgrade.JarUpgradeNotification;
import bubble.server.BubbleConfiguration;
import bubble.service.notify.NotificationService;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.daemon.SimpleDaemon;
import org.cobbzilla.util.http.HttpUtil;
import org.cobbzilla.util.io.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static bubble.ApiConstants.AUTH_ENDPOINT;
import static bubble.ApiConstants.EP_UPGRADE;
import static bubble.model.cloud.notify.NotificationType.hello_to_sage;
import static bubble.model.cloud.notify.NotificationType.upgrade_request;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.shortError;
import static org.cobbzilla.util.io.FileUtil.*;
import static org.cobbzilla.util.json.JsonUtil.COMPACT_MAPPER;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.util.system.Sleep.sleep;

@Service @Slf4j
public class SageHelloService extends SimpleDaemon {
public class SageHelloService extends JarUpgradeMonitor {

public static final long HELLO_SAGE_INTERVAL = HOURS.toMillis(6);
public static final long HELLO_SAGE_START_DELAY = SECONDS.toMillis(10);
@@ -89,4 +100,27 @@ public class SageHelloService extends SimpleDaemon {
if (getIsDone()) throw e;
sleep(HELLO_SAGE_INTERVAL / 10, "hello_to_sage: awaiting next hello after error");
}

@Override public void downloadJar(File upgradeJar, BubbleVersionInfo sageVersion) {
// ask the sage to allow us to download the upgrade
final String key = notificationService.notifySync(configuration.getSageNode(), upgrade_request, new JarUpgradeNotification(sageVersion));
log.info("downloadJar: received upgrade key from sage: "+key);

// request the jar from the sage
final String uri = AUTH_ENDPOINT + EP_UPGRADE + "/" + configuration.getThisNode().getUuid() + "/" + key;
final String url = configuration.nodeBaseUri(configuration.getSageNode()) + uri;
final File newJar;
try {
newJar = temp(".jar");
@Cleanup final InputStream in = HttpUtil.getUrlInputStream(url);
FileUtil.toFile(newJar, in);
} catch (Exception e) {
log.error("downloadJar: error downloading jar: "+shortError(e));
return;
}

// move to upgrade location, should trigger upgrade monitor
log.info("downloadJar: writing upgradeJar: "+abs(upgradeJar));
renameOrDie(newJar, upgradeJar);
}
}

+ 12
- 3
bubble-server/src/main/java/bubble/service/boot/StandardSelfNodeService.java Ver fichero

@@ -29,6 +29,7 @@ import lombok.Getter;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.cache.Refreshable;
import org.cobbzilla.util.daemon.SimpleDaemon;
import org.cobbzilla.util.http.HttpSchemes;
import org.cobbzilla.util.http.HttpUtil;
import org.cobbzilla.util.io.FileUtil;
@@ -93,6 +94,8 @@ public class StandardSelfNodeService implements SelfNodeService {
@Autowired private RedisService redisService;
@Getter(lazy=true) private final RedisService nodeConfig = redisService.prefixNamespace(getClass().getSimpleName());

@Getter private JarUpgradeMonitor jarUpgradeMonitorBean;

@Override public boolean initThisNode(BubbleNode thisNode) {
log.info("initThisNode: initializing with thisNode="+thisNode.id());
final BubbleConfiguration c = configuration;
@@ -146,12 +149,14 @@ public class StandardSelfNodeService implements SelfNodeService {
}
}

// start hello sage and spare devices services, if we have a sage that is not ourselves
// start jar upgrade monitor and spare devices services, if we have a sage that is not ourselves
if (!c.isSage()) {
if (thisNode.node() && !c.isSelfSage()) {
log.info("onStart: starting SageHelloService");
c.getBean(SageHelloService.class).start();
jarUpgradeMonitorBean = c.getBean(SageHelloService.class);
} else {
jarUpgradeMonitorBean = c.getBean(PublicUpgradeMonitorService.class);
}
jarUpgradeMonitorBean.start();

log.info("onStart: building spare devices for all account that are not root account");
background(() -> {
@@ -164,6 +169,10 @@ public class StandardSelfNodeService implements SelfNodeService {
deviceDAO.refreshVpnUsers();
}
}, "StandardSelfNodeService.onStart.spareDevices");

} else {
jarUpgradeMonitorBean = c.getBean(PublicUpgradeMonitorService.class);
jarUpgradeMonitorBean.start();
}

// start RefundService if payments are enabled and this is a SageLauncher


+ 5
- 20
bubble-server/src/main/java/bubble/service/upgrade/BubbleJarUpgradeService.java Ver fichero

@@ -11,6 +11,8 @@ import bubble.model.cloud.BubbleVersionInfo;
import bubble.notify.upgrade.JarUpgradeNotification;
import bubble.server.BubbleConfiguration;
import bubble.service.backup.BackupService;
import bubble.service.boot.JarUpgradeMonitor;
import bubble.service.boot.StandardSelfNodeService;
import bubble.service.notify.NotificationService;
import lombok.Cleanup;
import lombok.Getter;
@@ -46,6 +48,7 @@ public class BubbleJarUpgradeService {
@Autowired private BubbleBackupDAO backupDAO;
@Autowired private NotificationService notificationService;
@Autowired private RedisService redis;
@Autowired private StandardSelfNodeService selfNodeService;

@Getter(lazy=true) private final RedisService nodeUpgradeRequests = redis.prefixNamespace(getClass().getName());

@@ -91,25 +94,7 @@ public class BubbleJarUpgradeService {
return;
}

// ask the sage to allow us to download the upgrade
final String key = notificationService.notifySync(configuration.getSageNode(), upgrade_request, new JarUpgradeNotification(sageVersion));
log.info("upgrade: received upgrade key from sage: "+key);

// request the jar from the sage
final String uri = AUTH_ENDPOINT + EP_UPGRADE + "/" + configuration.getThisNode().getUuid() + "/" + key;
final String url = configuration.nodeBaseUri(configuration.getSageNode()) + uri;
final File newJar;
try {
newJar = temp(".jar");
@Cleanup final InputStream in = HttpUtil.getUrlInputStream(url);
FileUtil.toFile(newJar, in);
} catch (Exception e) {
log.error("upgrade: error downloading jar: "+shortError(e));
return;
}

// move to upgrade location, should trigger upgrade monitor
log.info("upgrade: writing upgradeJar: "+abs(upgradeJar));
renameOrDie(newJar, upgradeJar);
final JarUpgradeMonitor jarUpgradeMonitor = selfNodeService.getJarUpgradeMonitorBean();
jarUpgradeMonitor.downloadJar(upgradeJar, sageVersion);
}
}

+ 1
- 1
bubble-server/src/main/resources/packer/roles/bubble/tasks/main.yml Ver fichero

@@ -115,7 +115,7 @@
src: supervisor_bubble_upgrade_monitor.conf
dest: /etc/supervisor/conf.d/bubble_upgrade_monitor.conf

- name: Install log_namager monitor cron
- name: Install log_manager monitor cron
cron:
name: "Log flag check and manager"
minute: "*/5"


Cargando…
Cancelar
Guardar