Consolidate service scripts into apps directories
- Move blockchain scripts to apps/blockchain-node/scripts/ - Move marketplace scripts to apps/marketplace/scripts/ - Move agent daemon to apps/agent-coordinator/scripts/ - Move monitor to apps/monitor/ - Update systemd service files to point to new locations - Update internal path references in moved scripts - Remove empty /opt/aitbc/services directory
This commit is contained in:
223
apps/agent-coordinator/scripts/agent_daemon.py
Executable file
223
apps/agent-coordinator/scripts/agent_daemon.py
Executable file
@@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
AITBC Autonomous Agent Listener Daemon
|
||||
Listens for blockchain transactions addressed to an agent wallet and autonomously replies.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
import json
|
||||
import hashlib
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from cryptography.hazmat.primitives.asymmetric import ed25519
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
|
||||
# Default configuration
|
||||
DEFAULT_KEYSTORE_DIR = Path("/var/lib/aitbc/keystore")
|
||||
DEFAULT_DB_PATH = "/var/lib/aitbc/data/ait-mainnet/chain.db"
|
||||
DEFAULT_RPC_URL = "http://localhost:8006"
|
||||
DEFAULT_POLL_INTERVAL = 2
|
||||
|
||||
|
||||
def decrypt_wallet(keystore_path: Path, password: str) -> bytes:
|
||||
"""Decrypt private key from keystore file.
|
||||
|
||||
Supports both keystore formats:
|
||||
- AES-256-GCM (blockchain-node standard)
|
||||
- Fernet (scripts/utils standard)
|
||||
"""
|
||||
with open(keystore_path) as f:
|
||||
data = json.load(f)
|
||||
|
||||
crypto = data.get('crypto', data) # Handle both nested and flat crypto structures
|
||||
|
||||
# Detect encryption method
|
||||
cipher = crypto.get('cipher', crypto.get('algorithm', ''))
|
||||
|
||||
if cipher == 'aes-256-gcm':
|
||||
# AES-256-GCM (blockchain-node standard)
|
||||
salt = bytes.fromhex(crypto['kdfparams']['salt'])
|
||||
ciphertext = bytes.fromhex(crypto['ciphertext'])
|
||||
nonce = bytes.fromhex(crypto['cipherparams']['nonce'])
|
||||
|
||||
kdf = PBKDF2HMAC(
|
||||
algorithm=hashes.SHA256(),
|
||||
length=crypto['kdfparams']['dklen'],
|
||||
salt=salt,
|
||||
iterations=crypto['kdfparams']['c'],
|
||||
backend=default_backend()
|
||||
)
|
||||
key = kdf.derive(password.encode())
|
||||
aesgcm = AESGCM(key)
|
||||
return aesgcm.decrypt(nonce, ciphertext, None)
|
||||
|
||||
elif cipher == 'fernet' or cipher == 'PBKDF2-SHA256-Fernet':
|
||||
# Fernet (scripts/utils standard)
|
||||
from cryptography.fernet import Fernet
|
||||
import base64
|
||||
|
||||
kdfparams = crypto.get('kdfparams', {})
|
||||
if 'salt' in kdfparams:
|
||||
salt = base64.b64decode(kdfparams['salt'])
|
||||
else:
|
||||
salt = bytes.fromhex(kdfparams.get('salt', ''))
|
||||
|
||||
# Simple KDF: hash(password + salt) - matches scripts/utils/keystore.py
|
||||
dk = hashlib.sha256(password.encode() + salt).digest()
|
||||
fernet_key = base64.urlsafe_b64encode(dk)
|
||||
|
||||
f = Fernet(fernet_key)
|
||||
ciphertext = base64.b64decode(crypto['ciphertext'])
|
||||
priv = f.decrypt(ciphertext)
|
||||
return priv.encode()
|
||||
|
||||
else:
|
||||
raise ValueError(f"Unsupported cipher: {cipher}")
|
||||
|
||||
|
||||
def create_tx(private_bytes: bytes, from_addr: str, to_addr: str, amount: float, fee: float, payload: str) -> dict:
|
||||
"""Create and sign a transaction"""
|
||||
priv_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_bytes)
|
||||
pub_hex = priv_key.public_key().public_bytes(
|
||||
encoding=serialization.Encoding.Raw,
|
||||
format=serialization.PublicFormat.Raw
|
||||
).hex()
|
||||
|
||||
tx = {
|
||||
"type": "transfer",
|
||||
"from": from_addr,
|
||||
"to": to_addr,
|
||||
"amount": amount,
|
||||
"fee": fee,
|
||||
"nonce": int(time.time() * 1000),
|
||||
"payload": payload,
|
||||
"chain_id": "ait-mainnet"
|
||||
}
|
||||
|
||||
tx_string = json.dumps(tx, sort_keys=True)
|
||||
tx_hash = hashlib.sha256(tx_string.encode()).hexdigest()
|
||||
tx["signature"] = priv_key.sign(tx_string.encode()).hex()
|
||||
tx["public_key"] = pub_hex
|
||||
return tx
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="AITBC Autonomous Agent Listener Daemon")
|
||||
parser.add_argument("--wallet", required=True, help="Wallet name (e.g., temp-agent2)")
|
||||
parser.add_argument("--address", required=True, help="Agent wallet address")
|
||||
parser.add_argument("--password", help="Wallet password")
|
||||
parser.add_argument("--password-file", help="Path to file containing wallet password")
|
||||
parser.add_argument("--keystore-dir", default=DEFAULT_KEYSTORE_DIR, help="Keystore directory")
|
||||
parser.add_argument("--db-path", default=DEFAULT_DB_PATH, help="Path to blockchain database")
|
||||
parser.add_argument("--rpc-url", default=DEFAULT_RPC_URL, help="RPC endpoint URL")
|
||||
parser.add_argument("--poll-interval", type=int, default=DEFAULT_POLL_INTERVAL, help="Poll interval in seconds")
|
||||
parser.add_argument("--reply-message", default="pong", help="Message to send as reply")
|
||||
parser.add_argument("--trigger-message", default="ping", help="Message that triggers reply")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Get password
|
||||
if args.password_file:
|
||||
with open(args.password_file) as f:
|
||||
password = f.read().strip()
|
||||
elif args.password:
|
||||
password = args.password
|
||||
else:
|
||||
print("Error: password or password-file is required")
|
||||
sys.exit(1)
|
||||
|
||||
# Setup paths
|
||||
keystore_path = Path(args.keystore_dir) / f"{args.wallet}.json"
|
||||
|
||||
print(f"Agent daemon started. Listening for messages to {args.address}...")
|
||||
print(f"Trigger message: '{args.trigger_message}'")
|
||||
print(f"Reply message: '{args.reply_message}'")
|
||||
|
||||
# Decrypt wallet
|
||||
try:
|
||||
priv_bytes = decrypt_wallet(keystore_path, password)
|
||||
print("Wallet unlocked successfully.")
|
||||
except Exception as e:
|
||||
print(f"Failed to unlock wallet: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
# Setup database connection
|
||||
processed_txs = set()
|
||||
sys.path.insert(0, "/opt/aitbc/apps/blockchain-node/src")
|
||||
|
||||
try:
|
||||
from sqlmodel import create_engine, Session, select
|
||||
from aitbc_chain.models import Transaction
|
||||
|
||||
engine = create_engine(f"sqlite:///{args.db_path}")
|
||||
print(f"Connected to database: {args.db_path}")
|
||||
except ImportError as e:
|
||||
print(f"Error importing sqlmodel: {e}")
|
||||
print("Make sure sqlmodel is installed in the virtual environment")
|
||||
sys.exit(1)
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
# Main polling loop
|
||||
while True:
|
||||
try:
|
||||
with Session(engine) as session:
|
||||
txs = session.exec(
|
||||
select(Transaction).where(Transaction.recipient == args.address)
|
||||
).all()
|
||||
|
||||
for tx in txs:
|
||||
if tx.id in processed_txs:
|
||||
continue
|
||||
|
||||
processed_txs.add(tx.id)
|
||||
|
||||
# Extract payload
|
||||
data = ""
|
||||
if hasattr(tx, "tx_metadata") and tx.tx_metadata:
|
||||
if isinstance(tx.tx_metadata, dict):
|
||||
data = tx.tx_metadata.get("payload", "")
|
||||
elif isinstance(tx.tx_metadata, str):
|
||||
try:
|
||||
data = json.loads(tx.tx_metadata).get("payload", "")
|
||||
except:
|
||||
pass
|
||||
elif hasattr(tx, "payload") and tx.payload:
|
||||
if isinstance(tx.payload, dict):
|
||||
data = tx.payload.get("payload", "")
|
||||
|
||||
sender = tx.sender
|
||||
|
||||
# Check if message matches trigger
|
||||
if sender != args.address and args.trigger_message in str(data):
|
||||
print(f"Received '{data}' from {sender}! Sending '{args.reply_message}'...")
|
||||
reply_tx = create_tx(priv_bytes, args.address, sender, 0, 10, args.reply_message)
|
||||
|
||||
try:
|
||||
res = requests.post(f"{args.rpc_url}/rpc/transaction", json=reply_tx, timeout=10)
|
||||
if res.status_code == 200:
|
||||
print(f"Reply sent successfully: {res.json()}")
|
||||
else:
|
||||
print(f"Failed to send reply: {res.text}")
|
||||
except requests.RequestException as e:
|
||||
print(f"Network error sending reply: {e}")
|
||||
|
||||
sys.stdout.flush()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error querying database: {e}")
|
||||
sys.stdout.flush()
|
||||
|
||||
time.sleep(args.poll_interval)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
52
apps/blockchain-node/scripts/blockchain_http_launcher.py
Executable file
52
apps/blockchain-node/scripts/blockchain_http_launcher.py
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Blockchain HTTP Launcher for AITBC Production
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def main():
|
||||
"""Main blockchain HTTP launcher function"""
|
||||
logger.info("Starting AITBC Blockchain HTTP Launcher")
|
||||
|
||||
try:
|
||||
# Launch blockchain HTTP service
|
||||
logger.info("Launching blockchain HTTP API")
|
||||
subprocess.run([
|
||||
'/opt/aitbc/venv/bin/python',
|
||||
'-m', 'uvicorn',
|
||||
'aitbc_chain.app:app',
|
||||
'--host', '0.0.0.0',
|
||||
'--port', '8005'
|
||||
], check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"Blockchain HTTP service failed with exit code {e.returncode}: {e}")
|
||||
# Fallback
|
||||
import time
|
||||
while True:
|
||||
logger.info("Blockchain HTTP service heartbeat (fallback mode)")
|
||||
time.sleep(30)
|
||||
except (FileNotFoundError, PermissionError) as e:
|
||||
logger.error(f"Cannot launch blockchain HTTP service: {type(e).__name__}: {e}")
|
||||
# Fallback
|
||||
import time
|
||||
while True:
|
||||
logger.info("Blockchain HTTP service heartbeat (fallback mode)")
|
||||
time.sleep(30)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error launching blockchain HTTP: {type(e).__name__}: {e}")
|
||||
# Fallback
|
||||
import time
|
||||
while True:
|
||||
logger.info("Blockchain HTTP service heartbeat (fallback mode)")
|
||||
time.sleep(30)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
139
apps/blockchain-node/scripts/blockchain_simple.py
Executable file
139
apps/blockchain-node/scripts/blockchain_simple.py
Executable file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Blockchain Node Service for AITBC Production
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Add the blockchain app to Python path
|
||||
sys.path.insert(0, '/opt/aitbc/apps/blockchain-node/src')
|
||||
sys.path.insert(0, '/opt/aitbc/apps/blockchain-node/scripts')
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def main():
|
||||
"""Main blockchain service function"""
|
||||
logger.info("Starting AITBC Blockchain Node Service")
|
||||
|
||||
try:
|
||||
# Set environment variables
|
||||
os.environ.setdefault('PYTHONPATH', '/opt/aitbc/apps/blockchain-node/src')
|
||||
os.environ.setdefault('BLOCKCHAIN_DATA_DIR', '/var/lib/aitbc/data/blockchain')
|
||||
os.environ.setdefault('BLOCKCHAIN_CONFIG_DIR', '/etc/aitbc')
|
||||
os.environ.setdefault('BLOCKCHAIN_LOG_DIR', '/var/log/aitbc/production/blockchain')
|
||||
|
||||
# Try to import and run the actual blockchain node
|
||||
logger.info("Attempting to start blockchain node...")
|
||||
|
||||
# Check if we can import the blockchain app
|
||||
try:
|
||||
from aitbc_chain.app import app
|
||||
logger.info("Successfully imported blockchain app")
|
||||
|
||||
# Run the blockchain FastAPI app
|
||||
import uvicorn
|
||||
logger.info("Starting blockchain FastAPI app on port 8545")
|
||||
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("BLOCKCHAIN_PORT", 8545)))
|
||||
|
||||
except ImportError as e:
|
||||
logger.error(f"Failed to import blockchain app: {e}")
|
||||
|
||||
# Try to run the main blockchain function
|
||||
try:
|
||||
from aitbc_chain.main import main as blockchain_main
|
||||
logger.info("Successfully imported blockchain main")
|
||||
blockchain_main()
|
||||
|
||||
except ImportError as e2:
|
||||
logger.error(f"Failed to import blockchain main: {e2}")
|
||||
logger.info("Starting blockchain node with basic functionality")
|
||||
basic_blockchain_node()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error starting blockchain service: {e}")
|
||||
logger.info("Starting fallback blockchain node")
|
||||
basic_blockchain_node()
|
||||
|
||||
def basic_blockchain_node():
|
||||
"""Basic blockchain node functionality"""
|
||||
logger.info("Starting basic blockchain node")
|
||||
|
||||
try:
|
||||
# Create a simple FastAPI app for blockchain node
|
||||
from fastapi import FastAPI
|
||||
import uvicorn
|
||||
import time
|
||||
import threading
|
||||
|
||||
app = FastAPI(title="AITBC Blockchain Node")
|
||||
|
||||
# Blockchain state
|
||||
blockchain_state = {
|
||||
"status": "running",
|
||||
"block_height": 0,
|
||||
"last_block": None,
|
||||
"peers": [],
|
||||
"start_time": time.time()
|
||||
}
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
return {
|
||||
"status": "healthy",
|
||||
"service": "blockchain-node",
|
||||
"block_height": blockchain_state["block_height"],
|
||||
"uptime": time.time() - blockchain_state["start_time"]
|
||||
}
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {
|
||||
"service": "blockchain-node",
|
||||
"status": "running",
|
||||
"endpoints": ["/health", "/", "/blocks", "/status"]
|
||||
}
|
||||
|
||||
@app.get("/blocks")
|
||||
async def get_blocks():
|
||||
return {
|
||||
"blocks": [],
|
||||
"count": 0,
|
||||
"latest_height": blockchain_state["block_height"]
|
||||
}
|
||||
|
||||
@app.get("/status")
|
||||
async def get_status():
|
||||
return blockchain_state
|
||||
|
||||
# Simulate blockchain activity
|
||||
def blockchain_activity():
|
||||
while True:
|
||||
time.sleep(30) # Simulate block generation every 30 seconds
|
||||
blockchain_state["block_height"] += 1
|
||||
blockchain_state["last_block"] = f"block_{blockchain_state['block_height']}"
|
||||
logger.info(f"Generated block {blockchain_state['block_height']}")
|
||||
|
||||
# Start blockchain activity in background
|
||||
activity_thread = threading.Thread(target=blockchain_activity, daemon=True)
|
||||
activity_thread.start()
|
||||
|
||||
logger.info("Starting basic blockchain API on port 8545")
|
||||
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("BLOCKCHAIN_PORT", 8545)))
|
||||
|
||||
except ImportError:
|
||||
# Fallback to simple heartbeat
|
||||
logger.info("FastAPI not available, using simple blockchain node")
|
||||
while True:
|
||||
logger.info("Blockchain node heartbeat - active")
|
||||
time.sleep(30)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
78
apps/marketplace/scripts/gpu_marketplace_launcher.py
Executable file
78
apps/marketplace/scripts/gpu_marketplace_launcher.py
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
GPU Marketplace Launcher for AITBC Production
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def main():
|
||||
"""Main GPU marketplace launcher function"""
|
||||
logger.info("Starting AITBC GPU Marketplace Launcher")
|
||||
|
||||
try:
|
||||
# Set environment variables
|
||||
os.environ.setdefault('PYTHONPATH', '/opt/aitbc/apps/marketplace/scripts:/opt/aitbc/apps/marketplace/src:/opt/aitbc/apps/coordinator-api/src')
|
||||
|
||||
# Try to run the GPU marketplace service
|
||||
logger.info("Launching GPU marketplace service")
|
||||
|
||||
# Check if the main marketplace service exists
|
||||
marketplace_path = '/opt/aitbc/apps/marketplace/scripts/marketplace.py'
|
||||
if os.path.exists(marketplace_path):
|
||||
logger.info("Found marketplace service, launching...")
|
||||
subprocess.run([
|
||||
'/opt/aitbc/venv/bin/python',
|
||||
marketplace_path
|
||||
], check=True)
|
||||
else:
|
||||
logger.error(f"Marketplace service not found at {marketplace_path}")
|
||||
# Fallback to simple service
|
||||
fallback_service()
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"GPU marketplace service failed with exit code {e.returncode}: {e}")
|
||||
logger.info("Starting fallback GPU marketplace service")
|
||||
fallback_service()
|
||||
except (FileNotFoundError, PermissionError) as e:
|
||||
logger.error(f"Cannot launch GPU marketplace service: {type(e).__name__}: {e}")
|
||||
logger.info("Starting fallback GPU marketplace service")
|
||||
fallback_service()
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error launching GPU marketplace: {type(e).__name__}: {e}")
|
||||
logger.info("Starting fallback GPU marketplace service")
|
||||
fallback_service()
|
||||
|
||||
def fallback_service():
|
||||
"""Fallback GPU marketplace service"""
|
||||
logger.info("Starting fallback GPU marketplace service")
|
||||
|
||||
try:
|
||||
# Simple GPU marketplace heartbeat
|
||||
import time
|
||||
|
||||
while True:
|
||||
logger.info("GPU Marketplace service heartbeat - active")
|
||||
time.sleep(30)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("GPU Marketplace service stopped by user")
|
||||
except (OSError, IOError) as e:
|
||||
logger.error(f"System error in fallback service: {type(e).__name__}: {e}")
|
||||
time.sleep(5)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in fallback service: {type(e).__name__}: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
87
apps/marketplace/scripts/marketplace.py
Executable file
87
apps/marketplace/scripts/marketplace.py
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Marketplace Service for AITBC Production
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
# Add paths
|
||||
sys.path.insert(0, '/opt/aitbc/apps/marketplace/src')
|
||||
sys.path.insert(0, '/opt/aitbc/apps/coordinator-api/src')
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def main():
|
||||
"""Main marketplace service function"""
|
||||
logger.info("Starting AITBC Marketplace Service")
|
||||
|
||||
try:
|
||||
# Try to import and run the actual marketplace service
|
||||
from production.services.marketplace import app
|
||||
logger.info("Successfully imported marketplace app")
|
||||
|
||||
# Run the marketplace service
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8007)
|
||||
|
||||
except ImportError as e:
|
||||
logger.error(f"Failed to import marketplace app: {e}")
|
||||
logger.info("Trying alternative marketplace import...")
|
||||
|
||||
try:
|
||||
# Try the unified marketplace
|
||||
from production.services.unified_marketplace import app
|
||||
logger.info("Successfully imported unified marketplace app")
|
||||
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8007)
|
||||
|
||||
except ImportError as e2:
|
||||
logger.error(f"Failed to import unified marketplace: {e2}")
|
||||
logger.info("Starting simple marketplace heartbeat service")
|
||||
heartbeat_service()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error starting marketplace service: {e}")
|
||||
heartbeat_service()
|
||||
|
||||
def heartbeat_service():
|
||||
"""Simple heartbeat service for marketplace"""
|
||||
logger.info("Starting marketplace heartbeat service")
|
||||
|
||||
try:
|
||||
# Create a simple FastAPI app for health checks
|
||||
from fastapi import FastAPI
|
||||
import uvicorn
|
||||
|
||||
app = FastAPI(title="AITBC Marketplace Service")
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
return {"status": "healthy", "service": "marketplace", "message": "Marketplace service running"}
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {"service": "marketplace", "status": "running", "endpoints": ["/health", "/"]}
|
||||
|
||||
logger.info("Starting simple marketplace API on port 8007")
|
||||
uvicorn.run(app, host="0.0.0.0", port=8007)
|
||||
|
||||
except ImportError:
|
||||
# Fallback to simple heartbeat
|
||||
logger.info("FastAPI not available, using simple heartbeat")
|
||||
while True:
|
||||
logger.info("Marketplace service heartbeat - active")
|
||||
time.sleep(30)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
49
apps/marketplace/scripts/real_marketplace_launcher.py
Executable file
49
apps/marketplace/scripts/real_marketplace_launcher.py
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Real Marketplace Launcher for AITBC Production
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def main():
|
||||
"""Main real marketplace launcher function"""
|
||||
logger.info("Starting AITBC Real Marketplace Launcher")
|
||||
|
||||
try:
|
||||
# Launch real marketplace service
|
||||
logger.info("Launching real marketplace service")
|
||||
subprocess.run([
|
||||
'/opt/aitbc/venv/bin/python',
|
||||
'/opt/aitbc/apps/marketplace/scripts/marketplace.py'
|
||||
], check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.error(f"Marketplace service failed with exit code {e.returncode}: {e}")
|
||||
# Fallback
|
||||
import time
|
||||
while True:
|
||||
logger.info("Real Marketplace service heartbeat (fallback mode)")
|
||||
time.sleep(30)
|
||||
except (FileNotFoundError, PermissionError) as e:
|
||||
logger.error(f"Cannot launch marketplace service: {type(e).__name__}: {e}")
|
||||
# Fallback
|
||||
import time
|
||||
while True:
|
||||
logger.info("Real Marketplace service heartbeat (fallback mode)")
|
||||
time.sleep(30)
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error launching marketplace: {type(e).__name__}: {e}")
|
||||
# Fallback
|
||||
import time
|
||||
while True:
|
||||
logger.info("Real Marketplace service heartbeat (fallback mode)")
|
||||
time.sleep(30)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
apps/monitor/monitor.py
Normal file
48
apps/monitor/monitor.py
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
AITBC Monitor Service
|
||||
"""
|
||||
|
||||
import time
|
||||
import logging
|
||||
import json
|
||||
from pathlib import Path
|
||||
import psutil
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger('aitbc-monitor')
|
||||
|
||||
while True:
|
||||
try:
|
||||
# System stats
|
||||
cpu_percent = psutil.cpu_percent()
|
||||
memory_percent = psutil.virtual_memory().percent
|
||||
logger.info(f'System: CPU {cpu_percent}%, Memory {memory_percent}%')
|
||||
|
||||
# Blockchain stats
|
||||
blockchain_file = Path('/var/lib/aitbc/data/blockchain/aitbc/blockchain.json')
|
||||
if blockchain_file.exists():
|
||||
with open(blockchain_file, 'r') as f:
|
||||
data = json.load(f)
|
||||
logger.info(f'Blockchain: {len(data.get("blocks", []))} blocks')
|
||||
|
||||
# Marketplace stats
|
||||
marketplace_dir = Path('/var/lib/aitbc/data/marketplace')
|
||||
if marketplace_dir.exists():
|
||||
listings_file = marketplace_dir / 'gpu_listings.json'
|
||||
if listings_file.exists():
|
||||
with open(listings_file, 'r') as f:
|
||||
listings = json.load(f)
|
||||
logger.info(f'Marketplace: {len(listings)} GPU listings')
|
||||
|
||||
time.sleep(30)
|
||||
except (json.JSONDecodeError, FileNotFoundError, PermissionError, IOError) as e:
|
||||
logger.error(f'Monitoring error: {type(e).__name__}: {e}')
|
||||
time.sleep(60)
|
||||
except psutil.Error as e:
|
||||
logger.error(f'System monitoring error: {type(e).__name__}: {e}')
|
||||
time.sleep(60)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user