Switch to using a blob of JSON encoded data

- ipmi_user VARCHAR(50),
- ipmi_password VARCHAR(50),
- port_hwaddr VARCHAR(50),
- cpu_arch VARCHAR(50),
- cpus INTEGER,
- ram_mb INTEGER,
- disk_gb INTEGER,
+ blob VARCHAR(2000),

Change-Id: I7a329d8137f877f111213af4332f50b1d8ff7295
This commit is contained in:
Mark Hamzy 2016-11-03 12:00:09 -05:00
parent 24bf07c892
commit 952d4b133f
12 changed files with 939 additions and 539 deletions

View File

@ -118,10 +118,12 @@ class MoltenIron(object):
return self.response_json
@command
def add(self, subparsers=None):
"""Generate a request to add a node to the MoltenIron database """
def add_baremetal(self, subparsers=None):
"""Generate a request to add a node to the MoltenIron database.
All parameters are manditory."""
if subparsers is not None:
sp = subparsers.add_parser("add",
sp = subparsers.add_parser("add_baremetal",
help="Add a node to the MoltenIron"
" database.")
sp.add_argument("name",
@ -154,7 +156,7 @@ class MoltenIron(object):
type=int,
help="Amount of disk (in GiB)"
" that the node has")
sp.set_defaults(func=self.add)
sp.set_defaults(func=self.add_baremetal)
return
# Make a map of our arguments
@ -163,7 +165,72 @@ class MoltenIron(object):
# But delete the class function pointer. json can't serialize it!
del request['func']
request['method'] = 'add'
request['method'] = 'add_baremetal'
return request
@command
def add_keyvalue_pairs(self, subparsers=None):
"""Generate a request to add a node to the MoltenIron database.
args are a list of key=value pairs."""
if subparsers is not None:
sp = subparsers.add_parser("add_keyvalue_pairs",
help="Add a node to the MoltenIron"
" database.")
sp.add_argument("name",
help="Name of the baremetal node")
sp.add_argument("ipmi_ip",
help="IP for issuing IPMI commands to"
" this node")
sp.add_argument("allocation_pool",
help="Comma separated list of"
" IPs to be used in deployment")
sp.add_argument("args",
nargs=argparse.REMAINDER,
help="Architecture of the node")
sp.set_defaults(func=self.add_keyvalue_pairs)
return
# Make a map of our arguments
request = vars(self.argv)
# But delete the class function pointer. json can't serialize it!
del request['func']
request['method'] = 'add_keyvalue_pairs'
return request
@command
def add_json_blob(self, subparsers=None):
"""Generate a request to add a node to the MoltenIron database.
blob is a JSON encoded string."""
if subparsers is not None:
sp = subparsers.add_parser("add_json_blob",
help="Add a node to the MoltenIron"
" database.")
sp.add_argument("name",
help="Name of the baremetal node")
sp.add_argument("ipmi_ip",
help="IP for issuing IPMI commands to"
" this node")
sp.add_argument("allocation_pool",
help="Comma separated list of"
" IPs to be used in deployment")
sp.add_argument("blob",
help="JSON encoded string")
sp.set_defaults(func=self.add_json_blob)
return
# Make a map of our arguments
request = vars(self.argv)
# But delete the class function pointer. json can't serialize it!
del request['func']
request['method'] = 'add_json_blob'
return request
@ -262,6 +329,8 @@ class MoltenIron(object):
help="Field name to set")
sp.add_argument("value",
help="Field value to set")
sp.add_argument("type",
help="Field Python type to set")
sp.set_defaults(func=self.set_field)
return
@ -303,6 +372,34 @@ class MoltenIron(object):
return request
@command
def status_baremetal(self, subparsers=None):
"""Return status """
if subparsers is not None:
sp = subparsers.add_parser("status_baremetal",
help="Return a list of current"
" MoltenIron Node database"
" entries.")
sp.add_argument("-t",
"--type",
action="store",
type=str,
default="human",
dest="type",
help="Either human (the default) or csv")
sp.set_defaults(func=self.status_baremetal)
return
# Make a map of our arguments
request = vars(self.argv)
# But delete the class function pointer. json can't serialize it!
del request['func']
request['method'] = 'status_baremetal'
return request
@command
def delete_db(self, subparsers=None):
"""Delete all database entries"""

View File

