-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPiSync.py
More file actions
155 lines (137 loc) · 5.07 KB
/
Copy pathPiSync.py
File metadata and controls
155 lines (137 loc) · 5.07 KB
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
"""master.py: Start up script for master device"""
__author__ = "Tom Hanson"
__copyright__ = "Copyright 2014"
__credits__ = ["Tom Hanson"]
__license__ = "GPL"
__maintainer__ = "Tom Hanson"
__email__ = "tom@aporcupine.com"
from argparse import ArgumentParser
import threading
import logging
import json
import sys
import os
from lib import pidfile
import daemon
import Pyro4
import base_config
# Need to use edited version of eyed3
dirname, _ = os.path.split(os.path.abspath(__file__))
sys.path.append(dirname + '/lib')
class Loader(object):
"""Gets config and provides function to start the program"""
def __init__(self, role):
self.config = self.get_config(role)
if self.config:
self.device_type = self.config['device_type']
logging.info('Configuration Loaded! Device Type: %s' % self.device_type)
else:
if role == 'auto':
logging.info('No config file found, detecting device_type')
self.device_type = self.detect_device_type()
logging.info('Detected device type as %s' % self.device_type)
else:
self.device_type = role
self.config = self.create_config()
def get_config(self, arg):
"""Reads pisync.json file or enrolls and returns config"""
if os.path.isfile(os.path.expanduser(base_config.CONFIG_FILE_PATH)):
try:
with open(os.path.expanduser(base_config.CONFIG_FILE_PATH)) as f:
config = json.loads(f.read())
if arg != 'auto' and arg != config['device_type']:
return
except Exception as e:
logging.error('Error loading configuration file!')
logging.error('To generate a new file please delete the existing file!')
sys.exit()
return config
def detect_device_type(self):
"""Searches for master on network, if so returns slave else master"""
try:
nameserver = Pyro4.locateNS()
nameserver.lookup('pisync.device_enroll')
return 'slave'
except Pyro4.errors.NamingError:
return 'master'
def create_config(self):
"""Creates a configuration file"""
logging.info('Enrolling device!')
if self.device_type == 'master':
logging.info('Device enrolling as a Master Device')
from pisync.core import groupenroll
config = groupenroll.GroupEnrollHandler().enroll()
config['slave_device_ids'] = []
elif self.device_type == 'slave':
logging.info('Device enrolling as a Slave Device')
device_enroll = Pyro4.Proxy('PYRONAME:pisync.device_enroll')
try:
config = device_enroll.enroll()
except Pyro4.errors.PyroError:
logging.error('Unable to find Master Device, cannot start as a slave.')
sys.exit()
else:
raise ValueError('device_type must be either master or slave')
config['device_type'] = self.device_type
with open(os.path.expanduser(base_config.CONFIG_FILE_PATH), 'w') as f:
f.seek(0)
f.write(json.dumps(config))
f.truncate()
return config
def start(self):
"""Calls the appropriate start method using device_type provided"""
if self.device_type == 'master':
try:
Pyro4.locateNS()
except Pyro4.errors.NamingError:
self.start_name_server()
from pisync import master
master.Master(self.config).start()
elif self.device_type == 'slave':
from pisync import slave
slave.Slave(self.config).start()
else:
raise ValueError('device_type must be either master or slave')
def start_name_server(self):
"""Starts Pyro4 nameserver in a new thread"""
t = threading.Thread(target=Pyro4.naming.startNSloop, args=('0.0.0.0',))
t.daemon = True
t.start()
def main():
"""Runs if the script is started directly"""
parser = ArgumentParser(prog='PiSync.py')
parser.add_argument('--role', choices=['slave', 'master', 'auto'],
help='slave, master or auto to detect')
parser.add_argument('--daemon', action='store_true',
help='Run PiSync as a daemon')
parser.add_argument('--pidfile', help='Location of PID file')
options = parser.parse_args(sys.argv[1:])
if options.role:
device_type = options.role
else:
device_type = 'auto'
if not os.path.exists(os.path.expanduser(base_config.CONFIG_DIR)):
os.makedirs(os.path.expanduser(base_config.CONFIG_DIR))
if options.daemon:
context = daemon.DaemonContext()
if options.pidfile:
if os.access(options.pidfile, os.W_OK):
context.pidfile = pidfile.PidFile(options.pidfile)
else:
logging.error('Unable to access pidfile specified, check permissions.')
logging.error('Starting with no pidfile.')
with context:
log_file_path = os.path.expanduser(base_config.LOG_FILE_PATH)
logging.basicConfig(filename=log_file_path, level=logging.DEBUG)
try:
loader = Loader(device_type)
loader.start()
except (SystemExit, KeyboardInterrupt):
logging.info('Shutting down.')
except Exception as e:
logging.exception(e)
else:
logging.basicConfig(level=logging.DEBUG)
Loader(device_type).start()
if __name__ == '__main__':
main()