summaryrefslogtreecommitdiffstats
path: root/pyflashbmc/bmc_update.py
blob: 9fa54ac6eba24791ae5069c4cb1fc20803d3c0bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/python -u

import gobject
import dbus
import dbus.service
import dbus.mainloop.glib
import shutil
import tarfile
import os
from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager

DBUS_NAME = 'org.openbmc.control.BmcFlash'
OBJ_NAME = '/org/openbmc/control/flash/bmc'
FLASH_INTF = 'org.openbmc.Flash'
DOWNLOAD_INTF = 'org.openbmc.managers.Download'

UPDATE_PATH = '/run/initramfs'


def doExtract(members,files):
    for tarinfo in members:
        if files.has_key(tarinfo.name) == True:
            yield tarinfo


class BmcFlashControl(DbusProperties,DbusObjectManager):
	def __init__(self,bus,name):
		self.dbus_objects = { }
		DbusProperties.__init__(self)
		DbusObjectManager.__init__(self)
		dbus.service.Object.__init__(self,bus,name)
		
		self.Set(DBUS_NAME,"status","Idle")
		self.Set(DBUS_NAME,"filename","")
		self.Set(DBUS_NAME,"preserve_network_settings",False)
		self.Set(DBUS_NAME,"restore_application_defaults",False)
		self.Set(DBUS_NAME,"update_kernel_and_apps",False)
		self.Set(DBUS_NAME,"clear_persistent_files",False)
	
		bus.add_signal_receiver(self.download_error_handler,signal_name = "DownloadError")
		bus.add_signal_receiver(self.download_complete_handler,signal_name = "DownloadComplete")

		self.InterfacesAdded(name,self.properties)


	@dbus.service.method(DBUS_NAME,
		in_signature='ss', out_signature='')
	def updateViaTftp(self,ip,filename):
		self.TftpDownload(ip,filename)
		self.Set(DBUS_NAME,"status","Downloading")
		
	@dbus.service.method(DBUS_NAME,
		in_signature='s', out_signature='')
	def update(self,filename):
		self.Set(DBUS_NAME,"filename",filename)
		self.download_complete_handler(filename, filename)

	@dbus.service.signal(DOWNLOAD_INTF,signature='ss')
	def TftpDownload(self,ip,filename):
		self.Set(DBUS_NAME,"filename",filename)
		pass		


	## Signal handler
	def download_error_handler(self,filename):
		if (filename == self.Get(DBUS_NAME,"filename")):
			self.Set(DBUS_NAME,"status","Download Error")

	def download_complete_handler(self,outfile,filename):
		## do update
		if (filename != self.Get(DBUS_NAME,"filename")):
			return
	
		print "Download complete. Updating..."
	
		self.Set(DBUS_NAME,"status","Download Complete")
		copy_files = {}
		
		## determine needed files
		if (self.Get(DBUS_NAME,"update_kernel_and_apps") == False):
			copy_files["image-bmc"] = True
		else:
			copy_files["image-kernel"] = True
			copy_files["image-initramfs"] = True
			copy_files["image-rofs"] = True

		if (self.Get(DBUS_NAME,"restore_application_defaults") == True):
			copy_files["image-rwfs"] = True
			
		
		## make sure files exist in archive
		try:
			tar = tarfile.open(outfile,"r")
			files = {}
			for f in tar.getnames():
				files[f] = True
			tar.close()
			for f in copy_files.keys():
				if (files.has_key(f) == False):
					raise Exception("ERROR: File not found in update archive: "+f)							

		except Exception as e:
			print e
			self.Set(DBUS_NAME,"status","Update Error")
			return

		try:
			tar = tarfile.open(outfile,"r")
			tar.extractall(UPDATE_PATH,members=doExtract(tar,copy_files))
			tar.close()

			if (self.Get(DBUS_NAME,"clear_persistent_files") == True):
				print "Removing persistent files"
				os.unlink(UPDATE_PATH+"/whitelist")
			if (self.Get(DBUS_NAME,"preserve_network_settings") == True):
				print "Preserving network settings"
				shutil.copy2("/dev/mtd2",UPDATE_PATH+"/image-u-boot-env")
				
		except Exception as e:
			print e
			self.Set(DBUS_NAME,"status","Update Error")
				
		

		self.Set(DBUS_NAME,"status","Update Success.  Please reboot.")
		

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = get_dbus()
    name = dbus.service.BusName(DBUS_NAME, bus)
    obj = BmcFlashControl(bus, OBJ_NAME)
    mainloop = gobject.MainLoop()
    
    print "Running Bmc Flash Control"
    mainloop.run()

OpenPOWER on IntegriCloud