@ -127,8 +127,27 @@ def MakeMoltenIronHandlerWithConf(conf):
# Try to json-ify the request_string
request = json.loads(request_string)
method = request.pop('method')
if method == 'add':
response = database.addBMNode(request)
if method == 'add_baremetal':
node = {}
node['ipmi_user'] = request.pop('ipmi_user')
node['ipmi_password'] = request.pop('ipmi_password')
node['port_hwaddr'] = request.pop('port_hwaddr')
node['disk_gb'] = request.pop('disk_gb')
node['cpu_arch'] = request.pop('cpu_arch')
node['ram_mb'] = request.pop('ram_mb')
node['cpus'] = request.pop('cpus')
response = database.addBMNode(request, node)
elif method == 'add_keyvalue_pairs':
node = {}
for elm in request["args"]:
idx = elm.find("=")
if idx > -1:
node[elm[:idx]] = elm[idx + 1:]
response = database.addBMNode(request, node)
elif method == 'add_json_blob':
node = json.loads(request.pop("blob"))
response = database.addBMNode(request, node)
elif method == 'allocate':
response = database.allocateBM(request['owner_name'],
request['number_of_nodes'])
@ -140,9 +159,12 @@ def MakeMoltenIronHandlerWithConf(conf):
elif method == 'set_field':
response = database.set_field(request['id'],
request['key'],
request['value'])
request['value'],
request['type'])
elif method == 'status':
response = database.status(request["type"])
elif method == 'status_baremetal':
response = database.status_baremetal(request["type"])
elif method == 'delete_db':
response = database.delete_db()
database.close()
@ -169,13 +191,7 @@ class Nodes(declarative_base()):
# id INTEGER NOT NULL AUTO_INCREMENT, #@TODO(hamzy) UNSIGNED
# name VARCHAR(50),
# ipmi_ip VARCHAR(50),
# ipmi_user VARCHAR(50),
# ipmi_password VARCHAR(50),
# port_hwaddr VARCHAR(50),
# cpu_arch VARCHAR(50),
# cpus INTEGER,
# ram_mb INTEGER,
# disk_gb INTEGER,
# blob VARCHAR(2000),
# status VARCHAR(20),
# provisioned VARCHAR(50),
# timestamp TIMESTAMP NULL,
@ -185,13 +201,7 @@ class Nodes(declarative_base()):
id = Column('id', Integer, primary_key=True)
name = Column('name', String(50))
ipmi_ip = Column('ipmi_ip', String(50))
ipmi_user = Column('ipmi_user', String(50))
ipmi_password = Column('ipmi_password', String(50))
port_hwaddr = Column('port_hwaddr', String(50))
cpu_arch = Column('cpu_arch', String(50))
cpus = Column('cpus', Integer)
ram_mb = Column('ram_mb', Integer)
disk_gb = Column('disk_gb', Integer)
blob = Column('blob', String(2000))
status = Column('status', String(20))
provisioned = Column('provisioned', String(50))
timestamp = Column('timestamp', TIMESTAMP)
@ -201,13 +211,7 @@ class Nodes(declarative_base()):
id,
name,
ipmi_ip,
ipmi_user,
ipmi_password,
port_hwaddr,
cpu_arch,
cpus,
ram_mb,
disk_gb,
blob,
status,
provisioned,
timestamp)
@ -222,13 +226,7 @@ class Nodes(declarative_base()):
def __repr__(self):
fmt = """<Node(name='%s',
ipmi_ip='%s',
ipmi_user='%s',
ipmi_password='%s',
port='%s',
cpu_arch='%s',
cpus='%d',
ram='%d',
disk='%d',
blob='%s',
status='%s',
provisioned='%s',
timestamp='%s'/>"""
@ -236,13 +234,7 @@ timestamp='%s'/>"""
return fmt % (self.name,
self.ipmi_ip,
self.ipmi_user,
self.ipmi_password,
self.port_hwaddr,
self.cpu_arch,
self.cpus,
self.ram_mb,
self.disk_gb,
self.blob,
self.status,
self.provisioned,
self.timestamp)
@ -323,26 +315,45 @@ class DataBase(object):
self.create_metadata()
self.element_info = [
# The following are returned from the query call
self.blob_status = {
"element_info": [
# The following are returned from the query call
# field_name length special_fmt skip
("id", 4, int, False),
("name", 6, str, False),
("ipmi_ip", 9, str, False),
("ipmi_user", 11, str, False),
("ipmi_password", 15, str, False),
("port_hwaddr", 19, str, False),
("cpu_arch", 10, str, False),
("cpus", 6, int, False),
("ram_mb", 8, int, False),
("disk_gb", 9, int, False),
("status", 8, str, False),
("provisioned", 13, str, False),
# We add timeString
("time", 14, float, False),
]
self.setup_status()
# field_name length special_fmt skip
("id", 4, int, False),
("name", 6, str, False),
("blob", 40, str, False),
("status", 8, str, False),
("provisioned", 13, str, False),
# We add timeString
("time", 14, float, False),
]
}
self.baremetal_status = {
"element_info": [
# The following are returned from the query call
# field_name length special_fmt skip
("id", 4, int, False),
("name", 6, str, False),
("ipmi_ip", 9, str, False),
("ipmi_user", 11, str, False),
("ipmi_password", 15, str, False),
("port_hwaddr", 19, str, False),
("cpu_arch", 10, str, False),
("cpus", 6, int, False),
("ram_mb", 8, int, False),
("disk_gb", 9, int, False),
("status", 8, str, False),
("provisioned", 13, str, False),
# We add timeString
("time", 14, float, False),
]
}
# Pass map by reference but update our copy with the new information
self.baremetal_status = self.setup_status(**self.baremetal_status)
self.blob_status = self.setup_status(**self.blob_status)
def create_engine(self):
"""Create the sqlalchemy database engine"""
@ -602,59 +613,57 @@ class DataBase(object):
return {'status': 200}
def addBMNode(self, node):
def addBMNode(self, request, data_map):
"""Add a new node to molten iron.
ex:
node = {u'name': u'test',
u'ipmi_user': u'user',
u'port_hwaddr': u'de:ad:be:ef:00:01',
u'disk_gb': 32,
u'cpu_arch': u'ppc64el',
u'ram_mb': 2048,
u'cpus': 8,
u'allocation_pool': u'0.0.0.1,0.0.0.2',
u'ipmi_password': u'password',
u'ipmi_ip': u'0.0.0.0'}
request = {u'name': u'test',
u'ipmi_ip': u'0.0.0.0',
u'status': u'',
u'provisioned': u'',
u'timestamp': u'',
u'allocation_pool': u'0.0.0.1,0.0.0.2'}
data_map = {u'ipmi_user': u'user',
u'ipmi_password': u'password',
u'port_hwaddr': u'de:ad:be:ef:00:01',
u'disk_gb': 32,
u'cpu_arch': u'ppc64el',
u'ram_mb': 2048,
u'cpus': 8}
"""
try:
if DEBUG:
print("addBMNode: node = %s" % (node, ))
print("addBMNode: request = %s data_map = %s"
% (request, data_map, ))
with self.session_scope() as session, \
self.connection_scope() as conn:
# Check if it already exists
query = session.query(Nodes)
query = query.filter_by(name=node['name'])
query = query.filter_by(name=request['name'])
count = query.count()
if count == 1:
return {'status': 400, 'message': "Node already exists"}
log(self.conf,
"adding node %(name)s ipmi_ip: %(ipmi_ip)s" % node)
"adding node %(name)s ipmi_ip: %(ipmi_ip)s" % request)
# Add Node to database
# Note: ID is always 0 as it is an auto-incrementing field
stmt = insert(Nodes)
stmt = stmt.values(name=node['name'])
stmt = stmt.values(ipmi_ip=node['ipmi_ip'])
stmt = stmt.values(ipmi_user=node['ipmi_user'])
stmt = stmt.values(ipmi_password=node['ipmi_password'])
stmt = stmt.values(port_hwaddr=node['port_hwaddr'])
stmt = stmt.values(cpu_arch=node['cpu_arch'])
stmt = stmt.values(cpus=node['cpus'])
stmt = stmt.values(ram_mb=node['ram_mb'])
stmt = stmt.values(disk_gb=node['disk_gb'])
stmt = stmt.values(name=request['name'])
stmt = stmt.values(ipmi_ip=request['ipmi_ip'])
stmt = stmt.values(blob=json.dumps(data_map))
stmt = stmt.values(status='ready')
if 'status' in node:
stmt = stmt.values(status=node['status'])
if 'provisioned' in node:
stmt = stmt.values(provisioned=node['provisioned'])
if 'timestamp' in node:
timestamp_str = node['timestamp']
if 'status' in request:
stmt = stmt.values(status=request['status'])
if 'provisioned' in request:
stmt = stmt.values(provisioned=request['provisioned'])
if 'timestamp' in request:
timestamp_str = request['timestamp']
if DEBUG:
print("timestamp_str = %s" % (timestamp_str, ))
if len(timestamp_str) != 0 and timestamp_str != "-1":
@ -672,14 +681,14 @@ class DataBase(object):
session.close()
session = self.get_session()
query = session.query(Nodes).filter_by(name=node['name'])
query = session.query(Nodes).filter_by(name=request['name'])
new_node = query.one()
# new_node is now a proper Node with an id
# Add IPs to database
# Note: id is always 0 as it is an auto-incrementing field
ips = node['allocation_pool'].split(',')
ips = request['allocation_pool'].split(',')
for ip in ips:
stmt = insert(IPs)
stmt = stmt.values(node_id=new_node.id, ip=ip)
@ -877,10 +886,6 @@ class DataBase(object):
def get_field(self, owner_name, field):
"""Return entries list with id, field for a given owner, field. """
if not hasattr(Nodes, field):
return {'status': 400,
'message': 'field %s does not exist' % (field,)}
results = []
try:
@ -900,7 +905,16 @@ class DataBase(object):
for node in nodes:
result = {'id': node.id}
result['field'] = getattr(node, field)
try:
result["field"] = getattr(node, field)
except AttributeError:
blob = json.loads(node.blob)
if field in blob:
result["field"] = blob[field]
else:
msg = "field %s does not exist" % (field, )
return {'status': 400, 'message': msg}
results.append(result)
@ -914,28 +928,42 @@ class DataBase(object):
return {'status': 200, 'result': results}
def set_field(self, node_id, key, value):
def set_field(self, node_id, key, value, python_type):
"""Given an identifying id, set specified key to the passed value. """
if not hasattr(Nodes, key):
return {'status': 400,
'message': 'field %s does not exist' % (key,)}
try:
with self.session_scope() as session, \
self.connection_scope() as conn:
if python_type.upper().lower() == "string":
pass
elif python_type.upper().lower() == "int":
value = int(value)
else:
return {'status': 400,
'message': 'Python type of %s is not supported!'
% (python_type, )}
query = session.query(Nodes)
nodes = query.filter_by(id=node_id)
if nodes.count() == 0:
return {'status': 404,
'message': 'Node with id of %s does not exist!'
% node_id}
% (node_id, )}
nodes.one()
node = nodes.one()
kv = {key: value}
if hasattr(Nodes, key):
kv = {key: value}
else:
blob = json.loads(node.blob)
if key in blob:
blob[key] = value
kv = {"blob": json.dumps(blob)}
else:
return {'status': 400,
'message': 'field %s does not exist' % (key,)}
stmt = update(Nodes)
stmt = stmt.where(Nodes.id == node_id)
@ -953,54 +981,63 @@ class DataBase(object):
return {'status': 200}
def setup_status(self):
def setup_status(self, **status_map):
"""Setup the status formatting strings.
Which depends on the skipped elements, lengths, and types.
"""
self.result_separator = "+"
for (_, length, _, skip) in self.element_info:
if skip:
continue
self.result_separator += '-' * (1 + length + 1) + "+"
ei = status_map["element_info"]
self.description_line = "+"
for (field, length, _, skip) in self.element_info:
rs = "+"
for (_, length, _, skip) in ei:
if skip:
continue
self.description_line += (" " +
field +
' ' * (length - len(field)) +
" +")
rs += '-' * (1 + length + 1) + "+"
dl = "+"
for (field, length, _, skip) in ei:
if skip:
continue
dl += (" " +
field +
' ' * (length - len(field)) +
" +")
index = 0
self.format_line = "|"
for (_, length, special_fmt, skip) in self.element_info:
fl = "|"
for (_, length, special_fmt, skip) in ei:
if skip:
continue
if special_fmt is int:
self.format_line += " {%d:<%d} |" % (index, length)
fl += " {%d:<%d} |" % (index, length)
elif special_fmt is str:
self.format_line += " {%d:%d} |" % (index, length)
fl += " {%d:%d} |" % (index, length)
elif special_fmt is float:
self.format_line += " {%d:<%d.%d} |" \
% (index, length, length - 2)
fl += " {%d:<%d.%d} |" \
% (index, length, length - 2)
index += 1
index = 0
self.format_line_csv = ""
for (_, length, special_fmt, skip) in self.element_info:
flc = ""
for (_, length, special_fmt, skip) in ei:
if skip:
continue
if special_fmt is int:
self.format_line_csv += "{%d}," % (index, )
flc += "{%d}," % (index, )
elif special_fmt is str:
self.format_line_csv += "{%d}," % (index, )
flc += "{%d}," % (index, )
elif special_fmt is float:
self.format_line_csv += "{%d}," % (index, )
flc += "{%d}," % (index, )
index += 1
status_map["result_separator"] = rs
status_map["description_line"] = dl
status_map["format_line"] = fl
status_map["format_line_csv"] = flc
return status_map
def status(self, output_type):
"""Return a table that details the state of each bare metal node.
@ -1011,18 +1048,72 @@ class DataBase(object):
output_type = output_type.upper().lower()
if output_type == "csv":
return self.status_csv()
return self.status_csv(self.blob_status_elements,
**self.blob_status)
elif output_type == "human":
return self.status_full()
return self.status_full(self.blob_status_elements,
**self.blob_status)
else:
return {'status': 400,
'message': "Unknown --type=%s" % (output_type, )}
def status_csv(self):
def status_baremetal(self, output_type):
"""Return a table that details the state of each bare metal node.
Currently this table is being created manually, there is probably a
better way to be doing this.
"""
output_type = output_type.upper().lower()
if output_type == "csv":
return self.status_csv(self.baremetal_status_elements,
**self.baremetal_status)
elif output_type == "human":
return self.status_full(self.baremetal_status_elements,
**self.baremetal_status)
else:
return {'status': 400,
'message': "Unknown --type=%s" % (output_type, )}
def blob_status_elements(self, node, timeString):
blob = json.loads(node.blob)
return (node.id,
node.name,
node.ipmi_ip,
blob,
node.status,
node.provisioned,
timeString)
def baremetal_status_elements(self, node, timeString):
blob = json.loads(node.blob)
return (node.id,
node.name,
node.ipmi_ip,
blob["ipmi_user"],
blob["ipmi_password"],
blob["port_hwaddr"],
blob["cpu_arch"],
blob["cpus"],
blob["ram_mb"],
blob["disk_gb"],
node.status,
node.provisioned,
timeString)
def status_csv(self, get_status_elements, **status_map):
"""Return a comma separated list of values"""
result = ""
ei = status_map["element_info"]
flc = status_map["format_line_csv"]
try:
with self.session_scope() as session:
@ -1030,36 +1121,30 @@ class DataBase(object):
for node in query:
timeString = ""
try:
if node.timestamp is not None:
elapsedTime = datetime.utcnow() - node.timestamp
timeString = str(elapsedTime)
except Exception:
pass
elements = (node.id,
node.name,
node.ipmi_ip,
node.ipmi_user,
node.ipmi_password,
node.port_hwaddr,
node.cpu_arch,
node.cpus,
node.ram_mb,
node.disk_gb,
node.status,
node.provisioned,
timeString)
timeString = ""
try:
if node.timestamp is not None:
et = datetime.utcnow() - node.timestamp
timeString = str(et)
except Exception:
pass
new_elements = []
index = 0
for (_, _, _, skip) in self.element_info:
if not skip:
new_elements.append(elements[index])
index += 1
elements = get_status_elements(node, timeString)
result += self.format_line_csv.format(*new_elements) + "\n"
new_elements = []
index = 0
for (_, _, _, skip) in ei:
if not skip:
new_elements.append(elements[index])
index += 1
result += flc.format(*new_elements) + "\n"
except KeyError:
result += "blob missing baremetal fields\n"
except Exception as e:
@ -1071,54 +1156,53 @@ class DataBase(object):
return {'status': 200, 'result': result}
def status_full(self):
def status_full(self, get_status_elements, **status_map):
"""Return an ASCII table of the database entries"""
result = ""
ei = status_map["element_info"]
rs = status_map["result_separator"]
dl = status_map["description_line"]
fl = status_map["format_line"]
try:
with self.session_scope() as session:
query = session.query(Nodes)
result += self.result_separator + "\n"
result += self.description_line + "\n"
result += self.result_separator + "\n"
result += rs + "\n"
result += dl + "\n"
result += rs + "\n"
for node in query:
timeString = ""
try:
if node.timestamp is not None:
elapsedTime = datetime.utcnow() - node.timestamp
timeString = str(elapsedTime)
except Exception:
pass
elements = (node.id,
node.name,
node.ipmi_ip,
node.ipmi_user,
node.ipmi_password,
node.port_hwaddr,
node.cpu_arch,
node.cpus,
node.ram_mb,
node.disk_gb,
node.status,
node.provisioned,
timeString)
timeString = ""
try:
if node.timestamp is not None:
et = datetime.utcnow() - node.timestamp
timeString = str(et)
except Exception:
pass
new_elements = []
index = 0
for (_, _, _, skip) in self.element_info:
if not skip:
new_elements.append(elements[index])
index += 1
elements = get_status_elements(node, timeString)
result += self.format_line.format(*new_elements) + "\n"
new_elements = []
index = 0
for (_, _, _, skip) in ei:
if not skip:
new_elements.append(elements[index])
index += 1
result += self.result_separator + "\n"
result += fl.format(*new_elements) + "\n"
except KeyError:
result += "blob missing baremetal fields\n"
result += rs + "\n"
except Exception as e:

