Browse Source

sporestack-python: 0.1.0

v2
Teran McKinney 5 years ago
commit
4ef1c6efe8
  1. 6
      .gitignore
  2. 24
      LICENSE.txt
  3. 70
      README.md
  4. 73
      examples/bitcoinunlimited.py
  5. 76
      examples/bitcoinunlimited.sh
  6. 66
      examples/torrelay.py
  7. 74
      examples/torrelay.sh
  8. 2
      requirements.txt
  9. 2
      setup.cfg
  10. 32
      setup.py
  11. 87
      sporestack/__init__.py
  12. 97
      sporestack/nodemeup.py
  13. 35
      test.py
  14. 5
      test.sh

6
.gitignore

@ -0,0 +1,6 @@
*.pyc
venv
build
dist
*.egg-info
.eggs

24
LICENSE.txt

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

70
README.md

@ -0,0 +1,70 @@
Python library for http://sporestack.com/
# Installation
* `pip install sporestack`
# Usage
Spawn one from your terminal.
```
import sporestack
from uuid import uuid4 as random_uuid
node_uuid = str(random_uuid())
ssh_key_path = '{}/.ssh/id_rsa.pub'.format(os.getenv('HOME'))
with open(ssh_key_path) as ssh_key_file:
sshkey = ssh_key_file.read()
while True:
node = sporestack.node(days=28,
sshkey=sshkey,
unique=node_uuid)
if node.payment_status is False:
amount = "{0:.8f}".format(node.satoshis *
0.00000001)
uri = 'bitcoin:{}?amount={}'.format(node.address, amount)
qr = pyqrcode.create(uri)
print(qr.terminal())
print(uri)
print('Pay with Bitcoin. Resize your terminal if QR code is unclear.')
else:
print('Node being built...')
if node.creation_status is True:
break
sleep(5)
banner = '''
UUID: {}
IPv6: {}
IPv4: {}
End of Life: {}
May take a few more moments to come online.
'''.format(node_uuid,
node.ip6,
node.ip4,
node.end_of_life)
print(banner)
```
Spawn one and SSH into it.
```
nodemeup
```
# Examples
* [Launch a tor relay](examples/torrelay.py)
# Licence
[Unlicense/Public domain](LICENSE.txt)

73
examples/bitcoinunlimited.py

@ -0,0 +1,73 @@
"""
Creates a 28 day Bitcoin Unlimited node in Dallas.
Doesn't work.
"""
from uuid import uuid4 as random_uuid
from time import sleep
import os
import pyqrcode
import sporestack
# 1 - 28
DAYS = 28
# 3 is DFW.
DCID = 3
# FreeBSD 11. Will need to change the startupscript if you adjust this.
OSID = 230
# 4GiB memory, 90GiB disk
FLAVOR=95
node_uuid = str(random_uuid())
ssh_key_path = '{}/.ssh/id_rsa.pub'.format(os.getenv('HOME'))
with open(ssh_key_path) as ssh_key_file:
sshkey = ssh_key_file.read()
with open('bitcoinunlimited.sh') as startup_file:
startupscript = startup_file.read()
# This is broken.
while False:
node = sporestack.node(days=28,
sshkey=sshkey,
startupscript=startupscript,
unique=node_uuid,
flavor=FLAVOR,
osid=OSID,
dcid=DCID)
if node.payment_status is False:
amount = "{0:.8f}".format(node.satoshis *
0.00000001)
uri = 'bitcoin:{}?amount={}'.format(node.address, amount)
qr = pyqrcode.create(uri)
print(qr.terminal())
print(uri)
print('Pay with Bitcoin. Resize your terminal if QR code is unclear.')
else:
print('Node being built...')
if node.creation_status is True:
break
sleep(5)
banner = '''
UUID: {}
IPv6: {}
IPv4: {}
End of Life: {}
May take a few more moments to come online.
'''.format(node_uuid,
node.ip6,
node.ip4,
node.end_of_life)
print(banner)

76
examples/bitcoinunlimited.sh

