UNPKG

6.8 kBPlain TextView Raw
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3
4# Copyright (c) 2002-2016 "Neo Technology,"
5# Network Engine for Objects in Lund AB [http://neotechnology.com]
6#
7# This file is part of Neo4j.
8#
9# Licensed under the Apache License, Version 2.0 (the "License");
10# you may not use this file except in compliance with the License.
11# You may obtain a copy of the License at
12#
13# http://www.apache.org/licenses/LICENSE-2.0
14#
15# Unless required by applicable law or agreed to in writing, software
16# distributed under the License is distributed on an "AS IS" BASIS,
17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18# See the License for the specific language governing permissions and
19# limitations under the License.
20
21"""
22Usage: neorun.py <cmd=arg>
23 --start=path/to/neo4j/home <cmd> [arg]
24 : start the neo4j server in the folder specified by the path
25 -v version : download the version provided if no neo4j detected
26 -n neo4j-version: download this specific neo4j enterprise nightly version from teamcity with basic access auth
27 -l download-url : download the neo4j provided by this url if no neo4j found
28 -p new-password : change the default password to this new password
29 --stop=path/to/neo4j/home : stop a neo4j server
30 -h : show this help message
31
32Example: neorun.py -h
33 neorun.py --start=path/to/neo4j/home -v 3.0.1 -p TOUFU
34 neorun.py --start=path/to/neo4j/home -n 3.0 -p TOUFU
35 neorun.py --start=path/to/neo4j/home -n 3.1
36 neorun.py --stop=path/to/neo4j/home
37"""
38import getopt
39from sys import argv, stdout, exit
40from neoget import neo4j_default_archive, neo4j_archive, download
41from neoctl import neo4j_start, neo4j_stop, neo4j_update_default_password
42from os import path, rename, getenv
43import socket
44from time import time, sleep, strftime
45
46KNOWN_HOST = path.join(path.expanduser("~"), ".neo4j", "known_hosts")
47NEORUN_START_ARGS_NAME = "NEORUN_START_ARGS"
48
49class Enum(set):
50 def __getattr__(self, name):
51 if name in self:
52 return name
53 raise AttributeError
54
55ServerStatus = Enum(["STARTED", "STOPPED" ])
56
57def main():
58
59 if len(argv) <= 1:
60 print_help()
61 exit(2)
62 try:
63 opts, args = getopt.getopt(argv[1:], "hv:n:l:p:", ["start=", "stop="])
64 except getopt.GetoptError as err:
65 print(str(err))
66 print_help()
67 exit(2)
68 else:
69 exit_code = 0
70 for opt, arg in opts:
71 if opt == '-h':
72 print_help()
73 exit(2)
74
75 if opt == "--start":
76 neo4j_home = path.abspath(arg)
77 if neo4j_status() == ServerStatus.STARTED:
78 stdout.write("Failed to start neo4j as a neo4j server is already running on this machine.\n")
79 exit(2)
80
81 # get the opts from env
82 env = getenv(NEORUN_START_ARGS_NAME)
83 if env:
84 stdout.write("WARNING: using env var `NEORUN_START_ARGS=%s`\n" % env)
85 try:
86 start_opts, start_args = getopt.getopt(env.split(), "v:n:l:p:")
87 except getopt.GetoptError as err:
88 print(str(err))
89 print_help()
90 exit(2)
91 else:
92 start_opts = opts
93
94 # parse the opts under --start
95 archive_url, archive_name, require_basic_auth = neo4j_default_archive()
96 password = ''
97 for start_opt, start_arg in start_opts:
98 if start_opt == "-p":
99 password = start_arg
100 elif start_opt in ['-v', '-n', '-l']:
101 archive_url, archive_name, require_basic_auth = neo4j_archive(start_opt, start_arg)
102
103 exit_code = handle_start(archive_url, archive_name, neo4j_home, require_basic_auth)
104 if exit_code == 0 and password:
105 exit_code = neo4j_update_default_password("localhost", 7474, new_password=password) or 0
106
107 elif opt == "--stop":
108 if neo4j_status() == ServerStatus.STOPPED:
109 stdout.write("Failed to stop server as no neo4j server is running on this machine.\n")
110 exit(2)
111 exit_code = neo4j_stop(neo4j_home=arg) or test_neo4j_status(ServerStatus.STOPPED) or 0
112
113 if exit_code != 0:
114 break
115 exit(exit_code)
116
117
118def handle_start(archive_url, archive_name, neo4j_home, require_basic_auth):
119 if not path.exists(neo4j_home):
120 folder_name=download(archive_url, archive_name, path.dirname(neo4j_home), require_basic_auth)
121 if not path.exists(neo4j_home):
122 # the untared name is different from what the user gives
123 rename(path.join(path.dirname(neo4j_home), folder_name), neo4j_home)
124 if path.exists(KNOWN_HOST):
125 known_host_backup_name = KNOWN_HOST + strftime("%Y%m%d-%H%M%S") + ".backup"
126 stdout.write("Found an existing known_host file, renaming it to %s.\n" % (known_host_backup_name))
127 rename(KNOWN_HOST, known_host_backup_name)
128
129 exit_code = neo4j_start(neo4j_home) or 0
130 if exit_code == 0:
131 exit_code = test_neo4j_status()
132 return exit_code
133
134
135# Test if the neo4j server is started (status = STARTED)
136# or if the neo4j server is stopped (status = STOPPED) within 4 mins.
137# Return 0 if the test success, otherwise 1
138def test_neo4j_status(status = ServerStatus.STARTED):
139 success = False
140 start_time = time()
141 timeout = 60 * 4 # in seconds
142 count = 0
143 while not success:
144 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
145 actual_status = s.connect_ex(("localhost", 7474))
146 if status == ServerStatus.STARTED:
147 success = True if actual_status == 0 else False
148 else:
149 success = True if actual_status != 0 else False
150 s.close()
151
152 current_time = time()
153 if current_time - start_time > timeout:
154 # failed to connect to server within timeout
155 stdout.write("Failed to start server in 4 mins\n")
156 return 1
157
158 count += 1
159 if count % 10 == 0:
160 stdout.write(".") # print .... to indicate working on it
161
162 sleep(0.1) # sleep for 100ms
163 # server is started
164 stdout.write("\n")
165 return 0
166
167
168def neo4j_status():
169 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
170 server_status = ServerStatus.STARTED if s.connect_ex(("localhost", 7474)) == 0 else ServerStatus.STOPPED
171 s.close()
172 return server_status
173
174
175def print_help():
176 print(__doc__)
177
178
179if __name__ == "__main__":
180 main()