Skip to content

Commit

Permalink
Merge pull request #952 from vnitinv/vmhost-reboot-support
Browse files Browse the repository at this point in the history
support for vmhost reboot
  • Loading branch information
Nitin Kr committed Jul 30, 2019
2 parents b6e548b + 6e034c0 commit 5b6c3a1
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 51 deletions.
21 changes: 14 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
language: python
sudo: false

python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
matrix:
include:
- python: 2.7
dist: trusty
sudo: false
- python: 3.5
dist: trusty
sudo: false
- python: 3.6
dist: trusty
sudo: false
- python: 3.7
dist: xenial
sudo: true

addons:
apt:
Expand Down
100 changes: 58 additions & 42 deletions lib/jnpr/junos/utils/sw.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from lxml import etree

# local modules
from jnpr.junos.decorators import timeoutDecorator
from jnpr.junos.utils.util import Util
from jnpr.junos.utils.scp import SCP
from jnpr.junos.utils.ftp import FTP
Expand Down Expand Up @@ -75,7 +76,7 @@ def __init__(self, dev):
# Branch SRX in an SRX cluster doesn't really support multi_RE
# functionality for SW.
if (dev.facts.get('personality', '') == 'SRX_BRANCH' and
dev.facts.get('srx_cluster') is True):
dev.facts.get('srx_cluster') is True):
self._multi_RE = False
self._multi_VC = bool(
self._multi_RE is True and dev.facts.get('vc_capable') is True and
Expand Down Expand Up @@ -162,7 +163,7 @@ def local_checksum(cls, package, algorithm='md5'):
@classmethod
def progress(cls, dev, report):
""" simple progress report function """
print (dev.hostname + ": " + report)
print(dev.hostname + ": " + report)

# -------------------------------------------------------------------------
# put - Copy the image onto the device
Expand Down Expand Up @@ -235,8 +236,8 @@ def pkgadd(self, remote_package, vmhost=False, **kvargs):
rsp = self.rpc.request_package_add(**args)
else:
rsp = self.rpc.request_vmhost_package_add(
package_name=remote_package,
**kvargs)
package_name=remote_package,
**kvargs)

return self._parse_pkgadd_response(rsp)

