diff --git a/bubble-server/src/main/java/bubble/cloud/dns/DnsDriverBase.java b/bubble-server/src/main/java/bubble/cloud/dns/DnsDriverBase.java index c19498b4..93833013 100644 --- a/bubble-server/src/main/java/bubble/cloud/dns/DnsDriverBase.java +++ b/bubble-server/src/main/java/bubble/cloud/dns/DnsDriverBase.java @@ -20,15 +20,15 @@ import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeUnit; +import static java.util.concurrent.TimeUnit.MINUTES; import static org.cobbzilla.util.daemon.ZillaRuntime.die; import static org.cobbzilla.util.network.NetworkUtil.IPv4_ALL_ADDRS; public abstract class DnsDriverBase extends CloudServiceDriverBase implements DnsServiceDriver { - private static final long DNS_LOCK_TIMEOUT = TimeUnit.MINUTES.toMillis(1); - private static final long DNS_DEADLOCK_TIMEOUT = TimeUnit.MINUTES.toMillis(5); + private static final long DNS_LOCK_TIMEOUT = MINUTES.toMillis(1); + private static final long DNS_DEADLOCK_TIMEOUT = MINUTES.toMillis(5); @Autowired protected BubbleDomainDAO domainDAO; @Autowired protected BubbleNetworkDAO networkDAO; @@ -36,10 +36,12 @@ public abstract class DnsDriverBase extends CloudServiceDriverBase impleme @Getter(lazy=true) private final RedisService dnsLocks = redis.prefixNamespace(getClass().getSimpleName()+"_dns_lock"); protected synchronized String lockDomain(String domain) { +// log.info("lockDomain: "+domain+" called from "+stacktrace()); return getDnsLocks().lock(domain, DNS_LOCK_TIMEOUT, DNS_DEADLOCK_TIMEOUT); } protected synchronized void unlockDomain(String domain, String lock) { +// log.info("unlockDomain: "+domain+" called from "+stacktrace()); getDnsLocks().unlock(domain, lock); } diff --git a/bubble-server/src/main/java/bubble/model/device/Device.java b/bubble-server/src/main/java/bubble/model/device/Device.java index 39f7a15a..ea2c8c90 100644 --- a/bubble-server/src/main/java/bubble/model/device/Device.java +++ b/bubble-server/src/main/java/bubble/model/device/Device.java @@ -119,4 +119,7 @@ public class Device extends IdentifiableBase implements HasAccount { // make ctime visible @JsonProperty public long getCtime () { return super.getCtime(); } + @Transient @Getter @Setter private DeviceStatus status; + public boolean hasStatus () { return status != null && status.hasIp(); } + } diff --git a/bubble-server/src/main/java/bubble/model/device/DeviceStatus.java b/bubble-server/src/main/java/bubble/model/device/DeviceStatus.java new file mode 100644 index 00000000..f764d73c --- /dev/null +++ b/bubble-server/src/main/java/bubble/model/device/DeviceStatus.java @@ -0,0 +1,134 @@ +package bubble.model.device; + +import bubble.cloud.geoLocation.GeoLocation; +import bubble.service.cloud.GeoService; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; +import org.cobbzilla.wizard.cache.redis.RedisService; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.cobbzilla.util.daemon.ZillaRuntime.now; +import static org.cobbzilla.util.daemon.ZillaRuntime.shortError; + +@NoArgsConstructor @Accessors(chain=true) @Slf4j +public class DeviceStatus { + + public static final DeviceStatus NO_DEVICE_STATUS = new DeviceStatus(); + + @Getter @Setter private String ip; + public boolean hasIp () { return ip != null; } + @Getter @Setter private int port; + + @Getter @Setter private GeoLocation location; + + @Getter @Setter private String bytesSent; + @Getter @Setter private String sentUnits; + @Getter @Setter private String bytesReceived; + @Getter @Setter private String receivedUnits; + + @Getter @Setter private Integer lastHandshakeMinutes; + @Getter @Setter private Integer lastHandshakeSeconds; + @Getter @Setter private Long lastHandshakeTime; + + public static final String DEVICE_STATUS_PREFIX = "wg_device_status_"; + public static final String DEVICE_STATUS_ENDPOINT_SUFFIX = "_endpoint"; + public static final String DEVICE_STATUS_TRANSFER_SUFFIX = "_transfer"; + public static final String DEVICE_STATUS_HANDSHAKE_SUFFIX = "_latestHandshake"; + + public DeviceStatus(RedisService redis, String geoAccount, GeoService geoService, String deviceUuid) { + + final String endpoint = redis.get_plaintext(DEVICE_STATUS_PREFIX+deviceUuid+DEVICE_STATUS_ENDPOINT_SUFFIX); + if (endpoint != null) { + try { + final int lastColon = endpoint.lastIndexOf(':'); + if (lastColon != -1) { + setIp(endpoint.substring(0, lastColon)); + setPort(Integer.parseInt(endpoint.substring(lastColon + 1))); + if (geoService != null) { + try { + setLocation(geoService.locate(geoAccount, getIp())); + } catch (Exception e) { + log.error("DeviceStatus: error calling geoService for ip="+getIp()+": "+shortError(e)); + } + } + } + } catch (Exception e) { + log.error("DeviceStatus: error parsing endpoint: "+endpoint+": "+shortError(e)); + } + } + + final String transfer = redis.get_plaintext(DEVICE_STATUS_PREFIX+deviceUuid+DEVICE_STATUS_TRANSFER_SUFFIX); + if (transfer != null) { + try { + final String[] parts = transfer.split("\\s+"); + if (parts.length != 6) { + log.error("DeviceStatus: error parsing transfer: " + transfer); + } else { + if (!parts[2].equals("received,")) throw new IllegalArgumentException("expected 'received,' in parts[2]"); + if (!parts[5].equals("sent")) throw new IllegalArgumentException("expected 'sent' in parts[5]"); + setBytesReceived(parts[0]); + setReceivedUnits(parseUnits(parts[1])); + setBytesSent(parts[3]); + setSentUnits(parseUnits(parts[4])); + } + } catch (Exception e) { + log.error("DeviceStatus: error parsing transfer: "+transfer+": "+shortError(e)); + } + } + + final String handshake = redis.get_plaintext(DEVICE_STATUS_PREFIX+deviceUuid+DEVICE_STATUS_HANDSHAKE_SUFFIX); + if (handshake == null) { + if (transfer != null) { + log.warn("DeviceStatus: transfer found but no handshake info for device "+deviceUuid); + } + } else { + try { + final String[] parts = handshake.split("\\s+"); + if (!parts[parts.length-1].equals("ago")) { + log.error("DeviceStatus: error parsing handshake, expected 'ago' as last token"); + } else { + if (parts.length == 3) { + if (parts[1].startsWith("minute")) { + setLastHandshakeMinutes(Integer.parseInt(parts[0])); + setLastHandshakeSeconds(0); + initLastHandshakeTime(); + } else if (parts[1].startsWith("second")) { + setLastHandshakeSeconds(Integer.parseInt(parts[0])); + setLastHandshakeMinutes(0); + initLastHandshakeTime(); + } else { + log.error("DeviceStatus: error parsing handshake, expected 'minutes' or 'seconds' in parts[1]: "+handshake); + } + } else if (parts.length == 5) { + if (!parts[1].startsWith("minute")) { + log.error("DeviceStatus: error parsing handshake, expected 'minute' or 'minutes' in parts[1]: "+handshake); + } else if (!parts[3].startsWith("second")) { + log.error("DeviceStatus: error parsing handshake, expected 'second' or 'seconds' in parts[3]: "+handshake); + } else { + setLastHandshakeMinutes(Integer.valueOf(parts[0])); + setLastHandshakeSeconds(Integer.valueOf(parts[2])); + initLastHandshakeTime(); + } + } else { + log.error("DeviceStatus: error parsing handshake: "+handshake+": expected 3 or 5 parts, found "+parts.length); + } + } + } catch (Exception e) { + log.error("DeviceStatus: error parsing handshake: "+handshake+": "+shortError(e)); + } + } + } + + private String parseUnits(String units) { + if (units.equalsIgnoreCase("b")) return "b"; + return units.substring(0, 1).toUpperCase(); + } + + private void initLastHandshakeTime() { + setLastHandshakeTime(now() - MINUTES.toMillis(getLastHandshakeMinutes()) - SECONDS.toMillis(getLastHandshakeSeconds())); + } +} diff --git a/bubble-server/src/main/java/bubble/model/device/DeviceStatusFirstComparator.java b/bubble-server/src/main/java/bubble/model/device/DeviceStatusFirstComparator.java new file mode 100644 index 00000000..22dd641a --- /dev/null +++ b/bubble-server/src/main/java/bubble/model/device/DeviceStatusFirstComparator.java @@ -0,0 +1,18 @@ +package bubble.model.device; + +import java.util.Comparator; + +public class DeviceStatusFirstComparator implements Comparator { + + public static DeviceStatusFirstComparator DEVICE_WITH_STATUS_FIRST = new DeviceStatusFirstComparator(); + + @Override public int compare(Device d1, Device d2) { + if (d1.hasStatus() && d2.hasStatus()) { + return Long.compare(d1.getCtime(), d2.getCtime()); + } + if (d1.hasStatus()) return -1; + if (d2.hasStatus()) return 1; + return Long.compare(d1.getCtime(), d2.getCtime()); + } + +} diff --git a/bubble-server/src/main/java/bubble/resources/account/AccountOwnedResource.java b/bubble-server/src/main/java/bubble/resources/account/AccountOwnedResource.java index e23180b5..ab58e4f8 100644 --- a/bubble-server/src/main/java/bubble/resources/account/AccountOwnedResource.java +++ b/bubble-server/src/main/java/bubble/resources/account/AccountOwnedResource.java @@ -66,7 +66,9 @@ public class AccountOwnedResource list(Request req, ContainerRequest ctx) { return list(ctx); } + protected List list(Request req, ContainerRequest ctx) { return sort(list(ctx), req, ctx); } + + protected List sort(List list, Request req, ContainerRequest ctx) { return list; } protected String getAccountUuid(ContainerRequest ctx) { return getAccountUuid(account, ctx); } diff --git a/bubble-server/src/main/java/bubble/resources/account/DevicesResource.java b/bubble-server/src/main/java/bubble/resources/account/DevicesResource.java index 02a2e1f5..b76afd07 100644 --- a/bubble-server/src/main/java/bubble/resources/account/DevicesResource.java +++ b/bubble-server/src/main/java/bubble/resources/account/DevicesResource.java @@ -10,7 +10,9 @@ import bubble.model.device.Device; import bubble.model.device.DeviceSecurityLevel; import bubble.server.BubbleConfiguration; import bubble.service.cloud.DeviceIdService; +import edu.emory.mathcs.backport.java.util.Collections; import lombok.extern.slf4j.Slf4j; +import org.glassfish.grizzly.http.server.Request; import org.glassfish.jersey.server.ContainerRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -24,6 +26,7 @@ import java.util.List; import java.util.stream.Collectors; import static bubble.ApiConstants.*; +import static bubble.model.device.DeviceStatusFirstComparator.DEVICE_WITH_STATUS_FIRST; import static org.cobbzilla.util.daemon.ZillaRuntime.empty; import static org.cobbzilla.wizard.resources.ResourceUtil.*; @@ -41,11 +44,22 @@ public class DevicesResource extends AccountOwnedResource { @Override protected List list(ContainerRequest ctx) { final Account caller = userPrincipal(ctx); + final List devices; if (caller.admin() && ctx.getRequestUri().getQuery() != null && ctx.getRequestUri().getQuery().contains("all")) { - return getDao().findAll().stream().filter(Device::initialized).collect(Collectors.toList()); + devices = getDao().findAll().stream().filter(Device::initialized).collect(Collectors.toList()); } else { - return super.list(ctx).stream().filter(Device::initialized).collect(Collectors.toList()); + devices = super.list(ctx).stream().filter(Device::initialized).collect(Collectors.toList()); } + return devices; + } + + @Override protected Device populate(ContainerRequest ctx, Device device) { + return device.setStatus(deviceIdService.getDeviceStatus(device.getUuid())); + } + + @Override protected List sort(List list, Request req, ContainerRequest ctx) { + Collections.sort(list, DEVICE_WITH_STATUS_FIRST); + return list; } @Override protected boolean canChangeName() { return true; } @@ -103,4 +117,12 @@ public class DevicesResource extends AccountOwnedResource { return ok(deviceIdService.findIpsByDevice(device.getUuid())); } + @GET @Path("/{id}"+EP_STATUS) + public Response getStatus(@Context ContainerRequest ctx, + @PathParam("id") String id) { + final Device device = getDao().findByAccountAndId(getAccountUuid(ctx), id); + if (device == null) return notFound(id); + return ok(deviceIdService.getLiveDeviceStatus(device.getUuid())); + } + } diff --git a/bubble-server/src/main/java/bubble/service/cloud/DeviceIdService.java b/bubble-server/src/main/java/bubble/service/cloud/DeviceIdService.java index 88d3e009..fc56d82a 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/DeviceIdService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/DeviceIdService.java @@ -5,6 +5,7 @@ package bubble.service.cloud; import bubble.model.device.Device; +import bubble.model.device.DeviceStatus; import java.util.List; @@ -18,4 +19,7 @@ public interface DeviceIdService { void setDeviceSecurityLevel(Device device); + DeviceStatus getDeviceStatus(String deviceUuid); + DeviceStatus getLiveDeviceStatus(String deviceUuid); + } diff --git a/bubble-server/src/main/java/bubble/service/cloud/StandardDeviceIdService.java b/bubble-server/src/main/java/bubble/service/cloud/StandardDeviceIdService.java index df0e7031..9eee3320 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/StandardDeviceIdService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/StandardDeviceIdService.java @@ -7,6 +7,7 @@ package bubble.service.cloud; import bubble.dao.account.AccountDAO; import bubble.dao.device.DeviceDAO; import bubble.model.device.Device; +import bubble.model.device.DeviceStatus; import bubble.server.BubbleConfiguration; import lombok.extern.slf4j.Slf4j; import org.cobbzilla.util.collection.ExpirationMap; @@ -24,6 +25,7 @@ import java.util.List; import java.util.Map; import static bubble.ApiConstants.HOME_DIR; +import static bubble.model.device.DeviceStatus.NO_DEVICE_STATUS; import static java.util.concurrent.TimeUnit.MINUTES; import static org.cobbzilla.util.daemon.ZillaRuntime.*; import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; @@ -45,6 +47,7 @@ public class StandardDeviceIdService implements DeviceIdService { @Autowired private DeviceDAO deviceDAO; @Autowired private AccountDAO accountDAO; @Autowired private RedisService redis; + @Autowired private GeoService geoService; @Autowired private BubbleConfiguration configuration; private final Map deviceCache = new ExpirationMap<>(MINUTES.toMillis(10)); @@ -117,6 +120,17 @@ public class StandardDeviceIdService implements DeviceIdService { } } + private final ExpirationMap deviceStatusCache = new ExpirationMap<>(MINUTES.toMillis(2)); + + @Override public DeviceStatus getDeviceStatus(String deviceUuid) { + return deviceStatusCache.computeIfAbsent(deviceUuid, k -> getLiveDeviceStatus(deviceUuid)); + } + + @Override public DeviceStatus getLiveDeviceStatus(String deviceUuid) { + if (configuration.testMode()) return NO_DEVICE_STATUS; + return new DeviceStatus(redis, accountDAO.getFirstAdmin().getUuid(), geoService, deviceUuid); + } + private Device findTestDevice(String ipAddr) { final String adminUuid = accountDAO.getFirstAdmin().getUuid(); final List adminDevices = deviceDAO.findByAccount(adminUuid); diff --git a/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterDeviceIdService.java b/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterDeviceIdService.java index 44e0672e..32692930 100644 --- a/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterDeviceIdService.java +++ b/bubble-server/src/main/java/bubble/service_dbfilter/DbFilterDeviceIdService.java @@ -5,6 +5,7 @@ package bubble.service_dbfilter; import bubble.model.device.Device; +import bubble.model.device.DeviceStatus; import bubble.service.cloud.DeviceIdService; import org.springframework.stereotype.Service; @@ -23,4 +24,7 @@ public class DbFilterDeviceIdService implements DeviceIdService { @Override public void setDeviceSecurityLevel(Device device) { notSupported("setDeviceSecurityLevel"); } + @Override public DeviceStatus getDeviceStatus(String deviceUuid) { return notSupported("getDeviceStats"); } + @Override public DeviceStatus getLiveDeviceStatus(String deviceUuid) { return notSupported("getLiveDeviceStatus"); } + } diff --git a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties index 96c755a6..baf2b059 100644 --- a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties +++ b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties @@ -1 +1 @@ -bubble.version=0.13.1 +bubble.version=0.13.2 diff --git a/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties b/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties index 2a7d4461..c969c6e2 100644 --- a/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties +++ b/bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties @@ -469,7 +469,12 @@ label_field_device_app=App label_field_device_certificate=Certificate label_field_device_enabled=Enabled? label_field_device_vpn_config=VPN -label_field_security_level=Security Level +label_field_device_security_level=Security Level +label_field_device_connection=Connection +label_field_device_connection_handshake=Last handshake +label_field_device_connection_handshake_ago=ago +label_field_device_transfer_sent=sent +label_field_device_transfer_received=received label_field_device_ctime=Added label_device_ctime_format={{MMM}} {{d}}, {{YYYY}} / {{h}}:{{m}}{{a}} message_device_vpn_show_config=Show VPN connection info diff --git a/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties b/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties index 3ff441be..fc799bd3 100644 --- a/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties +++ b/bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties @@ -165,6 +165,20 @@ price_period_yearly_name=annually price_period_yearly_unit=year price_format={{messages['currency_symbol_'+currency.toUpperCase()]}}{{priceMajorUnits}}{{priceMinorUnits === 0 ? '' : priceMinorUnits < 10 ? '.0'+priceMinorUnits : '.'+priceMinorUnits}} {{messages['price_period_'+period+'_name']}} +# Time units +units_second=second +units_seconds=seconds +units_seconds_short=s +units_minute=minute +units_minutes=minutes +units_minutes_short=m +units_hour=hour +units_hours=hours +units_hours_short=h +units_day=day +units_days=days +units_days_short=d + currency_symbol_= currency_symbol_USD=$ diff --git a/bubble-server/src/main/resources/packer/roles/algo/files/wg_monitor_connections.sh b/bubble-server/src/main/resources/packer/roles/algo/files/wg_monitor_connections.sh index e038be21..e9ea815c 100644 --- a/bubble-server/src/main/resources/packer/roles/algo/files/wg_monitor_connections.sh +++ b/bubble-server/src/main/resources/packer/roles/algo/files/wg_monitor_connections.sh @@ -22,45 +22,90 @@ fi while : ; do peer="" + device="" + endpoint="" + latest_handshake="" + transfer="" IFS=$'\n' for line in $(wg show all) ; do - if [[ ! -z "${peer}" ]] ; then - if [[ $(echo "${line}" | tr -d ' ') == allowed* ]] ; then - for ip in $(echo "${line}" | cut -d: -f2- | tr ',' '\n' | tr -d ' ' | cut -d/ -f1) ; do - device_uuids="$(find $(find $(find ${ALGO_CONFIGS} -type d -name wireguard) -type d -name public) -type f | xargs grep -l ${peer} | xargs -n 1 basename)" - if [[ $(echo "${device_uuids}" | wc -l | tr -d ' ') -gt 1 ]] ; then - log "Multiple device UUIDs found for IP ${ip} (not recording anything): ${device_uuids}" - continue - fi - device="$(echo "${device_uuids}" | head -1 | tr -d ' ')" + if [[ ! -z "${peer}" ]] ; then + if [[ $(echo "${line}" | tr -d ' ') == endpoint* ]] ; then + endpoint="$(echo "${line}" | cut -d: -f2- | awk '{$1=$1};1')" - ip_file="${BUBBLE_DEVICE_DIR}/ip_$(echo ${ip})" - if [[ ! -f ${ip_file} ]] ; then - touch ${ip_file} && chown bubble ${ip_file} && chmod 400 ${ip_file} || log "Error creating ${ip_file}" - fi - device_exists=$(grep -c "${ip}" ${ip_file}) - if [[ ${device_exists} -eq 0 ]] ; then - log "recorded device ${device} for IP ${ip}" - echo "${device}" > ${ip_file} || log "Error writing ${device} to ${ip_file}" - fi + elif [[ $(echo "${line}" | tr -d ' ') == latest* ]] ; then + latest_handshake="$(echo "${line}" | cut -d: -f2- | awk '{$1=$1};1')" - device_file="${BUBBLE_DEVICE_DIR}/device_$(echo ${device})" - if [[ ! -f ${device_file} ]] ; then - touch ${device_file} && chown bubble ${device_file} && chmod 400 ${device_file} || log "Error creating ${ip_file}" - fi - ip_exists=$(grep -c "${ip}" ${device_file}) - if [[ ${ip_exists} -eq 0 ]] ; then - log "recorded IP ${ip} for device ${device}" - echo "${ip}" >> ${device_file} || log "Error writing ${ip} to ${device_file}" - fi + elif [[ $(echo "${line}" | tr -d ' ') == transfer* ]] ; then + transfer="$(echo "${line}" | cut -d: -f2- | awk '{$1=$1};1')" - done - peer="" - fi + elif [[ $(echo "${line}" | tr -d ' ') == allowed* ]] ; then + for ip in $(echo "${line}" | cut -d: -f2- | tr ',' '\n' | tr -d ' ' | cut -d/ -f1) ; do + device_uuids="$(find $(find $(find ${ALGO_CONFIGS} -type d -name wireguard) -type d -name public) -type f | xargs grep -l ${peer} | xargs -n 1 basename)" + if [[ $(echo "${device_uuids}" | wc -l | tr -d ' ') -gt 1 ]] ; then + log "Multiple device UUIDs found for IP ${ip} (not recording anything): ${device_uuids}" + continue + fi + device="$(echo "${device_uuids}" | head -1 | tr -d ' ')" + + ip_file="${BUBBLE_DEVICE_DIR}/ip_$(echo ${ip})" + if [[ ! -f ${ip_file} ]] ; then + touch ${ip_file} && chown bubble ${ip_file} && chmod 400 ${ip_file} || log "Error creating ${ip_file}" + fi + device_exists=$(grep -c "${ip}" ${ip_file}) + if [[ ${device_exists} -eq 0 ]] ; then + # log "recorded device ${device} for IP ${ip}" + echo "${device}" > ${ip_file} || log "Error writing ${device} to ${ip_file}" + fi + + device_file="${BUBBLE_DEVICE_DIR}/device_$(echo ${device})" + if [[ ! -f ${device_file} ]] ; then + touch ${device_file} && chown bubble ${device_file} && chmod 400 ${device_file} || log "Error creating ${ip_file}" + fi + ip_exists=$(grep -c "${ip}" ${device_file}) + if [[ ${ip_exists} -eq 0 ]] ; then + # log "recorded IP ${ip} for device ${device}" + echo "${ip}" >> ${device_file} || log "Error writing ${ip} to ${device_file}" + fi + done + fi + fi - elif [[ ${line} == peer* ]] ; then - peer="$(echo "${line}" | awk '{print $NF}')" + if [[ ${line} == peer* ]] ; then + if [[ ! -z "${peer}" ]] ; then + if [[ ! -z "${device}" ]] ; then + echo "in-loop, setting stats for peer ${peer} device ${device}" + if [[ ! -z "${endpoint}" ]] ; then + echo "set wg_device_status_${device}_endpoint \"${endpoint}\"" | redis-cli + fi + if [[ ! -z "${latest_handshake}" ]] ; then + echo "set wg_device_status_${device}_latestHandshake \"${latest_handshake}\"" | redis-cli + fi + if [[ ! -z "${transfer}" ]] ; then + echo "set wg_device_status_${device}_transfer \"${transfer}\"" | redis-cli + fi + fi fi + peer="$(echo "${line}" | awk '{print $NF}')" + device="" + endpoint="" + latest_handshake="" + transfer="" + echo "in-loop, set peer: ${peer}" + fi done - sleep 30s + if [[ ! -z "${peer}" ]] ; then + echo "end-of-loop, setting stats for peer ${peer} device ${device}" + if [[ ! -z "${device}" ]] ; then + if [[ ! -z "${endpoint}" ]] ; then + echo "set wg_device_status_${device}_endpoint \"${endpoint}\"" | redis-cli + fi + if [[ ! -z "${latest_handshake}" ]] ; then + echo "set wg_device_status_${device}_latestHandshake \"${latest_handshake}\"" | redis-cli + fi + if [[ ! -z "${transfer}" ]] ; then + echo "set wg_device_status_${device}_transfer \"${transfer}\"" | redis-cli + fi + fi + fi + sleep 10s done diff --git a/bubble-server/src/main/resources/packer/roles/common/files/ensure_file_exists.sh b/bubble-server/src/main/resources/packer/roles/common/files/ensure_file_exists.sh index 6b468868..8f9f3a23 100644 --- a/bubble-server/src/main/resources/packer/roles/common/files/ensure_file_exists.sh +++ b/bubble-server/src/main/resources/packer/roles/common/files/ensure_file_exists.sh @@ -4,14 +4,16 @@ # TARGET_FILE=${1:?no target file provided} TIMEOUT=${2:?no timeout provided} +LOG=/tmp/ensure_file_$(echo ${TARGET_FILE} | tr '/' '_').log start=$(date +%s) while [[ ! -f ${TARGET_FILE} && $(expr $(date +%s) - ${start}) -le ${TIMEOUT} ]] ; do - echo "$(date): $0: waiting for target file to exist ${TARGET_FILE} (will timeout after ${TIMEOUT} seconds)" + echo "$(date): $0: waiting for target file to exist ${TARGET_FILE} (will timeout after ${TIMEOUT} seconds)" | tee -a ${LOG} sleep 1s done if [[ ! -f ${TARGET_FILE} ]] ; then - echo "target file did not get created: ${TARGET_FILE} (timeout after ${TIMEOUT} seconds)" + echo "target file did not get created: ${TARGET_FILE} (timeout after ${TIMEOUT} seconds)" | tee -a ${LOG} exit 1 fi +echo "target file has been created: ${TARGET_FILE}" | tee -a ${LOG} \ No newline at end of file diff --git a/bubble-web b/bubble-web index 6095552f..ddc83845 160000 --- a/bubble-web +++ b/bubble-web @@ -1 +1 @@ -Subproject commit 6095552f8359790d073a891eb4bcbd31bb1db3ed +Subproject commit ddc83845f63066c5388e9e5fa97735a5592fcd98 diff --git a/utils/cobbzilla-utils b/utils/cobbzilla-utils index 77a88753..009a52ed 160000 --- a/utils/cobbzilla-utils +++ b/utils/cobbzilla-utils @@ -1 +1 @@ -Subproject commit 77a8875358d5878da929783862d70d023bb3ad40 +Subproject commit 009a52edb53315fcb7d90c9feed382970aa9a4b8