Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ssh remote connection & validator installation for sn12 #39

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fff2ba6
feat: add validator installation scripts
drunest Sep 24, 2024
36e6be5
feat: add remote validator installation
drunest Sep 24, 2024
439a22b
chore: update script files
drunest Sep 25, 2024
51c4e58
feat: add remote installation
drunest Sep 25, 2024
d565298
feat: add action of installing validator on a remote server
drunest Sep 25, 2024
219687c
feat: add local scripts directory path
drunest Sep 25, 2024
213b0f2
chore: update scrips and secret
drunest Sep 25, 2024
02dd38f
chore: update pdm dependencies
drunest Sep 25, 2024
2f02c31
fix: update codespell
drunest Sep 25, 2024
d8c76b6
fix: update script file for linter
drunest Sep 25, 2024
b60b338
Merge branch 'master' into development
drunest Sep 30, 2024
0e5bf69
feat: add local scripts directory path
drunest Sep 25, 2024
51f3d7c
chore: update pdm dependencies
drunest Sep 25, 2024
af6d047
fix: udpate pdm lock
drunest Sep 28, 2024
a4c9374
feat: codename list on config file
drunest Oct 1, 2024
802b818
feat: dumper commands and codename api
drunest Oct 1, 2024
4126a22
feat: generating new child hotkey and hotkey option
drunest Oct 1, 2024
2236701
chore: pdm dependencies
drunest Oct 1, 2024
30327dc
chore: ruff format
drunest Oct 1, 2024
d820370
fix: store child hotkey to the model
drunest Oct 1, 2024
40c4460
perf: remove normalizing codename api
drunest Oct 4, 2024
408f542
fix: delete .env.template on local scripts
drunest Oct 7, 2024
20db475
refactor: separate dumper commands and view
drunest Oct 7, 2024
e85643c
update: creat wallet
drunest Oct 7, 2024
8feec14
update: add wallet info on settings
drunest Oct 7, 2024
291a4ff
refactor: add ssh childhotkey class
drunest Oct 7, 2024
7031184
perf: update utils
drunest Oct 7, 2024
e425673
fix: remove codename list
drunest Oct 7, 2024
9dc4262
chore: update dependencies
drunest Oct 7, 2024
6667ac6
chore: update chilhotkey
drunest Oct 7, 2024
cd62d68
refactor: revoke conftest
drunest Oct 7, 2024
bc6c88f
fix: update new version of wallet
drunest Oct 7, 2024
944397b
fix: update test conf
drunest Oct 7, 2024
7dea1d9
fix: test config
drunest Oct 8, 2024
c2582a0
chore: update dependencies
drunest Oct 8, 2024
e95e9c8
test: update config
drunest Oct 8, 2024
a34b0c5
fix: update scripts config path
drunest Oct 8, 2024
15cea39
feat: add pulling scripts from github
drunest Oct 8, 2024
c87dc95
update: vsubnet configuration path
drunest Oct 10, 2024
74a33ab
update: log format and error handling
drunest Oct 10, 2024
d0d7b9c
update: separate subnet scripts path and configuration file path
drunest Oct 10, 2024
0eecc4e
feat: add celery task for fetching subnet scripts periodically
drunest Oct 10, 2024
54b6441
fix: setting variable name on util
drunest Oct 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 4 additions & 30 deletions app/src/auto_validator/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
UploadedFile,
ValidatorInstance,
)
from auto_validator.core.utils.utils import fetch_and_compare_subnets, install_validator_on_remote_server
from auto_validator.core.utils.utils import fetch_and_compare_subnets

admin.site.site_header = "auto_validator Administration"
admin.site.site_title = "auto_validator"
Expand All @@ -32,10 +32,9 @@ class UploadedFileAdmin(admin.ModelAdmin):
@admin.register(Subnet)
class SubnetAdmin(admin.ModelAdmin):
list_display = (
"name",
"description",
"mainnet_id",
"testnet_id",
"codename",
"mainnet_netuid",
"testnet_netuid",
"owner_nick",
"registered_networks",
)
Expand Down Expand Up @@ -107,31 +106,6 @@ def get_queryset(self, request):
is_registered.admin_order_field = "is_registered_sort"
is_registered.short_description = "Is Registered"

