Merge "USM State Machine"
This commit is contained in:
commit
33b379914e
@ -38,43 +38,31 @@ class SoftwareAPIController(object):
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def deploy_create(self, *args, **kwargs):
|
||||
if sc.any_patch_host_installing():
|
||||
return dict(error="Rejected: One or more nodes are installing releases.")
|
||||
|
||||
try:
|
||||
result = sc.software_deploy_create_api(list(args), **kwargs)
|
||||
except SoftwareError as e:
|
||||
return dict(error="Error: %s" % str(e))
|
||||
|
||||
sc.software_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def deploy_delete(self, *args, **kwargs):
|
||||
def deploy_activate(self, *args):
|
||||
if sc.any_patch_host_installing():
|
||||
return dict(error="Rejected: One or more nodes are installing a release.")
|
||||
|
||||
try:
|
||||
result = sc.software_deploy_delete_api(list(args), **kwargs)
|
||||
result = sc.software_deploy_activate_api(list(args)[0])
|
||||
except SoftwareError as e:
|
||||
return dict(error="Error: %s" % str(e))
|
||||
|
||||
sc.software_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def deploy_start(self, *args):
|
||||
def deploy_complete(self, *args):
|
||||
if sc.any_patch_host_installing():
|
||||
return dict(error="Rejected: One or more nodes are installing a release.")
|
||||
|
||||
sc.send_latest_feed_commit_to_agent()
|
||||
try:
|
||||
result = sc.software_deploy_complete_api(list(args)[0])
|
||||
except SoftwareError as e:
|
||||
return dict(error="Error: %s" % str(e))
|
||||
|
||||
sc.software_sync()
|
||||
return dict(info="%s is ready to be deployed on all hosts" % list(args)[0])
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
@ -92,23 +80,29 @@ class SoftwareAPIController(object):
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def is_applied(self, *args):
|
||||
return sc.is_applied(list(args))
|
||||
|
||||
@expose('json')
|
||||
def is_available(self, *args):
|
||||
return sc.is_available(list(args))
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def query(self, **kwargs):
|
||||
def deploy_start(self, *args, **kwargs):
|
||||
if sc.any_patch_host_installing():
|
||||
return dict(error="Rejected: One or more nodes are installing releases.")
|
||||
|
||||
try:
|
||||
sd = sc.software_release_query_cached(**kwargs)
|
||||
result = sc.software_deploy_start_api(list(args)[0], **kwargs)
|
||||
except SoftwareError as e:
|
||||
return dict(error="Error: %s" % str(e))
|
||||
|
||||
return dict(sd=sd)
|
||||
sc.send_latest_feed_commit_to_agent()
|
||||
sc.software_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def is_completed(self, *args):
|
||||
return sc.is_completed(list(args))
|
||||
|
||||
@expose('json')
|
||||
def is_uploaded(self, *args):
|
||||
return sc.is_uploaded(list(args))
|
||||
|
||||
@expose('json')
|
||||
@expose('show.xml', content_type='application/xml')
|
||||
@ -142,11 +136,6 @@ class SoftwareAPIController(object):
|
||||
sc.software_sync()
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query_hosts.xml', content_type='application/xml')
|
||||
def query_hosts(self, *args): # pylint: disable=unused-argument
|
||||
return dict(data=sc.query_host_cache())
|
||||
|
||||
@expose('json')
|
||||
def upload_dir(self, **kwargs):
|
||||
# todo(abailey): extensions should be configurable or
|
||||
@ -172,6 +161,21 @@ class SoftwareAPIController(object):
|
||||
sc.software_sync()
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def query(self, **kwargs):
|
||||
try:
|
||||
sd = sc.software_release_query_cached(**kwargs)
|
||||
except SoftwareError as e:
|
||||
return dict(error="Error: %s" % str(e))
|
||||
|
||||
return dict(sd=sd)
|
||||
|
||||
@expose('json')
|
||||
@expose('query_hosts.xml', content_type='application/xml')
|
||||
def query_hosts(self, *args): # pylint: disable=unused-argument
|
||||
return dict(data=sc.query_host_cache())
|
||||
|
||||
|
||||
class RootController:
|
||||
"""pecan REST API root"""
|
||||
|
@ -24,16 +24,21 @@ ADDRESS_VERSION_IPV4 = 4
|
||||
ADDRESS_VERSION_IPV6 = 6
|
||||
CONTROLLER_FLOATING_HOSTNAME = "controller"
|
||||
|
||||
AVAILABLE = 'Available'
|
||||
APPLIED = 'Applied'
|
||||
PARTIAL_APPLY = 'Partial-Apply'
|
||||
PARTIAL_REMOVE = 'Partial-Remove'
|
||||
COMMITTED = 'Committed'
|
||||
ABORTING = 'aborting'
|
||||
AVAILABLE = 'available'
|
||||
COMMITTED = 'committed'
|
||||
DEPLOYED = 'deployed'
|
||||
DEPLOYING_ACTIVATE = 'deploying-activate'
|
||||
DEPLOYING_COMPLETE = 'deploying-complete'
|
||||
DEPLOYING_HOST = 'deploying-host'
|
||||
DEPLOYING_START = 'deploying-start'
|
||||
REMOVING = 'removing'
|
||||
UNAVAILABLE = 'unavailable'
|
||||
UNKNOWN = 'n/a'
|
||||
|
||||
STATUS_DEVELOPEMENT = 'DEV'
|
||||
STATUS_OBSOLETE = 'OBS'
|
||||
STATUS_RELEASED = 'REL'
|
||||
STATUS_DEVELOPEMENT = 'DEV'
|
||||
|
||||
PATCH_AGENT_STATE_IDLE = "idle"
|
||||
PATCH_AGENT_STATE_INSTALLING = "installing"
|
||||
@ -42,12 +47,12 @@ PATCH_AGENT_STATE_INSTALL_REJECTED = "install-rejected"
|
||||
|
||||
SOFTWARE_STORAGE_DIR = "/opt/software"
|
||||
|
||||
FEED_OSTREE_BASE_DIR = "/var/www/pages/feed"
|
||||
OSTREE_BASE_DEPLOYMENT_DIR = "/ostree/deploy/debian/deploy/"
|
||||
OSTREE_REF = "starlingx"
|
||||
OSTREE_REMOTE = "debian"
|
||||
FEED_OSTREE_BASE_DIR = "/var/www/pages/feed"
|
||||
SYSROOT_OSTREE = "/sysroot/ostree/repo"
|
||||
OSTREE_BASE_DEPLOYMENT_DIR = "/ostree/deploy/debian/deploy/"
|
||||
PATCH_SCRIPTS_STAGING_DIR = "/var/www/pages/updates/software-scripts"
|
||||
SYSROOT_OSTREE = "/sysroot/ostree/repo"
|
||||
|
||||
LOOPBACK_INTERFACE_NAME = "lo"
|
||||
|
||||
@ -57,7 +62,7 @@ SEMANTIC_ACTIONS = [SEMANTIC_PREAPPLY, SEMANTIC_PREREMOVE]
|
||||
|
||||
CHECKOUT_FOLDER = "checked_out_commit"
|
||||
|
||||
DEPLOYMENT_STATE_INACTIVE = "Inactive"
|
||||
DEPLOYMENT_STATE_ACTIVE = "Active"
|
||||
DEPLOYMENT_STATE_INACTIVE = "Inactive"
|
||||
DEPLOYMENT_STATE_PRESTAGING = "Prestaging"
|
||||
DEPLOYMENT_STATE_PRESTAGED = "Prestaged"
|
||||
|
@ -95,32 +95,29 @@ def print_software_op_result(req):
|
||||
hdr_version = "Version"
|
||||
hdr_rr = "RR"
|
||||
hdr_state = "State"
|
||||
hdr_deploy_state = "Deploy State"
|
||||
|
||||
width_release = len(hdr_release)
|
||||
width_version = len(hdr_version)
|
||||
width_rr = len(hdr_rr)
|
||||
width_state = len(hdr_state)
|
||||
width_deploy_state = len(hdr_deploy_state)
|
||||
|
||||
show_all = False
|
||||
|
||||
for release_id in list(sd):
|
||||
width_release = max(len(release_id), width_release)
|
||||
width_deploy_state = max(len(sd[release_id]["deploy_state"]), width_deploy_state)
|
||||
width_state = max(len(sd[release_id]["state"]), width_state)
|
||||
if "sw_version" in sd[release_id]:
|
||||
show_all = True
|
||||
width_version = max(len(sd[release_id]["sw_version"]), width_version)
|
||||
|
||||
if show_all:
|
||||
print("{0:^{width_release}} {1:^{width_rr}} {2:^{width_version}} {3:^{width_state}} {4:^{width_deploy_state}}".format(
|
||||
hdr_release, hdr_rr, hdr_version, hdr_state, hdr_deploy_state,
|
||||
print("{0:^{width_release}} {1:^{width_rr}} {2:^{width_version}} {3:^{width_state}}".format(
|
||||
hdr_release, hdr_rr, hdr_version, hdr_state,
|
||||
width_release=width_release, width_rr=width_rr,
|
||||
width_version=width_version, width_state=width_state, width_deploy_state=width_deploy_state))
|
||||
width_version=width_version, width_state=width_state))
|
||||
|
||||
print("{0} {1} {2} {3} {4}".format(
|
||||
'=' * width_release, '=' * width_rr, '=' * width_version, '=' * width_state, '=' * width_deploy_state))
|
||||
print("{0} {1} {2} {3}".format(
|
||||
'=' * width_release, '=' * width_rr, '=' * width_version, '=' * width_state))
|
||||
|
||||
for release_id in sorted(list(sd)):
|
||||
if "reboot_required" in sd[release_id]:
|
||||
@ -128,23 +125,20 @@ def print_software_op_result(req):
|
||||
else:
|
||||
rr = "Y"
|
||||
|
||||
print("{0:<{width_release}} {1:^{width_rr}} {2:^{width_version}} {3:^{width_state}} {4:^{width_deploy_state}}".format(
|
||||
print("{0:<{width_release}} {1:^{width_rr}} {2:^{width_version}} {3:^{width_state}}".format(
|
||||
release_id,
|
||||
rr,
|
||||
sd[release_id]["sw_version"],
|
||||
sd[release_id]["deploy_state"],
|
||||
sd[release_id]["state"],
|
||||
width_release=width_release, width_rr=width_rr,
|
||||
width_version=width_version, width_state=width_state,
|
||||
width_deploy_state=width_deploy_state))
|
||||
width_version=width_version, width_state=width_state))
|
||||
else:
|
||||
print("{0:^{width_release}} {1:^{width_state}} {2:^{width_deploy_state}}".format(
|
||||
hdr_release, hdr_state, hdr_deploy_state,
|
||||
width_release=width_release, width_state=width_state,
|
||||
width_deploy_state=width_deploy_state))
|
||||
print("{0:^{width_release}} {1:^{width_state}}".format(
|
||||
hdr_release, hdr_state,
|
||||
width_release=width_release, width_state=width_state))
|
||||
|
||||
print("{0} {1} {2}".format(
|
||||
'=' * width_release, '=' * width_state, '=' * width_deploy_state))
|
||||
print("{0} {1}".format(
|
||||
'=' * width_release, '=' * width_state))
|
||||
|
||||
for release_id in sorted(list(sd)):
|
||||
if "reboot_required" in sd[release_id]:
|
||||
@ -152,13 +146,12 @@ def print_software_op_result(req):
|
||||
else:
|
||||
rr = "Y"
|
||||
|
||||
print("{0:<{width_release}} {1:^{width_rr}} {2:^{width_state}} {3:^{width_deploy_state}}".format(
|
||||
print("{0:<{width_release}} {1:^{width_rr}} {2:^{width_state}}".format(
|
||||
release_id,
|
||||
rr,
|
||||
sd[release_id]["state"],
|
||||
sd[release_id]["deploy_state"],
|
||||
width_release=width_release, width_rr=width_rr,
|
||||
width_state=width_state, width_deploy_state=width_deploy_state))
|
||||
width_state=width_state))
|
||||
|
||||
print("")
|
||||
|
||||
@ -197,11 +190,6 @@ def print_release_show_result(req):
|
||||
print(textwrap.fill(" {0:<15} ".format("State:") + sd[release_id]["state"],
|
||||
width=TERM_WIDTH, subsequent_indent=' ' * 20))
|
||||
|
||||
if sd[release_id]["state"] == "n/a":
|
||||
if "deploy_state" in sd[release_id] and sd[release_id]["deploy_state"] != "":
|
||||
print(textwrap.fill(" {0:<15} ".format("Deploy State:") + sd[release_id]["deploy_state"],
|
||||
width=TERM_WIDTH, subsequent_indent=' ' * 20))
|
||||
|
||||
if "status" in sd[release_id] and sd[release_id]["status"] != "":
|
||||
print(textwrap.fill(" {0:<15} ".format("Status:") + sd[release_id]["status"],
|
||||
width=TERM_WIDTH, subsequent_indent=' ' * 20))
|
||||
@ -752,60 +740,13 @@ def release_upload_dir_req(args):
|
||||
return check_rc(req)
|
||||
|
||||
|
||||
def deploy_create_req(args):
|
||||
|
||||
# args.deployment is a list
|
||||
deployment = args.deployment
|
||||
|
||||
# Ignore interrupts during this function
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
# Issue deploy_create request
|
||||
deployments = "/".join(deployment)
|
||||
url = "http://%s/software/deploy_create/%s" % (api_addr, deployments)
|
||||
|
||||
headers = {}
|
||||
append_auth_token_if_required(headers)
|
||||
req = requests.post(url, headers=headers)
|
||||
|
||||
if args.debug:
|
||||
print_result_debug(req)
|
||||
else:
|
||||
print_software_op_result(req)
|
||||
|
||||
return check_rc(req)
|
||||
|
||||
|
||||
def deploy_delete_req(args):
|
||||
# args.deployment is a list
|
||||
deployment = args.deployment
|
||||
|
||||
# Ignore interrupts during this function
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
# Issue deploy_delete request
|
||||
deployments = "/".join(deployment)
|
||||
url = "http://%s/software/deploy_delete/%s" % (api_addr, deployments)
|
||||
|
||||
headers = {}
|
||||
append_auth_token_if_required(headers)
|
||||
req = requests.post(url, headers=headers)
|
||||
|
||||
if args.debug:
|
||||
print_result_debug(req)
|
||||
else:
|
||||
print_software_op_result(req)
|
||||
|
||||
return check_rc(req)
|
||||
|
||||
|
||||
def deploy_precheck_req(args):
|
||||
print(args.deployment)
|
||||
return 1
|
||||
|
||||
|
||||
def deploy_start_req(args):
|
||||
# args.deployment is a list
|
||||
# args.deployment is a string
|
||||
deployment = args.deployment
|
||||
|
||||
# Ignore interrupts during this function
|
||||
@ -827,13 +768,47 @@ def deploy_start_req(args):
|
||||
|
||||
|
||||
def deploy_activate_req(args):
|
||||
print(args.deployment)
|
||||
return 1
|
||||
# args.deployment is a string
|
||||
deployment = args.deployment
|
||||
|
||||
# Ignore interrupts during this function
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
# Issue deploy_start request
|
||||
url = "http://%s/software/deploy_activate/%s" % (api_addr, deployment)
|
||||
|
||||
headers = {}
|
||||
append_auth_token_if_required(headers)
|
||||
req = requests.post(url, headers=headers)
|
||||
|
||||
if args.debug:
|
||||
print_result_debug(req)
|
||||
else:
|
||||
print_software_op_result(req)
|
||||
|
||||
return check_rc(req)
|
||||
|
||||
|
||||
def deploy_complete_req(args):
|
||||
print(args.deployment)
|
||||
return 1
|
||||
# args.deployment is a string
|
||||
deployment = args.deployment
|
||||
|
||||
# Ignore interrupts during this function
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
|
||||
# Issue deploy_complete request
|
||||
url = "http://%s/software/deploy_complete/%s" % (api_addr, deployment)
|
||||
|
||||
headers = {}
|
||||
append_auth_token_if_required(headers)
|
||||
req = requests.post(url, headers=headers)
|
||||
|
||||
if args.debug:
|
||||
print_result_debug(req)
|
||||
else:
|
||||
print_software_op_result(req)
|
||||
|
||||
return check_rc(req)
|
||||
|
||||
|
||||
def deploy_list_req(args):
|
||||
@ -1119,8 +1094,6 @@ def check_for_os_region_name(args):
|
||||
|
||||
def register_deploy_commands(commands):
|
||||
"""deploy commands
|
||||
- create
|
||||
- delete
|
||||
- precheck
|
||||
- start
|
||||
- host
|
||||
@ -1151,28 +1124,6 @@ def register_deploy_commands(commands):
|
||||
)
|
||||
sub_cmds.required = True
|
||||
|
||||
# --- software deploy create -----------------------
|
||||
cmd = sub_cmds.add_parser(
|
||||
'create',
|
||||
help='Create and prestage a software deployment'
|
||||
)
|
||||
cmd.set_defaults(cmd='create')
|
||||
cmd.set_defaults(func=deploy_create_req)
|
||||
cmd.add_argument('deployment',
|
||||
nargs="+", # accepts a list
|
||||
help='Deployment ID to create')
|
||||
|
||||
# --- software deploy delete -----------------------
|
||||
cmd = sub_cmds.add_parser(
|
||||
'delete',
|
||||
help='Delete the software deployment'
|
||||
)
|
||||
cmd.set_defaults(cmd='delete')
|
||||
cmd.set_defaults(func=deploy_delete_req)
|
||||
cmd.add_argument('deployment',
|
||||
nargs="+",
|
||||
help='Deployment ID to delete')
|
||||
|
||||
# --- software deploy precheck -----------------------
|
||||
cmd = sub_cmds.add_parser(
|
||||
'precheck',
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -38,8 +38,15 @@ except Exception:
|
||||
|
||||
# Constants
|
||||
patch_dir = constants.SOFTWARE_STORAGE_DIR
|
||||
avail_dir = "%s/metadata/available" % patch_dir
|
||||
applied_dir = "%s/metadata/applied" % patch_dir
|
||||
available_dir = "%s/metadata/available" % patch_dir
|
||||
unavailable_dir = "%s/metadata/unavailable" % patch_dir
|
||||
deploying_start_dir = "%s/metadata/deploying_start" % patch_dir
|
||||
deploying_host_dir = "%s/metadata/deploying_host" % patch_dir
|
||||
deploying_activate_dir = "%s/metadata/deploying_activate" % patch_dir
|
||||
deploying_complete_dir = "%s/metadata/deploying_complete" % patch_dir
|
||||
deployed_dir = "%s/metadata/deployed" % patch_dir
|
||||
removing_dir = "%s/metadata/removing" % patch_dir
|
||||
aborting_dir = "%s/metadata/aborting" % patch_dir
|
||||
committed_dir = "%s/metadata/committed" % patch_dir
|
||||
semantics_dir = "%s/semantics" % patch_dir
|
||||
|
||||
@ -241,10 +248,10 @@ class ReleaseData(object):
|
||||
|
||||
def update_release(self, updated_release):
|
||||
for release_id in list(updated_release.metadata):
|
||||
# Update all fields except deploy_state
|
||||
cur_deploy_state = self.metadata[release_id]['deploy_state']
|
||||
# Update all fields except state
|
||||
cur_state = self.metadata[release_id]['state']
|
||||
self.metadata[release_id].update(updated_release.metadata[release_id])
|
||||
self.metadata[release_id]['deploy_state'] = cur_deploy_state
|
||||
self.metadata[release_id]['state'] = cur_state
|
||||
|
||||
def delete_release(self, release_id):
|
||||
del self.contents[release_id]
|
||||
@ -286,11 +293,11 @@ class ReleaseData(object):
|
||||
|
||||
def parse_metadata(self,
|
||||
filename,
|
||||
deploy_state=None):
|
||||
state=None):
|
||||
"""
|
||||
Parse an individual release metadata XML file
|
||||
:param filename: XML file
|
||||
:param deploy_state: Indicates Applied, Available, or Committed
|
||||
:param state: Indicates Applied, Available, or Committed
|
||||
:return: Release ID
|
||||
"""
|
||||
tree = ElementTree.parse(filename)
|
||||
@ -316,10 +323,7 @@ class ReleaseData(object):
|
||||
|
||||
self.metadata[release_id] = {}
|
||||
|
||||
self.metadata[release_id]["deploy_state"] = deploy_state
|
||||
|
||||
# Release state is unknown at this point
|
||||
self.metadata[release_id]["state"] = "n/a"
|
||||
self.metadata[release_id]["state"] = state
|
||||
|
||||
self.metadata[release_id]["sw_version"] = "unknown"
|
||||
|
||||
@ -372,20 +376,27 @@ class ReleaseData(object):
|
||||
|
||||
def load_all_metadata(self,
|
||||
loaddir,
|
||||
deploy_state=None):
|
||||
state=None):
|
||||
"""
|
||||
Parse all metadata files in the specified dir
|
||||
:return:
|
||||
"""
|
||||
for fname in glob.glob("%s/*.xml" % loaddir):
|
||||
self.parse_metadata(fname, deploy_state)
|
||||
self.parse_metadata(fname, state)
|
||||
|
||||
def load_all(self):
|
||||
# Reset the data
|
||||
self.__init__()
|
||||
self.load_all_metadata(applied_dir, deploy_state=constants.APPLIED)
|
||||
self.load_all_metadata(avail_dir, deploy_state=constants.AVAILABLE)
|
||||
self.load_all_metadata(committed_dir, deploy_state=constants.COMMITTED)
|
||||
self.load_all_metadata(available_dir, state=constants.AVAILABLE)
|
||||
self.load_all_metadata(unavailable_dir, state=constants.UNAVAILABLE)
|
||||
self.load_all_metadata(deploying_start_dir, state=constants.DEPLOYING_START)
|
||||
self.load_all_metadata(deploying_host_dir, state=constants.DEPLOYING_HOST)
|
||||
self.load_all_metadata(deploying_activate_dir, state=constants.DEPLOYING_ACTIVATE)
|
||||
self.load_all_metadata(deploying_complete_dir, state=constants.DEPLOYING_COMPLETE)
|
||||
self.load_all_metadata(deployed_dir, state=constants.DEPLOYED)
|
||||
self.load_all_metadata(removing_dir, state=constants.REMOVING)
|
||||
self.load_all_metadata(aborting_dir, state=constants.ABORTING)
|
||||
self.load_all_metadata(committed_dir, state=constants.COMMITTED)
|
||||
|
||||
def query_line(self,
|
||||
release_id,
|
||||
@ -785,7 +796,7 @@ class PatchFile(object):
|
||||
|
||||
@staticmethod
|
||||
def extract_patch(patch,
|
||||
metadata_dir=avail_dir,
|
||||
metadata_dir=available_dir,
|
||||
metadata_only=False,
|
||||
existing_content=None,
|
||||
base_pkgdata=None):
|
||||
|
@ -40,11 +40,6 @@ ${error}
|
||||
${s["sw_version"]}
|
||||
% endif
|
||||
</sw_version>
|
||||
<deploy_state>
|
||||
% if s["deploy_state"] != "":
|
||||
${s["deploy_state"]}
|
||||
% endif
|
||||
</deploy_state>
|
||||
<state>
|
||||
% if s["state"] != "":
|
||||
${s["state"]}
|
||||
|
@ -47,11 +47,6 @@ ${showpatch(release_id)}
|
||||
${r["sw_version"]}
|
||||
% endif
|
||||
</sw_version>
|
||||
<deploy_state>
|
||||
% if r["deploy_state"] != "":
|
||||
${r["deploy_state"]}
|
||||
% endif
|
||||
</deploy_state>
|
||||
<state>
|
||||
% if r["state"] != "":
|
||||
${r["state"]}
|
||||
|
@ -29,9 +29,8 @@ FAKE_PATCH_1_META = {
|
||||
"apply_active_release_only": "",
|
||||
"description": "Patch 1 description",
|
||||
"install_instructions": "Patch 1 instructions",
|
||||
"state": STATE_NA,
|
||||
"reboot_required": PATCH_FLAG_YES,
|
||||
"deploy_state": STATE_APPLIED,
|
||||
"state": STATE_APPLIED,
|
||||
"requires": [],
|
||||
"status": STATUS_DEV,
|
||||
"summary": "Patch 1 summary",
|
||||
@ -45,9 +44,8 @@ FAKE_PATCH_2_META = {
|
||||
"apply_active_release_only": "",
|
||||
"description": "Patch 2 description",
|
||||
"install_instructions": "Patch 2 instructions",
|
||||
"state": STATE_AVAILABLE,
|
||||
"reboot_required": PATCH_FLAG_NO,
|
||||
"deploy_state": STATE_AVAILABLE,
|
||||
"state": STATE_AVAILABLE,
|
||||
"requires": [FAKE_PATCH_ID_1],
|
||||
"status": STATUS_DEV,
|
||||
"summary": "Patch 2 summary",
|
||||
|
@ -37,6 +37,25 @@ def get_major_release_version(sw_release_version):
|
||||
return None
|
||||
|
||||
|
||||
def compare_release_version(sw_release_version_1, sw_release_version_2):
|
||||
"""Compares release versions and returns True if first is higher than second """
|
||||
if not sw_release_version_1 or not sw_release_version_2:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
separator = '.'
|
||||
separated_string_1 = sw_release_version_1.split(separator)
|
||||
separated_string_2 = sw_release_version_2.split(separator)
|
||||
if len(separated_string_1) != len(separated_string_2):
|
||||
return None
|
||||
for index, val in enumerate(separated_string_1):
|
||||
if int(val) > int(separated_string_2[index]):
|
||||
return True
|
||||
return False
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def gethostbyname(hostname):
|
||||
"""gethostbyname with IPv6 support """
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user