View File

@ -53,87 +53,95 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "2f024600fc5ef6f7",
"port_hwaddr": "97: c3:b0: 47:0c:0d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "6cf0957c985b2deb",
"port_hwaddr": "2d: 9e:3c:83:8a: be",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "cc777c10196db585",
"port_hwaddr": "47: b0:dc:d5: 82:d9",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "a700a2d789075276",
"port_hwaddr": "44: 94:1a: c7:8a:9f",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret['status'] == 400
assert ret['message'] == "Node already exists"
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret['status'] == 400
assert ret['message'] == "Node already exists"
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret['status'] == 400
assert ret['message'] == "Node already exists"

View File

@ -24,23 +24,51 @@ Tests the MoltenIron allocateBM command.
from __future__ import print_function
import argparse
import json
from molteniron import moltenirond
import os
import sys
import yaml
def compare_provisioned_nodes(lhs, rhs):
"""Specially compares lhs against rhs."""
lhs = lhs.copy()
rhs = rhs.copy()
rhs['provisioned'] = 'hamzy'
del lhs['status']
del lhs['timestamp']
del rhs['status']
del rhs['timestamp']
del lhs['id']
assert lhs == rhs
def result_to_r(res):
"""Takes a result and returns the request parameters."""
r = res.copy()
del r["blob"]
return r
def result_to_n(res):
"""Takes a result and returns the node parameters."""
n = {}
if "blob" in res:
blob = json.loads(res["blob"])
n["ipmi_user"] = blob["ipmi_user"]
n["ipmi_password"] = blob["ipmi_password"]
n["port_hwaddr"] = blob["port_hwaddr"]
n["cpu_arch"] = blob["cpu_arch"]
n["cpus"] = blob["cpus"]
n["ram_mb"] = blob["ram_mb"]
n["disk_gb"] = blob["disk_gb"]
return n
def compare_provisioned_nodes(lhs, rhs_r, rhs_n):
"""Specially compares lhs against the combined rhs_r and rhs_n."""
rhs_r = rhs_r.copy()
lhs_r = result_to_r(lhs)
lhs_n = result_to_n(lhs)
rhs_r['provisioned'] = 'hamzy'
del lhs_r['status']
del lhs_r['timestamp']
del rhs_r['status']
del rhs_r['timestamp']
del lhs_r['id']
assert lhs_r == rhs_r
assert lhs_n == rhs_n
if __name__ == "__main__":
@ -67,79 +95,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8: de: 29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c: c5:da: 28:2c:2d",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53: 76: c6:09:50:64",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85: e0: 73:e9:fc:ca",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -147,7 +183,7 @@ if __name__ == "__main__":
print(ret)
assert ret['status'] == 200
assert len(ret["nodes"]) == 1
compare_provisioned_nodes(ret["nodes"]["node_1"], node1)
compare_provisioned_nodes(ret["nodes"]["node_1"], request1, node1)
database.close()
del database
@ -159,16 +195,16 @@ if __name__ == "__main__":
del database
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -176,8 +212,8 @@ if __name__ == "__main__":
print(ret)
assert ret['status'] == 200
assert len(ret["nodes"]) == 2
compare_provisioned_nodes(ret["nodes"]["node_1"], node1)
compare_provisioned_nodes(ret["nodes"]["node_2"], node2)
compare_provisioned_nodes(ret["nodes"]["node_1"], request1, node1)
compare_provisioned_nodes(ret["nodes"]["node_2"], request2, node2)
database.close()
del database
@ -189,16 +225,16 @@ if __name__ == "__main__":
del database
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}

