forked from uncloud/uncloud
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 json
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
from functools import wraps
|
||||
from uncloud import UncloudException
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def db_logentry(message):
|
||||
timestamp = datetime.datetime.now()
|
||||
return {
|
||||
"timestamp": str(timestamp),
|
||||
"message": message
|
||||
}
|
||||
|
||||
|
||||
def readable_errors(func):
|
||||
@wraps(func)
|
||||
|
@ -99,6 +107,8 @@ class DB(object):
|
|||
# FIXME: iterate over clients in case of failure ?
|
||||
return self._db_clients[0].put(self.realkey(key), value, **kwargs)
|
||||
|
||||
|
||||
|
||||
@readable_errors
|
||||
def increment(self, key, **kwargs):
|
||||
print(self.realkey(key))
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import argparse
|
||||
import logging
|
||||
import re
|
||||
|
||||
import ldap3
|
||||
|
||||
|
||||
from uncloud.hack.vm import VM
|
||||
from uncloud.hack.config import Config
|
||||
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"
|
||||
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('--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('--product', choices=["dualstack-vm"])
|
||||
|
@ -107,7 +112,8 @@ def main(arguments):
|
|||
|
||||
if arguments['list_orders']:
|
||||
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))
|
||||
|
||||
if arguments['process_orders']:
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
import json
|
||||
import uuid
|
||||
import logging
|
||||
import re
|
||||
|
||||
from uncloud import UncloudException
|
||||
from uncloud.hack.db import DB
|
||||
from uncloud.hack.db import DB, db_logentry
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -32,38 +33,45 @@ class ProductOrder(object):
|
|||
self.config = config
|
||||
self.db = DB(self.config, prefix="/orders")
|
||||
self.db_entry = {}
|
||||
self.db_entry["db_version"] = 1
|
||||
self.db_entry["product"] = product_entry
|
||||
|
||||
|
||||
# Overwrite if we are loading an existing product order
|
||||
if db_entry:
|
||||
self.db_entry = db_entry
|
||||
|
||||
# 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 """
|
||||
|
||||
for k,v in self.db.get_prefix("", as_json=True):
|
||||
log.debug("{} {}".format(k,v))
|
||||
|
||||
yield self.__class__(self.config, db_entry=v)
|
||||
|
||||
def process_orders(self):
|
||||
for orders in self.list_orders():
|
||||
pass
|
||||
if filter_key and filter_regexp:
|
||||
if filter_key in v:
|
||||
if re.match(filter_regexp, v[filter_key]):
|
||||
yield self.__class__(self.config, db_entry=v)
|
||||
else:
|
||||
yield self.__class__(self.config, db_entry=v)
|
||||
|
||||
def set_required_values(self):
|
||||
"""Set values that are required to make the db entry valid"""
|
||||
if not "uuid" in self.db_entry:
|
||||
self.db_entry["uuid"] = str(uuid.uuid4())
|
||||
if not "status" in self.db_entry:
|
||||
self.db_entry["status"] = "NEW"
|
||||
if not "owner" in self.db_entry:
|
||||
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):
|
||||
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 True
|
||||
|
||||
|
@ -71,6 +79,25 @@ class ProductOrder(object):
|
|||
if not self.db_entry["status"] == "NEW":
|
||||
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):
|
||||
def __init__(self,
|
||||
|
@ -83,6 +110,7 @@ class Product(object):
|
|||
self.db_entry = {}
|
||||
self.db_entry["product_name"] = product_name
|
||||
self.db_entry["db_version"] = 1
|
||||
self.db_entry["log"] = []
|
||||
self.db_entry["features"] = {}
|
||||
|
||||
# Existing product? Read in db_entry
|
||||
|
@ -127,12 +155,9 @@ class Product(object):
|
|||
|
||||
def place_order(self):
|
||||
""" 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.order()
|
||||
|
||||
self.db.set(self.db_entry["uuid"], str(self))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return json.dumps(self.db_entry)
|
||||
|
|
|
@ -101,6 +101,7 @@ class VM(object):
|
|||
# self.features.append(self.define_feature(
|
||||
# self.super().__init__(
|
||||
|
||||
|
||||
def get_qemu_args(self):
|
||||
command = (
|
||||
"-name {owner}-{name}"
|
||||
|
|
Loading…
Reference in a new issue