# SPDX-FileCopyrightText: 2022 The Tor Project, Inc.
#
# SPDX-License-Identifier: BSD-3-Clause
import datetime
import logging
from django.db import models
from .base import BaseModel
logger = logging.getLogger(__name__)
BWLINE_KEYS = [
"node_id",
"nick",
"bw",
"bw_mean",
"bw_median",
"consensus_bandwidth",
"consensus_bandwidth_is_unmeasured",
"desc_bw_avg",
"desc_bw_bur",
"desc_bw_obs_last",
"desc_bw_obs_mean",
"error_circ",
"error_destination",
"error_misc",
"error_second_relay",
"error_stream",
"master_key_ed25519",
"relay_in_recent_consensus_count",
"relay_recent_measurement_attempt_count",
"relay_recent_measurements_excluded_error_count",
"relay_recent_priority_list_count",
"success",
"time",
"measured_at",
"updated_at",
"unmeasured",
"vote",
"circ_fail",
"pid_delta",
"pid_bw",
"pid_error",
"pid_error_sum",
]
BWLINE2RELABW = {
"node_id": "fingerprint",
"nick": "nickname",
# "time": "measured_at",
# "measured_at": "updated_at"
}
[docs]
class RelayBwManagerBase(models.Manager):
pass
[docs]
class RelayBwBase(BaseModel):
objects = RelayBwManagerBase()
fingerprint = models.CharField(max_length=40)
measured_at = models.DateTimeField(editable=True, null=True, blank=True)
updated_at = models.DateTimeField(editable=True, null=True, blank=True)
nickname = models.CharField(max_length=19, null=True, blank=True)
bw = models.PositiveIntegerField(null=True, blank=True)
consensus_bandwidth = models.PositiveIntegerField(null=True, blank=True)
consensus_bandwidth_is_unmeasured = models.BooleanField(
null=True, blank=True
)
desc_bw_avg = models.PositiveIntegerField(null=True, blank=True)
desc_bw_bur = models.PositiveIntegerField(null=True, blank=True)
desc_bw_obs_last = models.PositiveIntegerField(null=True, blank=True)
error_circ = models.PositiveSmallIntegerField(null=True, blank=True)
error_stream = models.PositiveSmallIntegerField(null=True, blank=True)
relay_in_recent_consensus_count = models.PositiveSmallIntegerField(
null=True, blank=True
)
relay_recent_measurement_attempt_count = models.PositiveSmallIntegerField(
null=True, blank=True
)
relay_recent_measurement_failure_count = models.PositiveSmallIntegerField(
null=True, blank=True
)
relay_recent_measurements_excluded_error_count = (
models.PositiveSmallIntegerField(null=True, blank=True)
)
relay_recent_priority_list_count = models.PositiveSmallIntegerField(
null=True, blank=True
)
success = models.PositiveSmallIntegerField(null=True, blank=True)
vote = models.BooleanField(null=True, blank=True)
under_min_report = models.BooleanField(null=True, blank=True)
def __str__(self):
return self.nickname
# for admin
[docs]
def relay_relaydesc_latest(self):
if not self.relay:
return None
return self.relay.relaydesc_latest()
[docs]
def relay_routerstatus_latest(self):
if not self.relay:
return None
return self.relay.routerstatus_latest()
[docs]
def is_exit(self):
rs_last = self.relay_routerstatus_latest()
if rs_last:
return rs_last.is_exit
return None
[docs]
def to_str_v15(self):
from onbasca.base import constants
kwargs = dict([(k, getattr(self, k, "")) for k in BWLINE_KEYS])
for k, v in BWLINE2RELABW.items():
kwargs[k] = getattr(self, v, None)
kwargs["node_id"] = "$" + kwargs["node_id"]
kwargs.pop("measured_at")
kwargs.pop("updated_at")
if kwargs["vote"] is not False:
kwargs.pop("vote")
if not kwargs["unmeasured"]:
kwargs.pop("unmeasured")
key_values = []
for key, value in sorted(kwargs.items()):
logger.debug("%s: %s", key, value)
# Ignore Torflow KeyValues atm.
if key.startswith("pid") or key.startswith("circ"):
continue
if isinstance(value, bool):
value = int(value)
if value is None:
value = 0
if isinstance(value, datetime.datetime):
value = value.strftime(constants.DATETIME_FORMAT)
key_values.append("{}={}".format(key, value))
key_values_str = " ".join(key_values)
return key_values_str
[docs]
def to_str(self):
return self.to_str_v15()