View File

@ -24,6 +24,7 @@ Tests the MoltenIron cull command.
from __future__ import print_function
import argparse
import json
from molteniron import moltenirond
import os
import sys
@ -31,16 +32,42 @@ import time
import yaml
def compare_culled_nodes(lhs, rhs):
def result_to_r(res):
"""Takes a result and returns the request parameters."""
r = res.copy()
del r["blob"]
return r
def result_to_n(res):
"""Takes a result and returns the node parameters."""
n = {}
if "blob" in res:
blob = json.loads(res["blob"])
n["ipmi_user"] = blob["ipmi_user"]
n["ipmi_password"] = blob["ipmi_password"]
n["port_hwaddr"] = blob["port_hwaddr"]
n["cpu_arch"] = blob["cpu_arch"]
n["cpus"] = blob["cpus"]
n["ram_mb"] = blob["ram_mb"]
n["disk_gb"] = blob["disk_gb"]
return n
def compare_culled_nodes(lhs, rhs_r, rhs_n):
"""Specially compares lhs against rhs."""
lhs = lhs.copy()
rhs = rhs.copy()
del rhs['allocation_pool']
rhs_r = rhs_r.copy()
lhs_r = result_to_r(lhs)
lhs_n = result_to_n(lhs)
del rhs_r['allocation_pool']
# timestamp can be converted on the server
del lhs['timestamp']
del rhs['timestamp']
del lhs['id']
assert lhs == rhs
del lhs_r['timestamp']
del rhs_r['timestamp']
del lhs_r['id']
assert lhs_r == rhs_r
assert lhs_n == rhs_n
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Molteniron CLI tool")
@ -66,80 +93,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "34118fd3509621ba",
"port_hwaddr": "ff: 2c: e1:cc:8e:7c",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "fa2125690a95b43c",
"port_hwaddr": "f6: 58:13:02:64:59",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "-1",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "3aee014d56425a6c",
"port_hwaddr": "6e: d4:a5:ae: 13:55",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
# NOTE: time() can return fractional values. Ex: 1460560140.47
"timestamp": str(time.time() - 1000.0),
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "254dd9fb34ddcac7",
"port_hwaddr": "a0: c9: 22:23:22:9d",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": str(time.time() - 2000.0),
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -148,8 +182,8 @@ if __name__ == "__main__":
assert ret['status'] == 200
assert len(ret['nodes']) == 2
compare_culled_nodes(ret['nodes']['node_3'], node3)
compare_culled_nodes(ret['nodes']['node_4'], node4)
compare_culled_nodes(ret['nodes']['node_3'], request3, node3)
compare_culled_nodes(ret['nodes']['node_4'], request4, node4)
database.close()
del database
@ -161,16 +195,16 @@ if __name__ == "__main__":
del database
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -179,7 +213,7 @@ if __name__ == "__main__":
assert ret['status'] == 200
assert len(ret['nodes']) == 1
compare_culled_nodes(ret['nodes']['node_4'], node4)
compare_culled_nodes(ret['nodes']['node_4'], request4, node4)
database.close()
del database
@ -191,16 +225,16 @@ if __name__ == "__main__":
del database
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}

