aszlig / hetzner Goto Github PK
View Code? Open in Web Editor NEWA high-level Python API for accessing the Hetzner robot.
Home Page: https://pypi.python.org/pypi/hetzner
License: Other
A high-level Python API for accessing the Hetzner robot.
Home Page: https://pypi.python.org/pypi/hetzner
License: Other
Hello,
are there any plans to release it on pypi?
saz
This is what's returned when trying to reset a server which doesn't have the option:
{
"error": {
"status": 404,
"code": "RESET_NOT_AVAILABLE",
"message": "resetting this server is not possible"
}
}
So let's try to raise a better exception than RobotError
I'd like to make a command-line tool very similar in structure to the hetznerctl tool you have. But, it would have different SubCommand
instances specific to the needs of my organization. It would be great to extract the definitions of the commands and the generic parts of the main function into libraries which would make it easy for my tool to use some of the same SubCommand instances, plus some new ones of my own design.
If you think this is a good idea, I'd be happy to provide you a pull-request refactoring the code for better reuse. (For now, I've just copied and pasted the parts I actually want from the hetznerctl tool.
Let me know.
I installed hetzner for python.
root@om:~# pip install hetzner
Collecting hetzner
Downloading hetzner-0.7.5.tar.gz
Building wheels for collected packages: hetzner
Running setup.py bdist_wheel for hetzner ... done
Stored in directory: /root/.cache/pip/wheels/ff/4e/42/3aac160c19e683ce1db4f7f47882187843907cc61939a3df4c
Successfully built hetzner
Installing collected packages: hetzner
Successfully installed hetzner-0.7.5
But the script is not executable:
root@om:~# hetznerctl
-bash: /usr/local/bin/hetznerctl: Keine Berechtigung
root@om:~# ls -l /usr/local/bin/hetznerctl
-rw-r--r-- 1 root root 8327 Feb 26 22:12 /usr/local/bin/hetznerctl
user> hetznerctl admin -C 1.2.3.4 --debug
usage: hetznerctl [-h] [-c CONFIGFILE] command ...
hetznerctl: error: unrecognized arguments: --debug
svm-nixops> hetznerctl admin -C 1.2.3.4
Traceback (most recent call last):
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/bin/..hetznerctl-wrapped-wrapped", line 378, in <module>
main()
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/bin/..hetznerctl-wrapped-wrapped", line 375, in main
subcommand.execute(robot, parser, args)
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/bin/..hetznerctl-wrapped-wrapped", line 255, in execute
login, passwd = server.admin.create(passwd=args.admpasswd)
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/server.py", line 425, in admin
self._admin_account = AdminAccount(self)
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/server.py", line 167, in __init__
self.update_info()
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/server.py", line 173, in update_info
self._scraper.login()
File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/robot.py", line 95, in login
" page".format(response.status))
hetzner.WebRobotError: Invalid status code 302 while visiting login page
Especially since most distros now ship with Python 3 being the default, it really makes sense to support py3k and with that refactor all that py2.x crap (probably refactoring has to wait until 1.0).
Hetzner offers IPv6-Only for Bare-Metal systems for since Nov. 2021. The current server_ip
field is empty and the server_ipv6_net
is filled instead. The query for the server can't be made via the Legacy-IP address anymore, but via the server id.
E.g. Colocation does not support server reset.
Server:
$ hetznerctl show 123
Number: 123
Main IP: None
Name: footlong-meatless-teriyaki
Product: RX170
Data center: FSN1-DC17
Traffic: unlimited
Status: ready
Cancelled: False
Paid until: 1970-01-01 00:00:00
Traceback (most recent call last): [TRUNCATED]
hetzner.RobotError: 404 - server not found (404)
Colocation:
$ hetznerctl show 122
Number: 122
Main IP: None
Name: filet-o-fish
Product: Colocation Rack Basic
Data center: FSN1-DC2-LOC9999-9999
Traffic: 10 TB
Status: ready
Cancelled: False
Paid until: 1970-01-01 00:00:00
hetzner.RobotError: 404 - server not found (404)
On Windows, any attempt to use the library will ultimately end up with a permission error. I tracked it down to the way you handle the certificate checks in case no bundles can be found (which you will not find on Windows, period). If you can't find a bundle, you ultimately end up writing out the root cert yourself using NamedTemporaryFile. However, NamedTemporaryFile does not work on Windows:
https://bugs.python.org/issue14243
My advice would be to simply bundle the cert as part of the Python package and read it from the class folder or alternatively disable automatic delete when using NamedTemporaryFile, make sure the file gets closed before being passed into wrap_socket, so that wrap_socket can actually open it, and then delete it yourself later when it is no longer needed. But IMHO the cleanest way is to simply get rid of any of that code and simply go with a bundled file.
There is an API enpoint for querying the host key of an activated rescue system:
https://robot.your-server.de/doc/webservice/en.html#get-boot-server-ip-rescue-last
Let's add support for that :-)
The API functionality exists since quite some time now, so if we want to have a full-featured library, we'd have to implement this as well:
https://robot.your-server.de/doc/webservice/en.html#server-ordering
It's about time that we have proper test cases, especially when it comes to encoding and py2/3 compatibility.
So essentially, we're replicating the API part of the robot and testing against it, so the test suite might be used for testing other Hetzner API implementations as well.
This really shouldn't belong to the API, so let's move it to the hetznerctl
tool entirely.
Scheduled for 1.0.0, because this is a backwards-incompatible change.
How does one actually use this library?
I got my RDNS kinda working, but the library does not output anything which can be used to determine if it was successful?
Hi!
We're using now new DELL servers and got some problems with the library.
One of the problems is the encoding, I see @dangra commited a pull request, and I commited another.
The other is that DELL servers don't have a reboot command available cause they have a second interface with its own IP, where the user can reboot the server, even cool boots.
When we try to enable rescue mode, it fails with the error:
hetzner.RobotError: 400 - invalid input, fields: type (400)
on line 500:
return self.conn.post('/reset/{0}'.format(self.ip), {'type': modekey})
The rescue mode is enabled, but we never get the password unless we do a 'info'.
I'm now testing some code to allow a reboot via ssh when DELL server is detected, but maybe the best is just to inform the user to reboot the server manually. What do you think?
I can provide my code as a pull request and then you decide what to do.
Regards,
Luar
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
thanks
I'm using Python 3.9 on OSX 10.15.7 and I've been running into the following error:
File "watch_server_and_reset.py", line 16, in hetzner_list
list(robot.servers)
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 391, in __iter__
return iter([Server(self.conn, s) for s in self.conn.get('/server')])
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 368, in get
return self.request('GET', path)
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 329, in request
response = self._request(method, path, data, headers)
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 301, in _request
self.conn.request(method.upper(), path, data, headers)
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1279, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1325, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1274, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1034, in _send_output
self.send(msg)
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 974, in send
self.connect()
File "/usr/local/lib/python3.9/site-packages/hetzner/util/http.py", line 68, in connect
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1405, in wrap_socket
return context.wrap_socket(
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)
I've found Stackoverflow threads where other people fixed this by running the python update .command files, or by modifying the ssl library's certificate validating mechanism (code below), but neither solution has fixed the issue for me.
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
A problem with the temporary file created from this was causing a failure.
http://tinyurl.com/ycfs48vu
"Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later)."
Solution:
line 61 in hetzner\util\http.py:
if bundle is None:
ca_certs = NamedTemporaryFile(delete=False)
ca_certs.write('\n'.join(
map(str.strip, self.CA_ROOT_CERT_FALLBACK.splitlines())
).encode('ascii'))
ca_certs.flush()
cafile = ca_certs.name
ca_certs.close()
try:
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
cert_reqs=ssl.CERT_REQUIRED,
ca_certs=cafile)
finally:
if bundle is None:
try:
os.remove(bundle)
except:
pass
Hi,
Could you put a README.md file with simple examples how to extract infos from Hetzner interface?
I have a hard time understanding what is the syntax of the config file, etc...
I'm getting the response bellow with right credentials, whats wrong ?
{"error":{"status":401,"code":"UNAUTHORIZED","message":"Unauthorized"}}
Please extend README. Please tell me how to install this python library.
nixops broke for me today when I was trying to provision a new hetzner server. Tracking down the bug I found that it brakes here https://github.com/aszlig/hetzner/blob/master/hetzner/robot.py#L173 , It seems the expected cookie is not set. I tried to change the cookie name to "robot" (which you get if you login with a web-browser) but with no success. Can anyone confirm this? Has hetzner broke there API or am I doing something wrong?
Cheers
Did something change again on Hetzner's side?
$ nixops deploy
runner1..> creating an exclusive robot admin sub-account for ‘runner1’... Traceback (most recent call last):
File "/nix/store/n82y5s41cqv05iq9ik4ryc1z28vvnwzn-python3.10-nixops-2.0.0-pre-fc9b55c/bin/.nixops-wrapped", line 9, in <module>
sys.exit(main())
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/__main__.py", line 56, in main
args.op(args)
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/script_defs.py", line 715, in op_deploy
depl.deploy(
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1365, in deploy
self.run_with_notify("deploy", lambda: self._deploy(**kwargs))
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1354, in run_with_notify
f()
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1365, in <lambda>
self.run_with_notify("deploy", lambda: self._deploy(**kwargs))
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1268, in _deploy
nixops.parallel.run_tasks(
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/parallel.py", line 106, in run_tasks
raise list(exceptions.values())[0]
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/parallel.py", line 70, in thread_fun
work_result = (worker_fun(t), None, t.name)
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1220, in worker
r.create(
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops_hetzner/backends/server.py", line 713, in create
) = server.admin.create()
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/server.py", line 425, in admin
self._admin_account = AdminAccount(self)
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/server.py", line 167, in __init__
self.update_info()
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/server.py", line 173, in update_info
self._scraper.login()
File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/robot.py", line 124, in login
raise WebRobotError(msg.format(ROBOT_WEBHOST, ROBOT_LOGINHOST,
hetzner.WebRobotError: https://robot.your-server.de/ does not redirect to https://accounts.hetzner.com/ but instead redirects to: https://robot.hetzner.com/
Hello,
Attempting to reset an AX root server does not work:
$ hetznerctl rescue -a $SSH_FINGERPRINT $IP
Server #1234567: Trying to reboot using the 'soft' method.
hetzner.RobotError: 400 - invalid input, fields: type (400)
According to the Robot documentation, the sw
reboot method (used by soft
) is no longer available:
"type":[
"power",
"power_long",
"hw",
"man"
]
Attempts to call the reset
API with the sw
reset method (used by soft
which is the default) fail with the above 400 error. Changing the default reset method to hw
(hard
) resolves the issue:
diff --git a/hetzner/reset.py b/hetzner/reset.py
index 4afc310..873ad9f 100644
--- a/hetzner/reset.py
+++ b/hetzner/reset.py
@@ -77,7 +77,7 @@ class Reset(object):
is_down = False
if tries is None:
- tries = ['soft', 'hard']
+ tries = ['hard']
for mode in tries:
self.server.logger.info("Trying to reboot using the %r method.",
@@ -110,7 +110,7 @@ class Reset(object):
else:
raise ConnectError("Server keeps playing dead after reboot :-(")
- def reboot(self, mode='soft'):
+ def reboot(self, mode='hard'):
"""
Reboot the server, modes are "soft" for reboot by triggering Ctrl-Alt-
Del, "hard" for triggering a hardware reset and "manual" for requesting
@@ -124,6 +124,6 @@ class Reset(object):
'power': 'power',
}
- modekey = modes.get(mode, modes['soft'])
+ modekey = modes.get(mode, modes['hard'])
return self.conn.post('/reset/{0}'.format(self.server.number),
{'type': modekey})
I am not happy with saving my Hetzner password to disk in plain text. So I was looking for a way to allow hetznerctl to query my password manager but did not see one (I could hack together a shell script that generates a temporary config file and calls hetznerctl, but that is ugly).
Would you be interested to support some kind of integration with password managers? I am interested in coding it.
Ideas
password_cmd
config option that can be set instead of password
and use it as a shell command that will output the password that will be used. I would implement this option as it is little work and fixes the issue for me. Down side: not very integrated UI, every user who wants to use it has to write a shell command into the config.Is there a way to change DNS records?
My domain is thomas-guettler.de. I want to add a new DNS entry (foo.thomas-guettler.de) which points to FritzBox at home.
I want to update the DNS record with the hetzner-python library.
Can you please provide a hint how to do this?
root@om:~# host -a thomas-guettler.de
Trying "thomas-guettler.de"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20548
;; flags: qr rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;thomas-guettler.de. IN ANY
;; ANSWER SECTION:
thomas-guettler.de. 7200 IN SOA ns1.your-server.de. postmaster.your-server.de. 2015052000 86400 1800 3600000 86400
thomas-guettler.de. 7200 IN NS ns1.your-server.de.
thomas-guettler.de. 7200 IN NS ns.second-ns.com.
thomas-guettler.de. 7200 IN NS ns3.second-ns.de.
thomas-guettler.de. 7200 IN A 178.63.61.147
thomas-guettler.de. 7200 IN MX 10 mail.thomas-guettler.de.
thomas-guettler.de. 7200 IN TXT "v=spf1 a a:thomas-guettler.de a:hz1.yz.to mx -all"
;; ADDITIONAL SECTION:
mail.thomas-guettler.de. 7200 IN A 178.63.61.147
Received 286 bytes from 127.0.1.1#53 in 90 ms
Not sure what I'm doing wrong here. Have the module installed and configured properly. hetznerctl list shows the servers.
But running
hetznerctl reboot IP x.x.x.x or herznerctl reboot x.x.x.x gives this error
File "/usr/local/bin/hetznerctl", line 414, in <module>
main()
File "/usr/local/bin/hetznerctl", line 410, in main
subcommand.execute(robot, parser, args)
File "/usr/local/bin/hetznerctl", line 60, in execute
server = robot.servers.get(ip)
File "/usr/local/lib/python3.10/dist-packages/hetzner/robot.py", line 388, in get
return Server(self.conn, self.conn.get('/server/{0}'.format(ip)))
File "/usr/local/lib/python3.10/dist-packages/hetzner/robot.py", line 368, in get
return self.request('GET', path)
File "/usr/local/lib/python3.10/dist-packages/hetzner/robot.py", line 333, in request
raise RobotError(msg.format(response.status), response.status)
hetzner.RobotError: Empty response, status 404. (404)`
I've installed the newest release from pypi and RescueSystem.activate()
seems to lack the authorized_keys
parameter.
In master, everything's looking good:
Line 103 in 0c9c313
Downloaded 0.8.3 from pypi and the activate
method of RescueSystem
is in line 94?
I've put in a support ticket with Hetzner that instead of 401 - Unauthorized
they should return a more descriptive error code when using the API fails because 2-factor auth is enabled.
Their reply:
thank you for your suggestion. We will add a info about 2fa in the error message.
We should check soon if that is really returned.
I noticed that the robot.py
in the release tags v0.7.4
and v0.7.5
is different from what's on master:
v0.7.5
: 76a9fafmaster
: https://github.com/RedMoonStudios/hetzner/blob/280f8d3105937d46da21d534f82315f83db3ed84/hetzner/robot.pyand strangely the v0.7.5
has newer changes than master.
Will these changes make it into master
?
I'm trying to modify hetzner
but I'm not quite sure on what base commit I should put my changes.
File "/usr/local/bin/hetznerctl", line 414, in <module>
main()
File "/usr/local/bin/hetznerctl", line 410, in main
subcommand.execute(robot, parser, args)
File "/usr/local/bin/hetznerctl", line 127, in execute
for server in robot.servers:
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 391, in __iter__
return iter([Server(self.conn, s) for s in self.conn.get('/server')])
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 368, in get
return self.request('GET', path)
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 329, in request
response = self._request(method, path, data, headers)
File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 301, in _request
self.conn.request(method.upper(), path, data, headers)
File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1279, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1325, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1274, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1034, in _send_output
self.send(msg)
File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 974, in send
self.connect()
File "/usr/local/lib/python3.9/site-packages/hetzner/util/http.py", line 55, in connect
sock = socket.create_connection((self.host, self.port),
File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socket.py", line 832, in create_connection
sock.connect(sa)
Hetzner deprecated the "arch" parameter in the "POST /boot/{server-number}/rescue" Endpoint.
There is no technical issue here, but it might make sense to remove that from the module to prevent it from becoming an issue in future API versions.
Python's httplib doesn't do certificate validation, so we need to do it ourselves to prevent man-in-the-middle attacks of the users of this library.
Probably the best is to validate the certificate chain using Thawte's root certificate, to compensate for certificate expiration (it's valid until 2020, which should be long enough).
Not able to confirm this yet but I'm going to test it tomorrow, but it seems that right now creation of per-server admin accounts are not possible.
Originally reported in NixOS/nixops#563 by @grahamc:
nix-dev...............> creating an exclusive robot admin account for ‘nix-dev’... Traceback (most recent call last): File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/bin/..nixops-wrapped-wrapped", line 939, in <module> args.op() File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/bin/..nixops-wrapped-wrapped", line 374, in op_deploy repair=args.repair, dry_activate=args.dry_activate) File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/deployment.py", line 971, in deploy self._deploy(**kwargs) File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/deployment.py", line 928, in _deploy nixops.parallel.run_tasks(nr_workers=-1, tasks=self.active_resources.itervalues(), worker_fun=worker) File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/parallel.py", line 41, in thread_fun result_queue.put((worker_fun(t), None)) File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/deployment.py", line 901, in worker r.create(self.definitions[r.name], check=check, allow_reboot=allow_reboot, allow_recreate=allow_recreate) File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/backends/hetzner.py", line 589, in create self.robot_admin_pass) = server.admin.create() File "/nix/store/lwqybpcw6vyd8s9gm4jbh1q069pnkbp2-python2.7-hetzner-0.7.4/lib/python2.7/site-packages/hetzner/server.py", line 222, in create assert "msgbox_success" in response.read() AssertionError
once I created a user with an arbitrary password, it seemed to do okay (though I have not yet successfully deployed to it.)
Initial debugging by @FPtje:
Also hitting this issue. Printing
response.read()
gives the following:<form id="admin_update" onsubmit="new Ajax.Updater('admin_422502', '/server/adminUpdate', {asynchronous:true, evalScripts:true, onLoading:function(request, json){addAjaxLoader('admin_422502')}, parameters:Form.serialize(this)}); return false;" action="/server/adminUpdate" method="post"><table class="form"> <tr> <td class="label_req">Login</td> <td class="element"></td> </tr> <tr class="submit_row"> <td class="label"> <input class='button calltoaction' type='submit' value='Save' /> <input type="hidden" name="id" value="422502" /> </td> </tr> </table> </form> <input class='button' type='button' value='Delete account' onclick="javascript: new Ajax.Updater('admin_422502', '/server/adminDelete/id/422502', {asynchronous:true, evalScripts:true}); addAjaxLoader('admin_422502'); return false; ">
Cc: @grahamc, @FPtje, @domenkozar
When I run ./hetznerctl
from within the cloned source directory, it works as expected.
However, when I install it with pip install hetzner
or by running python setup.py install
in the cloned source directory, and then just run hetznerctl
from the command line I get:
Traceback (most recent call last):
File "/usr/local/bin/hetznerctl", line 7, in <module>
from ConfigParser import RawConfigParser, Error
ImportError: No module named 'ConfigParser'
This only happens with python 2.x.
With the following commands I get a happy installation:
$> python3 setup.py install
$> /Library/Frameworks/Python.framework/Versions/3.5/bin/hetznerctl list
I'm cautious just to put that bin directory on my PATH before the corresponding python2 directory because I think OS X maybe expecting certain python tools to be written in python2.
The specific versions of python I am using are:
$> python --version
Python 2.7.12
$> python3 --version
Python 3.5.2
Please advise.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.