Add filtering support:
(venv) [12:54] diamond:uncloud% ./bin/uncloud-run-reinstall hack --product 'dualstack-vm' --os-image-name alpine311 --username nicocustomer --password '...' --hackprefix ~/vcs/uncloud/uncloud/hack/hackcloud/ --etcd-host etcd1.ungleich.ch --etcd-ca-cert ~/vcs/ungleich-dot-cdist/files/etcd/ca.pem --etcd-cert-cert ~/vcs/ungleich-dot-cdist/files/etcd/nico.pem --etcd-cert-key ~/vcs/ungleich-dot-cdist/files/etcd/nico-key.pem --list-orders --filter-order-key "status" --filter-order-regexp NEW
This commit is contained in:
parent
5ef009cc9b
commit
a80a279ba5
5 changed files with 59 additions and 16 deletions
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -23,12 +23,20 @@
|
||||||
import etcd3
|
import etcd3
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import datetime
|
||||||
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from uncloud import UncloudException
|
from uncloud import UncloudException
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def db_logentry(message):
|
||||||
|
timestamp = datetime.datetime.now()
|
||||||
|
return {
|
||||||
|
"timestamp": str(timestamp),
|
||||||
|
"message": message
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def readable_errors(func):
|
def readable_errors(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
|
@ -99,6 +107,8 @@ class DB(object):
|
||||||
# FIXME: iterate over clients in case of failure ?
|
# FIXME: iterate over clients in case of failure ?
|
||||||
return self._db_clients[0].put(self.realkey(key), value, **kwargs)
|
return self._db_clients[0].put(self.realkey(key), value, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@readable_errors
|
@readable_errors
|
||||||
def increment(self, key, **kwargs):
|
def increment(self, key, **kwargs):
|
||||||
print(self.realkey(key))
|
print(self.realkey(key))
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
import ldap3
|
import ldap3
|
||||||
|
|
||||||
|
|
||||||
from uncloud.hack.vm import VM
|
from uncloud.hack.vm import VM
|
||||||
from uncloud.hack.config import Config
|
from uncloud.hack.config import Config
|
||||||
from uncloud.hack.mac import MAC
|
from uncloud.hack.mac import MAC
|
||||||
|
@ -43,6 +45,9 @@ arg_parser.add_argument('--hackprefix', help="hackprefix, if you need it you kno
|
||||||
# order based commands => later to be shifted below "order"
|
# order based commands => later to be shifted below "order"
|
||||||
arg_parser.add_argument('--order', action='store_true')
|
arg_parser.add_argument('--order', action='store_true')
|
||||||
arg_parser.add_argument('--list-orders', help="List all orders", action='store_true')
|
arg_parser.add_argument('--list-orders', help="List all orders", action='store_true')
|
||||||
|
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")
|
||||||
|
|
||||||
arg_parser.add_argument('--process-orders', help="Process all (pending) orders", action='store_true')
|
arg_parser.add_argument('--process-orders', help="Process all (pending) orders", action='store_true')
|
||||||
|
|
||||||
arg_parser.add_argument('--product', choices=["dualstack-vm"])
|
arg_parser.add_argument('--product', choices=["dualstack-vm"])
|
||||||
|
@ -107,7 +112,8 @@ def main(arguments):
|
||||||
|
|
||||||
if arguments['list_orders']:
|
if arguments['list_orders']:
|
||||||
p = ProductOrder(config)
|
p = ProductOrder(config)
|
||||||
for product_order in p.list_orders():
|
for product_order in p.list_orders(filter_key=arguments['filter_order_key'],
|
||||||
|
filter_regexp=arguments['filter_order_regexp']):
|
||||||
print("Order {}: {}".format(product_order.db_entry['uuid'], product_order.db_entry))
|
print("Order {}: {}".format(product_order.db_entry['uuid'], product_order.db_entry))
|
||||||
|
|
||||||
if arguments['process_orders']:
|
if arguments['process_orders']:
|
||||||
|
|
|
@ -21,9 +21,10 @@
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
from uncloud import UncloudException
|
from uncloud import UncloudException
|
||||||
from uncloud.hack.db import DB
|
from uncloud.hack.db import DB, db_logentry
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -32,38 +33,45 @@ class ProductOrder(object):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.db = DB(self.config, prefix="/orders")
|
self.db = DB(self.config, prefix="/orders")
|
||||||
self.db_entry = {}
|
self.db_entry = {}
|
||||||
self.db_entry["db_version"] = 1
|
|
||||||
self.db_entry["product"] = product_entry
|
self.db_entry["product"] = product_entry
|
||||||
|
|
||||||
|
|
||||||
# Overwrite if we are loading an existing product order
|
# Overwrite if we are loading an existing product order
|
||||||
if db_entry:
|
if db_entry:
|
||||||
self.db_entry = db_entry
|
self.db_entry = db_entry
|
||||||
|
|
||||||
# FIXME: this should return a list of our class!
|
# FIXME: this should return a list of our class!
|
||||||
def list_orders(self, filter_key=None, filter_regexp_value=None):
|
def list_orders(self, filter_key=None, filter_regexp=None):
|
||||||
"""List all orders with - filtering not yet implemented """
|
"""List all orders with - filtering not yet implemented """
|
||||||
|
|
||||||
for k,v in self.db.get_prefix("", as_json=True):
|
for k,v in self.db.get_prefix("", as_json=True):
|
||||||
log.debug("{} {}".format(k,v))
|
log.debug("{} {}".format(k,v))
|
||||||
|
if filter_key and filter_regexp:
|
||||||
yield self.__class__(self.config, db_entry=v)
|
if filter_key in v:
|
||||||
|
if re.match(filter_regexp, v[filter_key]):
|
||||||
def process_orders(self):
|
yield self.__class__(self.config, db_entry=v)
|
||||||
for orders in self.list_orders():
|
else:
|
||||||
pass
|
yield self.__class__(self.config, db_entry=v)
|
||||||
|
|
||||||
def set_required_values(self):
|
def set_required_values(self):
|
||||||
|
"""Set values that are required to make the db entry valid"""
|
||||||
if not "uuid" in self.db_entry:
|
if not "uuid" in self.db_entry:
|
||||||
self.db_entry["uuid"] = str(uuid.uuid4())
|
self.db_entry["uuid"] = str(uuid.uuid4())
|
||||||
if not "status" in self.db_entry:
|
if not "status" in self.db_entry:
|
||||||
self.db_entry["status"] = "NEW"
|
self.db_entry["status"] = "NEW"
|
||||||
if not "owner" in self.db_entry:
|
if not "owner" in self.db_entry:
|
||||||
self.db_entry["owner"] = "UNKNOWN"
|
self.db_entry["owner"] = "UNKNOWN"
|
||||||
|
if not "log" in self.db_entry:
|
||||||
|
self.db_entry["log"] = []
|
||||||
|
if not "db_version" in self.db_entry:
|
||||||
|
self.db_entry["db_version"] = 1
|
||||||
|
|
||||||
def validate_status(self):
|
def validate_status(self):
|
||||||
if "status" in self.db_entry:
|
if "status" in self.db_entry:
|
||||||
if self.db_entry["status"] in [ "NEW", "SCHEDULED", "CREATED", "DELETED", "REJECTED" ]:
|
if self.db_entry["status"] in [ "NEW",
|
||||||
|
"SCHEDULED",
|
||||||
|
"CREATED_ACTIVE",
|
||||||
|
"CANCELLED",
|
||||||
|
"REJECTED" ]:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -71,6 +79,25 @@ class ProductOrder(object):
|
||||||
if not self.db_entry["status"] == "NEW":
|
if not self.db_entry["status"] == "NEW":
|
||||||
raise UncloudException("Cannot re-order same order. Status: {}".format(self.db_entry["status"]))
|
raise UncloudException("Cannot re-order same order. Status: {}".format(self.db_entry["status"]))
|
||||||
|
|
||||||
|
def process_orders(self):
|
||||||
|
for order in self.list_orders():
|
||||||
|
if order.db_entry["status"] == "NEW":
|
||||||
|
log.info("Handling new order: {}".format(order))
|
||||||
|
|
||||||
|
# FIXME: these all should be a transactions! -> fix concurrent access! !
|
||||||
|
if not "log" in order.db_entry:
|
||||||
|
order.db_entry['log'] = []
|
||||||
|
|
||||||
|
for must_attribute in [ "owner", "product" ]:
|
||||||
|
if not must_attribute in order.db_entry:
|
||||||
|
order.db_entry['log'].append(db_logentry("Missing {} entry, rejecting order".format(must_attribute)))
|
||||||
|
order.db_entry['status'] = "REJECTED"
|
||||||
|
self.db.set(order.db_entry['uuid'], order.db_entry, as_json=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.db_entry)
|
||||||
|
|
||||||
class Product(object):
|
class Product(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
@ -83,6 +110,7 @@ class Product(object):
|
||||||
self.db_entry = {}
|
self.db_entry = {}
|
||||||
self.db_entry["product_name"] = product_name
|
self.db_entry["product_name"] = product_name
|
||||||
self.db_entry["db_version"] = 1
|
self.db_entry["db_version"] = 1
|
||||||
|
self.db_entry["log"] = []
|
||||||
self.db_entry["features"] = {}
|
self.db_entry["features"] = {}
|
||||||
|
|
||||||
# Existing product? Read in db_entry
|
# Existing product? Read in db_entry
|
||||||
|
@ -127,12 +155,9 @@ class Product(object):
|
||||||
|
|
||||||
def place_order(self):
|
def place_order(self):
|
||||||
""" Schedule creating the product in etcd """
|
""" Schedule creating the product in etcd """
|
||||||
order = ProductOrder(self.config, self.db_entry)
|
order = ProductOrder(self.config, product_entry=self.db_entry)
|
||||||
order.set_required_values()
|
order.set_required_values()
|
||||||
order.order()
|
order.order()
|
||||||
|
|
||||||
self.db.set(self.db_entry["uuid"], str(self))
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return json.dumps(self.db_entry)
|
return json.dumps(self.db_entry)
|
||||||
|
|
|
@ -101,6 +101,7 @@ class VM(object):
|
||||||
# self.features.append(self.define_feature(
|
# self.features.append(self.define_feature(
|
||||||
# self.super().__init__(
|
# self.super().__init__(
|
||||||
|
|
||||||
|
|
||||||
def get_qemu_args(self):
|
def get_qemu_args(self):
|
||||||
command = (
|
command = (
|
||||||
"-name {owner}-{name}"
|
"-name {owner}-{name}"
|
||||||
|
|
Loading…
Reference in a new issue