1 # Copyright (c) 2018 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """DUT setup library."""
16 from robot.api import logger
18 from resources.libraries.python.Constants import Constants
19 from resources.libraries.python.ssh import SSH, exec_cmd_no_error
20 from resources.libraries.python.topology import NodeType, Topology
23 class DUTSetup(object):
24 """Contains methods for setting up DUTs."""
27 def get_service_logs(node, service):
28 """Get specific service unit logs from node.
30 :param node: Node in the topology.
31 :param service: Service unit name.
35 if DUTSetup.running_in_container(node):
36 command = ('echo $(< /var/log/supervisord.log);'
37 'echo $(< /tmp/*supervisor*.log)')
39 command = ('journalctl --no-pager --unit={name} '
40 '--since="$(echo `systemctl show -p '
41 'ActiveEnterTimestamp {name}` | '
42 'awk \'{{print $2 $3}}\')"'.
44 message = 'Node {host} failed to get logs from unit {name}'.\
45 format(host=node['host'], name=service)
47 exec_cmd_no_error(node, command, timeout=30, sudo=True,
51 def get_service_logs_on_all_duts(nodes, service):
52 """Get specific service unit logs from all DUTs.
54 :param nodes: Nodes in the topology.
55 :param service: Service unit name.
59 for node in nodes.values():
60 if node['type'] == NodeType.DUT:
61 DUTSetup.get_service_logs(node, service)
64 def start_service(node, service):
65 """Start up the named service on node.
67 :param node: Node in the topology.
68 :param service: Service unit name.
72 if DUTSetup.running_in_container(node):
73 command = 'supervisorctl restart {name}'.format(name=service)
75 command = 'service {name} restart'.format(name=service)
76 message = 'Node {host} failed to start service {name}'.\
77 format(host=node['host'], name=service)
79 exec_cmd_no_error(node, command, timeout=30, sudo=True, message=message)
81 DUTSetup.get_service_logs(node, service)
84 def start_service_on_all_duts(nodes, service):
85 """Start up the named service on all DUTs.
87 :param node: Nodes in the topology.
88 :param service: Service unit name.
92 for node in nodes.values():
93 if node['type'] == NodeType.DUT:
94 DUTSetup.start_service(node, service)
97 def stop_service(node, service):
98 """Stop the named service on node.
100 :param node: Node in the topology.
101 :param service: Service unit name.
105 if DUTSetup.running_in_container(node):
106 command = 'supervisorctl stop {name}'.format(name=service)
108 command = 'service {name} stop'.format(name=service)
109 message = 'Node {host} failed to stop service {name}'.\
110 format(host=node['host'], name=service)
112 exec_cmd_no_error(node, command, timeout=30, sudo=True, message=message)
114 DUTSetup.get_service_logs(node, service)
117 def stop_service_on_all_duts(nodes, service):
118 """Stop the named service on all DUTs.
120 :param node: Nodes in the topology.
121 :param service: Service unit name.
125 for node in nodes.values():
126 if node['type'] == NodeType.DUT:
127 DUTSetup.stop_service(node, service)
131 """Run script over SSH to setup the DUT node.
133 :param node: DUT node to set up.
136 :raises Exception: If the DUT setup fails.
138 command = 'bash {0}/{1}/dut_setup.sh'.\
139 format(Constants.REMOTE_FW_DIR, Constants.RESOURCES_LIB_SH)
140 message = 'DUT test setup script failed at node {name}'.\
141 format(name=node['host'])
143 exec_cmd_no_error(node, command, timeout=120, sudo=True,
147 def setup_all_duts(nodes):
148 """Run script over SSH to setup all DUT nodes.
150 :param nodes: Topology nodes.
153 for node in nodes.values():
154 if node['type'] == NodeType.DUT:
155 DUTSetup.setup_dut(node)
158 def get_vpp_pid(node):
159 """Get PID of running VPP process.
161 :param node: DUT node.
165 :raises RuntimeError: If it is not possible to get the PID.
171 logger.trace('Try {}: Get VPP PID'.format(i))
172 ret_code, stdout, stderr = ssh.exec_command('pidof vpp')
175 raise RuntimeError('Not possible to get PID of VPP process '
176 'on node: {0}\n {1}'.
177 format(node['host'], stdout + stderr))
179 pid_list = stdout.split()
180 if len(pid_list) == 1:
183 logger.debug("No VPP PID found on node {0}".
184 format(node['host']))
187 logger.debug("More then one VPP PID found on node {0}".
188 format(node['host']))
189 return [int(pid) for pid in pid_list]
194 def get_vpp_pids(nodes):
195 """Get PID of running VPP process on all DUTs.
197 :param nodes: DUT nodes.
203 for node in nodes.values():
204 if node['type'] == NodeType.DUT:
205 pids[node['host']] = DUTSetup.get_vpp_pid(node)
209 def crypto_device_verify(node, crypto_type, numvfs, force_init=False):
210 """Verify if Crypto QAT device virtual functions are initialized on all
211 DUTs. If parameter force initialization is set to True, then try to
212 initialize or remove VFs on QAT.
214 :param node: DUT node.
215 :crypto_type: Crypto device type - HW_DH895xcc or HW_C3xxx.
216 :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
217 :param force_init: If True then try to initialize to specific value.
219 :type crypto_type: string
221 :type force_init: bool
223 :raises RuntimeError: If QAT VFs are not created and force init is set
226 pci_addr = Topology.get_cryptodev(node)
227 sriov_numvfs = DUTSetup.get_sriov_numvfs(node, pci_addr)
229 if sriov_numvfs != numvfs:
231 # QAT is not initialized and we want to initialize with numvfs
232 DUTSetup.crypto_device_init(node, crypto_type, numvfs)
234 raise RuntimeError('QAT device failed to create VFs on {host}'.
235 format(host=node['host']))
238 def crypto_device_init(node, crypto_type, numvfs):
239 """Init Crypto QAT device virtual functions on DUT.
241 :param node: DUT node.
242 :crypto_type: Crypto device type - HW_DH895xcc or HW_C3xxx.
243 :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
245 :type crypto_type: string
248 :raises RuntimeError: If failed to stop VPP or QAT failed to initialize.
250 if crypto_type == "HW_DH895xcc":
251 kernel_mod = "qat_dh895xcc"
252 kernel_drv = "dh895xcc"
253 elif crypto_type == "HW_C3xxx":
254 kernel_mod = "qat_c3xxx"
257 raise RuntimeError('Unsupported crypto device type on {host}'.
258 format(host=node['host']))
260 pci_addr = Topology.get_cryptodev(node)
262 # QAT device must be re-bound to kernel driver before initialization.
263 DUTSetup.verify_kernel_module(node, kernel_mod, force_load=True)
265 # Stop VPP to prevent deadlock.
266 DUTSetup.stop_service(node, Constants.VPP_UNIT)
268 current_driver = DUTSetup.get_pci_dev_driver(
269 node, pci_addr.replace(':', r'\:'))
270 if current_driver is not None:
271 DUTSetup.pci_driver_unbind(node, pci_addr)
273 # Bind to kernel driver.
274 DUTSetup.pci_driver_bind(node, pci_addr, kernel_drv)
276 # Initialize QAT VFs.
278 DUTSetup.set_sriov_numvfs(node, pci_addr, numvfs)
281 def get_virtfn_pci_addr(node, pf_pci_addr, vf_id):
282 """Get PCI address of Virtual Function.
284 :param node: DUT node.
285 :param pf_pci_addr: Physical Function PCI address.
286 :param vf_id: Virtual Function number.
288 :type pf_pci_addr: str
290 :returns: Virtual Function PCI address.
292 :raises RuntimeError: If failed to get Virtual Function PCI address.
295 "'basename $(readlink /sys/bus/pci/devices/{pci}/virtfn{vf_id})'".\
296 format(pci=pf_pci_addr, vf_id=vf_id)
297 message = 'Failed to get virtual function PCI address.'
299 stdout, _ = exec_cmd_no_error(node, command, timeout=30, sudo=True,
302 return stdout.strip()
305 def get_sriov_numvfs(node, pf_pci_addr):
306 """Get number of SR-IOV VFs.
308 :param node: DUT node.
309 :param pf_pci_addr: Physical Function PCI device address.
311 :type pf_pci_addr: str
312 :returns: Number of VFs.
314 :raises RuntimeError: If PCI device is not SR-IOV capable.
316 command = 'cat /sys/bus/pci/devices/{pci}/sriov_numvfs'.\
317 format(pci=pf_pci_addr.replace(':', r'\:'))
318 message = 'PCI device {pci} is not a SR-IOV device.'.\
319 format(pci=pf_pci_addr)
322 stdout, _ = exec_cmd_no_error(node, command, timeout=30, sudo=True,
325 sriov_numvfs = int(stdout)
327 logger.trace('Reading sriov_numvfs info failed on {host}'.
328 format(host=node['host']))
333 def set_sriov_numvfs(node, pf_pci_addr, numvfs=0):
334 """Init or reset SR-IOV virtual functions by setting its number on PCI
335 device on DUT. Setting to zero removes all VFs.
337 :param node: DUT node.
338 :param pf_pci_addr: Physical Function PCI device address.
339 :param numvfs: Number of VFs to initialize, 0 - removes the VFs.
341 :type pf_pci_addr: str
343 :raises RuntimeError: Failed to create VFs on PCI.
346 "'echo {num} | tee /sys/bus/pci/devices/{pci}/sriov_numvfs'".\
347 format(num=numvfs, pci=pf_pci_addr.replace(':', r'\:'))
348 message = 'Failed to create {num} VFs on {pci} device on {host}'.\
349 format(num=numvfs, pci=pf_pci_addr, host=node['host'])
351 exec_cmd_no_error(node, command, timeout=120, sudo=True,
355 def pci_driver_unbind(node, pci_addr):
356 """Unbind PCI device from current driver on node.
358 :param node: DUT node.
359 :param pci_addr: PCI device address.
362 :raises RuntimeError: If PCI device unbind failed.
365 "'echo {pci} | tee /sys/bus/pci/devices/{pcie}/driver/unbind'".\
366 format(pci=pci_addr, pcie=pci_addr.replace(':', r'\:'))
367 message = 'Failed to unbind PCI device {pci} on {host}'.\
368 format(pci=pci_addr, host=node['host'])
370 exec_cmd_no_error(node, command, timeout=120, sudo=True,
374 def pci_driver_bind(node, pci_addr, driver):
375 """Bind PCI device to driver on node.
377 :param node: DUT node.
378 :param pci_addr: PCI device address.
379 :param driver: Driver to bind.
383 :raises RuntimeError: If PCI device bind failed.
385 message = 'Failed to bind PCI device {pci} to {driver} on host {host}'.\
386 format(pci=pci_addr, driver=driver, host=node['host'])
389 "'echo {driver} | tee /sys/bus/pci/devices/{pci}/driver_override'".\
390 format(driver=driver, pci=pci_addr.replace(':', r'\:'))
392 exec_cmd_no_error(node, command, timeout=120, sudo=True,
396 "'echo {pci} | tee /sys/bus/pci/drivers/{driver}/bind'".\
397 format(pci=pci_addr, driver=driver)
399 exec_cmd_no_error(node, command, timeout=120, sudo=True,
403 "'echo | tee /sys/bus/pci/devices/{pci}/driver_override'".\
404 format(pci=pci_addr.replace(':', r'\:'))
406 exec_cmd_no_error(node, command, timeout=120, sudo=True,
410 def pci_vf_driver_unbind(node, pf_pci_addr, vf_id):
411 """Unbind Virtual Function from driver on node.
413 :param node: DUT node.
414 :param pf_pci_addr: PCI device address.
415 :param vf_id: Virtual Function ID.
417 :type pf_pci_addr: str
419 :raises RuntimeError: If Virtual Function unbind failed.
421 vf_pci_addr = DUTSetup.get_virtfn_pci_addr(node, pf_pci_addr, vf_id)
422 vf_path = "/sys/bus/pci/devices/{pf_pci_addr}/virtfn{vf_id}".\
423 format(pf_pci_addr=pf_pci_addr.replace(':', r'\:'), vf_id=vf_id)
426 "'echo {vf_pci_addr} | tee {vf_path}/driver/unbind'".\
427 format(vf_pci_addr=vf_pci_addr, vf_path=vf_path)
429 message = 'Failed to unbind VF {vf_pci_addr} to on {host}'.\
430 format(vf_pci_addr=vf_pci_addr, host=node['host'])
432 exec_cmd_no_error(node, command, timeout=120, sudo=True,
436 def pci_vf_driver_bind(node, pf_pci_addr, vf_id, driver):
437 """Bind Virtual Function to driver on node.
439 :param node: DUT node.
440 :param pf_pci_addr: PCI device address.
441 :param vf_id: Virtual Function ID.
442 :param driver: Driver to bind.
444 :type pf_pci_addr: str
447 :raises RuntimeError: If PCI device bind failed.
449 vf_pci_addr = DUTSetup.get_virtfn_pci_addr(node, pf_pci_addr, vf_id)
450 vf_path = "/sys/bus/pci/devices/{pf_pci_addr}/virtfn{vf_id}".\
451 format(pf_pci_addr=pf_pci_addr.replace(':', r'\:'), vf_id=vf_id)
453 message = 'Failed to bind VF {vf_pci_addr} to {driver} on {host}'.\
454 format(vf_pci_addr=vf_pci_addr, driver=driver, host=node['host'])
457 "'echo {driver} | tee {vf_path}/driver_override'".\
458 format(driver=driver, vf_path=vf_path)
460 exec_cmd_no_error(node, command, timeout=120, sudo=True,
464 "'echo {vf_pci_addr} | tee /sys/bus/pci/drivers/{driver}/bind'".\
465 format(vf_pci_addr=vf_pci_addr, driver=driver)
467 exec_cmd_no_error(node, command, timeout=120, sudo=True,
471 "'echo | tee {vf_path}/driver_override'".\
472 format(vf_path=vf_path)
474 exec_cmd_no_error(node, command, timeout=120, sudo=True,
478 def get_pci_dev_driver(node, pci_addr):
479 """Get current PCI device driver on node.
482 # lspci -vmmks 0000:00:05.0
484 Class: Ethernet controller
486 Device: Virtio network device
487 SVendor: Red Hat, Inc
492 :param node: DUT node.
493 :param pci_addr: PCI device address.
496 :returns: Driver or None
497 :raises RuntimeError: If PCI rescan or lspci command execution failed.
498 :raises RuntimeError: If it is not possible to get the interface driver
499 information from the node.
505 logger.trace('Try number {0}: Get PCI device driver'.format(i))
507 cmd = 'lspci -vmmks {0}'.format(pci_addr)
508 ret_code, stdout, _ = ssh.exec_command(cmd)
510 raise RuntimeError("'{0}' failed on '{1}'"
511 .format(cmd, node['host']))
513 for line in stdout.splitlines():
519 name, value = line.split("\t", 1)
521 if name == "Driver:":
523 if name == 'Driver:':
527 logger.trace('Driver for PCI device {} not found, executing '
528 'pci rescan and retrying'.format(pci_addr))
529 cmd = 'sh -c "echo 1 > /sys/bus/pci/rescan"'
530 ret_code, _, _ = ssh.exec_command_sudo(cmd)
531 if int(ret_code) != 0:
532 raise RuntimeError("'{0}' failed on '{1}'"
533 .format(cmd, node['host']))
538 def verify_kernel_module(node, module, force_load=False):
539 """Verify if kernel module is loaded on node. If parameter force
540 load is set to True, then try to load the modules.
543 :param module: Module to verify.
544 :param force_load: If True then try to load module.
547 :type force_load: bool
548 :raises RuntimeError: If module is not loaded or failed to load.
550 command = 'grep -w {module} /proc/modules'.format(module=module)
551 message = 'Kernel module {module} is not loaded on host {host}'.\
552 format(module=module, host=node['host'])
555 exec_cmd_no_error(node, command, timeout=30, sudo=False,
559 # Module is not loaded and we want to load it
560 DUTSetup.load_kernel_module(node, module)
565 def verify_kernel_module_on_all_duts(nodes, module, force_load=False):
566 """Verify if kernel module is loaded on all DUTs. If parameter force
567 load is set to True, then try to load the modules.
569 :param node: DUT nodes.
570 :param module: Module to verify.
571 :param force_load: If True then try to load module.
574 :type force_load: bool
576 for node in nodes.values():
577 if node['type'] == NodeType.DUT:
578 DUTSetup.verify_kernel_module(node, module, force_load)
581 def verify_uio_driver_on_all_duts(nodes):
582 """Verify if uio driver kernel module is loaded on all DUTs. If module
583 is not present it will try to load it.
585 :param node: DUT nodes.
588 for node in nodes.values():
589 if node['type'] == NodeType.DUT:
590 uio_driver = Topology.get_uio_driver(node)
591 DUTSetup.verify_kernel_module(node, uio_driver, force_load=True)
594 def load_kernel_module(node, module):
595 """Load kernel module on node.
597 :param node: DUT node.
598 :param module: Module to load.
602 :raises RuntimeError: If loading failed.
604 command = 'modprobe {module}'.format(module=module)
605 message = 'Failed to load {module} on host {host}'.\
606 format(module=module, host=node['host'])
608 exec_cmd_no_error(node, command, timeout=30, sudo=True, message=message)
611 def install_vpp_on_all_duts(nodes, vpp_pkg_dir):
612 """Install VPP on all DUT nodes.
614 :param nodes: Nodes in the topology.
615 :param vpp_pkg_dir: Path to directory where VPP packages are stored.
617 :type vpp_pkg_dir: str
618 :raises RuntimeError: If failed to remove or install VPP.
620 for node in nodes.values():
621 message = 'Failed to install VPP on host {host}!'.\
622 format(host=node['host'])
623 if node['type'] == NodeType.DUT:
624 command = 'ln -s /dev/null /etc/sysctl.d/80-vpp.conf || true'
625 exec_cmd_no_error(node, command, sudo=True)
627 command = '. /etc/lsb-release; echo "${DISTRIB_ID}"'
628 stdout, _ = exec_cmd_no_error(node, command)
630 if stdout.strip() == 'Ubuntu':
631 exec_cmd_no_error(node, 'apt-get purge -y "*vpp*" || true',
632 timeout=120, sudo=True)
633 exec_cmd_no_error(node, 'dpkg -i --force-all {dir}*.deb'.
634 format(dir=vpp_pkg_dir), timeout=120,
635 sudo=True, message=message)
636 exec_cmd_no_error(node, 'dpkg -l | grep vpp', sudo=True)
638 exec_cmd_no_error(node, 'yum -y remove "*vpp*" || true',
639 timeout=120, sudo=True)
640 exec_cmd_no_error(node, 'rpm -ivh {dir}*.rpm'.
641 format(dir=vpp_pkg_dir), timeout=120,
642 sudo=True, message=message)
643 exec_cmd_no_error(node, 'rpm -qai *vpp*', sudo=True)
646 def running_in_container(node):
647 """This method tests if topology node is running inside container.
649 :param node: Topology node.
651 :returns: True if running in docker container, false if not or failed
655 command = "fgrep docker /proc/1/cgroup"
656 message = 'Failed to get cgroup settings.'
658 exec_cmd_no_error(node, command, timeout=30, sudo=False,
665 def get_docker_mergeddir(node, uuid):
666 """Get Docker overlay for MergedDir diff.
668 :param node: DUT node.
669 :param uuid: Docker UUID.
672 :returns: Docker container MergedDir.
674 :raises RuntimeError: If getting output failed.
676 command = "docker inspect --format='"\
677 "{{{{.GraphDriver.Data.MergedDir}}}}' {uuid}".format(uuid=uuid)
678 message = 'Failed to get directory of {uuid} on host {host}'.\
679 format(uuid=uuid, host=node['host'])
681 stdout, _ = exec_cmd_no_error(node, command, sudo=True, message=message)
682 return stdout.strip()
685 def get_huge_page_size(node):
686 """Get default size of huge pages in system.
688 :param node: Node in the topology.
690 :returns: Default size of free huge pages in system.
692 :raises RuntimeError: If reading failed for three times.
698 ret_code, stdout, _ = ssh.exec_command_sudo(
699 "grep Hugepagesize /proc/meminfo | awk '{ print $2 }'")
702 huge_size = int(stdout)
704 logger.trace('Reading huge page size information failed')
708 raise RuntimeError('Getting huge page size information failed.')
712 def get_huge_page_free(node, huge_size):
713 """Get number of free huge pages in system.
715 :param node: Node in the topology.
716 :param huge_size: Size of hugepages.
719 :returns: Number of free huge pages in system.
721 :raises RuntimeError: If reading failed for three times.
723 # TODO: add numa aware option
728 ret_code, stdout, _ = ssh.exec_command_sudo(
729 'cat /sys/kernel/mm/hugepages/hugepages-{0}kB/free_hugepages'.
733 huge_free = int(stdout)
735 logger.trace('Reading free huge pages information failed')
739 raise RuntimeError('Getting free huge pages information failed.')
743 def get_huge_page_total(node, huge_size):
744 """Get total number of huge pages in system.
746 :param node: Node in the topology.
747 :param huge_size: Size of hugepages.
751 :returns: Total number of huge pages in system.
753 :raises RuntimeError: If reading failed for three times.
755 # TODO: add numa aware option
760 ret_code, stdout, _ = ssh.exec_command_sudo(
761 'cat /sys/kernel/mm/hugepages/hugepages-{0}kB/nr_hugepages'.
765 huge_total = int(stdout)
767 logger.trace('Reading total huge pages information failed')
771 raise RuntimeError('Getting total huge pages information failed.')
775 def check_huge_page(node, huge_mnt, mem_size, allocate=False):
776 """Check if there is enough HugePages in system. If allocate is set to
777 true, try to allocate more HugePages.
779 :param node: Node in the topology.
780 :param huge_mnt: HugePage mount point.
781 :param mem_size: Requested memory in MB.
782 :param allocate: Whether to allocate more memory if not enough.
788 :raises RuntimeError: Mounting hugetlbfs failed or not enough HugePages
789 or increasing map count failed.
791 # TODO: split function into smaller parts.
795 # Get huge pages information
796 huge_size = DUTSetup.get_huge_page_size(node)
797 huge_free = DUTSetup.get_huge_page_free(node, huge_size)
798 huge_total = DUTSetup.get_huge_page_total(node, huge_size)
800 # Check if memory reqested is available on host
801 if (mem_size * 1024) > (huge_free * huge_size):
802 # If we want to allocate hugepage dynamically
804 mem_needed = (mem_size * 1024) - (huge_free * huge_size)
805 huge_to_allocate = ((mem_needed / huge_size) * 2) + huge_total
806 max_map_count = huge_to_allocate*4
807 # Increase maximum number of memory map areas a process may have
808 ret_code, _, _ = ssh.exec_command_sudo(
809 'echo "{0}" | sudo tee /proc/sys/vm/max_map_count'.
810 format(max_map_count))
811 if int(ret_code) != 0:
812 raise RuntimeError('Increase map count failed on {host}'.
813 format(host=node['host']))
814 # Increase hugepage count
815 ret_code, _, _ = ssh.exec_command_sudo(
816 'echo "{0}" | sudo tee /proc/sys/vm/nr_hugepages'.
817 format(huge_to_allocate))
818 if int(ret_code) != 0:
819 raise RuntimeError('Mount huge pages failed on {host}'.
820 format(host=node['host']))
821 # If we do not want to allocate dynamicaly end with error
823 raise RuntimeError('Not enough free huge pages: {0}, {1} MB'.
824 format(huge_free, huge_free * huge_size))
825 # Check if huge pages mount point exist
827 ret_code, stdout, _ = ssh.exec_command('cat /proc/mounts')
828 if int(ret_code) == 0:
829 for line in stdout.splitlines():
830 # Try to find something like:
831 # none /mnt/huge hugetlbfs rw,relatime,pagesize=2048k 0 0
833 if mount[2] == 'hugetlbfs' and mount[1] == huge_mnt:
836 # If huge page mount point not exist create one
838 ret_code, _, _ = ssh.exec_command_sudo(
839 'mkdir -p {mnt}'.format(mnt=huge_mnt))
840 if int(ret_code) != 0:
841 raise RuntimeError('Create mount dir failed on {host}'.
842 format(host=node['host']))
843 ret_code, _, _ = ssh.exec_command_sudo(
844 'mount -t hugetlbfs -o pagesize=2048k none {mnt}'.
845 format(mnt=huge_mnt))
846 if int(ret_code) != 0:
847 raise RuntimeError('Mount huge pages failed on {host}'.
848 format(host=node['host']))