View File

@ -24,23 +24,52 @@ Tests the MoltenIron deallocateBM command.
from __future__ import print_function
import argparse
import json
from molteniron import moltenirond
import os
import sys
import yaml
def compare_provisioned_nodes(lhs, rhs):
"""Specially compares lhs against rhs."""
lhs = lhs.copy()
rhs = rhs.copy()
rhs['provisioned'] = 'hamzy'
del lhs['status']
del lhs['timestamp']
del rhs['status']
del rhs['timestamp']
del lhs['id']
assert lhs == rhs
def result_to_r(res):
"""Takes a result and returns the request parameters."""
r = res.copy()
del r["blob"]
return r
def result_to_n(res):
"""Takes a result and returns the node parameters."""
n = {}
if "blob" in res:
blob = json.loads(res["blob"])
n["ipmi_user"] = blob["ipmi_user"]
n["ipmi_password"] = blob["ipmi_password"]
n["port_hwaddr"] = blob["port_hwaddr"]
n["cpu_arch"] = blob["cpu_arch"]
n["cpus"] = blob["cpus"]
n["ram_mb"] = blob["ram_mb"]
n["disk_gb"] = blob["disk_gb"]
return n
def compare_provisioned_nodes(lhs, rhs_r, rhs_n):
"""Specially compares lhs against the combined rhs_r and rhs_n."""
rhs_r = rhs_r.copy()
lhs_r = result_to_r(lhs)
lhs_n = result_to_n(lhs)
rhs_r['provisioned'] = 'hamzy'
del lhs_r['status']
del lhs_r['timestamp']
del rhs_r['status']
del rhs_r['timestamp']
del lhs_r['id']
assert lhs_r == rhs_r
assert lhs_n == rhs_n
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Molteniron CLI tool")
@ -66,79 +95,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "16f6954d347c4de2",
"port_hwaddr": "28: 5a: e7:e3:fe:75",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "3a23241cfa516699",
"port_hwaddr": "7d: 0a: e5:b9:41:9b",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "4f7e47c57f27ec55",
"port_hwaddr": "5a: e8: 11:e9:11:a2",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "aeff165ded2c2f9f",
"port_hwaddr": "4d: 18:82: dc:2c:d6",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -146,10 +183,12 @@ if __name__ == "__main__":
print(ret)
assert ret['status'] == 200
assert len(ret["nodes"]) == 1
compare_provisioned_nodes(ret["nodes"]["node_1"], node1)
compare_provisioned_nodes(ret["nodes"]["node_1"], request1, node1)
session = database.get_session()
n1 = session.query(moltenirond.Nodes).filter_by(name=node1["name"]).one()
n1 = session.query(moltenirond.Nodes)
n1 = n1.filter_by(name=request1["name"])
n1 = n1.one()
session.close()
ret = database.deallocateBM(n1.id)
print(ret)
@ -165,16 +204,16 @@ if __name__ == "__main__":
del database
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -182,10 +221,12 @@ if __name__ == "__main__":
print(ret)
assert ret['status'] == 200
assert len(ret["nodes"]) == 1
compare_provisioned_nodes(ret["nodes"]["node_1"], node1)
compare_provisioned_nodes(ret["nodes"]["node_1"], request1, node1)
session = database.get_session()
n1 = session.query(moltenirond.Nodes).filter_by(name=node1["name"]).one()
n1 = session.query(moltenirond.Nodes)
n1 = n1.filter_by(name=request1["name"])
n1 = n1.one()
session.close()
ret = database.deallocateBM(n1.ipmi_ip)
print(ret)

