Skip to content

Commit

Permalink
Add an inventory file for OpenShift Baremetal Deployments
Browse files Browse the repository at this point in the history
OpenShift Baremetal deployments require two MACs to be specified
per host. The current instackenv.json provides only one MAC (provisioning)
per host. It would be possible to add another mac into the list of macs
for each host in instackenv.json itself, but it is unclear how this affects
existing OpenStack deployment automation (especially with SuperMicros).
This commit adds the ability to serve another inventory file, with just a
minor modification of having two MACs per host. The adavntage with having a
separate ocpinventory.json file is that automation could consume it and save time
as well as we now have the ability to further enhance this file in the future
to accomodate more OpenShift specific items. This commit acts as a bridge between
QUADS and automation to deploy OpenShift on Baremetal.

Change-Id: Ib88ee205d59dab627d18aa952f4f809f312e744d
  • Loading branch information
smalleni authored and grafuls committed Apr 20, 2020
1 parent 847432b commit 934fe81
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 934fe81

Please sign in to comment.