forked from pythonhacker/rotating-proxy-daemon
/
utils.py
168 lines (132 loc) · 4.91 KB
/
utils.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
161
162
163
164
165
166
167
168
""" Utility functions & classes """
import os
import sys
import pwd
import uuid
import functools
import boto3
def enum(*sequential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
return type('Enum', (), enums)
def randpass():
""" Return a random password """
return uuid.uuid4().bytes.encode('base64')[:16]
class Log(object):
"""A dead-simple, stupid logging class """
def __init__(self, f):
self.f = f
def write(self, s):
try:
s = unicode(s, 'ascii', 'ignore').encode()
except TypeError:
s = s.encode('ascii', 'ignore')
self.f.write(s)
self.f.flush()
def flush(self):
self.f.flush()
def drop_privileges(uid_name='alpha', gid_name='alpha'):
""" Drop privileges of current process to given user and group """
if os.getuid() != 0:
# We're not root so, like, whatever dude
return
# Get the uid/gid from the name
pwstruct = pwd.getpwnam(uid_name)
running_uid = pwstruct.pw_uid
running_gid = pwstruct.pw_gid
# Remove group privileges
os.setgroups([])
# Try setting the new uid/gid
os.setgid(running_gid)
os.setuid(running_uid)
# Ensure a very conservative umask
old_umask = os.umask(077)
def daemonize(pidfile, logfile=None, user='ubuntu', drop=True):
""" Make a daemon with the given pidfile and optional logfile """
# Disconnect from controlling TTY as a service
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# Do not prevent unmounting...
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent, print eventual PID before
#print "Daemon PID %d" % pid
open(pidfile,'w').write("%d"%pid)
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# Drop privileges to given user by default
if drop:
drop_privileges(user, user)
# Redirect stdout/stderr to log file
if logfile != None:
log=Log(open(logfile,'a'))
sys.stdout.close()
sys.stderr.close()
sys.stdin.close()
sys.stdout=sys.stderr=log
class LinodeCommand(object):
""" Class encapsulating linode CLI commands """
def __init__(self, binary='linode', verbose=False, config=None):
self.binary = binary
self.verbose = verbose
self.cmd_template = {'create': 'create -d %d -p %d -o %d -i %d -l %s -r %s',
'delete': 'delete -l %d',
'list_proxies': 'find -g %s -s %s' % (config.group, config.proxylb),
'info': 'info -l %d',
'update': 'update -l %d -L %s -g %s'
}
# Dynamically create command methods
self.dyn_create()
def _run(self, command, *args):
""" Run a command and return the output """
template = self.cmd_template.get(command)
if template == None:
print 'No such command configured =>',command
return -1
cmd = ' '.join((self.binary, template % args))
if self.verbose: print 'Command is',cmd
return os.popen(cmd).read()
def dyn_create(self):
""" Dynamically create linode methods """
for cmd in self.cmd_template:
method_name = 'linode_' + cmd
method = functools.partial(self._run, cmd)
if self.verbose: print 'Dyn-creating method',method_name,'...'
setattr(self, method_name, method)
def get_label(self, linode_id):
""" Return the label, given the linode id """
data = self.linode_info(linode_id)
return data.split('\n')[0].split(':')[-1].strip()
class AWSCommand(object):
'''Class encapsulating the aws ec2 API'''
def __init__(self, config=None):
self.ec2 = boto3.resource('ec2')
self.config = config
def create_ec2(self, **params):
return self.ec2.create_instances(MaxCount=1, MinCount=1, **params)[0]
def list_proxies(self):
proxies = []
filters=[
{'Name':'image-id', 'Values':[self.config.aws_image_id]},
{'Name': 'instance-state-name', 'Values': ['running']}
]
for instance in self.ec2.instances.filter(Filters=filters):
proxies.append(','.join([instance.public_ip_address, '0', instance.id,'0','0']))
return proxies
def delete_ec2(self, instance_id):
instance = self.ec2.Instance(instance_id)
instance.terminate()
instance.wait_until_terminated()
if __name__ == "__main__":
l = LinodeCommand()
l.get_label(int(sys.argv[1]))