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
|
||||
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
|
||||
|
|
|
@ -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"
|
||||
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('--process-orders', help="Process all (pending) orders", action='store_true')
|
||||
|
||||
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)
|
||||
|
@ -51,6 +53,10 @@ arg_parser.add_argument('--username')
|
|||
arg_parser.add_argument('--password')
|
||||
|
||||
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']:
|
||||
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']:
|
||||
vm = VM(config)
|
||||
|
|
|
@ -20,52 +20,40 @@
|
|||
|
||||
import json
|
||||
import uuid
|
||||
import logging
|
||||
|
||||
from uncloud import UncloudException
|
||||
from uncloud.hack.db import DB
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class ProductOrder(object):
|
||||
def __init__(self, config):
|
||||
def __init__(self, config, product_entry=None, db_entry=None):
|
||||
self.config = config
|
||||
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["product_name"] = product_name
|
||||
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:
|
||||
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
|
||||
def define_feature(self,
|
||||
name,
|
||||
feature,
|
||||
one_time_price,
|
||||
recurring_price,
|
||||
recurring_period,
|
||||
minimum_period):
|
||||
feature = {}
|
||||
feature[name] = {}
|
||||
for k,v in self.db.get_prefix("", as_json=True):
|
||||
log.debug("{} {}".format(k,v))
|
||||
|
||||
def valid_status(self):
|
||||
if "status" in self.db_entry:
|
||||
if self.db_entry["status"] in [ "NEW", "SCHEDULED", "CREATED", "DELETED" ]:
|
||||
return False
|
||||
return True
|
||||
yield self.__class__(self.config, db_entry=v)
|
||||
|
||||
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:
|
||||
self.db_entry["uuid"] = str(uuid.uuid4())
|
||||
if not "status" in self.db_entry:
|
||||
|
@ -73,14 +61,75 @@ class Product(object):
|
|||
if not "owner" in self.db_entry:
|
||||
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):
|
||||
""" Schedule creating the product in etcd """
|
||||
self.validate_product()
|
||||
|
||||
# FIXME: very status
|
||||
if not self.db_entry["status"] == "NEW":
|
||||
raise UncloudException("Cannot re-order product")
|
||||
order = ProductOrder(self.config, self.db_entry)
|
||||
order.set_required_values()
|
||||
order.order()
|
||||
|
||||
self.db.set(self.db_entry["uuid"], str(self))
|
||||
|
||||
|
|
|
@ -90,6 +90,12 @@ class VM(object):
|
|||
self.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.append(self.define_feature(
|
||||
|
|
Loading…
Reference in a new issue