View File

@ -24,23 +24,52 @@ Tests the MoltenIron deallocateOwner command.
from __future__ import print_function
import argparse
import json
from molteniron import moltenirond
import os
import sys
import yaml
def compare_provisioned_nodes(lhs, rhs):
"""Specially compares lhs against rhs."""
lhs = lhs.copy()
rhs = rhs.copy()
rhs['provisioned'] = 'hamzy'
del lhs['status']
del lhs['timestamp']
del rhs['status']
del rhs['timestamp']
del lhs['id']
assert lhs == rhs
def result_to_r(res):
"""Takes a result and returns the request parameters."""
r = res.copy()
del r["blob"]
return r
def result_to_n(res):
"""Takes a result and returns the node parameters."""
n = {}
if "blob" in res:
blob = json.loads(res["blob"])
n["ipmi_user"] = blob["ipmi_user"]
n["ipmi_password"] = blob["ipmi_password"]
n["port_hwaddr"] = blob["port_hwaddr"]
n["cpu_arch"] = blob["cpu_arch"]
n["cpus"] = blob["cpus"]
n["ram_mb"] = blob["ram_mb"]
n["disk_gb"] = blob["disk_gb"]
return n
def compare_provisioned_nodes(lhs, rhs_r, rhs_n):
"""Specially compares lhs against the combined rhs_r and rhs_n."""
rhs_r = rhs_r.copy()
lhs_r = result_to_r(lhs)
lhs_n = result_to_n(lhs)
rhs_r['provisioned'] = 'hamzy'
del lhs_r['status']
del lhs_r['timestamp']
del rhs_r['status']
del rhs_r['timestamp']
del lhs_r['id']
assert lhs_r == rhs_r
assert lhs_n == rhs_n
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Molteniron CLI tool")
@ -66,79 +95,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "f367d07be07d6358",
"port_hwaddr": "6d: 9a:78: f3:ed:3a",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "1c6a27307f8fe79d",
"port_hwaddr": "16: 23: e8:07:b4:a9",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "1766d597a024dd8d",
"port_hwaddr": "12: 33:9f:04:07:9b",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "7c55be8b4ef42869",
"port_hwaddr": "c2: 31: e9:8a:75:96",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -146,7 +183,7 @@ if __name__ == "__main__":
print(ret)
assert ret['status'] == 200
assert len(ret["nodes"]) == 1
compare_provisioned_nodes(ret["nodes"]["node_1"], node1)
compare_provisioned_nodes(ret["nodes"]["node_1"], request1, node1)
ret = database.deallocateOwner("hamzy")
print(ret)

