mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Merge pull request #60 from jnealtowns/master
System Loader and ONIE Upgrade Support
This commit is contained in:
5
Makefile
5
Makefile
@@ -58,3 +58,8 @@ docker: docker_check
|
||||
# create an interative docker shell, for debugging builds
|
||||
docker-debug: docker_check
|
||||
@docker/tools/onlbuilder -$(VERSION) --isolate --hostname onlbuilder$(VERSION) --pull
|
||||
|
||||
|
||||
versions:
|
||||
$(ONL)/tools/make-versions.py --import-file=$(ONL)/tools/onlvi --class-name=OnlVersionImplementation --output-dir $(ONL)/make --force
|
||||
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
*INSTALLER
|
||||
kernel-*
|
||||
initrd-*
|
||||
lib/
|
||||
usr/
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
- parted
|
||||
- smartmontools
|
||||
- grub2
|
||||
- onl-upgrade
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#
|
||||
############################################################
|
||||
- u-boot-tools
|
||||
- onl-loader-fit
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
- parted
|
||||
- smartmontools
|
||||
- grub2
|
||||
- onl-upgrade
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
############################################################
|
||||
- u-boot-tools
|
||||
|
||||
- onl-loader-fit
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,4 +15,9 @@ for script in `ls /etc/boot.d/[0-9]* | sort`; do
|
||||
$script
|
||||
done
|
||||
|
||||
#
|
||||
# Wait for console to flush prior to starting rc.S
|
||||
#
|
||||
sleep 1
|
||||
|
||||
|
||||
|
||||
55
packages/base/all/vendor-config-onl/src/boot.d/61.upgrade-onie
Executable file
55
packages/base/all/vendor-config-onl/src/boot.d/61.upgrade-onie
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/python -u
|
||||
from onl.upgrade import ubase
|
||||
|
||||
class ONIE_Upgrade(ubase.BaseOnieUpgrade):
|
||||
name="onie"
|
||||
Name="ONIE"
|
||||
title="ONIE Upgrade Check"
|
||||
atype="An ONIE"
|
||||
|
||||
current_version_key="Current ONIE Version"
|
||||
next_version_key="Next ONIE Version"
|
||||
|
||||
def init_versions(self):
|
||||
|
||||
# Get the current platform ONIE version
|
||||
self.current_version = self.platform.onie_version()
|
||||
self.next_version = None
|
||||
self.updater = None
|
||||
|
||||
(udir, um, data) = self.platform.upgrade_manifest("onie")
|
||||
self.udir = udir
|
||||
self.data = data
|
||||
|
||||
if data:
|
||||
self.next_version = data.get('onie-version', None)
|
||||
|
||||
if data:
|
||||
self.updater = data.get('onie-updater', None)
|
||||
|
||||
if self.updater is None:
|
||||
self.finish("No ONIE updater available for the current platform.")
|
||||
|
||||
def summarize(self):
|
||||
self.logger.info("Current ONIE Version: %s" % self.current_version)
|
||||
self.logger.info(" Next ONIE Version: %s" % self.next_version)
|
||||
self.logger.info(" Force-Update: %s" % self.data['force-update'])
|
||||
self.logger.info(" Updater: %s" % self.updater)
|
||||
self.logger.info("")
|
||||
|
||||
def upgrade_notes(self):
|
||||
return """
|
||||
* The system will reboot into ONIE to complete the update, and then reboot to return to Switch Light
|
||||
"""
|
||||
|
||||
def do_upgrade(self, forced=False):
|
||||
self.install_onie_updater(self.udir, self.updater)
|
||||
self.initiate_onie_update()
|
||||
|
||||
def do_no_upgrade(self):
|
||||
self.clean_onie_updater()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ONIE_Upgrade().main()
|
||||
|
||||
153
packages/base/all/vendor-config-onl/src/boot.d/62.upgrade-loader
Executable file
153
packages/base/all/vendor-config-onl/src/boot.d/62.upgrade-loader
Executable file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/python
|
||||
############################################################
|
||||
#
|
||||
# ONL Loader Upgrade
|
||||
#
|
||||
############################################################
|
||||
import os
|
||||
import fnmatch
|
||||
from onl.upgrade import ubase
|
||||
|
||||
class Loader_Upgrade(ubase.BaseUpgrade):
|
||||
name="loader"
|
||||
Name="Loader"
|
||||
title="Loader Upgrade Check"
|
||||
atype="A Loader"
|
||||
|
||||
current_version_key="Current Loader Version"
|
||||
next_version_key="Next Loader Version"
|
||||
|
||||
def init_versions(self):
|
||||
#
|
||||
# Current Loader version file.
|
||||
# If this file doesn't exist then in-place upgrade is not supported.
|
||||
#
|
||||
ETC_LOADER_VERSIONS_JSON = "/etc/onl/loader/versions.json"
|
||||
|
||||
# Upgrade Loader Version file.
|
||||
NEXT_LOADER_VERSIONS_JSON = "/etc/onl/upgrade/%s/manifest.json" % self.arch
|
||||
|
||||
self.current_version = self.load_json(ETC_LOADER_VERSIONS_JSON,
|
||||
"RELEASE_ID",
|
||||
None)
|
||||
|
||||
self.next_version = self.load_json(NEXT_LOADER_VERSIONS_JSON,
|
||||
"version", {}).get('RELEASE_ID', None)
|
||||
|
||||
def summarize(self):
|
||||
self.logger.info("Current Loader Version: %s" % self.current_version)
|
||||
self.logger.info(" Next Loader Version: %s" % self.next_version)
|
||||
self.logger.info("")
|
||||
|
||||
|
||||
def upgrade_notes(self):
|
||||
return """
|
||||
* A single reboot will be required to complete this upgrade.
|
||||
"""
|
||||
|
||||
class Loader_Upgrade_ppc(Loader_Upgrade):
|
||||
|
||||
def do_upgrade(self, forced=False):
|
||||
|
||||
PPC_FIT_UPGRADE_IMAGE_PLATFORM="/etc/onl/upgrade/ppc/%s.itb" % self.platform.platform()
|
||||
PPC_FIT_UPGRADE_IMAGE_ALL="/etc/onl/upgrade/ppc/onl-loader-fit.itb"
|
||||
PPC_FIT_LOADER_IMAGE_NAME="%s.itb" % self.platform.platform()
|
||||
|
||||
#
|
||||
# The upgrade/ppc directory must have a FIT image called $PPC_FIT_UPGRADE_IMAGE (see constants above)
|
||||
# This is obviously a little janky.
|
||||
#
|
||||
fit_image = None
|
||||
|
||||
if os.path.exists(PPC_FIT_UPGRADE_IMAGE_PLATFORM):
|
||||
fit_image = PPC_FIT_UPGRADE_IMAGE_PLATFORM
|
||||
elif os.path.exists(PPC_FIT_UPGRADE_IMAGE_ALL):
|
||||
fit_image = PPC_FIT_UPGRADE_IMAGE_ALL
|
||||
else:
|
||||
self.abort("The PPC Upgrade FIT image is missing. Upgrade cannot continue.")
|
||||
|
||||
#
|
||||
# The platform configuration file will describe which partition
|
||||
# and which format should be used to store the FIT image.
|
||||
#
|
||||
partition = None
|
||||
raw = False
|
||||
pc = self.platform.platform_config
|
||||
|
||||
if pc:
|
||||
if 'loader' in pc and pc['loader']:
|
||||
if 'partition' in pc['loader']:
|
||||
partition = pc['loader']['partition']
|
||||
else:
|
||||
self.abort("No partition listed in the loader section of the platform configuration.")
|
||||
raw = pc['loader'].get('raw', False)
|
||||
else:
|
||||
self.abort("No loader section listed in the platform configuration.")
|
||||
else:
|
||||
self.abort("No platform configuration.")
|
||||
|
||||
if raw:
|
||||
#
|
||||
# The loader file is written raw to the given partition.
|
||||
#
|
||||
print "Writing %s to %s..." % (fit_image, partition)
|
||||
if os.system("dd of=%s if=%s" % (partition, fit_image)) != 0:
|
||||
self.abort("Failure writing loader data to partition %s." % (partition))
|
||||
|
||||
else:
|
||||
#
|
||||
# Mount the loader partition and rewrite the loader image.
|
||||
#
|
||||
mdir="/mnt/upgrade/loader"
|
||||
self.mount(mdir, partition=partition)
|
||||
self.copyfile(fit_image, os.path.join(mdir, PPC_FIT_LOADER_IMAGE_NAME))
|
||||
self.umount(mdir)
|
||||
|
||||
self.reboot()
|
||||
|
||||
|
||||
|
||||
class Loader_Upgrade_x86_64(Loader_Upgrade):
|
||||
|
||||
X86_64_UPGRADE_DIR="/etc/onl/upgrade/x86_64/"
|
||||
X86_64_UPGRADE_PATTERNS = [ "kernel-*", "initrd-*" ]
|
||||
|
||||
def do_upgrade(self, forced=False):
|
||||
#
|
||||
# Mount the ONL-BOOT partition
|
||||
#
|
||||
mdir="/mnt/onl-boot"
|
||||
self.mount(mdir, label="ONL-BOOT")
|
||||
|
||||
for f in os.listdir(self.X86_64_UPGRADE_DIR):
|
||||
for pattern in self.X86_64_UPGRADE_PATTERNS:
|
||||
if fnmatch.fnmatch(f, pattern):
|
||||
self.copyfile(os.path.join(self.X86_64_UPGRADE_DIR, f), os.path.join(mdir, f))
|
||||
|
||||
src = "/lib/platform-config/current/onl/boot/grub.cfg"
|
||||
dst = os.path.join(mdir, "grub/grub.cfg")
|
||||
if os.path.exists(src):
|
||||
self.copyfile(src, dst)
|
||||
|
||||
self.umount(mdir)
|
||||
self.reboot()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import platform
|
||||
|
||||
arch = platform.machine()
|
||||
klass = None
|
||||
|
||||
if arch =='ppc':
|
||||
klass = Loader_Upgrade_ppc
|
||||
elif arch == 'x86_64':
|
||||
klass = Loader_Upgrade_x86_64
|
||||
else:
|
||||
raise Exception("The current architecture (%s) is not supported for upgrade." % arch)
|
||||
|
||||
klass().main()
|
||||
|
||||
@@ -105,6 +105,16 @@ class OnlPlatformBase(object):
|
||||
self.add_info_json("platform_info", "%s/platform-info.json" % self.basedir_onl(),
|
||||
required=False)
|
||||
|
||||
# Load the platform config yaml file
|
||||
y = os.path.join(self.basedir_onl(), "%s.yml" % self.platform())
|
||||
if os.path.exists(y):
|
||||
self.platform_config = yaml.load(open(y))
|
||||
if self.platform() in self.platform_config:
|
||||
self.platform_config = self.platform_config[self.platform()]
|
||||
else:
|
||||
self.platform_config = {}
|
||||
|
||||
|
||||
def add_info_dict(self, name, d, klass=None):
|
||||
setattr(self, name, OnlInfoObject(d, klass))
|
||||
|
||||
@@ -191,6 +201,20 @@ class OnlPlatformBase(object):
|
||||
self.sys_oid_vendor() +
|
||||
self.sys_oid_platform());
|
||||
|
||||
def onie_version(self):
|
||||
return self.onie_info.ONIE_VERSION
|
||||
|
||||
def upgrade_manifest(self, type_, override_dir=None):
|
||||
if override_dir:
|
||||
m = os.path.join(override_dir, "manifest.json")
|
||||
else:
|
||||
m = os.path.join(self.basedir_onl(), "upgrade", type_, "manifest.json")
|
||||
|
||||
if os.path.exists(m):
|
||||
return (os.path.dirname(m), m, json.load(file(m)))
|
||||
else:
|
||||
return (None, None, None)
|
||||
|
||||
|
||||
def new_device(self, driver, addr, bus, devdir):
|
||||
if not os.path.exists(os.path.join(bus, devdir)):
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2013 v=none>
|
||||
#
|
||||
# Copyright 2013, 2014 BigSwitch Networks, Inc.
|
||||
#
|
||||
#
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
@@ -0,0 +1,426 @@
|
||||
############################################################
|
||||
#
|
||||
# Upgrade Base Classes
|
||||
#
|
||||
############################################################
|
||||
import logging
|
||||
import logging.handlers
|
||||
import platform as pp
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import json
|
||||
import string
|
||||
import argparse
|
||||
from time import sleep
|
||||
from onl.platform.current import OnlPlatform
|
||||
|
||||
class BaseUpgrade(object):
|
||||
|
||||
# Customized by deriving class
|
||||
name = None
|
||||
Name = None
|
||||
atype = None
|
||||
current_version_key = None
|
||||
next_version_key = None
|
||||
def __init__(self):
|
||||
|
||||
if not (self.name and self.Name and self.atype and self.title and
|
||||
self.current_version_key and self.next_version_key):
|
||||
raise Exception("Name descriptors must be provided by deriving class.")
|
||||
|
||||
self.init_logger()
|
||||
self.init_argparser()
|
||||
self.load_config()
|
||||
self.arch = pp.machine()
|
||||
self.platform = OnlPlatform()
|
||||
|
||||
#
|
||||
# TODO.
|
||||
#
|
||||
# DEFAULT_CONFIG = {
|
||||
# "auto-upgrade" : "advisory",
|
||||
# }
|
||||
#
|
||||
# CONFIG_FILES = [
|
||||
# "/etc/boot.d/upgrade/.upgrade-config.json",
|
||||
# "/mnt/flash/override-upgrade-config.json"
|
||||
# ]
|
||||
#
|
||||
# def load_config(self):
|
||||
# self.config = self.DEFAULT_CONFIG
|
||||
# for f in self.CONFIG_FILES:
|
||||
# if os.path.exists(f):
|
||||
# self.config.update(json.load(file(f)))
|
||||
#
|
||||
# self.logger.debug("Loaded Configuration:\n%s\n" % (json.dumps(self.config, indent=2)))
|
||||
#
|
||||
# if self.name in self.config:
|
||||
# self.config = self.config['name']
|
||||
#
|
||||
# self.logger.debug("Final Configuration:\n%s\n" % (json.dumps(self.config, indent=2)))
|
||||
#
|
||||
def load_config(self):
|
||||
pass
|
||||
|
||||
|
||||
def init_logger(self):
|
||||
fmt = '%(asctime)s.%(msecs)d %(levelname)s %(name)s: %(message)s'
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
formatter = logging.Formatter(fmt, datefmt)
|
||||
|
||||
logging.basicConfig(format=fmt, datefmt=datefmt)
|
||||
|
||||
self.logger = logging.getLogger(string.rjust("%s-upgrade" % self.name, 16))
|
||||
self.logger.setLevel(logging.INFO)
|
||||
if os.getenv("DEBUG"):
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
def init_argparser(self):
|
||||
self.ap = argparse.ArgumentParser("%s-upgrade" % self.name)
|
||||
self.ap.add_argument("--enable", action='store_true', help="Enable updates.")
|
||||
self.ap.add_argument("--force", action='store_true', help="Force update.")
|
||||
self.ap.add_argument("--no-reboot", action='store_true', help="Don't reboot.")
|
||||
self.ap.add_argument("--check", action='store_true', help="Check only.")
|
||||
self.ap.add_argument("--auto-upgrade", help="Override auto-upgrade mode.", default='advisory')
|
||||
self.ap.add_argument("--summarize", action='store_true', help="Summarize only, no upgrades.")
|
||||
|
||||
def banner(self):
|
||||
self.logger.info("************************************************************")
|
||||
self.logger.info("* %s" % self.title)
|
||||
self.logger.info("************************************************************")
|
||||
self.logger.info("")
|
||||
|
||||
def finish(self, message=None, rc=0):
|
||||
if message:
|
||||
self.logger.info("")
|
||||
if rc == 0:
|
||||
self.logger.info(message)
|
||||
else:
|
||||
self.logger.error(message)
|
||||
self.logger.info("")
|
||||
self.logger.info("************************************************************")
|
||||
self.update_upgrade_status(self.current_version_key, self.current_version)
|
||||
self.update_upgrade_status(self.next_version_key, self.next_version)
|
||||
# Flush stdout
|
||||
sleep(.1)
|
||||
sys.exit(rc)
|
||||
|
||||
def abort(self, message=None, rc=1):
|
||||
if message:
|
||||
message = "Error: %s" % message
|
||||
self.finish(message, rc)
|
||||
|
||||
def fw_getenv(self, var):
|
||||
FW_PRINTENV="/usr/bin/fw_printenv"
|
||||
if os.path.exists(FW_PRINTENV):
|
||||
try:
|
||||
if var:
|
||||
return subprocess.check_output("%s -n %s" % FW_PRINTENV, stderr=subprocess.STDOUT);
|
||||
else:
|
||||
variables = {}
|
||||
for v in subprocess.check_output("/usr/bin/fw_printenv", shell=True).split('\n'):
|
||||
(name, eq, value) = v.partition('=')
|
||||
variables[name] = value
|
||||
return variables
|
||||
except Exception, e:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
def fw_setenv(self, var, value):
|
||||
FW_SETENV="/usr/bin/fw_setenv"
|
||||
if os.system("%s %s %s" % (FW_SETENV, var, value)) != 0:
|
||||
self.abort("Error setting environment variable %s=%s. Upgrade cannot continue." % (var, value))
|
||||
|
||||
def copyfile(self, src, dst):
|
||||
self.logger.info("Installing %s -> %s..." % (src, dst))
|
||||
if not os.path.exists(src):
|
||||
self.abort("Source file '%s' does not exist." % src)
|
||||
|
||||
try:
|
||||
shutil.copyfile(src, dst)
|
||||
except Exception, e:
|
||||
self.abort("Exception while copying: %s" % e)
|
||||
|
||||
def reboot(self):
|
||||
if self.ops.no_reboot:
|
||||
self.finish("[ No Reboot ]")
|
||||
elif self.ops.check:
|
||||
self.finish("[ Check Abort ]")
|
||||
else:
|
||||
self.logger.info("The system will reboot to complete the update.")
|
||||
sleep(1)
|
||||
os.system("sync")
|
||||
sleep(1)
|
||||
while True:
|
||||
os.system("reboot -f")
|
||||
sleep(30)
|
||||
self.abort("The system did not reboot as expected.")
|
||||
|
||||
|
||||
def load_json(self, fname, key=None, default=None):
|
||||
if os.path.exists(fname):
|
||||
with open(fname) as f:
|
||||
data = json.load(f)
|
||||
if key:
|
||||
return data.get(key, default)
|
||||
else:
|
||||
return data
|
||||
else:
|
||||
return default
|
||||
|
||||
|
||||
UPGRADE_STATUS_JSON = "/lib/platform-config/current/upgrade.json"
|
||||
|
||||
def update_upgrade_status(self, key, value):
|
||||
data = {}
|
||||
if os.path.exists(self.UPGRADE_STATUS_JSON):
|
||||
with open(self.UPGRADE_STATUS_JSON) as f:
|
||||
data = json.load(f)
|
||||
data[key] = value
|
||||
with open(self.UPGRADE_STATUS_JSON, "w") as f:
|
||||
json.dump(data, f)
|
||||
|
||||
|
||||
#
|
||||
# Initialize self.current_version, self.next_Version
|
||||
# and anything required for summarize()
|
||||
#
|
||||
def init_versions(self):
|
||||
raise Exception("init_versions() must be provided by the deriving class.")
|
||||
|
||||
|
||||
#
|
||||
# Perform actual upgrade. Provided by derived class.
|
||||
#
|
||||
def do_upgrade(self, forced=False):
|
||||
raise Exception("do_upgrade() must be provided by the deriving class.")
|
||||
|
||||
#
|
||||
# Perform any clean up necessary if the system is current (no upgrade required.)
|
||||
#
|
||||
def do_no_upgrade(self):
|
||||
pass
|
||||
|
||||
|
||||
def init_upgrade(self):
|
||||
self.current_version = None
|
||||
self.next_version = None
|
||||
self.init_versions()
|
||||
self.update_upgrade_status(self.current_version_key, self.current_version)
|
||||
self.update_upgrade_status(self.next_version_key, self.next_version)
|
||||
|
||||
def summarize(self):
|
||||
pass
|
||||
|
||||
|
||||
def __upgrade_prompt(self, instructions, default="yes"):
|
||||
valid = {"yes": True, "y": True, "ye": True,
|
||||
"no": False, "n": False}
|
||||
if default is None:
|
||||
prompt = " [y/n] "
|
||||
elif default == "yes":
|
||||
prompt = " [Y/n] "
|
||||
elif default == "no":
|
||||
prompt = " [y/N] "
|
||||
else:
|
||||
raise ValueError("invalid default answer: '%s'" % default)
|
||||
|
||||
notes = self.upgrade_notes()
|
||||
if notes:
|
||||
instructions = instructions + "\n" + notes + "\n"
|
||||
|
||||
instructions = "\n\n" + instructions + "\n\nStart the upgrade? "
|
||||
|
||||
while True:
|
||||
sys.stdout.write(instructions + prompt)
|
||||
choice = raw_input().lower()
|
||||
if default is not None and choice == '':
|
||||
return valid[default]
|
||||
elif choice in valid:
|
||||
return valid[choice]
|
||||
else:
|
||||
sys.stdout.write("Please respond with 'yes' or 'no' "
|
||||
"(or 'y' or 'n').\n")
|
||||
|
||||
def upgrade_prompt(self, instructions, default='yes'):
|
||||
try:
|
||||
return self.__upgrade_prompt(instructions, default)
|
||||
except Exception, e:
|
||||
self.logger.error("")
|
||||
self.logger.error("Exception: %s" % e)
|
||||
self.abort("No upgrade will be performed.")
|
||||
return False
|
||||
except KeyboardInterrupt:
|
||||
return False
|
||||
|
||||
def upgrade_notes(self):
|
||||
raise Exception("Must be provided by derived class.")
|
||||
|
||||
def __upgrade_advisory(self):
|
||||
if not self.ops.enable:
|
||||
self.finish("%s updates are not enabled." % self.Name)
|
||||
self.__do_upgrade()
|
||||
self.finish()
|
||||
|
||||
def __upgrade_force(self):
|
||||
self.logger.info("This system is configured for automatic %s updates." % self.Name)
|
||||
self.__do_upgrade()
|
||||
self.finish()
|
||||
|
||||
def __do_upgrade(self):
|
||||
if self.ops.check:
|
||||
self.finish("[ Check abort. ]")
|
||||
self.do_upgrade()
|
||||
|
||||
|
||||
def __upgrade_optional(self):
|
||||
instructions = """%s upgrade should be performed before continuing for optimal
|
||||
performance on this system.
|
||||
|
||||
While it is recommended that you perform this upgrade it is optional and you
|
||||
may continue booting for testing purposes at this time.
|
||||
|
||||
Please note that you will be asked again each time at boot to perform
|
||||
this upgrade. Automatic booting will not be possible until the upgrade
|
||||
is performed.""" % self.atype
|
||||
|
||||
if self.upgrade_prompt(instructions) == True:
|
||||
self.__do_upgrade()
|
||||
self.finish()
|
||||
else:
|
||||
self.finish("Upgrade cancelled.")
|
||||
|
||||
def __upgrade_required(self):
|
||||
instructions = """%s upgrade must be performed before the software can run on this system.
|
||||
If you choose not to perform this upgrade booting cannot continue.""" % self.atype
|
||||
|
||||
if self.upgrade_prompt(instructions) == True:
|
||||
self.__do_upgrade()
|
||||
self.finish()
|
||||
else:
|
||||
self.logger.info("The system cannot continue without performing %s update. The system will now reboot if you would like to take alternative actions." % self.atype)
|
||||
self.reboot()
|
||||
|
||||
|
||||
def __upgrade(self):
|
||||
self.logger.info("%s upgrade is required." % self.atype)
|
||||
|
||||
auto_upgrade = self.ops.auto_upgrade
|
||||
|
||||
#
|
||||
# auto-upgrade modes are:
|
||||
# advisory : Advisory only. This is the default.
|
||||
# force : Perform the upgrade automatically.
|
||||
# optional : Ask the user whether an upgrade should be performed.
|
||||
# required : Ask the user whether an upgrade should be performed.
|
||||
# Reboot if the answer is 'no'.
|
||||
#
|
||||
if auto_upgrade == 'advisory':
|
||||
self.__upgrade_advisory()
|
||||
elif auto_upgrade == 'force':
|
||||
self.__upgrade_force();
|
||||
elif auto_upgrade == 'optional':
|
||||
self.__upgrade_optional()
|
||||
elif auto_upgrade == 'required':
|
||||
self.__upgrade_required()
|
||||
else:
|
||||
self.abort("auto-upgrade mode '%s' is not supported." % auto_upgrade)
|
||||
|
||||
|
||||
def upgrade_check(self):
|
||||
|
||||
if self.current_version == self.next_version:
|
||||
# Versions match. Only continue if forced.
|
||||
if self.ops.force:
|
||||
self.logger.info("%s version %s is current." % (self.Name,
|
||||
self.current_version))
|
||||
self.logger.info("[ Upgrade Forced. ]")
|
||||
else:
|
||||
self.logger.info("%s version %s is current." % (self.Name,
|
||||
self.current_version))
|
||||
self.do_no_upgrade()
|
||||
self.finish()
|
||||
|
||||
if self.next_version:
|
||||
self.__upgrade()
|
||||
|
||||
|
||||
def mount(self, location, partition=None, label=None):
|
||||
if not os.path.isdir(location):
|
||||
os.makedirs(location)
|
||||
|
||||
if partition:
|
||||
cmd = "mount %s %s " % (partition,location)
|
||||
name = partition
|
||||
|
||||
if label:
|
||||
cmd = "mount LABEL=%s %s" % (label, location)
|
||||
name = label
|
||||
|
||||
if os.system(cmd) != 0:
|
||||
self.abort("Could not mount %s @ %s. Upgrade cannot continue." % (name, location))
|
||||
|
||||
def umount(self, location):
|
||||
if os.system("umount %s" % location) != 0:
|
||||
self.abort("Could not unmount %s. Upgrade cannot continue." % location)
|
||||
|
||||
|
||||
def main(self):
|
||||
self.ops = self.ap.parse_args()
|
||||
self.banner()
|
||||
self.init_upgrade()
|
||||
self.summarize()
|
||||
if not self.ops.summarize:
|
||||
self.upgrade_check()
|
||||
|
||||
|
||||
|
||||
|
||||
class BaseOnieUpgrade(BaseUpgrade):
|
||||
|
||||
ONIE_UPDATER_PATH = "/mnt/flash2/onie-updater"
|
||||
|
||||
def install_onie_updater(self, src_dir, updater):
|
||||
if type(updater) is list:
|
||||
# Copy all files in the list to /mnt/flash2
|
||||
for f in updater:
|
||||
src = os.path.join(src_dir, f)
|
||||
dst = os.path.join("/mnt/flash2", f)
|
||||
self.copyfile(src, dst)
|
||||
else:
|
||||
# Copy single updater to /mnt/flash2/onie-updater
|
||||
src = os.path.join(src_dir, updater)
|
||||
self.copyfile(src, self.ONIE_UPDATER_PATH)
|
||||
|
||||
|
||||
def initiate_onie_update(self):
|
||||
self.logger.info("Initiating %s Update." % self.Name)
|
||||
if self.arch == 'ppc':
|
||||
# Initiate update
|
||||
self.fw_setenv('onie_boot_reason', 'update')
|
||||
self.reboot()
|
||||
|
||||
elif self.arch == 'x86_64':
|
||||
OB = "/mnt/onie-boot"
|
||||
self.mount(OB, label="ONIE-BOOT")
|
||||
if os.system("/mnt/onie-boot/onie/tools/bin/onie-boot-mode -o update") != 0:
|
||||
self.abort("Could not set ONIE Boot Mode to Update. Upgrade cannot continue.")
|
||||
self.umount(OB)
|
||||
|
||||
SL = "/mnt/sl-boot"
|
||||
self.mount(SL, label="SL-BOOT")
|
||||
with open("/mnt/sl-boot/grub/grub.cfg", "a") as f:
|
||||
f.write("set default=ONIE\n")
|
||||
self.umount(SL)
|
||||
self.reboot()
|
||||
|
||||
else:
|
||||
self.abort("Architecture %s unhandled." % self.arch)
|
||||
|
||||
def clean_onie_updater(self):
|
||||
if os.path.exists(self.ONIE_UPDATER_PATH):
|
||||
self.logger.info("Removing previous onie-updater.")
|
||||
os.remove(self.ONIE_UPDATER_PATH)
|
||||
1
packages/base/amd64/upgrade/Makefile
Normal file
1
packages/base/amd64/upgrade/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
26
packages/base/amd64/upgrade/PKG.yml
Normal file
26
packages/base/amd64/upgrade/PKG.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
prerequisites:
|
||||
packages:
|
||||
- onl-kernel-3.9.6-x86-64-all:amd64
|
||||
- onl-kernel-3.2-deb7-x86-64-all:amd64
|
||||
- onl-kernel-3.18-x86-64-all:amd64
|
||||
- onl-loader-initrd:amd64
|
||||
|
||||
common:
|
||||
arch: amd64
|
||||
version: 1.0.0
|
||||
copyright: Copyright 2013, 2014, 2015 Big Switch Networks
|
||||
maintainer: support@bigswitch.com
|
||||
|
||||
packages:
|
||||
- name: onl-upgrade
|
||||
version: 1.0.0
|
||||
summary: Open Network Linux Upgrade package for AMD64 platforms.
|
||||
|
||||
files:
|
||||
builds/files : /etc/onl/upgrade/x86_64
|
||||
|
||||
changelog: Change changes changes.,
|
||||
|
||||
|
||||
|
||||
|
||||
1
packages/base/amd64/upgrade/builds/.gitignore
vendored
Normal file
1
packages/base/amd64/upgrade/builds/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
files
|
||||
18
packages/base/amd64/upgrade/builds/Makefile
Normal file
18
packages/base/amd64/upgrade/builds/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
include $(ONL)/make/config.amd64.mk
|
||||
|
||||
# All amd64 kernels
|
||||
KERNELS := $(shell $(ONLPM) --find-file onl-kernel-3.9.6-x86-64-all:amd64 kernel-3.9.6-x86-64-all) \
|
||||
$(shell $(ONLPM) --find-file onl-kernel-3.2-deb7-x86-64-all:amd64 kernel-3.2-deb7-x86_64-all) \
|
||||
$(shell $(ONLPM) --find-file onl-kernel-3.18-x86-64-all:amd64 kernel-3.18-x86_64-all) \
|
||||
|
||||
# Loader initrd
|
||||
INITRD := $(shell $(ONLPM) --find-file onl-loader-initrd:amd64 onl-loader-initrd-amd64.cpio.gz)
|
||||
MANIFEST := $(shell $(ONLPM) --find-file onl-loader-initrd:amd64 manifest.json)
|
||||
|
||||
all:
|
||||
mkdir -p files
|
||||
cp $(KERNELS) files
|
||||
cp $(INITRD) files/initrd-amd64
|
||||
cp $(MANIFEST) files
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ packages:
|
||||
summary: Open Network Linux FIT Loader Image
|
||||
|
||||
files:
|
||||
builds/onl-loader-fit.itb : $$PKG_INSTALL/
|
||||
builds/onl-loader-fit.itb : /etc/onl/upgrade/ppc/
|
||||
builds/manifest.json : /etc/onl/upgrade/ppc/
|
||||
|
||||
changelog: Change changes changes.,
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@ kernel-*
|
||||
*.itb
|
||||
*.its
|
||||
loader-initrd-powerpc
|
||||
manifest.json
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
include $(ONL)/make/config.powerpc.mk
|
||||
|
||||
.PHONY: onl-loader-fit.itb onl-loader-fit.its
|
||||
|
||||
onl-loader-fit.itb:
|
||||
$(ONL)/tools/flat-image-tree.py --initrd onl-loader-initrd:powerpc,onl-loader-initrd-powerpc.cpio.gz --add-platform initrd --itb $@
|
||||
$(ONLPM) --copy-file onl-loader-initrd:powerpc manifest.json .
|
||||
|
||||
onl-loader-fit.its:
|
||||
$(ONL)/tools/flat-image-tree.py --initrd onl-loader-initrd:powerpc,onl-loader-initrd-powerpc.cpio.gz --add-platform initrd --its $@
|
||||
|
||||
Submodule packages/platforms-closed updated: ca6abea540...51991fb381
@@ -3,3 +3,5 @@ powerpc-accton-as4600-54t-r0:
|
||||
kernel: onl-kernel-3.9.6-powerpc-e500v:powerpc, kernel-3.9.6-powerpc-e500v.bin.gz
|
||||
dtb: onl-kernel-3.9.6-powerpc-e500v:powerpc, powerpc-as4600-54t.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
|
||||
@@ -2,3 +2,6 @@ powerpc-accton-as5610-52x-r0:
|
||||
flat_image_tree:
|
||||
kernel: onl-kernel-3.9.6-powerpc-e500v:powerpc, kernel-3.9.6-powerpc-e500v.bin.gz
|
||||
dtb: onl-kernel-3.9.6-powerpc-e500v:powerpc, powerpc-as5610-52x.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
@@ -3,4 +3,7 @@ powerpc-accton-as5710-54x-r0:
|
||||
kernel: onl-kernel-3.8.13-powerpc-e500mc:powerpc, kernel-3.8.13-powerpc-e500mc.bin.gz
|
||||
dtb: onl-kernel-3.8.13-powerpc-e500mc:powerpc, powerpc-accton-as5710-54x-r0.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
raw: True
|
||||
|
||||
|
||||
@@ -3,4 +3,7 @@ powerpc-accton-as5710-54x-r0b:
|
||||
kernel: onl-kernel-3.8.13-powerpc-e500mc:powerpc, kernel-3.8.13-powerpc-e500mc.bin.gz
|
||||
dtb: onl-kernel-3.8.13-powerpc-e500mc:powerpc, powerpc-accton-as5710-54x-r0b.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
raw: True
|
||||
|
||||
|
||||
@@ -3,4 +3,6 @@ powerpc-accton-as6700-32x-r0:
|
||||
kernel: onl-kernel-3.8.13-powerpc-e500mc:powerpc, kernel-3.8.13-powerpc-e500mc.bin.gz
|
||||
dtb: onl-kernel-3.8.13-powerpc-e500mc:powerpc, powerpc-accton-as6700-32x-r0.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
|
||||
|
||||
@@ -3,4 +3,6 @@ powerpc-accton-as6700-32x-r1:
|
||||
kernel: onl-kernel-3.8.13-powerpc-e500mc:powerpc, kernel-3.8.13-powerpc-e500mc.bin.gz
|
||||
dtb: onl-kernel-3.8.13-powerpc-e500mc:powerpc, powerpc-accton-as6700-32x-r1.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class OnlPlatform_x86_64_accton_as7716_32x_r0(OnlPlatformAccton):
|
||||
('pca9548', 0x77, 0),
|
||||
|
||||
# initiate leaf multiplexer (PCA9548)
|
||||
('pca9548', 0x76 1),
|
||||
('pca9548', 0x76, 1),
|
||||
|
||||
# initiate chassis fan
|
||||
('as7716_32x_fan', 0x66, 9),
|
||||
@@ -87,4 +87,4 @@ class OnlPlatform_x86_64_accton_as7716_32x_r0(OnlPlatformAccton):
|
||||
('24c02', 0x56, 0),
|
||||
])
|
||||
|
||||
return True),
|
||||
return True
|
||||
|
||||
@@ -3,3 +3,6 @@ powerpc-quanta-lb9-r0:
|
||||
kernel: onl-kernel-3.9.6-powerpc-e500v:powerpc, kernel-3.9.6-powerpc-e500v.bin.gz
|
||||
dtb: onl-kernel-3.9.6-powerpc-e500v:powerpc, powerpc-quanta-lb9-r0.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/sda1
|
||||
raw: True
|
||||
|
||||
@@ -3,3 +3,5 @@ powerpc-quanta-ly2-r0:
|
||||
kernel: onl-kernel-3.9.6-powerpc-e500v:powerpc, kernel-3.9.6-powerpc-e500v.bin.gz
|
||||
dtb: onl-kernel-3.9.6-powerpc-e500v:powerpc, powerpc-quanta-ly2-r0.dtb
|
||||
|
||||
loader:
|
||||
partition: /dev/mmcblk0p1
|
||||
|
||||
Reference in New Issue
Block a user