PowerFlex Pre-Upgrade Readiness Checker Script
Resumo: Script mencionado na seção Documentação de upgrade do PowerFlex para a versão v3.6.x "Verifique a compatibilidade de capacidade do NVDIMM para futuros upgrades do PowerFlex"
Este artigo aplica-se a
Este artigo não se aplica a
Este artigo não está vinculado a nenhum produto específico.
Nem todas as versões do produto estão identificadas neste artigo.
Instruções
1. Crie um arquivo chamado "FlexOS_PreUpgrade_Readiness_Checker.py" no diretório /tmp no MDM primário dos clusters. Copie e cole o conteúdo do script python no arquivo.
2. Execute o comando a seguir para tornar o script executável.
chmod 755 FlexOS_PreUpgrade_Readiness_Checker.py
FlexOS_PreUpgrade_Readiness_Checker.py Sumário
2. Execute o comando a seguir para tornar o script executável.
chmod 755 FlexOS_PreUpgrade_Readiness_Checker.py
FlexOS_PreUpgrade_Readiness_Checker.py Sumário
#!/usr/bin/python
import logging
import os
import platform
import re
import subprocess
import sys
from argparse import ArgumentParser
from argparse import SUPPRESS
from collections import namedtuple
from contextlib import contextmanager
from functools import reduce
from getpass import getpass
from math import ceil
from tempfile import mkstemp
# To-Dos:
# Add hidden parameters that allow changing the 100,670 hard coded values (for bash setup environment)
def validate_python_version():
assert float(platform.python_version()[0:3]) >= 2.7, 'The script is supported only by python 2.7 and above'
def get_cli_cmd_prefix(
mdm_ip,
cli_bin,
session_token_filename,
use_nonsecure_communication=False):
"""
Builds the base for CLI command that includes CLI binary and global options
"""
cmd = "%s --session_token_filename %s" % (cli_bin, session_token_filename)
if mdm_ip:
cmd += ' --mdm_ip %s' % (str(mdm_ip),)
if use_nonsecure_communication:
cmd += ' --use_nonsecure_communication'
return cmd
def execute_command(cmd):
try:
return subprocess.check_output(cmd, shell=True)
except subprocess.CalledProcessError as e:
# sanitize command line (may contain password)
raise RuntimeError('Command execution failed')
def cli_login(cli_cmd_prefix, username, password):
cli_cmd = cli_cmd_prefix + ' --login --username %s --password %s' % (username, password)
execute_command(cli_cmd)
def cli_logout(cli_cmd_prefix):
cli_cmd = cli_cmd_prefix + ' --logout'
execute_command(cli_cmd)
def get_output_sections(output, separator_regex):
# Split to sections by regex
sections = re.split(separator_regex, output.decode('utf-8'))
# Filter last item which is an empty string
sections = filter(None, sections)
for section in sections:
yield section
def parse_command_line_arguments():
parser = ArgumentParser(description='FlexOS Pre-Upgrade Readiness Checker')
parser.add_argument(
'--username',
'-u',
dest='username',
required=True,
help='Login username'
)
parser.add_argument(
'--password',
'-p',
dest='password',
default=None,
help='Login password'
)
parser.add_argument(
'--cli_executable',
'-c',
dest='cli_bin',
default='/opt/emc/scaleio/mdm/bin/cli',
help='CLI application path'
)
parser.add_argument(
'--use_nonsecure_communication',
'-f',
action='store_true',
dest='use_nonsecure_communication',
default=False,
help='Use nonsecure communication'
)
parser.add_argument(
'--mdm_ip',
'-m',
dest='mdm_ip',
default=None,
help='MDM IP, or comma separated list of MDM IPs'
)
parser.add_argument(
'--verbose',
'-v',
action='store_true',
dest='verbose',
default=False,
help=SUPPRESS
)
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(level=logging.DEBUG)
if args.password is None:
args.password = getpass('Enter password: ')
return args
class FglDevice:
def __init__(self, device_id, capacity_tb):
self.device_id = device_id
self.capacity_tb = capacity_tb
def __repr__(self):
return '<FglDevice %s (%.5f TB, overhead %s MB)>' % (self.device_id, self.capacity_tb, self.acceleration_capacity_mb)
@property
def acceleration_capacity_mb(self):
# each FGL device consumes acceleration capacity of 100 Mib (device overhead) + 670 MiB per Tb
return 100 + ceil(670.0 * float(self.capacity_tb))
class AccDevice:
def __init__(self, device_id, capacity_mb):
self.device_id = device_id
self.capacity_mb = capacity_mb
self.fgl_devices = []
def add_fgl_device(self, fgl_device):
assert isinstance(fgl_device, FglDevice)
assert not next((x for x in self.fgl_devices if x.device_id == fgl_device.device_id), None),\
'Tried to add an existing acc device %s' % fgl_device.device_id
self.fgl_devices.append(fgl_device)
def __repr__(self):
return '<AccDevice %s (%s Mb), %s fgl devices (%s Mb)>' % (self.device_id, self.capacity_mb, len(self.fgl_devices), self.used_capacity_mb)
@property
def used_capacity_mb(self):
return reduce(lambda capacity_mb, fgl_device: capacity_mb + fgl_device.acceleration_capacity_mb, self.fgl_devices, 0)
@property
def is_exceeding_capacity_limit(self):
return self.used_capacity_mb > self.capacity_mb
class DeviceRegistry:
def __init__(self):
self.acc_devices = {}
def add_acc_device(self, acc_device_id, acc_capacity_mb):
assert acc_device_id not in self.acc_devices, 'Trying to add an existing acc device %s' % acc_device_id
acc_device = AccDevice(device_id=acc_device_id, capacity_mb=acc_capacity_mb)
self.acc_devices[acc_device_id] = acc_device
logging.debug('Added acc device: %s' % (acc_device,))
def add_fgl_device(self, fgl_device_id, fgl_capacity_tb, acc_device_id):
assert acc_device_id in self.acc_devices, 'Tried to add fgl device to unregistered acc device %s' % acc_device_id
fgl_device = FglDevice(device_id=fgl_device_id, capacity_tb=fgl_capacity_tb)
self.acc_devices[acc_device_id].add_fgl_device(fgl_device=fgl_device)
logging.debug('Added fgl device: %s to acc device %s' % (fgl_device, self.acc_devices[acc_device_id]))
def __repr__(self):
return '<DeviceRegistry: %s acc devices>' % len(self.acc_devices)
@property
def is_exceeding_acceleration_capacity_limit(self):
return reduce(lambda is_exceeding, acc_device: is_exceeding or acc_device.is_exceeding_capacity_limit, self.acc_devices.values(), False)
def cli_get_device_registry(cli_cmd_prefix):
cli_cmd = cli_cmd_prefix + ' --query_properties --object_type DEVICE --all_objects --properties ID,ACCELERATION_POOL_ID,DEST_FGL_DEVICE_ID,CAPACITY_LIMIT --dont_format_capacity'
output = execute_command(cli_cmd)
assert output, 'No output from command: %s' % (cmd,)
return parse_output(output)
def parse_output(output):
sections = get_output_sections(output, separator_regex='DEVICE [0-9a-fA-F]+:')
# Output is expected to be in the following format:
# DEVICE dbbf780200000000:
# ID dbbf780200000000
# ACCELERATION_POOL_ID 1c1ddd7f00000001
# DEST_FGL_DEVICE_ID 0000000000000000
# CAPACITY_LIMIT 192937984 Bytes
#
# DEVICE dbbf780300000001:
# ID dbbf780300000001
# ACCELERATION_POOL_ID 0000000000000000
# DEST_FGL_DEVICE_ID dbbf780200000000
# CAPACITY_LIMIT 264241152 Bytes
#
# DEVICE dbbf780400010000:
# ID dbbf780400010000
# ACCELERATION_POOL_ID 1c1ddd7f00000001
# DEST_FGL_DEVICE_ID 0000000000000000
# CAPACITY_LIMIT 192937984 Bytes
#
# DEVICE dbbf780500010001:
# ID dbbf780500010001
# ACCELERATION_POOL_ID 0000000000000000
# DEST_FGL_DEVICE_ID dbbf780400010000
# CAPACITY_LIMIT 264241152 Bytes
#
# Note that for Rfcache devices the DEST_FGL_DEVICE_ID may be missing (in 3.0)
# or appear as "<Undefined>" (in 3.5)
# Accumulate fgl devices in tuple objects
FglDevice = namedtuple('FglDevice', ['device_id', 'fgl_acc_device_id', 'capacity_tb'])
fgl_devices = []
# Create registry
device_registry = DeviceRegistry()
# Iterating console output sections, each representing a device
for device_section in sections:
regex = "(" \
"\s+ID\s+((?P<device_id>[0-9a-fA-F]+)\s*)|" \
"(\s*ACCELERATION_POOL_ID\s+(?P<acceleration_pool_id>[0-9a-fA-F]+)\s*)|" \
"(\s*DEST_FGL_DEVICE_ID\s+(?P<dest_fgl_device_id>(([0-9a-fA-F]+)|(<Undefined>)))\s*)|" \
"(\s*CAPACITY_LIMIT\s+(?P<capacity_bytes>\d+) Bytes\s*)" \
")+"
comp = re.compile(regex)
search_results = comp.search(device_section)
is_acc_device=int(search_results.group('acceleration_pool_id'), 16) != 0
dest_fgl_device_id = search_results.group('dest_fgl_device_id')
is_fgl_device=dest_fgl_device_id and dest_fgl_device_id != '<Undefined>' and \
int(dest_fgl_device_id, 16) != 0
if not is_acc_device and not is_fgl_device:
continue
# Acceleration devices can be added to the registry immediately
if is_acc_device:
device_registry.add_acc_device(
acc_device_id=search_results.group('device_id'),
# convert bytes to MB
acc_capacity_mb=ceil(float(search_results.group('capacity_bytes')) / (1024 * 1024)))
continue
# FGL devices can only be added to the registry after all acceleration devices are there
# so for now just accumulate them
fgl_device = FglDevice(
device_id=search_results.group('device_id'),
fgl_acc_device_id=dest_fgl_device_id,
# convert bytes to TB
capacity_tb=float(search_results.group('capacity_bytes')) / (1024 * 1024 * 1024 * 1024))
fgl_devices.append(fgl_device)
# Add fgl devices to the registry
for fgl_device in fgl_devices:
device_registry.add_fgl_device(
fgl_device_id=fgl_device.device_id,
fgl_capacity_tb=fgl_device.capacity_tb,
acc_device_id=fgl_device.fgl_acc_device_id)
return device_registry
@contextmanager
def login_context(cli_cmd_prefix, username, password, session_token_filename):
assert username and password and session_token_filename
cli_login(cli_cmd_prefix=cli_cmd_prefix, username=username, password=password)
try:
yield
finally:
cli_logout(cli_cmd_prefix=cli_cmd_prefix)
if os.path.isfile(session_token_filename):
os.unlink(session_token_filename)
def main():
logging.basicConfig(level=logging.INFO, format="%(message)s")
validate_python_version()
args = parse_command_line_arguments()
cli_session_token_filename = mkstemp()[1]
cli_cmd_prefix = get_cli_cmd_prefix(
mdm_ip=args.mdm_ip,
cli_bin=args.cli_bin,
session_token_filename=cli_session_token_filename,
use_nonsecure_communication=args.use_nonsecure_communication)
with login_context(cli_cmd_prefix=cli_cmd_prefix,
username=args.username,
password=args.password,
session_token_filename=cli_session_token_filename):
# Query for acceleration devices and fgl devices, and store them in the database
device_registry = cli_get_device_registry(cli_cmd_prefix=cli_cmd_prefix)
logging.debug('Device registry: %s' % (device_registry,))
is_exceeding_acceleration_capacity_limit = device_registry.is_exceeding_acceleration_capacity_limit
if is_exceeding_acceleration_capacity_limit:
logging.info("Upgrade cannot proceed")
logging.info("System exceeding acceleration capacity limit")
return 1
logging.info("System is ready for upgrade")
return 0
if __name__ == "__main__":
try:
rc = main()
except Exception as e:
logging.error(e)
rc = -1
sys.exit(rc)
Sintaxe do script
usage: FlexOS_PreUpgrade_Readiness_Checker.py [-h] --username USERNAME
[--password PASSWORD]
[--cli_executable CLI_BIN]
[--use_nonsecure_communication]
[--mdm_ip MDM_IP]
3. Execute o script para verificar o preparo para upgrade.
Python FlexOS_PreUpgrade_Readiness_Checker.py --username admin --mdm_ip 10.10.10.20
Ex.
[root@svm1 tmp]# python FlexOS_PreUpgrade_Readiness_Checker.py --username admin --mdm_ip 10.10.10.20 Enter password: System is ready for upgradeSe você receber o seguinte resultado. Abra um caso de suporte técnico.
[root@svm1 tmp]# python FlexOS_PreUpgrade_Readiness_Checker.py --username admin --mdm_ip 10.10.10.20 Enter password: Upgrade cannot proceed System exceeding acceleration capacity limit
Produtos afetados
PowerFlex SoftwarePropriedades do artigo
Número do artigo: 000211830
Tipo de artigo: How To
Último modificado: 13 fev. 2025
Versão: 5
Encontre as respostas de outros usuários da Dell para suas perguntas.
Serviços de suporte
Verifique se o dispositivo está coberto pelos serviços de suporte.