View File

@ -54,79 +54,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "e23af1e52896cf02",
"port_hwaddr": "5d: 7e:05: dd:fe:65",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "57212373db56c76a",
"port_hwaddr": "7e: 41:89: e1:28:03",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "c2f4b0bfa31fe9de",
"port_hwaddr": "4f: a7: 48:59:6a:a7",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "f99d122fc129c1dd",
"port_hwaddr": "a2: 0d: bc:ca:c5:a5",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}

View File

@ -54,79 +54,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "7db1486ac9ea6533",
"port_hwaddr": "ca: 2c: ab:88:47:b0",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "hamzy",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "c3f8e3f3407e880b",
"port_hwaddr": "90: 24:5c: d5:0e:b3",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "mjturek",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "1bcbf739c7108291",
"port_hwaddr": "9c: 6b:1b:31: a5:2d",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"ipmi_password": "0c200c858ac46280",
"port_hwaddr": "64: 49:12: c6:3f:bd",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "mjturek",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -143,7 +151,11 @@ if __name__ == "__main__":
assert ret['result'][0]['field'] == node2["port_hwaddr"]
assert ret['result'][1]['field'] == node4["port_hwaddr"]
ret = database.get_field("mmedvede", "candy")
ret = database.get_field("mmedvede", "cpus")
print(ret)
assert ret == {'status': 404, 'message': 'mmedvede does not own any nodes'}
ret = database.get_field("hamzy", "candy")
print(ret)
assert ret == {'status': 400, 'message': 'field candy does not exist'}

View File

@ -54,79 +54,87 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "1aa328d7767653ad",
"port_hwaddr": "17: e7:f1:ab:a5: 9f",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "hamzy",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "84b9d9ceb866f612",
"port_hwaddr": "0b: f1: 9c:9d:a6:eb",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "mjturek",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "ba60285a1fd69800",
"port_hwaddr": "da: e0: 86:2a:80:9c",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"ipmi_password": "7810c66057ef4f2d",
"port_hwaddr": "d6: bc:ca: 83:95:e7",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "mjturek",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
@ -134,13 +142,13 @@ if __name__ == "__main__":
print(ret)
assert ret['status'] == 200
assert len(ret['ips']) == 1
assert ret['ips'] == [node1["ipmi_ip"]]
assert ret['ips'] == [request1["ipmi_ip"]]
ret = database.get_ips("mjturek")
print(ret)
assert ret['status'] == 200
assert len(ret['ips']) == 2
assert ret['ips'] == [node2["ipmi_ip"], node4["ipmi_ip"]]
assert ret['ips'] == [request2["ipmi_ip"], request4["ipmi_ip"]]
database.close()
del database

