Skip to content

Commit 9521d88

Browse files
authored
Merge pull request #249 from guydavis/integration
v0.5.3 release
2 parents 5d1ac0d + ec81679 commit 9521d88

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2209
-959
lines changed

.github/workflows/develop.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
platforms: linux/amd64
4040
push: true
4141
build-args: |
42-
"CHIA_BRANCH=1.2.3"
42+
"CHIA_BRANCH=1.2.4"
4343
"FLAX_BRANCH=main"
4444
tags: |
4545
${{ secrets.DOCKERHUB_USERNAME }}/machinaris:develop

.github/workflows/main.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
platforms: linux/amd64,linux/arm64
4141
push: true
4242
build-args: |
43-
"CHIA_BRANCH=1.2.3"
43+
"CHIA_BRANCH=1.2.4"
4444
"FLAX_BRANCH=main"
4545
tags: |
4646
${{ secrets.DOCKERHUB_USERNAME }}/machinaris:latest

.github/workflows/test.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
platforms: linux/amd64,linux/arm64
4040
push: true
4141
build-args: |
42-
"CHIA_BRANCH=1.2.3"
42+
"CHIA_BRANCH=1.2.4"
4343
"FLAX_BRANCH=main"
4444
tags: |
4545
${{ secrets.DOCKERHUB_USERNAME }}/machinaris:test

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
44