def install_validator(self, request, queryset):
if queryset.count() > 1:
self.message_user(request, "Please select only one subnet slot.", level="ERROR")
return
subnet_slot = queryset.first()
# change the path to the actual path of the private key
# change the hotkey to the actual hotkey of the validator
# change the IP address to the actual IP address of the server
# change the username to the actual username of the server
# change the path to the actual path of the private key
# change the passphrase to the actual passphrase of the private key
install_validator_on_remote_server(
subnet_slot.subnet.codename,
subnet_slot.blockchain,
subnet_slot.netuid,
"/root/.bittensor/wallets/validator",
"validator-hotkey",
"219.15.67.27",
"root",
"/root/.ssh/id_rsa",
"1234567890",
)

actions = [install_validator]


@admin.register(ValidatorInstance)
class ValidatorInstanceAdmin(admin.ModelAdmin):
Expand Down
33 changes: 17 additions & 16 deletions app/src/auto_validator/core/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import yaml
import logging
import pathlib

from django.conf import settings
from rest_framework import mixins, parsers, routers, status, viewsets
from rest_framework.exceptions import AuthenticationFailed
Expand All @@ -11,8 +13,12 @@

from .authentication import HotkeyAuthentication
from .utils.bot import trigger_bot_send_message
from .utils.utils import get_dumper_commands

SUBNETS_CONFIG_PATH = pathlib.Path(settings.LOCAL_SUBNETS_SCRIPTS_PATH) / "subnets.yaml"

YAML_FILE_PATH = settings.LOCAL_SUBNETS_SCRIPTS_PATH + "/subnets.yaml"
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)


class FilesViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
Expand Down Expand Up @@ -62,20 +68,15 @@ class DumperCommandsViewSet(viewsets.ViewSet):
def list(self, request):
subnet_identifier = request.headers.get("SubnetID")
if not subnet_identifier:
return Response({"error": "subnet_identifier is required"}, status=status.HTTP_400_BAD_REQUEST)

try:
with open(YAML_FILE_PATH) as file:
data = yaml.safe_load(file)
codename_lower = subnet_identifier.lower()
for normalized_codename, sn_config in data.items():
codenames = sn_config.get("codename_list", [])
if codename_lower in map(str.lower, codenames):
return Response((normalized_codename, sn_config.get("dumper_commands", [])))
else:
return Response({"error": "subnet_identifier not found"}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response({"error": "SubnetID is required"}, status=status.HTTP_400_BAD_REQUEST)

dumper_commands = get_dumper_commands(subnet_identifier, SUBNETS_CONFIG_PATH)
if dumper_commands is not None:
logger.info(f"SubnetID: {subnet_identifier}, dumper_commands: {dumper_commands}")
return Response(dumper_commands)
drunest marked this conversation as resolved.
Show resolved Hide resolved
else:
logger.error(f"SubnetID: {subnet_identifier} not found")
return Response({"error": "SubnetID not found"}, status=status.HTTP_404_NOT_FOUND)


class APIRootView(routers.DefaultRouter.APIRootView):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Generated by Django 4.2.16 on 2024-10-08 01:54

import django.contrib.postgres.fields
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("core", "0011_alter_subnet_hw_requirements"),
]