Expand Down Expand Up @@ -274,19 +275,19 @@ def pkgaddISSU(self, remote_package, vmhost=False, **kvargs):
The file-path to the install package on the remote (Junos) device.
:param bool vhmhost:
:param bool vmhost:
(Optional) A boolean indicating if this is a software update of the
vhmhost. The default is ``vmhost=False``.
"""

if vmhost is False:
rsp = self.rpc.request_package_in_service_upgrade(
package_name=remote_package,
**kvargs)
package_name=remote_package,
**kvargs)
else:
rsp = self.rpc.request_vmhost_package_in_service_upgrade(
package_name=remote_package,
**kvargs)
package_name=remote_package,
**kvargs)
return self._parse_pkgadd_response(rsp)

def _parse_pkgadd_response(self, rsp):
Expand Down Expand Up @@ -321,7 +322,7 @@ def validate(self, remote_package, issu=False, nssu=False, **kwargs):
* * ``False`` otherwise
"""
if nssu and not self._issu_nssu_requirement_validation():
return False
return False
if issu:
if not self._issu_requirement_validation():
return False
Expand Down Expand Up @@ -374,8 +375,8 @@ def _issu_requirement_validation(self):
output = ''
try:
op = self._dev.rpc.request_shell_execute(
routing_engine='backup',
command="cli show system switchover")
routing_engine='backup',
command="cli show system switchover")
if op.findtext('.//switchover-state', default='').lower() == 'on':
self.log('Graceful switchover status is On')
return True
Expand All @@ -397,7 +398,7 @@ def _issu_requirement_validation(self):
self.log('Requirement FAILED: Not able run '
'"show system switchover"')
return False
gres_status = re.search('Graceful switchover: (\w+)', output, re.I)
gres_status = re.search(r'Graceful switchover: (\w+)', output, re.I)
if not (gres_status is not None and
gres_status.group(1).lower() == 'on'):
self.log('Requirement FAILED: Graceful switchover status '
Expand Down Expand Up @@ -453,16 +454,16 @@ def _issu_nssu_requirement_validation(self):
return False
self.log('Checking NSR configuration')
conf = self._dev.rpc.get_config(
filter_xml=etree.XML('''
filter_xml=etree.XML('''
<configuration>
<routing-options>
<nonstop-routing/>
</routing-options>
</configuration>
'''),
options={'database': 'committed',
'inherit': 'inherit',
'commit-scripts': 'apply'})
options={'database': 'committed',
'inherit': 'inherit',
'commit-scripts': 'apply'})
if conf.find('routing-options/nonstop-routing') is None:
self.log('Requirement FAILED: NSR is not Enabled in configuration')
return False
Expand Down Expand Up @@ -604,9 +605,9 @@ def _progress(report):
_progress('before copy, computing checksum on remote package: %s' %
remote_package)
remote_checksum = self.remote_checksum(
remote_package,
timeout=checksum_timeout,
algorithm=checksum_algorithm)
remote_package,
timeout=checksum_timeout,
algorithm=checksum_algorithm)

if remote_checksum != checksum:
# Need to copy the file.
Expand Down Expand Up @@ -784,7 +785,7 @@ def myprogress(dev, report):
all Routing Engines of the Junos device. When ``False`` if the
only preform the software install on the current Routing Engine.
:param bool vhmhost:
:param bool vmhost:
(Optional) A boolean indicating if this is a software update of the
vhmhost. The default is ``vmhost=False``.
Expand Down Expand Up @@ -823,7 +824,7 @@ def _progress(report):

remote_pkg_set = []
if ((sys.version < '3' and isinstance(package, (str, unicode))) or
isinstance(package, str)):
isinstance(package, str)):
pkg_set = [package]
if isinstance(pkg_set, (list, tuple)) and len(pkg_set) > 0:
for pkg in pkg_set:
Expand All @@ -833,15 +834,15 @@ def _progress(report):
# To disable cleanfs after 1st iteration
cleanfs = cleanfs and pkg_set.index(pkg) == 0
copy_ok = self.safe_copy(
pkg,
remote_path=remote_path,
progress=progress,
cleanfs=cleanfs,
checksum=checksum,
cleanfs_timeout=cleanfs_timeout,
checksum_timeout=checksum_timeout,
checksum_algorithm=checksum_algorithm,
force_copy=force_copy)
pkg,
remote_path=remote_path,
progress=progress,
cleanfs=cleanfs,
checksum=checksum,
cleanfs_timeout=cleanfs_timeout,
checksum_timeout=checksum_timeout,
checksum_algorithm=checksum_algorithm,
force_copy=force_copy)
if copy_ok is False:
return False
pkg = remote_path + '/' + path.basename(pkg)
Expand Down Expand Up @@ -945,8 +946,8 @@ def _progress(report):
# -------------------------------------------------------------------------
# reboot - system reboot
# -------------------------------------------------------------------------

def reboot(self, in_min=0, at=None, all_re=True, on_node=None):
def reboot(self, in_min=0, at=None, all_re=True, on_node=None,
vmhost=False):
"""
Perform a system reboot, with optional delay (in minutes) or at
a specified date and time.
Expand All @@ -966,6 +967,10 @@ def reboot(self, in_min=0, at=None, all_re=True, on_node=None):
reboot the whole device. If any specific node is mentioned,
reboot will be performed on mentioned node
:param bool vmhost:
(Optional) A boolean indicating to run 'request vmhost reboot'.
The default is ``vmhost=False``.
:returns:
* reboot message (string) if command successful
Expand All @@ -979,29 +984,40 @@ def reboot(self, in_min=0, at=None, all_re=True, on_node=None):
else:
cmd = E('request-node-reboot')
cmd.append(E('node', on_node))
elif vmhost is True:
cmd = E('request-vmhost-reboot')
else:
cmd = E('request-reboot')
if all_re is True:
if self._multi_RE is True and self._multi_VC is False:
cmd.append(E('both-routing-engines'))
elif self._mixed_VC is True:
cmd.append(E('all-members'))
if all_re is True:
if vmhost is True:
cmd.append(E('routing-engine', 'both'))
elif self._multi_RE is True and self._multi_VC is False:
cmd.append(E('both-routing-engines'))
elif self._mixed_VC is True:
cmd.append(E('all-members'))
if in_min >= 0 and at is None:
cmd.append(E('in', str(in_min)))
else:
cmd.append(E('at', str(at)))
try:
rsp = self.rpc(cmd)
rsp = self.rpc(cmd, ignore_warning=True, normalize=True)
if self._dev.facts['_is_linux']:
got = rsp.text
else:
got = rsp.getparent().findtext('.//request-reboot-status').strip()
got = rsp.getparent().findtext('.//request-reboot-status')
if got is None:
# Oon some platforms stopping/rebooting both
# REs produces <output> messages and
# <request-reboot-status> messages.
output_msg = '\n'.join([i.text for i in got.findall('output')
if i.text is not None])
if output_msg is not '':
got = output_msg
return got
except RpcTimeoutError as err:
raise err
except Exception as err:
if err.rsp.findtext('.//error-severity') != 'warning':
raise err
raise err

# -------------------------------------------------------------------------
# poweroff - system shutdown
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Application Frameworks',
'Topic :: Software Development :: Libraries :: Python Modules',
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/utils/test_sw.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ def _read_file(self, fname):
return rpc_reply

def _mock_manager(self, *args, **kwargs):
if kwargs:
if kwargs and 'ignore_warning' not in kwargs:
# Little hack for mocked execute
if 'dev_timeout' in kwargs:
if (args and args[0].findtext('package-name') ==
Expand Down

0 comments on commit 5b6c3a1

Please sign in to comment.