Skip to content

Commit c7db7bc

Browse files
committed
Add a firmware downloader
To make keeping firmware up-to-date even easier, add a script that downloads the latest firmware. Data about this firmware is fetched from the github repo of this project. It is also used by Ilo.update_rib_firmware(): if the filename passed to this function is "latest", it will download and use the latest firmware.
1 parent 36e36a8 commit c7db7bc

File tree

5 files changed

+107
-2
lines changed

5 files changed

+107
-2
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ build
44
dist
55
MANIFEST
66
hp
7+
*.bin
8+
*.scexe

firmware.conf

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[ilo2]
2+
version = 2.09
3+
released = 2012-06-04
4+
url = http://ftp.hp.com/pub/softlib2/software1/sc-linux-fw-ilo/p1285463034/v75848/CP017013.scexe
5+
file = ilo2_209.bin
6+
7+
[ilo3]
8+
version = 1.28
9+
released = 2012-03-06
10+
url = http://ftp.hp.com/pub/softlib2/software1/sc-linux-fw-ilo/p1255562964/v73832/CP016462.scexe
11+
file = ilo3_128.bin

hpilo.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def wrap_socket(sock, *args, **kwargs):
2525
import xml.etree.cElementTree as etree
2626
except ImportError:
2727
import cElementTree as etree
28+
import hpilo_fw
2829

2930
# Which protocol to use
3031
ILO_RAW = 1
@@ -950,10 +951,25 @@ def uid_control(self, uid="No"):
950951
return self._control_tag('SERVER_INFO', 'UID_CONTROL', attrib={"UID": uid.title()})
951952

952953
def update_rib_firmware(self, filename, progress=None):
953-
"""Upload new RIB firmware"""
954+
"""Upload new RIB firmware, use "latest" as filename to automatically
955+
download and use the latest firmware"""
954956
if not self.protocol:
955957
self._detect_protocol()
956958

959+
if self.protocol == 'ILO_LOCAL':
960+
raise ValueError("Cannot update iLO firmware using hponcfg")
961+
962+
if filename == 'latest':
963+
config = hpilo_fw.config()
964+
current = self.get_fw_version()
965+
ilo = current['management_processor'].lower()
966+
if ilo not in config:
967+
raise IloError("Cannot update %s to the latest version automatically" % ilo)
968+
if current['firmware_version'] >= config[ilo]['version']:
969+
return "Already up-to-date"
970+
hpilo_fw.download(ilo)
971+
filename = config[ilo]['file']
972+
957973
if progress:
958974
def progress_(data):
959975
if data is None:

hpilo_fw.py

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Downloader / extracter for latest iLO2 / iLO3 firmware
2+
3+
import tarfile
4+
import os
5+
import sys
6+
PY3 = sys.version_info[0] >= 3
7+
8+
if PY3:
9+
import urllib.request as urllib2
10+
import configparser as ConfigParser
11+
import io as StringIO
12+
b = bytes
13+
else:
14+
import urllib2
15+
import ConfigParser
16+
import StringIO
17+
b = lambda x: x
18+
19+
_config = None
20+
def config():
21+
global _config
22+
if not _config:
23+
conf = _download('https://raw.github.com/seveas/python-hpilo/master/firmware.conf').decode('ascii')
24+
parser = ConfigParser.ConfigParser()
25+
parser.readfp(StringIO.StringIO(conf))
26+
_config = {}
27+
for section in parser.sections():
28+
_config[section] = {}
29+
for option in parser.options(section):
30+
_config[section][option] = parser.get(section, option)
31+
return _config
32+
33+
def _download(url):
34+
req = urllib2.urlopen(url)
35+
size = int(req.headers['Content-Length'])
36+
if size < 4096:
37+
return req.read()
38+
downloaded = 0
39+
data = b('')
40+
while downloaded < size:
41+
new = req.read(4096)
42+
data += new
43+
downloaded += len(new)
44+
sys.stdout.write('\r\033[K%d/%d (%d%%)' % (downloaded, size, downloaded*100.0/size))
45+
sys.stdout.flush()
46+
print("")
47+
return data
48+
49+
def download(ilo, path=None):
50+
if not path:
51+
path = os.getcwd()
52+
conf = config()
53+
if os.path.exists(os.path.join(path, conf[ilo]['file'])):
54+
return
55+
print("Downloading %s firmware version %s" % (ilo, conf[ilo]['version']))
56+
scexe = _download(conf[ilo]['url'])
57+
58+
# An scexe is a shell script with an embedded compressed tarball. Find the tarball.
59+
skip_start = scexe.index(b('_SKIP=')) + 6
60+
skip_end = scexe.index('\n', skip_start)
61+
skip = int(scexe[skip_start:skip_end]) - 1
62+
tarball = scexe.split('\n', skip)[-1]
63+
64+
# Now uncompress it
65+
if tarball[:2] != '\x1f\x8b':
66+
raise ValueError("Downloaded scexe file seems corrupt")
67+
68+
tf = tarfile.open(fileobj=StringIO.StringIO(tarball), mode='r:gz')
69+
tf.extract(conf[ilo]['file'], path)
70+
71+
if __name__ == '__main__':
72+
path = os.getcwd()
73+
if len(sys.argv) > 1:
74+
path = sys.argv[1]
75+
conf = config()
76+
[download(x, path) for x in conf]

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
author_email = "[email protected]",
99
url = "http://github.com/seveas/python-hpilo",
1010
description = "Accessing HP iLO interfaces from python",
11-
py_modules = ["hpilo"],
11+
py_modules = ["hpilo", "hpilo_fw"],
1212
scripts = ["hpilo_cli", "hpilo_ca"],
1313
classifiers = [
1414
'Development Status :: 5 - Production/Stable',

0 commit comments

Comments
 (0)