2020-01-14 10:05:42 +00:00
|
|
|
import argparse
|
2020-01-23 17:41:59 +00:00
|
|
|
import logging
|
2020-02-09 11:54:52 +00:00
|
|
|
import re
|
2020-01-14 10:05:42 +00:00
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
import ldap3
|
|
|
|
|
2020-02-09 11:54:52 +00:00
|
|
|
|
2020-01-14 10:22:04 +00:00
|
|
|
from uncloud.hack.vm import VM
|
2020-02-09 18:27:24 +00:00
|
|
|
from uncloud.hack.host import Host
|
2020-01-14 13:23:26 +00:00
|
|
|
from uncloud.hack.config import Config
|
2020-01-14 18:02:15 +00:00
|
|
|
from uncloud.hack.mac import MAC
|
2020-01-19 08:16:29 +00:00
|
|
|
from uncloud.hack.net import VXLANBridge, DNSRA
|
|
|
|
|
2020-01-15 12:26:05 +00:00
|
|
|
from uncloud import UncloudException
|
2020-02-09 10:14:50 +00:00
|
|
|
from uncloud.hack.product import ProductOrder
|
2020-01-14 10:22:04 +00:00
|
|
|
|
2020-01-14 10:05:42 +00:00
|
|
|
arg_parser = argparse.ArgumentParser('hack', add_help=False)
|
2020-01-14 10:25:06 +00:00
|
|
|
#description="Commands that are unfinished - use at own risk")
|
2020-01-14 18:02:15 +00:00
|
|
|
arg_parser.add_argument('--last-used-mac', action='store_true')
|
|
|
|
arg_parser.add_argument('--get-new-mac', action='store_true')
|
2020-01-19 08:16:29 +00:00
|
|
|
|
2020-01-19 10:30:41 +00:00
|
|
|
arg_parser.add_argument('--init-network', help="Initialise networking", action='store_true')
|
|
|
|
arg_parser.add_argument('--create-vxlan', help="Initialise networking", action='store_true')
|
|
|
|
arg_parser.add_argument('--network', help="/64 IPv6 network")
|
|
|
|
arg_parser.add_argument('--vxlan-uplink-device', help="The VXLAN underlay device, i.e. eth0")
|
|
|
|
arg_parser.add_argument('--vni', help="VXLAN ID (decimal)", type=int)
|
2020-01-15 12:26:05 +00:00
|
|
|
arg_parser.add_argument('--run-dns-ra', action='store_true',
|
|
|
|
help="Provide router advertisements and DNS resolution via dnsmasq")
|
2020-01-19 11:55:06 +00:00
|
|
|
arg_parser.add_argument('--use-sudo', help="Use sudo for command requiring root!", action='store_true')
|
2020-01-28 08:25:25 +00:00
|
|
|
|
|
|
|
arg_parser.add_argument('--create-vm', action='store_true')
|
|
|
|
arg_parser.add_argument('--destroy-vm', action='store_true')
|
|
|
|
arg_parser.add_argument('--get-vm-status', action='store_true')
|
2020-01-28 10:02:18 +00:00
|
|
|
arg_parser.add_argument('--get-vm-vnc', action='store_true')
|
|
|
|
arg_parser.add_argument('--list-vms', action='store_true')
|
2020-02-09 07:51:35 +00:00
|
|
|
arg_parser.add_argument('--memory', help="Size of memory (GB)", type=int, default=2)
|
|
|
|
arg_parser.add_argument('--cores', help="Amount of CPU cores", type=int, default=1)
|
2020-01-28 08:25:25 +00:00
|
|
|
arg_parser.add_argument('--image', help="Path (under hackprefix) to OS image")
|
2020-02-09 07:51:35 +00:00
|
|
|
|
2020-02-06 14:13:08 +00:00
|
|
|
arg_parser.add_argument('--image-format', help="Image format: qcow2 or raw", choices=['raw', 'qcow2'])
|
2020-01-28 08:25:25 +00:00
|
|
|
arg_parser.add_argument('--uuid', help="VM UUID")
|
|
|
|
|
2020-01-24 12:56:08 +00:00
|
|
|
arg_parser.add_argument('--no-db', help="Disable connection to etcd. For local testing only!", action='store_true')
|
2020-01-24 16:12:50 +00:00
|
|
|
arg_parser.add_argument('--hackprefix', help="hackprefix, if you need it you know it (it's where the iso is located and ifup/down.sh")
|
2020-01-24 12:56:08 +00:00
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
# order based commands => later to be shifted below "order"
|
|
|
|
arg_parser.add_argument('--order', action='store_true')
|
2020-02-09 10:14:50 +00:00
|
|
|
arg_parser.add_argument('--list-orders', help="List all orders", action='store_true')
|
2020-02-09 11:54:52 +00:00
|
|
|
arg_parser.add_argument('--filter-order-key', help="Which key to filter on")
|
|
|
|
arg_parser.add_argument('--filter-order-regexp', help="Which regexp the value should match")
|
|
|
|
|
2020-02-09 11:12:15 +00:00
|
|
|
arg_parser.add_argument('--process-orders', help="Process all (pending) orders", action='store_true')
|
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
arg_parser.add_argument('--product', choices=["dualstack-vm"])
|
|
|
|
arg_parser.add_argument('--os-image-name', help="Name of OS image (successor to --image)")
|
|
|
|
arg_parser.add_argument('--os-image-size', help="Size of OS image in GB", type=int, default=10)
|
|
|
|
|
|
|
|
arg_parser.add_argument('--username')
|
|
|
|
arg_parser.add_argument('--password')
|
|
|
|
|
2020-02-09 10:14:50 +00:00
|
|
|
arg_parser.add_argument('--api', help="Run the API")
|
2020-02-09 11:12:15 +00:00
|
|
|
arg_parser.add_argument('--mode',
|
|
|
|
choices=["direct", "api", "client"],
|
|
|
|
default="client",
|
|
|
|
help="Directly manipulate etcd, spawn the API server or behave as a client")
|
2020-02-09 10:14:50 +00:00
|
|
|
|
|
|
|
|
2020-02-09 18:27:24 +00:00
|
|
|
arg_parser.add_argument('--add-vm-host', help="Add a host that can run VMs")
|
|
|
|
arg_parser.add_argument('--list-vm-hosts', action='store_true')
|
|
|
|
|
|
|
|
arg_parser.add_argument('--max-cores-per-vm')
|
|
|
|
arg_parser.add_argument('--max-cores-total')
|
|
|
|
arg_parser.add_argument('--max-memory-in-gb')
|
|
|
|
|
2020-01-15 12:26:05 +00:00
|
|
|
|
2020-01-23 17:41:59 +00:00
|
|
|
log = logging.getLogger(__name__)
|
2020-01-14 10:05:42 +00:00
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
def authenticate(username, password, totp_token=None):
|
|
|
|
server = ldap3.Server("ldaps://ldap1.ungleich.ch")
|
|
|
|
dn = "uid={},ou=customer,dc=ungleich,dc=ch".format(username)
|
|
|
|
|
2020-02-09 08:36:50 +00:00
|
|
|
log.debug("LDAP: connecting to {} as {}".format(server, dn))
|
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
try:
|
|
|
|
conn = ldap3.Connection(server, dn, password, auto_bind=True)
|
|
|
|
except ldap3.core.exceptions.LDAPBindError as e:
|
|
|
|
raise UncloudException("Credentials not verified by LDAP server: {}".format(e))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def order(config):
|
|
|
|
for required_arg in [ 'product', 'username', 'password' ]:
|
|
|
|
if not config.arguments[required_arg]:
|
|
|
|
raise UncloudException("Missing required argument: {}".format(required_arg))
|
|
|
|
|
|
|
|
if config.arguments['product'] == 'dualstack-vm':
|
|
|
|
for required_arg in [ 'cores', 'memory', 'os_image_name', 'os_image_size' ]:
|
|
|
|
if not config.arguments[required_arg]:
|
|
|
|
raise UncloudException("Missing required argument: {}".format(required_arg))
|
|
|
|
|
2020-02-09 08:36:50 +00:00
|
|
|
log.debug(config.arguments)
|
2020-02-09 07:51:35 +00:00
|
|
|
authenticate(config.arguments['username'], config.arguments['password'])
|
|
|
|
|
|
|
|
# create DB entry for VM
|
|
|
|
vm = VM(config)
|
2020-02-09 18:27:24 +00:00
|
|
|
return vm.product.place_order(owner=config.arguments['username'])
|
|
|
|
|
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
|
|
|
|
|
2020-01-14 10:05:42 +00:00
|
|
|
|
|
|
|
def main(arguments):
|
2020-01-14 13:23:26 +00:00
|
|
|
config = Config(arguments)
|
|
|
|
|
2020-02-09 18:27:24 +00:00
|
|
|
if arguments['add_vm_host']:
|
|
|
|
h = Host(config)
|
|
|
|
h.cmdline_add_host()
|
|
|
|
|
|
|
|
if arguments['list_vm_hosts']:
|
|
|
|
h = Host(config)
|
|
|
|
|
|
|
|
for host in h.list_hosts(filter_key=arguments['filter_order_key'],
|
|
|
|
filter_regexp=arguments['filter_order_regexp']):
|
|
|
|
print("Host {}: {}".format(host.db_entry['uuid'], host.db_entry))
|
2020-02-09 10:14:50 +00:00
|
|
|
|
2020-02-09 07:51:35 +00:00
|
|
|
if arguments['order']:
|
2020-02-09 18:27:24 +00:00
|
|
|
print("Created order: {}".format(order(config)))
|
2020-02-09 07:51:35 +00:00
|
|
|
|
2020-02-09 10:14:50 +00:00
|
|
|
if arguments['list_orders']:
|
|
|
|
p = ProductOrder(config)
|
2020-02-09 11:54:52 +00:00
|
|
|
for product_order in p.list_orders(filter_key=arguments['filter_order_key'],
|
|
|
|
filter_regexp=arguments['filter_order_regexp']):
|
2020-02-09 11:12:15 +00:00
|
|
|
print("Order {}: {}".format(product_order.db_entry['uuid'], product_order.db_entry))
|
|
|
|
|
|
|
|
if arguments['process_orders']:
|
|
|
|
p = ProductOrder(config)
|
|
|
|
p.process_orders()
|
2020-02-09 10:14:50 +00:00
|
|
|
|
2020-01-14 10:22:04 +00:00
|
|
|
if arguments['create_vm']:
|
2020-01-14 13:23:26 +00:00
|
|
|
vm = VM(config)
|
2020-01-28 08:25:25 +00:00
|
|
|
vm.create()
|
|
|
|
|
|
|
|
if arguments['destroy_vm']:
|
|
|
|
vm = VM(config)
|
|
|
|
vm.stop()
|
|
|
|
|
|
|
|
if arguments['get_vm_status']:
|
|
|
|
vm = VM(config)
|
|
|
|
vm.status()
|
2020-01-14 18:02:15 +00:00
|
|
|
|
2020-01-28 10:02:18 +00:00
|
|
|
if arguments['get_vm_vnc']:
|
|
|
|
vm = VM(config)
|
|
|
|
vm.vnc_addr()
|
|
|
|
|
|
|
|
if arguments['list_vms']:
|
|
|
|
vm = VM(config)
|
|
|
|
vm.list()
|
|
|
|
|
2020-01-14 18:02:15 +00:00
|
|
|
if arguments['last_used_mac']:
|
|
|
|
m = MAC(config)
|
|
|
|
print(m.last_used_mac())
|
|
|
|
|
|
|
|
if arguments['get_new_mac']:
|
2020-01-14 18:10:59 +00:00
|
|
|
print(MAC(config).get_next())
|
2020-01-15 12:26:05 +00:00
|
|
|
|
2020-01-19 10:30:41 +00:00
|
|
|
#if arguments['init_network']:
|
|
|
|
if arguments['create_vxlan']:
|
|
|
|
if not arguments['network'] or not arguments['vni'] or not arguments['vxlan_uplink_device']:
|
|
|
|
raise UncloudException("Initialising the network requires an IPv6 network and a VNI. You can use fd00::/64 and vni=1 for testing (non production!)")
|
|
|
|
vb = VXLANBridge(vni=arguments['vni'],
|
2020-01-19 11:55:06 +00:00
|
|
|
route=arguments['network'],
|
|
|
|
uplinkdev=arguments['vxlan_uplink_device'],
|
|
|
|
use_sudo=arguments['use_sudo'])
|
2020-01-19 10:30:41 +00:00
|
|
|
vb._setup_vxlan()
|
2020-01-19 11:55:06 +00:00
|
|
|
vb._setup_bridge()
|
2020-01-24 13:15:48 +00:00
|
|
|
vb._add_vxlan_to_bridge()
|
2020-01-19 11:55:06 +00:00
|
|
|
vb._route_network()
|
2020-01-19 08:16:29 +00:00
|
|
|
|
2020-01-15 12:26:05 +00:00
|
|
|
if arguments['run_dns_ra']:
|
2020-01-23 17:43:41 +00:00
|
|
|
if not arguments['network'] or not arguments['vni']:
|
|
|
|
raise UncloudException("Providing DNS/RAs requires a /64 IPv6 network and a VNI. You can use fd00::/64 and vni=1 for testing (non production!)")
|
2020-01-19 08:16:29 +00:00
|
|
|
|
2020-01-24 13:15:48 +00:00
|
|
|
dnsra = DNSRA(route=arguments['network'],
|
2020-01-23 17:43:41 +00:00
|
|
|
vni=arguments['vni'],
|
|
|
|
use_sudo=arguments['use_sudo'])
|
|
|
|
dnsra._setup_dnsmasq()
|