operations = [
migrations.RenameField(
model_name="subnet",
old_name="hw_requirements",
new_name="hardware_description",
),
migrations.RenameField(
model_name="subnet",
old_name="mainnet_id",
new_name="mainnet_netuid",
),
migrations.RenameField(
model_name="subnet",
old_name="maintainers_ids",
new_name="maintainer_discord_ids",
),
migrations.RenameField(
model_name="subnet",
old_name="owner_id",
new_name="owner_discord_id",
),
migrations.RenameField(
model_name="subnet",
old_name="testnet_id",
new_name="testnet_netuid",
),
migrations.AddField(
model_name="subnet",
name="allowed_secrets",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.CharField(max_length=255),
blank=True,
null=True,
size=None,
),
),
migrations.AddField(
model_name="subnet",
name="dumper_commands",
field=django.contrib.postgres.fields.ArrayField(
base_field=models.CharField(max_length=255),
blank=True,
null=True,
size=None,
),
),
]
12 changes: 7 additions & 5 deletions app/src/auto_validator/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ class Subnet(models.Model):
description = models.TextField(null=True, blank=True)
operators = models.ManyToManyField("Operator", related_name="subnets", blank=True)
codename = models.CharField(max_length=255, null=True, blank=True)
mainnet_id = models.IntegerField(null=True, blank=True)
testnet_id = models.IntegerField(null=True, blank=True)
mainnet_netuid = models.IntegerField(null=True, blank=True)
testnet_netuid = models.IntegerField(null=True, blank=True)
owner_nick = models.CharField(max_length=255, null=True, blank=True)
owner_id = models.CharField(max_length=255, null=True, blank=True)
maintainers_ids = ArrayField(models.CharField(max_length=255), null=True, blank=True)
owner_discord_id = models.CharField(max_length=255, null=True, blank=True)
maintainer_discord_ids = ArrayField(models.CharField(max_length=255), null=True, blank=True)
github_repo = models.CharField(max_length=255, null=True, blank=True)
hw_requirements = models.TextField(max_length=4095, null=True, blank=True)
hardware_description = models.TextField(max_length=4095, null=True, blank=True)
allowed_secrets = ArrayField(models.CharField(max_length=255), null=True, blank=True)
dumper_commands = ArrayField(models.CharField(max_length=255), null=True, blank=True)

def registered_networks(self):
mainnet_slots = self.slots.filter(
Expand Down

This file was deleted.

This file was deleted.

19 changes: 0 additions & 19 deletions app/src/auto_validator/core/subnet_scripts/computehorde/install.sh

This file was deleted.

3 changes: 0 additions & 3 deletions app/src/auto_validator/core/subnet_scripts/secrets.csv

This file was deleted.

26 changes: 0 additions & 26 deletions app/src/auto_validator/core/subnet_scripts/subnets.yaml

This file was deleted.

44 changes: 6 additions & 38 deletions app/src/auto_validator/core/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from collections.abc import Generator

import bittensor as bt
import pexpect
import pytest
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient
Expand Down Expand Up @@ -86,42 +85,11 @@ def __eq__(self, other):
def wallet():
coldkey_name = "auto-validator7"
hotkey_name = "testhotkey7"
command1 = f"btcli wallet new_coldkey --wallet.name {coldkey_name}"
command2 = f"btcli wallet new_hotkey --wallet.name {coldkey_name} --wallet.hotkey {hotkey_name}"
has_coldkey = False
has_hotkey = False
password = "your_password_here"

try:
wallet = bt.wallet(name=coldkey_name, hotkey=hotkey_name)
wallet.coldkeypub # make sure wallet has coldkey file, if not, it will raise an exception
has_coldkey = True
wallet.hotkey # make sure wallet has hotkey file, if not, it will raise an exception
has_hotkey = True
except bt.KeyFileError:
if not has_coldkey:
process = pexpect.spawn(command1, timeout=30)
try:
process.expect("Specify password for key encryption:")
process.sendline(password)

process.expect("Retype your password:")
process.sendline(password)

process.expect(pexpect.EOF)
except pexpect.TIMEOUT:
print("Timeout occurred while creating coldkey.")
finally:
process.close()

if not has_hotkey:
process = pexpect.spawn(command2, timeout=30)
try:
process.expect(pexpect.EOF)
except pexpect.TIMEOUT:
print("Timeout occurred while creating hotkey.")
finally:
process.close()
wallet = bt.wallet(name=coldkey_name, hotkey=hotkey_name)

wallet = bt.Wallet(name=coldkey_name, hotkey=hotkey_name, path=".bittensor/wallets")
if not wallet.coldkey_file.exists_on_device():
wallet.create_new_coldkey(overwrite=True, use_password=False)
if not wallet.hotkey_file.exists_on_device():
wallet.create_new_hotkey(overwrite=True, use_password=False)

return wallet
Loading
Loading