@ -0,0 +1,76 @@
#!/bin/sh
# Stops/breaks at:
# In file included from leveldb/db/builder.cc:7:
# In file included from ./leveldb/db/filename.h:14:
# In file included from ./leveldb/port/port.h:14:
# ./leveldb/port/port_posix.h:38:12: fatal error: 'endian.h' file not found
# #include <endian.h>
# ^
# 1 warning and 1 error generated.
# gmake[2]: *** [Makefile:3874: leveldb/db/leveldb_libleveldb_a-builder.o] Error 1
#
progress() {
echo "bitcoinunlimited: $*" > /dev/console
echo "bitcoinunlimited: $*"
}
# This runs at the top of cloud-init. We don't even have SSHD running without
# this.
# <- Does it still do that?
export ASSUME_ALWAYS_YES=yes
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
progress 'Starting pkg upgrade'
pkg upgrade
progress 'Starting pkg install'
pkg upgrade
pkg install ca_root_nss autotools pkgconf gmake boost-libs libevent2 openssl db48 git micro_httpd micro_inetd #FIXME TODO: Remove git
chmod 700 /root
mkdir /root/.bitcoin
echo 'rpcuser=bitcoinunlimited
rpcpassword=bitcoinunlimitedpassword' > /root/.bitcoin/bitcoin.conf
# ^ If the user and password are the same, it will fail.
mkdir /root/BitcoinUnlimited
# tmpfs for speed and because / is too small otherwise.
# growfs seems to have problems, not sure why.
mount -t tmpfs tmpfs /root/BitcoinUnlimited
cd /root/BitcoinUnlimited
#FIXME This seems to have a 302 loop right now.
#fetch -qo - https://github.com/bitcoinunlimited/bitcoinunlimited/archive/$TAG.tar.gz | tar xzf -
progress 'Starting git clone'
git clone --depth 1 https://github.com/BitcoinUnlimited/BitcoinUnlimited.git bu-src
cd BitcoinUnlimited
./autogen.sh
./configure --with-gui=no --without-miniupnpc --disable-wallet
progress 'About to compile'
gmake -j 2
gmake install
cd /
umount /root/BitcoinUnlimited
fetch -q \
https://raw.githubusercontent.com/teran-mckinney/bitnoder/master/fs/etc/rc.local \
-o /etc/rc.local
fetch -q \
https://raw.githubusercontent.com/teran-mckinney/bitnoder/master/fs/usr/local/bin/honeybadgermoneystats \
-o /usr/local/bin/honeybadgermoneystats
echo > /usr/local/etc/bitnoder.conf
echo 'ntpd_enable="YES"' >> /etc/rc.conf
chmod 500 /etc/rc.local
chmod 500 /usr/local/bin/honeybadgermoneystats
# Let the boot process start rc.local on its own.
#/etc/rc.local

66
examples/torrelay.py

@ -0,0 +1,66 @@
"""
Creates a 28 day tor relay in Dallas.
"""
from uuid import uuid4 as random_uuid
from time import sleep
import os
import pyqrcode
import sporestack
# 1 - 28
DAYS = 28
# 3 is DFW.
DCID = 3
# FreeBSD 11. Will need to change the startupscript if you adjust this.
OSID = 230
node_uuid = str(random_uuid())
ssh_key_path = '{}/.ssh/id_rsa.pub'.format(os.getenv('HOME'))
with open(ssh_key_path) as ssh_key_file:
sshkey = ssh_key_file.read()
with open('torrelay.sh') as startup_file:
startupscript = startup_file.read()
while True:
node = sporestack.node(days=28,
sshkey=sshkey,
startupscript=startupscript,
unique=node_uuid,
osid=OSID,
dcid=DCID)
if node.payment_status is False:
amount = "{0:.8f}".format(node.satoshis *
0.00000001)
uri = 'bitcoin:{}?amount={}'.format(node.address, amount)
qr = pyqrcode.create(uri)
print(qr.terminal())
print(uri)
print('Pay with Bitcoin. Resize your terminal if QR code is unclear.')
else:
print('Node being built...')
if node.creation_status is True:
break
sleep(5)
banner = '''
UUID: {}
IPv6: {}
IPv4: {}
End of Life: {}
May take a few more moments to come online.
'''.format(node_uuid,
node.ip6,
node.ip4,
node.end_of_life)
print(banner)

74
examples/torrelay.sh

