forked from snorp/linode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLinodeDynDNS.py
executable file
·158 lines (151 loc) · 5.08 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
#!/usr/bin/python3.1
#
# Easy Python3 Dynamic DNS
# By Jed Smith <jed@jedsmith.org> 4/29/2009
# This code and associated documentation is released into the public domain.
#
# Updated by Mike Swanson <rearden@atlantisvalley.com> 12/2/2012
# It appears there have been some changes to how to json load method works
# (it returns a list of dicts now, not just a single dict.) Also,
# the string request names are now in a dot syntax rather than the uppercase
# delimited format used originally in this script. The API call for listing
# a DNS resource now also requires a domainID in addition to the resourceID.
#
# This script **REQUIRES** Python 3.0 or above. Python 2.6 may work.
# To see what version you are using, run this:
#
# python --version
#
# To use:
#
# 0. You'll probably have to edit the shebang above.
#
# 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 'home'. Fill in 0.0.0.0 for the IP.
#
# 2. Save it.
#
# 3. Go back and edit the A record you just created. Make a note of the
# ResourceID in the URI of the page while editing the record.
#
# 4. Edit the four configuration options below, following the directions for
# each. As this is a quick hack, it assumes everything goes right.
#
# First, the resource ID that contains the 'home' record you created above. If
# the URI while editing that A record looks like this:
#
# linode.com/members/dns/resource_aud.cfm?DomainID=98765&ResourceID=123456
# ^
# You want 123456. The API key MUST have write access to this resource ID.
#
RESOURCE = "0000000"
DOMAIN = "000000"
#
# 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. You are
# welcome to leave this at the default value and use mine. If you want to run
# your own, the source code of that script is:
#
# <?php
# header("Content-type: text/plain");
# printf("%s", $_SERVER["REMOTE_ADDR"]);
#
GETIP = "http://zxcvfdsa.com/ip.php"
#
# 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/?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 dyndns.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
# 1 - 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
from urllib.parse import urlencode
from urllib.request import urlretrieve
except Exception as excp:
exit("Couldn't import the standard library. Are you running Python 3?")
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, urlencode(parameters))
if DEBUG:
print("-->", uri)
file, headers = 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 ip():
if DEBUG:
print("-->", GETIP)
file, headers = urlretrieve(GETIP)
if DEBUG:
print("<--", file)
print(headers, end="")
print(open(file).read())
print()
return open(file).read().strip()
def main():
try:
res = execute("domain.resource.list", {"DomainID": DOMAIN, "ResourceID": RESOURCE})["DATA"]
if(len(res)) == 0:
raise Exception("No such resource?".format(RESOURCE))
public = ip()
if res[0]["TARGET"] != public:
old = res[0]["TARGET"]
request = {
"ResourceID": res[0]["RESOURCEID"],
"DomainID": res[0]["DOMAINID"],
"Name": res[0]["NAME"],
"Type": res[0]["TYPE"],
"Target": public,
"TTL_Sec": res[0]["TTL_SEC"]
}
execute("domain.resource.update", request)
print("OK {0} -> {1}".format(old, public))
return 1
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())