This repository has been archived by the owner on May 12, 2018. It is now read-only.
forked from snorp/linode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LinodeDynDNS.py
executable file
·160 lines (148 loc) · 4.57 KB
/
LinodeDynDNS.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/bin/env python3.1
#
# Easy Python3 Dynamic DNS
# Originally by Jed Smith <[email protected]> 4/29/2009
# Modified by Ole Markus With <[email protected]>
# This code and associated documentation is released into the public domain.
#
# To use:
#
# 1. In the Linode DNS manager, edit your zone (must be master) and create
# an A record for your home computer. You can name it whatever you like;
# I call mine 'foo'. Fill in 0.0.0.0 for the IP.
#
# 2. Save it.
#
# 3. Edit the four configuration options below, following the directions for
# each. As this is a quick hack, it assumes everything goes right.
#
# Simply add your domain name and hostname here
#
DOMAIN="example.com"
HOSTNAME="foo"
#
# Your Linode API key. You can generate this by going to your profile in the
# Linode manager. It should be fairly long.
#
KEY = "abcdefghijklmnopqrstuvwxyz"
#
# The URI of a Web service that returns your IP address as plaintext.
#
# My personal one is ifconfig.me, but if you want your own, you can use the
# following lines of PHP.
#
# <?php
# header("Content-type: text/plain");
# printf("%s", $_SERVER["REMOTE_ADDR"]);
#
GETIP = "http://ifconfig.me"
#
# If for some reason the API URI changes, or you wish to send requests to a
# different URI for debugging reasons, edit this. {0} will be replaced with the
# API key set above, and & will be added automatically for parameters.
#
API = "https://api.linode.com/?api_key={0}&resultFormat=JSON"
#
# Comment or remove this line to indicate that you edited the options above.
#
exit("Did you edit the options? vi this file open.")
#
# That's it!
#
# Now run LinodeDynDNS.py manually, or add it to cron, or whatever. You can even have
# multiple copies of the script doing different zones.
#
# For automated processing, this script will always print EXACTLY one line, and
# will also communicate via a return code. The return codes are:
#
# 0 - No need to update, A record matches my public IP
# 0 - Updated record
# 2 - Some kind of error or exception occurred
#
# The script will also output one line that starts with either OK or FAIL. If
# an update was necessary, OK will have extra information after it.
#
# If you want to see responses for troubleshooting, set this:
#
DEBUG = False
#####################
# STOP EDITING HERE #
try:
from json import load
import urllib.request
except Exception as excp:
exit("Couldn't import the standard library. Are you running Python 3?")
class AppURLopener(urllib.request.FancyURLopener):
version = "curl"
urllib.request._urlopener = AppURLopener()
def execute(action, parameters = {}):
# Execute a query and return a Python dictionary.
uri = "{0}&action={1}".format(API.format(KEY), action)
if parameters and len(parameters) > 0:
uri = "{0}&{1}".format(uri, urllib.parse.urlencode(parameters))
if DEBUG:
print("-->", uri)
file, headers = urllib.request.urlretrieve(uri)
if DEBUG:
print("<--", file)
print(headers, end="")
print(open(file).read())
print()
json = load(open(file), encoding="utf-8")
if len(json["ERRORARRAY"]) > 0:
err = json["ERRORARRAY"][0]
raise Exception("Error {0}: {1}".format(int(err["ERRORCODE"]),
err["ERRORMESSAGE"]))
return load(open(file), encoding="utf-8")
def finddomainid():
domains = execute("domain.list")["DATA"]
for domain in domains:
if domain["DOMAIN"] == DOMAIN:
return domain["DOMAINID"]
raise Exception("Domain not found")
def findresource(domainid):
resources = execute("domain.resource.list", {"DomainId": domainid})["DATA"]
for resource in resources:
if resource["NAME"] == HOSTNAME:
return resource
raise Exception("Could not find hostname under this domain")
def ip():
if DEBUG:
print("-->", GETIP)
file, headers = urllib.request.urlretrieve(GETIP)
if DEBUG:
print("<--", file)
print(headers, end="")
print(open(file).read())
print()
return open(file).read().strip()
def main():
try:
domainid = finddomainid()
if DEBUG:
print("Found domain", domainid)
res = findresource(domainid)
if(len(res)) == 0:
raise Exception("No such resource?".format(RESOURCE))
public = ip()
if res["TARGET"] != public:
old = res["TARGET"]
request = {
"ResourceID": res["RESOURCEID"],
"DomainID": res["DOMAINID"],
"Name": res["NAME"],
"Type": res["TYPE"],
"Target": public,
"TTL_Sec": res["TTL_SEC"]
}
execute("domain.resource.update", request)
print("OK {0} -> {1}".format(old, public))
return 0
else:
print("OK")
return 0
except Exception as excp:
print("FAIL {0}: {1}".format(type(excp).__name__, excp))
return 2
if __name__ == "__main__":
exit(main())