View File

@ -54,84 +54,94 @@ if __name__ == "__main__":
with open(yaml_file, "r") as fobj:
conf = yaml.load(fobj)
node1 = {
request1 = {
"name": "pkvmci816",
"ipmi_ip": "10.228.219.134",
"ipmi_user": "user",
"ipmi_password": "2703f5fee17f2073",
"port_hwaddr": "b1: 71: dd:02:9e:20",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.10,10.228.112.11"
}
node2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
node1 = {
"ipmi_user": "user",
"ipmi_password": "c3f06ff4b798a4ea",
"port_hwaddr": "88: 6e:9e: fa:65:d8",
"ipmi_password": "e05cc5f061426e34",
"port_hwaddr": "f8:de:29:33:a4:ed",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request2 = {
"name": "pkvmci818",
"ipmi_ip": "10.228.219.133",
"status": "ready",
"provisioned": "",
"timestamp": "",
"allocation_pool": "10.228.112.8,10.228.112.9"
}
node3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
node2 = {
"ipmi_user": "user",
"ipmi_password": "2885d1af50781461",
"port_hwaddr": "a2: a2: 64:79:6b:69",
"ipmi_password": "0614d63b6635ea3d",
"port_hwaddr": "4c:c5:da:28:2c:2d",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request3 = {
"name": "pkvmci851",
"ipmi_ip": "10.228.118.129",
"status": "used",
"provisioned": "7a72eccd-3153-4d08-9848-c6d3b1f18f9f",
"timestamp": "1460489832",
"allocation_pool": "10.228.112.12,10.228.112.13"
}
node4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
node3 = {
"ipmi_user": "user",
"ipmi_password": "3e374dc88ca43b4f",
"port_hwaddr": "50: 4a:56:3c: e9:0f",
"ipmi_password": "928b056134e4d770",
"port_hwaddr": "53:76:c6:09:50:64",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500,
"disk_gb": 500
}
request4 = {
"name": "pkvmci853",
"ipmi_ip": "10.228.118.133",
"status": "used",
"provisioned": "6b8823ef-3e14-4811-98b9-32e27397540d",
"timestamp": "1460491566",
"allocation_pool": "10.228.112.14,10.228.112.15"
}
node4 = {
"ipmi_user": "user",
"ipmi_password": "33f448a4fc176492",
"port_hwaddr": "85:e0:73:e9:fc:ca",
"cpu_arch": "ppc64el",
"cpus": 20,
"ram_mb": 51000,
"disk_gb": 500
}
# 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----
database = moltenirond.DataBase(conf, moltenirond.TYPE_SQLITE_MEMORY)
ret = database.addBMNode(node1)
ret = database.addBMNode(request1, node1)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node2)
ret = database.addBMNode(request2, node2)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node3)
ret = database.addBMNode(request3, node3)
print(ret)
assert ret == {'status': 200}
ret = database.addBMNode(node4)
ret = database.addBMNode(request4, node4)
print(ret)
assert ret == {'status': 200}
session = database.get_session()
n1 = session.query(moltenirond.Nodes).filter_by(name=node1["name"]).one()
n1 = session.query(moltenirond.Nodes)
n1 = n1.filter_by(name=request1["name"])
n1 = n1.one()
session.close()
ret = database.removeBMNode(n1.id, False)
print(ret)

27
tox.ini
View File

@ -28,7 +28,32 @@ commands = mkdir -p testenv/var/run/
delete_db
molteniron \
--conf-dir=testenv/etc/molteniron/ \
add test 10.1.2.1 user password 10.1.2.3,10.1.2.4 de:ad:be:ef:00:01 ppc64el 8 2048 32
add_baremetal test1 10.1.2.1 user password 10.1.2.3,10.1.2.4 de:ad:be:ef:00:01 ppc64el 8 2048 32
molteniron \
--conf-dir=testenv/etc/molteniron/ \
add_keyvalue_pairs test2 \
10.1.2.2 \
10.1.2.5,10.1.2.6 \
'ipmi_user="user"' \
'ipmi_password="password"' \
'port_hwaddr="de:ad:be:ef:00:01"' \
'cpu_arch=ppc64el' \
'cpus=8' \
'ram_mb=2048' \
'disk_gb=32'
# @BUG - tox is broken
# passing in '{"ipmi_user": "user"}' results in:
# tox.ConfigError: ConfigError: No support for the "ipmi_user" substitution type
# and escaping the curly braces '\{"ipmi_user": "user"\}'
# mentioned in http://tox.readthedocs.io/en/latest/config.html#substitutions
# passes in '\\{"ipmi_user": "user"\\}' which breaks json.loads()
# ValueError: No JSON object could be decoded
# molteniron \
# --conf-dir=testenv/etc/molteniron/ \
# add_json_blob test3 \
# 10.1.2.3 \
# 10.1.2.7,10.1.2.8 \
# '{"ipmi_user": "user", "ipmi_password": "password", "port_hwaddr": "de:ad:be:ef:00:01", "cpu_arch": "ppc64el", "cpus": 8, "ram_mb": 2048, "disk_gb": 32''}'
molteniron \
--conf-dir=testenv/etc/molteniron/ \
allocate hamzy 1