Using click instead of argparse in uncloud script
This commit is contained in:
parent
2afb37daca
commit
cd2f0aaa0d
14 changed files with 279 additions and 20 deletions
0
uncloud/cli/__init__.py
Normal file
0
uncloud/cli/__init__.py
Normal file
0
uncloud/cli/commands/__init__.py
Executable file
0
uncloud/cli/commands/__init__.py
Executable file
62
uncloud/cli/commands/helper.py
Executable file
62
uncloud/cli/commands/helper.py
Executable file
|
@ -0,0 +1,62 @@
|
||||||
|
import json
|
||||||
|
import binascii
|
||||||
|
import click
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from os.path import join as join_path
|
||||||
|
|
||||||
|
from pyotp import TOTP
|
||||||
|
from uncloud.settings import settings
|
||||||
|
|
||||||
|
|
||||||
|
def load_dump_pretty(content):
|
||||||
|
if isinstance(content, bytes):
|
||||||
|
content = content.decode('utf-8')
|
||||||
|
parsed = json.loads(content)
|
||||||
|
return json.dumps(parsed, indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
|
||||||
|
def make_request(*args, data=None, request_method=requests.post):
|
||||||
|
r = request_method(
|
||||||
|
join_path(settings['client']['api_server'], *args), json=data
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
print(load_dump_pretty(r.content))
|
||||||
|
except Exception:
|
||||||
|
print('Error occurred while getting output from api server.')
|
||||||
|
|
||||||
|
|
||||||
|
def get_token(_, param, value):
|
||||||
|
if value is not None:
|
||||||
|
try:
|
||||||
|
token = TOTP(value).now()
|
||||||
|
except binascii.Error:
|
||||||
|
raise click.BadParameter('')
|
||||||
|
else:
|
||||||
|
param.name = 'token'
|
||||||
|
return token
|
||||||
|
|
||||||
|
|
||||||
|
def add_otp_options(f):
|
||||||
|
options = [
|
||||||
|
click.option('--name', show_default='name mentioned in config file.', prompt=True),
|
||||||
|
click.option('--realm', show_default='realm mentioned in config file.', prompt=True),
|
||||||
|
click.option('--seed', callback=get_token, show_default='seed mentioned in config file',
|
||||||
|
prompt=True)
|
||||||
|
]
|
||||||
|
|
||||||
|
for opt in reversed(options):
|
||||||
|
f = opt(f)
|
||||||
|
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
def add_vm_options(f):
|
||||||
|
options = [
|
||||||
|
click.option('--vm-name', required=True),
|
||||||
|
click.option('--action', required=True, default=f.__name__)
|
||||||
|
]
|
||||||
|
for opt in reversed(options):
|
||||||
|
f = opt(f)
|
||||||
|
|
||||||
|
return f
|
31
uncloud/cli/commands/host.py
Executable file
31
uncloud/cli/commands/host.py
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
import click
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from .helper import add_otp_options, make_request
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def host():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@host.command('create')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--hostname', required=True)
|
||||||
|
@click.option('--cpu', required=True, type=int)
|
||||||
|
@click.option('--ram', required=True)
|
||||||
|
@click.option('--os-ssd', required=True)
|
||||||
|
@click.option('--hdd', default=list(), multiple=True)
|
||||||
|
def create(**kwargs):
|
||||||
|
kwargs['specs'] = {
|
||||||
|
'cpu': kwargs.pop('cpu'),
|
||||||
|
'ram': kwargs.pop('ram'),
|
||||||
|
'os-ssd': kwargs.pop('os_ssd'),
|
||||||
|
'hdd': kwargs.pop('hdd')
|
||||||
|
}
|
||||||
|
make_request('host', 'create', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@host.command('list')
|
||||||
|
def list_host():
|
||||||
|
make_request('host', 'list', request_method=requests.get)
|
24
uncloud/cli/commands/image.py
Executable file
24
uncloud/cli/commands/image.py
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
import click
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from .helper import make_request
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def image():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@image.command('list')
|
||||||
|
@click.option('--public', is_flag=True)
|
||||||
|
def _list(public):
|
||||||
|
if public:
|
||||||
|
make_request('image', 'list-public', request_method=requests.get)
|
||||||
|
|
||||||
|
|
||||||
|
@image.command('create-from-file')
|
||||||
|
@click.option('--name', required=True)
|
||||||
|
@click.option('--uuid', required=True)
|
||||||
|
@click.option('--image-store-name', 'image_store', required=True)
|
||||||
|
def create_from_file(**kwargs):
|
||||||
|
make_request('image', 'create', data=kwargs)
|
17
uncloud/cli/commands/network.py
Normal file
17
uncloud/cli/commands/network.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import click
|
||||||
|
|
||||||
|
from .helper import add_otp_options, make_request
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def network():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@network.command('create')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--network-name', required=True)
|
||||||
|
@click.option('--network-type', 'type', required=True)
|
||||||
|
@click.option('--user', required=True, type=bool, default=False)
|
||||||
|
def create(**kwargs):
|
||||||
|
make_request('network', 'create', data=kwargs)
|
48
uncloud/cli/commands/user.py
Executable file
48
uncloud/cli/commands/user.py
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
import click
|
||||||
|
|
||||||
|
from .helper import add_otp_options, make_request
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def user():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@user.command('files')
|
||||||
|
@add_otp_options
|
||||||
|
def list_files(**kwargs):
|
||||||
|
make_request('user', 'files', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@user.command('vms')
|
||||||
|
@add_otp_options
|
||||||
|
def list_vms(**kwargs):
|
||||||
|
make_request('user', 'vms', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@user.command('networks')
|
||||||
|
@add_otp_options
|
||||||
|
def list_networks(**kwargs):
|
||||||
|
make_request('user', 'network', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@user.command('add-ssh')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--key-name', required=True)
|
||||||
|
@click.option('--key', required=True)
|
||||||
|
def add_ssh(**kwargs):
|
||||||
|
make_request('user', 'add-ssh', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@user.command('remove-ssh')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--key-name', required=True)
|
||||||
|
def remove_ssh(**kwargs):
|
||||||
|
make_request('user', 'remove-ssh', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@user.command('get-ssh')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--key-name', default='')
|
||||||
|
def get_ssh(**kwargs):
|
||||||
|
make_request('user', 'get-ssh', data=kwargs)
|
63
uncloud/cli/commands/vm.py
Executable file
63
uncloud/cli/commands/vm.py
Executable file
|
@ -0,0 +1,63 @@
|
||||||
|
import click
|
||||||
|
|
||||||
|
from .helper import add_otp_options, make_request, add_vm_options
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def vm():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@vm.command('create')
|
||||||
|
@add_otp_options
|
||||||
|
@add_vm_options
|
||||||
|
@click.option('--cpu', required=True, type=int)
|
||||||
|
@click.option('--ram', required=True)
|
||||||
|
@click.option('--os-ssd', required=True)
|
||||||
|
@click.option('--hdd', default=list(), multiple=True)
|
||||||
|
@click.option('--image', required=True)
|
||||||
|
@click.option('--network', default=list(), multiple=True)
|
||||||
|
def create(**kwargs):
|
||||||
|
kwargs['specs'] = {
|
||||||
|
'cpu': kwargs.pop('cpu'),
|
||||||
|
'ram': kwargs.pop('ram'),
|
||||||
|
'os-ssd': kwargs.pop('os_ssd'),
|
||||||
|
'hdd': kwargs.pop('hdd')
|
||||||
|
}
|
||||||
|
make_request('vm', kwargs.pop('action'), data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@vm.command('start')
|
||||||
|
@add_otp_options
|
||||||
|
@add_vm_options
|
||||||
|
def start(**kwargs):
|
||||||
|
make_request('vm', 'action', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@vm.command('stop')
|
||||||
|
@add_otp_options
|
||||||
|
@add_vm_options
|
||||||
|
def stop(**kwargs):
|
||||||
|
make_request('vm', 'action', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@vm.command('delete')
|
||||||
|
@add_otp_options
|
||||||
|
@add_vm_options
|
||||||
|
def delete(**kwargs):
|
||||||
|
make_request('vm', 'action', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@vm.command('status')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--vm-name', required=True)
|
||||||
|
def status(**kwargs):
|
||||||
|
make_request('vm', 'status', data=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@vm.command('migrate')
|
||||||
|
@add_otp_options
|
||||||
|
@click.option('--vm-name', required=True)
|
||||||
|
@click.option('--destination', required=True)
|
||||||
|
def vm_migration(**kwargs):
|
||||||
|
make_request('vm', 'migrate', data=kwargs)
|
24
uncloud/cli/main.py
Normal file
24
uncloud/cli/main.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from uncloud.cli.commands.vm import vm
|
||||||
|
from uncloud.cli.commands.user import user
|
||||||
|
from uncloud.cli.commands.host import host
|
||||||
|
from uncloud.cli.commands.image import image
|
||||||
|
from uncloud.cli.commands.network import network
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def cli():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
cli.add_command(vm)
|
||||||
|
cli.add_command(user)
|
||||||
|
cli.add_command(image)
|
||||||
|
cli.add_command(host)
|
||||||
|
cli.add_command(network)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
cli()
|
|
@ -67,7 +67,7 @@ def track_file(file, base_dir):
|
||||||
os.setxattr(file, "user.utracked", b"True")
|
os.setxattr(file, "user.utracked", b"True")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main(debug=False):
|
||||||
base_dir = settings["storage"]["file_dir"]
|
base_dir = settings["storage"]["file_dir"]
|
||||||
|
|
||||||
# Recursively Get All Files and Folder below BASE_DIR
|
# Recursively Get All Files and Folder below BASE_DIR
|
||||||
|
|
|
@ -40,7 +40,7 @@ def maintenance(host):
|
||||||
shared.vm_pool.put(vm)
|
shared.vm_pool.put(vm)
|
||||||
|
|
||||||
|
|
||||||
def main(hostname):
|
def main(hostname, debug=False):
|
||||||
host_pool = shared.host_pool
|
host_pool = shared.host_pool
|
||||||
host = next(filter(lambda h: h.hostname == hostname, host_pool.hosts), None)
|
host = next(filter(lambda h: h.hostname == hostname, host_pool.hosts), None)
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ def qemu_img_type(path):
|
||||||
return qemu_img_info["format"]
|
return qemu_img_info["format"]
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main(debug=False):
|
||||||
# We want to get images entries that requests images to be created
|
# We want to get images entries that requests images to be created
|
||||||
images = shared.etcd_client.get_prefix(
|
images = shared.etcd_client.get_prefix(
|
||||||
settings["etcd"]["image_prefix"], value_in_json=True
|
settings["etcd"]["image_prefix"], value_in_json=True
|
||||||
|
|
|
@ -111,8 +111,8 @@ class Root(Resource):
|
||||||
api.add_resource(Root, "/")
|
api.add_resource(Root, "/")
|
||||||
|
|
||||||
|
|
||||||
def main(port=None):
|
def main(port=None, debug=False):
|
||||||
app.run(debug=True, host="::", port=port)
|
app.run(debug=debug, host="::", port=port)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -43,29 +43,19 @@ def main(debug=False):
|
||||||
dead_host_mitigation(dead_hosts)
|
dead_host_mitigation(dead_hosts)
|
||||||
|
|
||||||
elif request_entry.type == RequestType.ScheduleVM:
|
elif request_entry.type == RequestType.ScheduleVM:
|
||||||
print(request_event.value)
|
logger.debug("%s, %s", request_entry.key, request_entry.value)
|
||||||
logger.debug(
|
|
||||||
"%s, %s", request_entry.key, request_entry.value
|
|
||||||
)
|
|
||||||
|
|
||||||
vm_entry = shared.vm_pool.get(request_entry.uuid)
|
vm_entry = shared.vm_pool.get(request_entry.uuid)
|
||||||
if vm_entry is None:
|
if vm_entry is None:
|
||||||
logger.info(
|
logger.info("Trying to act on {} but it is deleted".format(request_entry.uuid))
|
||||||
"Trying to act on {} but it is deleted".format(
|
|
||||||
request_entry.uuid
|
|
||||||
)
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
shared.etcd_client.client.delete(
|
|
||||||
request_entry.key
|
shared.etcd_client.client.delete(request_entry.key) # consume Request
|
||||||
) # consume Request
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
assign_host(vm_entry)
|
assign_host(vm_entry)
|
||||||
except NoSuitableHostFound:
|
except NoSuitableHostFound:
|
||||||
vm_entry.add_log(
|
vm_entry.add_log("Can't schedule VM. No Resource Left.")
|
||||||
"Can't schedule VM. No Resource Left."
|
|
||||||
)
|
|
||||||
shared.vm_pool.put(vm_entry)
|
shared.vm_pool.put(vm_entry)
|
||||||
|
|
||||||
logger.info("No Resource Left. Emailing admin....")
|
logger.info("No Resource Left. Emailing admin....")
|
||||||
|
|
Loading…
Reference in a new issue