forked from uncloud/uncloud
Begin to phase in features and processing orders
This commit is contained in:
parent
5da6dbb32e
commit
5ef009cc9b
4 changed files with 108 additions and 38 deletions
|
@ -81,9 +81,13 @@ class DB(object):
|
||||||
|
|
||||||
@readable_errors
|
@readable_errors
|
||||||
def get_prefix(self, key, as_json=False, **kwargs):
|
def get_prefix(self, key, as_json=False, **kwargs):
|
||||||
key_range = self._db_clients[0].get_prefix(self.realkey(key), **kwargs)
|
for value, meta in self._db_clients[0].get_prefix(self.realkey(key), **kwargs):
|
||||||
|
k = meta.key.decode("utf-8")
|
||||||
|
value = value.decode("utf-8")
|
||||||
|
if as_json:
|
||||||
|
value = json.loads(value)
|
||||||
|
|
||||||
return key_range
|
yield (k, value)
|
||||||
|
|
||||||
|
|
||||||
@readable_errors
|
@readable_errors
|
||||||
|
|
|
@ -43,6 +43,8 @@ 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('--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"])
|
||||||
arg_parser.add_argument('--os-image-name', help="Name of OS image (successor to --image)")
|
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('--os-image-size', help="Size of OS image in GB", type=int, default=10)
|
||||||
|
@ -51,6 +53,10 @@ arg_parser.add_argument('--username')
|
||||||
arg_parser.add_argument('--password')
|
arg_parser.add_argument('--password')
|
||||||
|
|
||||||
arg_parser.add_argument('--api', help="Run the API")
|
arg_parser.add_argument('--api', help="Run the API")
|
||||||
|
arg_parser.add_argument('--mode',
|
||||||
|
choices=["direct", "api", "client"],
|
||||||
|
default="client",
|
||||||
|
help="Directly manipulate etcd, spawn the API server or behave as a client")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,7 +107,12 @@ def main(arguments):
|
||||||
|
|
||||||
if arguments['list_orders']:
|
if arguments['list_orders']:
|
||||||
p = ProductOrder(config)
|
p = ProductOrder(config)
|
||||||
p.list_orders()
|
for product_order in p.list_orders():
|
||||||
|
print("Order {}: {}".format(product_order.db_entry['uuid'], product_order.db_entry))
|
||||||
|
|
||||||
|
if arguments['process_orders']:
|
||||||
|
p = ProductOrder(config)
|
||||||
|
p.process_orders()
|
||||||
|
|
||||||
if arguments['create_vm']:
|
if arguments['create_vm']:
|
||||||
vm = VM(config)
|
vm = VM(config)
|
||||||
|
|
|
@ -20,52 +20,40 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
|
import logging
|
||||||
|
|
||||||
from uncloud import UncloudException
|
from uncloud import UncloudException
|
||||||
from uncloud.hack.db import DB
|
from uncloud.hack.db import DB
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
class ProductOrder(object):
|
class ProductOrder(object):
|
||||||
def __init__(self, config):
|
def __init__(self, config, product_entry=None, db_entry=None):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.db = DB(self.config, prefix="/orders")
|
self.db = DB(self.config, prefix="/orders")
|
||||||
|
|
||||||
def list_orders(self, filter_key=None, filter_regexp_value=None):
|
|
||||||
for k,m in self.db.get_prefix(""):
|
|
||||||
print("{} {}".format(k,m))
|
|
||||||
|
|
||||||
|
|
||||||
class Product(object):
|
|
||||||
def __init__(self, config, product_name, db_entry=None):
|
|
||||||
self.config = config
|
|
||||||
self.db = DB(self.config, prefix="/orders")
|
|
||||||
|
|
||||||
self.db_entry = {}
|
self.db_entry = {}
|
||||||
self.db_entry["product_name"] = product_name
|
|
||||||
self.db_entry["db_version"] = 1
|
self.db_entry["db_version"] = 1
|
||||||
|
self.db_entry["product"] = product_entry
|
||||||
|
|
||||||
# Existing product? Read in db_entry
|
|
||||||
|
# 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!
|
||||||
|
def list_orders(self, filter_key=None, filter_regexp_value=None):
|
||||||
|
"""List all orders with - filtering not yet implemented """
|
||||||
|
|
||||||
@staticmethod
|
for k,v in self.db.get_prefix("", as_json=True):
|
||||||
def define_feature(self,
|
log.debug("{} {}".format(k,v))
|
||||||
name,
|
|
||||||
feature,
|
|
||||||
one_time_price,
|
|
||||||
recurring_price,
|
|
||||||
recurring_period,
|
|
||||||
minimum_period):
|
|
||||||
feature = {}
|
|
||||||
feature[name] = {}
|
|
||||||
|
|
||||||
def valid_status(self):
|
yield self.__class__(self.config, db_entry=v)
|
||||||
if "status" in self.db_entry:
|
|
||||||
if self.db_entry["status"] in [ "NEW", "SCHEDULED", "CREATED", "DELETED" ]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def validate_product(self):
|
def process_orders(self):
|
||||||
|
for orders in self.list_orders():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_required_values(self):
|
||||||
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:
|
||||||
|
@ -73,14 +61,75 @@ class Product(object):
|
||||||
if not "owner" in self.db_entry:
|
if not "owner" in self.db_entry:
|
||||||
self.db_entry["owner"] = "UNKNOWN"
|
self.db_entry["owner"] = "UNKNOWN"
|
||||||
|
|
||||||
|
def validate_status(self):
|
||||||
|
if "status" in self.db_entry:
|
||||||
|
if self.db_entry["status"] in [ "NEW", "SCHEDULED", "CREATED", "DELETED", "REJECTED" ]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def order(self):
|
||||||
|
if not self.db_entry["status"] == "NEW":
|
||||||
|
raise UncloudException("Cannot re-order same order. Status: {}".format(self.db_entry["status"]))
|
||||||
|
|
||||||
|
|
||||||
|
class Product(object):
|
||||||
|
def __init__(self,
|
||||||
|
config,
|
||||||
|
product_name,
|
||||||
|
db_entry=None):
|
||||||
|
self.config = config
|
||||||
|
self.db = DB(self.config, prefix="/orders")
|
||||||
|
|
||||||
|
self.db_entry = {}
|
||||||
|
self.db_entry["product_name"] = product_name
|
||||||
|
self.db_entry["db_version"] = 1
|
||||||
|
self.db_entry["features"] = {}
|
||||||
|
|
||||||
|
# Existing product? Read in db_entry
|
||||||
|
if db_entry:
|
||||||
|
self.db_entry = db_entry
|
||||||
|
|
||||||
|
self.valid_periods = [ "per_year", "per_month", "per_week",
|
||||||
|
"per_day", "per_hour",
|
||||||
|
"per_minute", "per_second" ]
|
||||||
|
|
||||||
|
def define_feature(self,
|
||||||
|
name,
|
||||||
|
one_time_price,
|
||||||
|
recurring_price,
|
||||||
|
recurring_period,
|
||||||
|
minimum_period):
|
||||||
|
|
||||||
|
self.db_entry['features'][name] = {}
|
||||||
|
self.db_entry['features'][name]['one_time_price'] = one_time_price
|
||||||
|
self.db_entry['features'][name]['recurring_price'] = recurring_price
|
||||||
|
|
||||||
|
if not recurring_period in self.valid_periods:
|
||||||
|
raise UncloudException("Invalid recurring period: {}".format(recurring_period))
|
||||||
|
|
||||||
|
self.db_entry['features'][name]['recurring_period'] = recurring_period
|
||||||
|
|
||||||
|
if not minimum_period in self.valid_periods:
|
||||||
|
raise UncloudException("Invalid recurring period: {}".format(recurring_period))
|
||||||
|
|
||||||
|
recurring_index = self.valid_periods.index(recurring_period)
|
||||||
|
minimum_index = self.valid_periods.index(minimum_period)
|
||||||
|
|
||||||
|
if minimum_index < recurring_index:
|
||||||
|
raise UncloudException("Minimum period for product '{}' feature '{}' must be shorter or equal than/as recurring period: {} > {}".format(self.db_entry['product_name'], name, minimum_period, recurring_period))
|
||||||
|
|
||||||
|
self.db_entry['features'][name]['minimum_period'] = minimum_period
|
||||||
|
|
||||||
|
|
||||||
|
def validate_product(self):
|
||||||
|
for feature in self.db_entry['features']:
|
||||||
|
pass
|
||||||
|
|
||||||
def place_order(self):
|
def place_order(self):
|
||||||
""" Schedule creating the product in etcd """
|
""" Schedule creating the product in etcd """
|
||||||
self.validate_product()
|
order = ProductOrder(self.config, self.db_entry)
|
||||||
|
order.set_required_values()
|
||||||
# FIXME: very status
|
order.order()
|
||||||
if not self.db_entry["status"] == "NEW":
|
|
||||||
raise UncloudException("Cannot re-order product")
|
|
||||||
|
|
||||||
self.db.set(self.db_entry["uuid"], str(self))
|
self.db.set(self.db_entry["uuid"], str(self))
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,12 @@ class VM(object):
|
||||||
self.vm = {}
|
self.vm = {}
|
||||||
|
|
||||||
self.product = Product(config, product_name="dualstack-vm")
|
self.product = Product(config, product_name="dualstack-vm")
|
||||||
|
self.product.define_feature(name="base",
|
||||||
|
one_time_price=0,
|
||||||
|
recurring_price=9,
|
||||||
|
recurring_period="per_month",
|
||||||
|
minimum_period="per_hour")
|
||||||
|
|
||||||
|
|
||||||
self.features = []
|
self.features = []
|
||||||
# self.features.append(self.define_feature(
|
# self.features.append(self.define_feature(
|
||||||
|
|
Loading…
Reference in a new issue