Skip to content

Commit 031c15a

Browse files
author
zOxta
committed
init
0 parents  commit 031c15a

6 files changed

+154
-0
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# prerequisites
2+
3+
1. Create two DigitalOcean servers in the same data center.
4+
2. Create a floating IP @ DigitalOcean (you can find that in the 'Networking' tab).
5+
3. Point the floating IP to the primary server.
6+
7+
# steps
8+
9+
1. Make sure you python3 is installed, as well as python3-requests `apt-get install python3 python3-requests`
10+
11+
2. Edit `floating-ip-droplet-id.py` and replace `YOU_DIGITAL_OCEAN_API_KEY` by your actual DigitalOcean API key.
12+
13+
3. Move `floating-ip-droplet-id.py` to /usr/local/bin/floating-ip-droplet-id then make it executable `chmod +x /usr/local/bin/floating-ip-droplet-id`
14+
15+
4. Edit `do-assign-floating-ip.py` and replace `YOU_DIGITAL_OCEAN_API_KEY` by your actual DigitalOcean API key.
16+
17+
5. Move `do-assign-floating-ip.py` to /usr/local/bin/do-assign-floating-ip then make it executable `chmod +x /usr/local/bin/do-assign-floating-ip`
18+
19+
# syncing both servers
20+
21+
- You can either deploy your code via git to both servers (can be easily done using Laravel Forge).
22+
- You can setup file syncing between the two servers using rsync, both servers first need to be able to use a public/private key authentication to communicate with each other.

crontab-entry

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# for the primary server, add the following cron command
2+
* * * * * sh /path/to/primary-server-failover.sh >> /path/to/primary-server-failover.log 2>&1
3+
4+
# for the secondary server, add the following cron command
5+
* * * * * sh /path/to/secondary-server-failover.sh >> /path/to/secondary-server-failover.log 2>&1

do-assign-floating-ip.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/python3
2+
3+
import os
4+
import sys
5+
import requests
6+
import json
7+
8+
api_base = 'https://api.digitalocean.com/v2'
9+
10+
11+
def usage():
12+
print('{} [Floating IP] [Droplet ID]'.format(sys.argv[0]))
13+
14+
15+
def main(floating_ip, droplet_id):
16+
payload = {'type': 'assign', 'droplet_id': droplet_id}
17+
headers = {'Authorization': 'Bearer YOU_DIGITAL_OCEAN_API_KEY',
18+
'Content-type': 'application/json'}
19+
url = api_base + "/floating_ips/{}/actions".format(floating_ip)
20+
r = requests.post(url, headers=headers, data=json.dumps(payload))
21+
22+
resp = r.json()
23+
if 'message' in resp:
24+
print('{0}: {1}'.format(resp['id'], resp['message']))
25+
sys.exit(1)
26+
else:
27+
print('Moving IP address: {}'.format(resp['action']['status']))
28+
29+
if __name__ == "__main__":
30+
if not len(sys.argv) > 2:
31+
usage()
32+
sys.exit()
33+
main(sys.argv[1], sys.argv[2])

floating-ip-droplet-id.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/python3
2+
3+
import os
4+
import sys
5+
import requests
6+
import json
7+
8+
api_base = 'https://api.digitalocean.com/v2'
9+
10+
def main():
11+
headers = {'Authorization': 'Bearer YOU_DIGITAL_OCEAN_API_KEY',
12+
'Content-type': 'application/json'}
13+
url = api_base + "/floating_ips"
14+
r = requests.get(url, headers=headers)
15+
16+
resp = r.json()
17+
if 'message' in resp:
18+
print('{0}: {1}'.format(resp['id'], resp['message']))
19+
sys.exit(1)
20+
else:
21+
print('{}'.format(resp['floating_ips'][0]['droplet']['id']))
22+
23+
if __name__ == "__main__":
24+
main()

primary-server-failover.sh

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# digital ocean PRIMARY server failover script
2+
3+
echo "\nchecking SECONDARY server status"
4+
5+
# digital ocean floating ip
6+
IP='xx.xx.xx.xx'
7+
8+
# digital ocean PRIMARY server droplet id
9+
ID='xxxxxx'
10+
11+
# digital ocean SECONDARY server public ip
12+
SECONDARY_SERVER_PUBLIC_IP='xx.xx.xx.xx'
13+
14+
# digital ocean SECONDARY server health check
15+
SECONDARY_SERVER_STATUS=$(curl -o /dev/null --silent --head --write-out '%{http_code}\n' http://$SECONDARY_SERVER_PUBLIC_IP)
16+
17+
HAS_FLOATING_IP=$(python3 /usr/local/bin/floating-ip-droplet-id)
18+
19+
# if i the floating ip is not pointing to me and the SECONDARY server is down then assign floating ip to me
20+
if [ $HAS_FLOATING_IP != $ID ] && [ $SECONDARY_SERVER_STATUS = 000 ]; then
21+
22+
echo "\nSECONDARY server is down and has the floating ip"
23+
24+
n=0
25+
while [ $n -lt 10 ]
26+
do
27+
echo "\nswitching to PRIMARY server $ID"
28+
python3 /usr/local/bin/assign-ip $IP $ID && break
29+
n=$((n+1))
30+
sleep 3
31+
done
32+
else
33+
echo "\nno switch necessary\n"
34+
echo $HAS_FLOATING_IP $SECONDARY_SERVER_STATUS $ID
35+
fi

secondary-server-failover.sh

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# digital ocean SECONDARY server failover script
2+
3+
echo "\nchecking PRIMARY server status"
4+
5+
# digital ocean floating ip
6+
IP='xx.xx.xx.xx'
7+
8+
# digital ocean SECONDARY server droplet id
9+
ID='xxxxxx'
10+
11+
# digital ocean PRIMARY server public ip
12+
PRIMARY_SERVER_PUBLIC_IP='xx.xx.xx.xx'
13+
14+
# digital ocean PRIMARY server health check
15+
PRIMARY_SERVER_STATUS=$(curl -o /dev/null --silent --head --write-out '%{http_code}\n' http://$PRIMARY_SERVER_PUBLIC_IP)
16+
17+
HAS_FLOATING_IP=$(python3 /usr/local/bin/floating-ip-droplet-id)
18+
19+
# if i the floating ip is not pointing to me and the PRIMARY server is down then assign floating ip to me
20+
if [ $HAS_FLOATING_IP != $ID ] && [ $PRIMARY_SERVER_STATUS = 000 ]; then
21+
22+
echo "\nPRIMARY server is down and has the floating ip"
23+
24+
n=0
25+
while [ $n -lt 10 ]
26+
do
27+
echo "\nswitching to SECONDARY server $ID"
28+
python3 /usr/local/bin/assign-ip $IP $ID && break
29+
n=$((n+1))
30+
sleep 3
31+
done
32+
else
33+
echo "\nno switch necessary\n"
34+
echo $HAS_FLOATING_IP $PRIMARY_SERVER_STATUS $ID
35+
fi

0 commit comments

Comments
 (0)