Skip to content

Commit

Permalink
Merge pull request #22 from cdot65:16-pypi-deployment
Browse files Browse the repository at this point in the history
Enhancements for PyPI Packaging and Improved Upgrade Process Handling
  • Loading branch information
cdot65 authored Jan 19, 2024
2 parents 0364e1a + fd5cbc9 commit 66822d1
Show file tree
Hide file tree
Showing 20 changed files with 32 additions and 81 deletions.
6 changes: 2 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,5 @@ cython_debug/
.env

# ignore my personal snapshots
assurance/configurations/
assurance/readiness_checks/
assurance/reports/
assurance/snapshots/
pan_os_upgrade/assurance
pan_os_upgrade/logs
Empty file removed assurance/.gitkeep
Empty file.
Empty file removed assurance/configurations/.gitkeep
Empty file.
Empty file.
Empty file removed assurance/reports/.gitkeep
Empty file.
Empty file removed assurance/snapshots/.gitkeep
Empty file.
Empty file removed logs/.gitkeep
Empty file.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
84 changes: 23 additions & 61 deletions upgrade.py → pan_os_upgrade/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
from panos.base import PanDevice
from panos.device import SystemSettings
from panos.errors import (
PanDeviceXapiError,
PanXapiError,
PanConnectionTimeout,
PanDeviceError,
PanDeviceXapiError,
PanURLError,
PanXapiError,
)
from panos.firewall import Firewall

Expand All @@ -31,7 +32,7 @@
from pydantic import BaseModel

# project imports
from models import SnapshotReport, ReadinessCheckReport
from pan_os_upgrade.models import SnapshotReport, ReadinessCheckReport


# ----------------------------------------------------------------------------
Expand Down Expand Up @@ -111,7 +112,7 @@ class AssuranceOptions:
},
"free_disk_space": {
"description": "Check if a there is enough space on the `/opt/panrepo` volume for downloading an PanOS image.",
"log_level": "error",
"log_level": "warning",
"exit_on_failure": False,
},
"ha": {
Expand Down Expand Up @@ -393,7 +394,6 @@ def parse_arguments() -> Args:
elif not (arguments["pan_username"] and arguments["pan_password"]):
logging.error(
f"{get_emoji('error')} Provide either API key --api-key argument or both --username and --password",
file=sys.stderr,
)
logging.error(f"{get_emoji('stop')} Halting script.")

Expand Down Expand Up @@ -1387,11 +1387,12 @@ def perform_upgrade(
)
time.sleep(retry_interval)

except PanDeviceXapiError as upgrade_error:
except PanDeviceError as upgrade_error:
logging.error(
f"{get_emoji('error')} {hostname} upgrade error: {upgrade_error}"
)
if "software manager is currently in use" in str(upgrade_error):
error_message = str(upgrade_error)
if "software manager is currently in use" in error_message:
attempt += 1
if attempt < max_retries:
logging.info(
Expand All @@ -1402,61 +1403,8 @@ def perform_upgrade(
logging.error(
f"{get_emoji('stop')} Critical error during upgrade. Halting script."
)

sys.exit(1)

# Define timeout and start time
timeout = 300 # 5 minutes in seconds
ha_suspend_start_time = time.time()

# First, check if ha_details exists
if ha_details:
while True:
try:
# Check if HA is enabled and synced
if ha_details["response"]["result"]["enabled"] == "yes":
logging.info(
f"{get_emoji('success')} HA peer sync test has been completed"
)
logging.info(
f"{get_emoji('start')} Suspending HA state of firewall..."
)
suspend_job = firewall.op(
"<request><high-availability><state><suspend/></state></high-availability></request>",
cmd_xml=False,
)
suspend_job_result = xml_to_dict(suspend_job)
logging.info(
f"{get_emoji('report')} {suspend_job_result['response']['result']}"
)
break # Exit the loop as the condition is met
else:
# If HA is enabled but not synced
current_time = time.time()
if current_time - ha_suspend_start_time > timeout:
logging.error(
f"{get_emoji('error')} Timeout reached while waiting for HA sync"
)
break # Exit the loop after timeout

logging.info(
f"{get_emoji('warning')} HA peer sync test was not successful, trying again in ten seconds..."
)
time.sleep(10)
# Re-fetch the HA details here if necessary, to check the current status

except KeyError:
# KeyError handling if 'enabled' key is not found
logging.error(
f"{get_emoji('error')} KeyError: Problem accessing HA details"
)
break

else:
logging.info(
f"{get_emoji('report')} Firewall is not in an HA pair, continuing in standalone mode..."
)


# ----------------------------------------------------------------------------
# Perform the reboot process
Expand Down Expand Up @@ -1516,7 +1464,7 @@ def perform_reboot(firewall: Firewall, ha_details: Optional[dict] = None) -> Non
rebooted = True
else:
logging.info(
f"{get_emoji('working')} Waiting for firewall to reboot and synchronize..."
f"{get_emoji('working')} Firewall is responding to requests but hasn't finished its reboot process..."
)
time.sleep(30)

Expand Down Expand Up @@ -1559,6 +1507,20 @@ def main() -> None:
- If the HA peer state is not synchronized.
- Upon completion of a dry run.
"""

# Create necessary directories
directories = [
"logs",
"assurance",
"assurance/configurations",
"assurance/readiness_checks",
"assurance/reports",
"assurance/snapshots",
]
for dir in directories:
ensure_directory_exists(os.path.join(dir, "dummy_file"))

# Configure logging right after directory setup
args = parse_arguments()
configure_logging(args["log_level"])

Expand Down
14 changes: 1 addition & 13 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[tool.poetry]
name = "pan-os-upgrade"
version = "0.1.0"
description = "Python script to automate the upgrade process of PAN-OS and Panorama"
description = "Python script to automate the upgrade process of PAN-OS firewalls."
authors = ["Calvin Remsburg <[email protected]>"]
license = "Apache 2.0"
readme = "README.md"
packages = [{include = "pan_os_upgrade"}]
packages = [{ include = "pan_os_upgrade" }]
include = ['pan_os_upgrade/.env']

[tool.poetry.dependencies]
python = "^3.11"
defusedxml = "^0.7.1"
pan-os-python = "^1.11.0"
panos-upgrade-assurance = "^0.3.1"
pydantic = "^2.5.3"
Expand All @@ -19,6 +19,9 @@ black = "^23.12.1"
flake8 = "^7.0.0"
ipdb = "^0.13.13"

[tool.poetry.scripts]
pan-os-upgrade = 'pan_os_upgrade.upgrade:main'

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

0 comments on commit 66822d1

Please sign in to comment.