@ -0,0 +1,74 @@
#!/bin/sh
progress() {
echo "$NAME: $*" > /dev/console
echo "$NAME: $*"
}
# This runs at the top of cloud-init. We don't even have SSHD running without
# this.
export ASSUME_ALWAYS_YES=yes
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
# pkg isn't installed by default on vultr, but this will bootstrap it
# with the above option of ASSUME_ALWAYS_YES=yes
progress 'Starting pkg upgrade'
pkg upgrade
progress 'Starting pkg install'
pkg upgrade
pkg install tor
sysctl net.inet.ip.random_id=1
echo 'net.inet.ip.random_id=1' >> /etc/sysctl.conf
# May need to consider bandwidth allowances with the plan and how high the
# rate limit is. This is 2.6TiB theoretical max, but probably would be a little
# higher in one month.
# IPv6 global address has to be specified manually.
# We also may not have it unless we probe for it explictly.
echo 'ifconfig_vtnet0_ipv6="inet6 accept_rtadv"
rtsold_enable=YES
ipv6_activate_all_interfaces=YES
dumpdev="NO"
moused_enable="NO"
sendmail_enable="NONE"
ip6addrctl_policy="ipv6_prefer"' >> /etc/rc.conf
# This is rather ugly, I'm sorry.
ifconfig vtnet0 inet6 auto_linklocal
ifconfig vtnet0 inet6 accept_rtadv
ifconfig vtnet0 inet6 -ifdisabled
service rtsold start
rtsold -fd1 vtnet0
sleep 10
rtsold -fd1 vtnet0
IPV6="$(ifconfig vtnet0 | grep inet6 | grep -v 'inet6 fe80' | awk '{print $2}')"
if [ -n "$IPV6" ]; then
echo "ORPort [$IPV6]:443" > /usr/local/etc/tor/torrc
fi
echo 'ORPort 443
Nickname BuiltAutomatically
RelayBandwidthRate 1024 KB
RelayBandwidthBurst 1024 KB
ContactInfo IThinkIWasBuiltAutomatically
ExitPolicy reject *:*
ExitPolicy reject6 *:*' >> /usr/local/etc/tor/torrc
# Running tor as root, partly for port 443 use. Since this server hopefully
# only runs tor, it's safe to do.
echo 'ntpd_enable="YES"
tor_enable="YES"
tor_user="root"' >> /etc/rc.conf
chown 0:0 /var/db/tor
service ntpd start
service tor start

2
requirements.txt

@ -0,0 +1,2 @@
pyyaml
pyqrcode

2
setup.cfg

@ -0,0 +1,2 @@
[metadata]
description-file = README.md

32
setup.py

@ -0,0 +1,32 @@
#!/usr/bin/env python
from setuptools import setup
VERSION = '0.1.0'
DOWNLOAD_URL = 'https://github.com/sporestack/sporestack-python/tarball/{}'
setup(
name='sporestack',
version=VERSION,
author='Teran McKinney',
author_email='sega01@go-beyond.org',
description='Create servers for Bitcoin. sporestack.com library.',
keywords=['bitcoin', 'servers', 'infrastructure'],
license='Unlicense',
url='http://sporestack.com/',
download_url=DOWNLOAD_URL.format(VERSION),
packages=['sporestack'],
setup_requires=[
'flake8'
],
install_requires=[
'pyyaml',
'pyqrcode'
],
entry_points={
'console_scripts': [
'nodemeup = sporestack.nodemeup:fakemain'
]
}
)

87
sporestack/__init__.py

@ -0,0 +1,87 @@
"""
sporestack.com Python API interface
Released into the public domain.
"""
from collections import namedtuple
from warnings import warn
from base64 import b64encode
import json
import urllib2
import yaml
ENDPOINT = 'http://sporestack.com/node'
# ENDPOINT = 'http://localhost:8082/node'
TIMEOUT = 30
def node(days,
unique,
sshkey=None,
cloudinit=None,
startupscript=None,
osid=None,
dcid=None,
flavor=None,
endpoint=ENDPOINT):
"""
Returns a node
Returns:
node.payment_status
node.end_of_life
node.ip6
node.ip4
"""
pre_data = {'days': days,
'unique': unique}
# There must be a better way to do this...
if cloudinit is not None:
b64_cloudinit = b64encode(cloudinit)
pre_data['cloudinit'] = b64_cloudinit
if sshkey is not None:
pre_data['sshkey'] = sshkey
if startupscript is not None:
pre_data['startupscript'] = startupscript
if osid is not None:
pre_data['osid'] = osid
if dcid is not None:
pre_data['dcid'] = dcid
if flavor is not None:
pre_data['flavor'] = flavor
post_data = json.dumps(pre_data)
try:
http_return = urllib2.urlopen(endpoint,
data=post_data,
timeout=TIMEOUT)
except urllib2.HTTPError as http_error:
if http_error.code == 400:
# Throw exception with output from endpoint..
raise Exception(http_error.read())
else:
raise
if http_return.getcode() == 200:
data = yaml.safe_load(http_return.read())
if 'deprecated' in data:
if data['deprecated'] is not False:
warn(str(data['deprecated']), DeprecationWarning)
node = namedtuple('node',
data.keys())
node.end_of_life = data['end_of_life']
node.payment_status = data['payment_status']
node.creation_status = data['creation_status']
node.address = data['address']
node.satoshis = data['satoshis']
node.ip4 = data['ip4']
node.ip6 = data['ip6']
return node
else:
raise Exception('Fatal issue with sporestack.')