5+
## [0.5.3] - 2021-08-27
6+
7+
- Worker page for each worker shows Warnings for certain configuraton issues.
8+
- Farming page now shows current disk usage for each drive (free and used)
9+
- Plotting page now shows recent disk usage for each drive (free and used)
10+
- Summary page now charts recent blockchain challenges and partial proofs
11+
- Fixes from feedback received by users on the Machinaris Discord. Thanks all!
12+
- Chia - Update to version 1.2.4. See their [changelog for details](https://github.com/Chia-Network/chia-blockchain/releases/tag/1.2.4).
13+
514
## [0.5.2] - 2021-08-13
615

716
- Machinaris - Docker images now available for [Apple M1](https://github.com/guydavis/machinaris/issues/43) and [Raspberry Pi OS](https://github.com/guydavis/machinaris/issues/155) architectures.

CREDITS.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ A huge thank-you to the great teams/devs behind these projects, being used by Ma
1919
* [Boostrap Sidebars](https://dev.to/codeply/bootstrap-5-sidebar-examples-38pb): Used for sidebar menu layout.
2020
* [Toplevel](https://github.com/and-semakin/marshmallow-toplevel): Used for list of objects sent to REST API.
2121
* [DataTables.js](https://datatables.net/): Filter/search/pagination of dynamic tables, as per [this tutorial](https://blog.miguelgrinberg.com/post/beautiful-interactive-tables-for-your-flask-templates).
22+
* [Charts.js](https://www.chartjs.org/): dynamic charting library.
2223

2324
## Blockchain Forks
2425
* [Flax](https://github.com/Flax-Network/flax-blockchain)
@@ -53,7 +54,7 @@ A big thanks to all that contributed with dev and test including:
5354
* dartec
5455
* elexx
5556
* danicraftscz
56-
57+
* Kris Moore
5758

5859
## Trademark Notice
5960
CHIA NETWORK INC, CHIA™, the CHIA BLOCKCHAIN™, the CHIA PROTOCOL™, CHIALISP™ and the “leaf Logo” (including the leaf logo alone when it refers to or indicates Chia), are trademarks or registered trademarks of Chia Network, Inc., a Delaware corporation. *There is no affliation between this Machinaris project and the main Chia Network project.*

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# machinaris
22

3-
A Docker image for plotting and farming the Chia™ cryptocurrency on [one computer](https://github.com/guydavis/machinaris/wiki/Docker) or across [many](https://github.com/guydavis/machinaris/wiki/Workers). Try the easy install using [Launch Wizard](https://machinaris.app).
3+
A Docker image for plotting and farming the Chia™ cryptocurrency on [one computer](https://github.com/guydavis/machinaris/wiki/Docker) or across [many](https://github.com/guydavis/machinaris/wiki/Workers). Try the easy install using the [Launch Wizard](https://machinaris.app).
44

55
![Home](https://raw.githubusercontent.com/guydavis/machinaris-unraid/master/docs/img/machinaris_home.png)
66

SECURITY.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Security Policy
2+
3+
## Supported Versions
4+
5+
Machinaris security patches will be made for the [current release](https://github.com/guydavis/machinaris/wiki/Releases#release-streams), aka `:latest`.
6+
7+
## Reporting a Vulnerability
8+
9+
Please create a new [Discussion](https://github.com/guydavis/machinaris/discussions) with full details of the vulnerability. I will provide a response asap. Thanks in advance!

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.5.2
1+
0.5.3

api/commands/chia_cli.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ def load_farm_summary(blockchain):
4848
proc.communicate()
4949
abort(500, description="The timeout is expired!")
5050
if errs:
51-
app.logger.info("Failed to load chia farm summary at.")
52-
app.logger.info(traceback.format_exc())
51+
app.logger.debug("Error from {0} farm summary because {1}".format(blockchain, outs.decode('utf-8')))
5352
farm_summary = chia.FarmSummary(cli_stdout=outs.decode('utf-8').splitlines())
5453
else: # Just get plot count and size
5554
farm_summary = chia.FarmSummary(farm_plots=load_plots_farming())
@@ -98,7 +97,7 @@ def load_wallet_show(blockchain):
9897
child = pexpect.spawn("{0} wallet show".format(chia_binary))
9998
wallet_index = 1
10099
while True:
101-
i = child.expect(["Wallet height:.*\r\n", "Choose wallet key:.*\r\n", "No online backup file found.*\r\n"])
100+
i = child.expect(["Wallet height:.*\r\n", "Choose wallet key:.*\r\n", "No online backup file found.*\r\n"], timeout=120)
102101
if i == 0:
103102
app.logger.debug("wallet show returned 'Wallet height...' so collecting details.")
104103
wallet_show += child.after.decode("utf-8") + child.before.decode("utf-8") + child.read().decode("utf-8")
@@ -120,7 +119,7 @@ def load_plotnft_show(blockchain):
120119
child = pexpect.spawn("{0} plotnft show".format(chia_binary))
121120
wallet_index = 1
122121
while True:
123-
i = child.expect(["Wallet height:.*\r\n", "Choose wallet key:.*\r\n", "No online backup file found.*\r\n"])
122+
i = child.expect(["Wallet height:.*\r\n", "Choose wallet key:.*\r\n", "No online backup file found.*\r\n"], timeout=120)
124123
if i == 0:
125124
app.logger.debug("wallet show returned 'Wallet height...' so collecting details.")
126125
wallet_show += child.after.decode("utf-8") + child.before.decode("utf-8") + child.read().decode("utf-8")

api/commands/chiadog_cli.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,12 @@ def dispatch_action(job):
6161
else:
6262
raise Exception("Unsupported action {0} for monitoring.".format(action))
6363

64-
def start_chiadog():
64+
def start_chiadog(chain = None):
6565
#app.logger.info("Starting monitoring....")
66-
blockchains = [ b.strip() for b in os.environ['blockchains'].split(',') ]
66+
if chain:
67+
blockchains = [ chain ]
68+
else:
69+
blockchains = [ b.strip() for b in os.environ['blockchains'].split(',') ]
6770
for blockchain in blockchains:
6871
try:
6972
workdir = "/{0}dog".format(blockchain)

api/commands/log_parser.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
CHIA_LOG = '/root/.chia/mainnet/log/debug.log'
2525
FLAX_LOG = '/root/.flax/mainnet/log/debug.log'
2626

27-
# Roughly 1 minutes worth of challenges
28-
CHALLENGES_TO_LOAD = 8
27+
# Roughly 2 minutes worth of challenges, sent 90 seconds, for overlap
28+
CHALLENGES_TO_LOAD = 16
2929

3030
# Most recent partial proofs, actually double as 2 log lines per partial
3131
PARTIALS_TO_LOAD = 50

api/gunicorn.conf.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ def on_starting(server):
2424
#scheduler.add_job(func=stats_disk.collect, trigger='interval', seconds=10) # Test immediately
2525

2626
# Status gathering - reported via API
27-
scheduler.add_job(func=status_challenges.update, name="challenges", trigger='interval', seconds=5)
28-
scheduler.add_job(func=status_worker.update, name="workers", trigger='interval', seconds=60, jitter=30)
29-
scheduler.add_job(func=status_controller.update, name="controller", trigger='interval', seconds=60, jitter=30)
30-
scheduler.add_job(func=status_farm.update, name="farms", trigger='interval', seconds=60, jitter=30)
31-
scheduler.add_job(func=status_plotting.update, name="plottings", trigger='interval', seconds=60, jitter=30)
32-
scheduler.add_job(func=status_plots.update, name="plots", trigger='interval', seconds=60, jitter=30)
33-
scheduler.add_job(func=status_wallets.update, name="wallets", trigger='interval', seconds=60, jitter=30)
34-
scheduler.add_job(func=status_plotnfts.update, name="plotnfts", trigger='interval', seconds=60, jitter=30)
35-
scheduler.add_job(func=status_blockchains.update, name="blockchains", trigger='interval', seconds=60, jitter=30)
36-
scheduler.add_job(func=status_connections.update, name="connections", trigger='interval', seconds=60, jitter=30)
37-
scheduler.add_job(func=status_keys.update, name="keys", trigger='interval', seconds=60, jitter=30)
38-
scheduler.add_job(func=status_alerts.update, name="alerts", trigger='interval', seconds=60, jitter=30)
39-
scheduler.add_job(func=status_pools.update, name="pools", trigger='interval', seconds=60, jitter=30)
40-
scheduler.add_job(func=status_partials.update, name="partials", trigger='interval', seconds=60, jitter=30)
27+
scheduler.add_job(func=status_challenges.update, name="challenges", trigger='interval', seconds=90, jitter=45)
28+
scheduler.add_job(func=status_worker.update, name="workers", trigger='interval', seconds=120, jitter=60)
29+
scheduler.add_job(func=status_controller.update, name="controller", trigger='interval', seconds=120, jitter=60)
30+
scheduler.add_job(func=status_farm.update, name="farms", trigger='interval', seconds=120, jitter=60)
31+
scheduler.add_job(func=status_plotting.update, name="plottings", trigger='interval', seconds=120, jitter=60)
32+
scheduler.add_job(func=status_plots.update, name="plots", trigger='interval', seconds=300, jitter=150)
33+
scheduler.add_job(func=status_wallets.update, name="wallets", trigger='interval', seconds=600, jitter=300)
34+
scheduler.add_job(func=status_plotnfts.update, name="plotnfts", trigger='interval', seconds=600, jitter=300)
35+
scheduler.add_job(func=status_blockchains.update, name="blockchains", trigger='interval', seconds=300, jitter=150)
36+
scheduler.add_job(func=status_connections.update, name="connections", trigger='interval', seconds=300, jitter=150)
37+
scheduler.add_job(func=status_keys.update, name="keys", trigger='interval', seconds=600, jitter=300)
38+
scheduler.add_job(func=status_alerts.update, name="alerts", trigger='interval', seconds=300, jitter=150)
39+
scheduler.add_job(func=status_pools.update, name="pools", trigger='interval', seconds=300, jitter=150)
40+
scheduler.add_job(func=status_partials.update, name="partials", trigger='interval', seconds=300, jitter=150)
4141

4242
#scheduler.add_job(func=status_points.update, name="points", trigger='interval', seconds=10, jitter=0)
4343
app.logger.debug("Starting background scheduler...")

api/models/chia.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def __init__(self, cli_stdout=None, farm_plots=None):
1616
if cli_stdout:
1717
next_line_local_harvester = False
1818
self.plot_count = 0
19-
self.plots_size = None
19+
self.plots_size = 0
2020
for line in cli_stdout:
2121
if next_line_local_harvester:
2222
self.plot_count = line.strip().split(' ')[0]
@@ -28,12 +28,8 @@ def __init__(self, cli_stdout=None, farm_plots=None):
2828
self.total_chia = line.split(':')[1].strip()
2929
elif "Total flax farmed" in line:
3030
self.total_chia = line.split(':')[1].strip()
31-
elif "Plot count:" in line:
32-
self.plot_count = line.split(':')[1].strip()
3331
elif "Local Harvester" in line:
3432
next_line_local_harvester = True
35-
elif not self.plots_size and "Total size of plots" in line:
36-
self.plots_size = line.split(':')[1].strip()
3733
elif "Estimated network space" in line:
3834
self.calc_netspace_size(line.split(':')[1].strip())
3935
elif "Expected time to win" in line:

api/models/log.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,25 @@ class Partials:
3636
def __init__(self, cli_stdout):
3737
self.columns = [ 'challenge_id', 'plots_past_filter', 'proofs_found', 'time_taken', 'created_at']
3838
self.rows = []
39+
launcher_id = None
3940
for line in cli_stdout:
4041
try:
4142
if "Submitting partial" in line:
4243
app.logger.debug(line)
4344
created_at = line.split()[0].replace('T', ' ')
4445
launcher_id = re.search('partial for (\w+) to', line, re.IGNORECASE).group(1)
4546
pool_url = re.search('to (.*)$', line, re.IGNORECASE).group(1)
46-
elif "Pool response" in line:
47+
elif "Pool response" in line and launcher_id:
4748
pool_response = line[line.index('{'):]
4849
self.rows.append({
4950
'launcher_id': launcher_id,
5051
'pool_url': pool_url.strip(),
5152
'pool_response': pool_response,
5253
'created_at': created_at
5354
})
55+
created_at = None
56+
launcher_id = None
57+
pool_url = None
5458
except:
5559
app.logger.info("Failed to parse partial line: {0}".format(line))
5660
app.logger.info(traceback.format_exc())

api/schedules/stats_disk.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
from flask import g
1313

1414
from common.config import globals
15-
from api import app
15+
from common.models import stats
16+
from api import app, utils
1617

1718
DATABASE = '/root/.chia/machinaris/dbs/stats.db'
1819

1920
TABLES = ['stat_plots_total_used', 'stat_plots_disk_used', 'stat_plots_disk_free',
2021
'stat_plotting_total_used', 'stat_plotting_disk_used', 'stat_plotting_disk_free']
2122

22-
DELETE_OLD_STATS_AFTER_DAYS = 2
23+
DELETE_OLD_STATS_AFTER_DAYS = 1
2324

2425
def get_db():
2526
db = getattr(g, '_stats_database', None)
@@ -89,3 +90,25 @@ def collect():
8990
store_disk_stats(db, current_datetime, 'plots')
9091
if gc['plotting_enabled']:
9192
store_disk_stats(db, current_datetime, 'plotting')
93+
if not gc['is_controller']:
94+
send_stats(stats.StatPlottingDiskUsed, '/stats/plottingdiskused')
95+
send_stats(stats.StatPlottingDiskFree, '/stats/plottingdiskfree')
96+
send_stats(stats.StatPlotsDiskUsed, '/stats/plotsdiskused')
97+
send_stats(stats.StatPlotsDiskFree, '/stats/plotsdiskfree')
98+
99+
def send_stats(model, endpoint):
100+
from api import db
101+
try:
102+
hostname = utils.get_displayname()
103+
payload = []
104+
for stat in db.session.query(model).all():
105+
payload.append({
106+
"hostname": stat.hostname,
107+
"path": stat.path,
108+
"value": stat.value,
109+
"created_at": stat.created_at,
110+
})
111+
utils.send_post(endpoint, payload, debug=False)
112+
except:
113+
app.logger.info("Failed to load recent {0} stats and send.".format(endpoint))
114+
app.logger.info(traceback.format_exc())

api/schedules/status_alerts.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def update():
3838
first_run = False
3939
else: # On subsequent schedules, load only last 5 minutes.
4040
since = (datetime.datetime.now() - datetime.timedelta(minutes=5)).strftime("%Y-%m-%d %H:%M:%S.000")
41-
alerts = db.session.query(a.Alert).filter(a.Alert.created_at >= since).order_by(a.Alert.created_at.desc()).limit(20).all()
41+
alerts = db.session.query(a.Alert).filter(a.Alert.created_at >= since, a.Alert.hostname == hostname).order_by(a.Alert.created_at.desc()).limit(20).all()
4242
payload = []
4343
for alert in alerts:
4444
payload.append({

api/schedules/status_challenges.py

+16
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,38 @@
22
# Performs a REST call to controller (possibly localhost) of latest blockchain challenges.
33
#
44

5+
import datetime
56
import os
67
import traceback
78

89
from flask import g
910

1011
from common.config import globals
12+
from common.models import challenges as c
1113
from common.utils import converters
1214
from api import app
1315
from api.commands import log_parser
1416
from api import utils
1517

18+
def delete_old_challenges(db):
19+
try:
20+
cutoff = datetime.datetime.now() - datetime.timedelta(hours=1)
21+
cutoff_str = "{0}".format(cutoff.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3])
22+
#app.logger.info("Purging old challenges earlier than {0}".format(cutoff_str))
23+
db.session.query(c.Challenge).filter(c.Challenge.created_at < cutoff_str).delete()
24+
db.session.commit()
25+
except:
26+
app.logger.info("Failed to delete old challenges.")
27+
app.logger.info(traceback.format_exc())
28+
1629
def update():
1730
if not globals.farming_enabled() and not globals.harvesting_enabled():
1831
#app.logger.info("Skipping recent challenges collection on plotting-only instance.")
1932
return
2033
with app.app_context():
34+
from api import db
35+
if globals.load()['is_controller']:
36+
delete_old_challenges(db)
2137
try:
2238
hostname = utils.get_displayname()
2339
blockchains = ['chia']

api/schedules/status_farm.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313
from api.commands import chia_cli
1414
from api import utils
1515

16+
# On initialization Chia outputs
17+
def safely_gather_plots_size_gibs(plots_size):
18+
plots_size_gibs = 0
19+
try:
20+
plots_size_gibs = converters.str_to_gibs(plots_size)
21+
except:
22+
app.logger.info("Unconvertable plots size: {0} Using zero.".format(plots_size))
23+
plots_size_gibs = 0
24+
try:
25+
float(plots_size_gibs)
26+
except:
27+
app.logger.info("Unfloatable plots size: {0} Using zero.".format(plots_size))
28+
plots_size_gibs = 0
29+
return plots_size_gibs
30+
1631
def update():
1732
if not globals.farming_enabled() and not globals.harvesting_enabled():
1833
#app.logger.info("Skipping farm summary status collection on plotting-only instance.")
@@ -26,7 +41,7 @@ def update():
2641
"mode": os.environ['mode'],
2742
"status": "" if not hasattr(farm_summary, 'status') else farm_summary.status,
2843
"plot_count": farm_summary.plot_count,
29-
"plots_size": converters.str_to_gibs(farm_summary.plots_size),
44+
"plots_size": safely_gather_plots_size_gibs(farm_summary.plots_size),
3045
"total_chia": 0 if not hasattr(farm_summary, 'total_chia') else farm_summary.total_chia,
3146
"netspace_size": 0 if not hasattr(farm_summary, 'netspace_size') else converters.str_to_gibs(farm_summary.netspace_size),
3247
"expected_time_to_win": "" if not hasattr(farm_summary, 'time_to_win') else farm_summary.time_to_win,

0 commit comments

Comments
 (0)