first commit
This commit is contained in:
110
.venv/lib/python3.12/site-packages/hetzner/reset.py
Normal file
110
.venv/lib/python3.12/site-packages/hetzner/reset.py
Normal file
@@ -0,0 +1,110 @@
|
||||
import socket
|
||||
import time
|
||||
|
||||
from hetzner import ConnectError, ManualReboot
|
||||
|
||||
|
||||
class Reset(object):
|
||||
def __init__(self, server):
|
||||
self.server = server
|
||||
self.conn = server.conn
|
||||
|
||||
def check_ssh(self, port=22, timeout=5):
|
||||
"""
|
||||
Check if the current server has an open SSH port. Return True if port
|
||||
is reachable, otherwise false. Time out after 'timeout' seconds.
|
||||
"""
|
||||
success = True
|
||||
old_timeout = socket.getdefaulttimeout()
|
||||
socket.setdefaulttimeout(5)
|
||||
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((self.server.ip, port))
|
||||
s.close()
|
||||
except socket.error:
|
||||
success = False
|
||||
|
||||
socket.setdefaulttimeout(old_timeout)
|
||||
return success
|
||||
|
||||
def observed_reboot(self, patience=300, tries=None, manual=False):
|
||||
"""
|
||||
Reboot and wait patience seconds until the system comes back.
|
||||
If not, retry with the next step in tries and wait another patience
|
||||
seconds. Repeat until there are no more tries left.
|
||||
|
||||
If manual is true, do a manual reboot in case the server doesn't come
|
||||
up again. Raises a ManualReboot exception if that is the case.
|
||||
|
||||
Return True on success and False if the system didn't come up.
|
||||
"""
|
||||
is_down = False
|
||||
|
||||
if tries is None:
|
||||
if self.server.is_vserver:
|
||||
tries = ['hard']
|
||||
else:
|
||||
tries = ['soft', 'hard']
|
||||
|
||||
for mode in tries:
|
||||
self.server.logger.info("Tring to reboot using the %r method.",
|
||||
mode)
|
||||
self.reboot(mode)
|
||||
|
||||
start_time = time.time()
|
||||
self.server.logger.info("Waiting for machine to become available.")
|
||||
while True:
|
||||
current_time = time.time()
|
||||
if current_time > start_time + patience:
|
||||
self.server.logger.info(
|
||||
"Machine didn't come up after %d seconds.",
|
||||
patience
|
||||
)
|
||||
break
|
||||
|
||||
is_up = self.check_ssh()
|
||||
time.sleep(1)
|
||||
|
||||
if is_up and is_down:
|
||||
self.server.logger.info("Machine just became available.")
|
||||
return
|
||||
elif not is_down:
|
||||
is_down = not is_up
|
||||
if manual:
|
||||
self.reboot('manual')
|
||||
raise ManualReboot("Issued a manual reboot because the server"
|
||||
" did not come back to life.")
|
||||
else:
|
||||
raise ConnectError("Server keeps playing dead after reboot :-(")
|
||||
|
||||
def reboot(self, mode='soft'):
|
||||
"""
|
||||
Reboot the server, modes are "soft" for reboot by triggering Ctrl-Alt-
|
||||
Del, "hard" for triggering a hardware reset and "manual" for requesting
|
||||
a poor devil from the data center to go to your server and press the
|
||||
power button.
|
||||
|
||||
On a vServer, rebooting with mode="soft" is a no-op, any other value
|
||||
results in a hard reset.
|
||||
"""
|
||||
if self.server.is_vserver:
|
||||
if mode == 'soft':
|
||||
return
|
||||
|
||||
self.conn.scraper.login(force=True)
|
||||
baseurl = '/server/vserverCommand/id/{0}/command/reset'
|
||||
url = baseurl.format(self.server.number)
|
||||
response = self.conn.scraper.request(url, method='POST')
|
||||
assert "msgbox_success" in response.read().decode('utf-8')
|
||||
return response
|
||||
|
||||
modes = {
|
||||
'manual': 'man',
|
||||
'hard': 'hw',
|
||||
'soft': 'sw',
|
||||
}
|
||||
|
||||
modekey = modes.get(mode, modes['soft'])
|
||||
return self.conn.post('/reset/{0}'.format(self.server.ip),
|
||||
{'type': modekey})
|
||||
Reference in New Issue
Block a user