Skip to content

Commit

Permalink
Merge "Add an inventory file for OpenShift Baremetal Deployments"
Browse files Browse the repository at this point in the history
  • Loading branch information
sadsfae authored and gerritforge-ltd committed Apr 20, 2020
2 parents 31dc848 + 934fe81 commit f7a1d3e
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 73 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ QUADS automates the future scheduling, end-to-end provisioning and delivery of b
- Automated network and provisioning validation prior to delivering sets of machines/networks to tenants
- Automated allocation of optional, publicly routable VLANs
- Generates/maintains user-configurable [instackenv.json](https://docs.openstack.org/tripleo-docs/latest/install/environments/baremetal.html#instackenv-json) to accomodate OpenStack deployment.
- Generates/maintains user-configurable ocpinventory.json for OpenShift on Baremetal Deployments
- Automatically generate/maintain documentation to illustrate current status, published to a [Wordpress instance](http://python-wordpress-xmlrpc.readthedocs.io/en/latest/examples/posts.html#pages)
* Current system details, infrastructure fleet inventory
* Current system group ownership (cloud), workloads and assignments
Expand Down
5 changes: 5 additions & 0 deletions conf/quads.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ pdu_management: false
# displaying instack env json files on quads wiki
openstack_management: false

# OpenShift variable for generation of inventory files
# Setting this to false will prevent quads from generating and
# displaying ocpinventory files on quads wiki
openshift_management: false

# Validation grace period in minutes
# This gives the validation logic some time for the hosts to complete
# provisioning. Value in minutes.
Expand Down
22 changes: 20 additions & 2 deletions quads/tools/create_input_assignments.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ def print_summary():
'**SUMMARY**',
'**OWNER**',
'**REQUEST**',
'     **STATUS**    '
'<span id="status">**STATUS**</span>'
]
if conf["openstack_management"]:
_headers.append("**INSTACKENV**")
_headers.append("**OSPENV**")
if conf["openshift_management"]:
_headers.append("**OCPINV**")
if conf["gather_ansible_facts"]:
_headers.append("**HWFACTS**")
if conf["gather_dell_configs"]:
Expand All @@ -66,6 +68,8 @@ def print_summary():
style_tag_start = '<span style="color:green">'
instack_link = os.path.join(conf["quads_url"], "cloud", "%s_instackenv.json" % cloud_name)
instack_text = "download"
ocpinv_link = os.path.join(conf["quads_url"], "cloud", "%s_ocpinventory.json" % cloud_name)
ocpinv_text = "download"
status = '<span class="progress" style="margin-bottom:0px"><span role="progressbar" aria-valuenow="100" ' \
'aria-valuemin="0" aria-valuemax="100" style="width:100%" class="progress-bar">100%</span></span> '
else:
Expand All @@ -76,6 +80,8 @@ def print_summary():
style_tag_start = '<span style="color:red">'
instack_link = "#"
instack_text = "validating"
ocpinv_link = "#"
ocpinv_text = "validating"
if percent < 15:
classes = ["progress-bar", "progress-bar-striped", "progress-bar-danger", "active"]
status = '<span class="progress" style="margin-bottom:0px"><span role="progressbar" ' \
Expand All @@ -102,6 +108,7 @@ def print_summary():
factstyle_tag_start = '<span style="color:red">'
ansible_facts_link = os.path.join(conf["quads_url"], "underconstruction")
if cloud_name == "cloud01":
_data.append("")
_data.append("")
_data.append(status)
_data.append("")
Expand All @@ -110,6 +117,10 @@ def print_summary():
"<a href=%s target=_blank>%s%s%s</a>"
% (instack_link, style_tag_start, instack_text, style_tag_end)
)
_data.append(
"<a href=%s target=_blank>%s%s%s</a>"
% (ocpinv_link, style_tag_start, ocpinv_text, style_tag_end)
)
_data.append(status)
_data.append(
"<a href=%s target=_blank>%sinventory%s</a>"
Expand All @@ -120,12 +131,19 @@ def print_summary():
if cloud_name == "cloud01":
if conf["openstack_management"]:
_data.append("")
if conf["openshift_management"]:
_data.append("")
else:
if conf["openstack_management"]:
_data.append(
"<a href=%s target=_blank>%s%s%s</a>"
% (instack_link, style_tag_start, instack_text, style_tag_end)
)
if conf["openshift_management"]:
_data.append(
"<a href=%s target=_blank>%s%s%s</a>"
% (ocpinv_link, style_tag_start, ocpinv_text, style_tag_end)
)

if conf["gather_dell_configs"]:
dellstyle_tag_end = "</span>"
Expand Down
164 changes: 93 additions & 71 deletions quads/tools/make_instackenv_json.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3

import asyncio
import json
import os
Expand All @@ -13,80 +14,101 @@
from quads.config import conf


def main():
if conf["openstack_management"]:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
foreman = Foreman(
conf["foreman_api_url"],
conf["foreman_username"],
conf["foreman_password"],
loop=loop,
)
def make_env_json(filename):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
foreman = Foreman(
conf["foreman_api_url"],
conf["foreman_username"],
conf["foreman_password"],
loop=loop,
)

cloud_list = Cloud.objects()
cloud_list = Cloud.objects()

if not os.path.exists(conf["json_web_path"]):
os.makedirs(conf["json_web_path"])

now = time.time()
old_jsons = [file for file in os.listdir(conf["json_web_path"]) if ":" in file]
for file in old_jsons:
if os.stat(os.path.join(conf["json_web_path"], file)).st_mtime < now - conf["json_retention_days"] * 86400:
os.remove(os.path.join(conf["json_web_path"], file))

for cloud in cloud_list:
host_list = Host.objects(cloud=cloud).order_by("name")

foreman_password = conf["ipmi_password"]
if cloud.ticket:
foreman_password = f"{conf['infra_location']}@{cloud.ticket}"

json_data = defaultdict(list)
for host in host_list:
if conf["foreman_unavailable"]:
overcloud = {"result": "true"}
else:
overcloud = loop.run_until_complete(foreman.get_host_param(host.name, "overcloud"))
if not overcloud:
overcloud = {"result": "true"}

if type(overcloud["result"]) != bool:
_overcloud_result = strtobool(overcloud["result"])
else:
_overcloud_result = overcloud["result"]

if "result" in overcloud and _overcloud_result:
mac = "00:00:00:00:00:00"
if not os.path.exists(conf["json_web_path"]):
os.makedirs(conf["json_web_path"])

now = time.time()
old_jsons = [file for file in os.listdir(conf["json_web_path"]) if ":" in file]
for file in old_jsons:
if (
os.stat(os.path.join(conf["json_web_path"], file)).st_mtime
< now - conf["json_retention_days"] * 86400
):
os.remove(os.path.join(conf["json_web_path"], file))

for cloud in cloud_list:
host_list = Host.objects(cloud=cloud).order_by("name")

foreman_password = conf["ipmi_password"]
if cloud.ticket:
foreman_password = f"{conf['infra_location']}@{cloud.ticket}"

data = defaultdict(list)
for host in host_list:
if conf["foreman_unavailable"]:
overcloud = {"result": "true"}
else:
overcloud = loop.run_until_complete(
foreman.get_host_param(host.name, "overcloud")
)
if not overcloud:
overcloud = {"result": "true"}

if type(overcloud["result"]) != bool:
_overcloud_result = strtobool(overcloud["result"])
else:
_overcloud_result = overcloud["result"]

if "result" in overcloud and _overcloud_result:
mac = []
if filename == "instackenv":
if len(host.interfaces) > 1:
mac = host.interfaces[1].mac_address
json_data['nodes'].append({
'pm_password': foreman_password,
'pm_type': "pxe_ipmitool",
'mac': [mac],
'cpu': "2",
'memory': "1024",
'disk': "20",
'arch': "x86_64",
'pm_user': conf["ipmi_cloud_username"],
'pm_addr': "mgmt-%s" % host.name})

content = json.dumps(json_data, indent=4, sort_keys=True)

if not os.path.exists(conf["json_web_path"]):
pathlib.Path(conf["json_web_path"]).mkdir(parents=True, exist_ok=True)

now = datetime.now()
new_json_file = os.path.join(
conf["json_web_path"],
"%s_instackenv.json_%s" % (cloud.name, now.strftime("%Y-%m-%d_%H:%M:%S"))
)
json_file = os.path.join(conf["json_web_path"], "%s_instackenv.json" % cloud.name)
with open(new_json_file, "w+") as _json_file:
_json_file.seek(0)
_json_file.write(content)
os.chmod(new_json_file, 0o644)
copyfile(new_json_file, json_file)
mac.append(host.interfaces[1].mac_address)
if filename == "ocpinventory":
if len(host.interfaces) > 1:
for i in range(0, 2):
mac.append(host.interfaces[i].mac_address)
data["nodes"].append(
{
"pm_password": foreman_password,
"pm_type": "pxe_ipmitool",
"mac": mac,
"cpu": "2",
"memory": "1024",
"disk": "20",
"arch": "x86_64",
"pm_user": conf["ipmi_cloud_username"],
"pm_addr": "mgmt-%s" % host.name,
}
)

content = json.dumps(data, indent=4, sort_keys=True)

if not os.path.exists(conf["json_web_path"]):
pathlib.Path(conf["json_web_path"]).mkdir(parents=True, exist_ok=True)

now = datetime.now()
new_json_file = os.path.join(
conf["json_web_path"],
"%s_%s.json_%s" % (cloud.name, filename, now.strftime("%Y-%m-%d_%H:%M:%S")),
)
json_file = os.path.join(
conf["json_web_path"], "%s_%s.json" % (cloud.name, filename)
)
with open(new_json_file, "w+") as _json_file:
_json_file.seek(0)
_json_file.write(content)
os.chmod(new_json_file, 0o644)
copyfile(new_json_file, json_file)


def main():
if conf["openstack_management"]:
make_env_json("instackenv")
if conf["openshift_management"]:
make_env_json("ocpinventory")


if __name__ == "__main__":
Expand Down

0 comments on commit f7a1d3e

Please sign in to comment.