97
sporestack/nodemeup.py

@ -0,0 +1,97 @@
"""
Build a server and SSH into it. Server will last for a day.
"""
import argparse
from uuid import uuid4 as random_uuid
from time import sleep
import os
from socket import create_connection
import pyqrcode
import sporestack
node_uuid = str(random_uuid())
ssh_key_path = '{}/.ssh/id_rsa.pub'.format(os.getenv('HOME'))
with open(ssh_key_path) as ssh_key_file:
sshkey = ssh_key_file.read()
parser = argparse.ArgumentParser()
parser.add_argument('--osid', help='Operating System ID '
'230: FreeBSD 11, 215: Ubuntu 16.04, '
'179: CoreOS Stable, 193: Debian 8, '
'167: CentOS 7',
type=int)
parser.add_argument('--dcid', help='Datacenter ID '
'3: Dallas, 2: Chicago, '
'12: San Jose, 5: Los Angeles, '
'6: Atlanta, 1: New Jersey, '
'39: Miami, 4: Seattle',
type=int)
args = parser.parse_args()
while True:
node = sporestack.node(days=1,
sshkey=sshkey,
unique=node_uuid,
osid=args.osid,
dcid=args.dcid)
if node.payment_status is False:
amount = "{0:.8f}".format(node.satoshis *
0.00000001)
uri = 'bitcoin:{}?amount={}'.format(node.address, amount)
qr = pyqrcode.create(uri)
print(qr.terminal())
print(uri)
print('Pay with Bitcoin. Resize your terminal if QR code is unclear.')
else:
print('Node being built...')
if node.creation_status is True:
break
sleep(5)
print('Waiting for node to come online.')
ipaddress = None
while True:
for ip in [node.ip6, node.ip4]:
try:
socket = create_connection((ip, 22), timeout=2)
socket.close()
ipaddress = ip
break
except:
print('Waiting for node to come online.')
sleep(2)
if ipaddress is not None:
break
banner = '''
UUID: {}
IPv6: {}
IPv4: {}
End of Life: {}
'''.format(node_uuid,
node.ip6,
node.ip4,
node.end_of_life)
print(banner)
command = ('ssh root@{} -p 22 -oStrictHostKeyChecking=no'
' -oUserKnownHostsFile=/dev/null'.format(ipaddress))
os.system(command)
print(banner)
def fakemain():
'''
NOOP
I need to fix this.
'''
a = 0

35
test.py

@ -0,0 +1,35 @@
"""
Just some basic tests.
Kinda broken.
"""
from uuid import uuid4 as random_uuid
import os
import sporestack
script = """#!/bin/sh
date > /date
"""
new_uuid = str(random_uuid())
ssh_key_path = '{}/.ssh/id_rsa.pub'.format(os.getenv('HOME'))
with open(ssh_key_path) as ssh_key_file:
sshkey = ssh_key_file.read()
for unique in ['3b69d7c9-ad4d-4d31-b04e-b224f02de4d4',
'4a79a54b-b763-4a52-9d1e-d0d72ec7f67d',
new_uuid]:
node = sporestack.node(days=1,
sshkey=sshkey,
unique=unique,
cloudinit=script,
startupscript=script)
print('Payment status: ' + str(node.payment_status))
print('Creation status: ' + str(node.creation_status))
print(node.address)
print(node.satoshis)
print(node.ip6)
print(node.ip4)

5
test.sh

@ -0,0 +1,5 @@
#!/bin/sh
set -e
python -W all -W error coinfee_test.py
Loading…
Cancel
Save