mirror of
				https://github.com/j-a-n/raspberrymatic-addon-rmupdate.git
				synced 2023-10-10 11:37:40 +00:00 
			
		
		
		
	-
This commit is contained in:
		| @@ -70,6 +70,16 @@ proc ::rmupdate::get_partion_start_and_size {device partition} { | |||||||
| 	return [list -1 -1] | 	return [list -1 -1] | ||||||
| } | } | ||||||
|  |  | ||||||
|  | proc ::rmupdate::is_system_upgradeable {} { | ||||||
|  | 	set ret [get_filesystem_size_and_usage "/"] | ||||||
|  | 	set size [lindex $ret 0] | ||||||
|  | 	set used [lindex $ret 1] | ||||||
|  | 	if { [expr {$used*1.5}] > $size && [expr {$used+50*1024*1024}] >= $size } { | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  | 	return 1 | ||||||
|  | } | ||||||
|  |  | ||||||
| proc ::rmupdate::mount_image_partition {image partition mountpoint} { | proc ::rmupdate::mount_image_partition {image partition mountpoint} { | ||||||
| 	variable loop_dev | 	variable loop_dev | ||||||
| 	variable sys_dev | 	variable sys_dev | ||||||
| @@ -337,7 +347,12 @@ proc ::rmupdate::install_process_running {} { | |||||||
| 	return 0 | 	return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
| proc ::rmupdate::install_firmware_version {version} { | proc ::rmupdate::delete_firmware_image {version} { | ||||||
|  | 	variable img_dir | ||||||
|  | 	eval {file delete [glob "${img_dir}/*${version}.img"]} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | proc ::rmupdate::install_firmware_version {version {reboot 1}} { | ||||||
| 	if {[rmupdate::install_process_running]} { | 	if {[rmupdate::install_process_running]} { | ||||||
| 		error "Another install process is running." | 		error "Another install process is running." | ||||||
| 	} | 	} | ||||||
| @@ -369,6 +384,11 @@ proc ::rmupdate::install_firmware_version {version} { | |||||||
| 	update_filesystems $firmware_image | 	update_filesystems $firmware_image | ||||||
| 	 | 	 | ||||||
| 	file delete $install_lock | 	file delete $install_lock | ||||||
|  | 	 | ||||||
|  | 	if {$reboot} { | ||||||
|  | 		write_log "Rebooting system." | ||||||
|  | 		exec /sbin/reboot -f | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| #puts [rmupdate::get_latest_firmware_version] | #puts [rmupdate::get_latest_firmware_version] | ||||||
|   | |||||||
| @@ -31,7 +31,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| 	<title>RaspberryMatic Update Addon</title> | 	<title>RaspberryMatic Update Addon</title> | ||||||
| 	<script> | 	<script> | ||||||
| 		var message_timer_id = null; | 		var message_timer_id = null; | ||||||
| 		var install_running = false; | 		var installation_running = ""; | ||||||
|  | 		var current_firmware = '?'; | ||||||
|  | 		var latest_firmware = '?'; | ||||||
| 		 | 		 | ||||||
| 		function display_message(type, html, millis) { | 		function display_message(type, html, millis) { | ||||||
| 			clear_message(); | 			clear_message(); | ||||||
| @@ -86,58 +88,123 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| 				$('#log-content').html(data.replace(/\n/g, '<br />')); | 				$('#log-content').html(data.replace(/\n/g, '<br />')); | ||||||
| 				$('#modal-log').modal('refresh'); | 				$('#modal-log').modal('refresh'); | ||||||
| 				$('#log-content').scrollTop($('#log-content').prop("scrollHeight")); | 				$('#log-content').scrollTop($('#log-content').prop("scrollHeight")); | ||||||
| 				if (install_running) { | 				if (installation_running) { | ||||||
| 					setTimeout(update_install_log, 1000); | 					setTimeout(update_install_log, 1000); | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		function delete_firmware_image(version) { | ||||||
|  | 			rest("POST", "/delete_firmware_image", JSON.stringify({"version":version}), | ||||||
|  | 				function(data) { | ||||||
|  | 					display_message('success', 'Firmware image ' + version + ' successfully deleted.', 5000); | ||||||
|  | 					get_firmware_info(); | ||||||
|  | 				} | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 		function install_firmware(version) { | 		function install_firmware(version) { | ||||||
| 			display_message('info', 'Installing firmware ' + version + '.', 6000000); |  | ||||||
| 			install_running = true; |  | ||||||
| 			clear_message(); |  | ||||||
| 			$('#log-content').html(''); | 			$('#log-content').html(''); | ||||||
| 			$('#modal-log').modal('show'); | 			$('#modal-log').modal('show'); | ||||||
| 			rest("POST", "/start_install_firmware", version, | 			if (installation_running) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 			installation_running = version; | ||||||
|  | 			$('[data-install-version="' + installation_running + '"]').addClass('loading'); | ||||||
|  | 			var reboot = $('#reboot-after-install').is(':checked'); | ||||||
|  | 			display_message('info', 'Installing firmware ' + version + '.', 6000000); | ||||||
|  | 			clear_message(); | ||||||
|  | 			rest("POST", "/start_install_firmware", JSON.stringify({"version":version, "reboot":reboot}), | ||||||
| 				function(data) { | 				function(data) { | ||||||
| 					install_running = false; | 					$('[data-install-version="' + installation_running + '"]').removeClass('loading'); | ||||||
|  | 					installation_running = ""; | ||||||
| 					display_message('success', 'Firmware ' + version + ' successfully installed.', 6000000); | 					display_message('success', 'Firmware ' + version + ' successfully installed.', 6000000); | ||||||
|  | 					if (!reboot) { | ||||||
|  | 						get_firmware_info(); | ||||||
|  | 					} | ||||||
| 				}, | 				}, | ||||||
| 				function(xhr, ajaxOptions, thrownError) { | 				function(xhr, ajaxOptions, thrownError) { | ||||||
| 					install_running = false; | 					$('[data-install-version="' + installation_running + '"]').removeClass('loading'); | ||||||
|  | 					installation_running = ""; | ||||||
| 					//$('#modal-log').modal('hide'); | 					//$('#modal-log').modal('hide'); | ||||||
|  | 					if (!reboot) { | ||||||
|  | 						get_firmware_info(); | ||||||
| 						default_error_callback(xhr, ajaxOptions, thrownError); | 						default_error_callback(xhr, ajaxOptions, thrownError); | ||||||
| 					} | 					} | ||||||
|  | 				} | ||||||
| 			); | 			); | ||||||
| 			setTimeout(update_install_log, 1000); | 			setTimeout(update_install_log, 1000); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		function install_latest_firmware() { | ||||||
|  | 			if (latest_firmware && latest_firmware != '?') { | ||||||
|  | 				install_firmware(latest_firmware); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		function get_firmware_info() { | ||||||
|  | 			rest("GET", "/get_firmware_info", null, function(data) { | ||||||
|  | 				$('#firmware_info tbody').empty(); | ||||||
|  | 				data.forEach(function(fw) { | ||||||
|  | 					if (fw.latest) latest_firmware = fw.version; | ||||||
|  | 					if (fw.installed) current_firmware = fw.version; | ||||||
|  | 					var color = 'yellow'; | ||||||
|  | 					if (fw.latest) color = 'green'; | ||||||
|  | 					if (fw.installed) color = 'gray'; | ||||||
|  | 					var disabled = (fw.image || fw.url ? '' : 'disabled'); | ||||||
|  | 					var binstall = $('<div class="ui '+ color +' basic '+ disabled +' button">').attr('data-install-version', fw.version).append($('<i class="sign in icon">'), 'install'); | ||||||
|  | 					binstall.click(function() { | ||||||
|  | 						install_firmware(this.getAttribute('data-install-version')); | ||||||
|  | 					}); | ||||||
|  | 					var bcls = ''; | ||||||
|  | 					if (!fw.image) bcls = 'disabled'; | ||||||
|  | 					if (fw.version == installation_running) bcls = 'loading'; | ||||||
|  | 					var bdelete = $('<div class="ui orange basic '+ bcls +' button">').attr('data-delete-version', fw.version).append($('<i class="delete icon">'), 'delete download'); | ||||||
|  | 					bdelete.click(function() { | ||||||
|  | 						delete_firmware_image(this.getAttribute('data-delete-version')); | ||||||
|  | 					}); | ||||||
|  | 					 | ||||||
|  | 					var available = (fw.url ? 'checked=""' : '') | ||||||
|  | 					var downloaded = (fw.image ? 'checked=""' : '') | ||||||
|  | 					var cls = ''; | ||||||
|  | 					if (fw.installed) cls = ' class="warning"'; | ||||||
|  | 					if (fw.latest) cls = ' class="positive"'; | ||||||
|  | 					$("#firmware_info tbody").append($('<tr' + cls + '>').append( | ||||||
|  | 						$('<td>').text(fw.version), | ||||||
|  | 						$('<td class="center aligned">').append($('<div class="ui disabled checkbox">').append($('<input type="checkbox" disabled="disabled" '+available+'>'),$('<label></label>'))), | ||||||
|  | 						$('<td class="center aligned">').append($('<div class="ui disabled checkbox">').append($('<input type="checkbox" disabled="disabled" '+downloaded+'>'),$('<label></label>'))), | ||||||
|  | 						$('<td class="center aligned">').append(bdelete, binstall) | ||||||
|  | 					)); | ||||||
|  | 				}); | ||||||
|  | 				var color = "#d01919"; | ||||||
|  | 				if (current_firmware == latest_firmware) { | ||||||
|  | 					color = "#21BA45"; | ||||||
|  | 				} | ||||||
|  | 				$("#firmware-summary").empty(); | ||||||
|  | 				$("#firmware-summary").append( | ||||||
|  | 					$('<div class="sub header">').html('Current installed version: <span style="color:'+ color +'">' + current_firmware + '</span>'), | ||||||
|  | 					$('<div class="sub header">').html('Latest avaialable version: ' + latest_firmware) | ||||||
|  | 				); | ||||||
|  | 				if (current_firmware != latest_firmware) { | ||||||
|  | 					$("#firmware-summary").append( | ||||||
|  | 						$('<div class="ui green basic button" style="margin-top:20px; margin-bottom:20px;">').click(install_latest_firmware).append($('<i class="sign in icon">'), 'Install latest firmware') | ||||||
|  | 					); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 		$(document).ready(function() { | 		$(document).ready(function() { | ||||||
| 			rest("GET", "/version", null, function(version) { | 			rest("GET", "/version", null, function(version) { | ||||||
| 				document.title = document.title + " " + version; | 				document.title = document.title + " " + version; | ||||||
| 			}); | 			}); | ||||||
| 			rest("GET", "/get_firmware_info", null, function(data) { | 			rest("GET", "/is_system_upgradeable", null, function(upgradeable) { | ||||||
| 				$('#firmware_info tbody').empty(); | 				if (!upgradeable) { | ||||||
| 				data.forEach(function(fw) { | 					var message = 'Filesystems to small, system not upgradeable!<br />'; | ||||||
| 					var disabled = (fw.image || fw.url ? '' : 'disabled'); | 					message += 'Please download and install adapted <a href="https://github.com/j-a-n/raspberrymatic-addon-rmupdate">RaspMatic image</a> first.'; | ||||||
| 					var binstall = $('<button class="ui green basic '+disabled+' button">').attr('data-version', fw.version).text('install'); | 					display_message('error', message, 6000000); | ||||||
| 					binstall.click(function() { | 				} | ||||||
| 						install_firmware(this.getAttribute('data-version')); |  | ||||||
| 					}); |  | ||||||
| 					var latest = (fw.latest ? 'checked=""' : '') |  | ||||||
| 					var installed = (fw.installed ? 'checked=""' : '') |  | ||||||
| 					var available = (fw.url ? 'checked=""' : '') |  | ||||||
| 					var downloaded = (fw.image ? 'checked=""' : '') |  | ||||||
| 					$("#firmware_info tbody").append($('<tr>').append( |  | ||||||
| 						$('<td>').text(fw.version), |  | ||||||
| 						$('<td class="center aligned">').append($('<div class="ui disabled checkbox">').append($('<input type="checkbox" disabled="disabled" '+latest+'>'),$('<label></label>'))), |  | ||||||
| 						$('<td class="center aligned">').append($('<div class="ui disabled checkbox">').append($('<input type="checkbox" disabled="disabled" '+installed+'>'),$('<label></label>'))), |  | ||||||
| 						$('<td class="center aligned">').append($('<div class="ui disabled checkbox">').append($('<input type="checkbox" disabled="disabled" '+available+'>'),$('<label></label>'))), |  | ||||||
| 						$('<td class="center aligned">').append($('<div class="ui disabled checkbox">').append($('<input type="checkbox" disabled="disabled" '+downloaded+'>'),$('<label></label>'))), |  | ||||||
| 						$('<td class="center aligned">').append(binstall) |  | ||||||
| 					)); |  | ||||||
| 				}); |  | ||||||
| 			}); | 			}); | ||||||
|  | 			get_firmware_info(); | ||||||
| 		}); | 		}); | ||||||
| 	</script> | 	</script> | ||||||
| </head> | </head> | ||||||
| @@ -147,12 +214,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| 		<div id="message" class="ui message hidden"> | 		<div id="message" class="ui message hidden"> | ||||||
| 		</div> | 		</div> | ||||||
| 		<h2 class="ui dividing header">Firmwares</h2> | 		<h2 class="ui dividing header">Firmwares</h2> | ||||||
|  | 		<div class="content" id="firmware-summary"> | ||||||
|  | 		</div> | ||||||
| 		<table id="firmware_info" class="ui celled stackable table"> | 		<table id="firmware_info" class="ui celled stackable table"> | ||||||
| 			<thead> | 			<thead> | ||||||
| 				<tr> | 				<tr> | ||||||
| 					<th>Version</th> | 					<th>Version</th> | ||||||
| 					<th class="center aligned">Latest</th> |  | ||||||
| 					<th class="center aligned">Installed</th> |  | ||||||
| 					<th class="center aligned">Available</th> | 					<th class="center aligned">Available</th> | ||||||
| 					<th class="center aligned">Downloaded</th> | 					<th class="center aligned">Downloaded</th> | ||||||
| 					<th class="center aligned">Action</th> | 					<th class="center aligned">Action</th> | ||||||
| @@ -161,12 +228,16 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| 			<tbody> | 			<tbody> | ||||||
| 			</tbody> | 			</tbody> | ||||||
| 		</table> | 		</table> | ||||||
|  | 		<div class="ui checkbox"> | ||||||
|  | 			<input id="reboot-after-install" type="checkbox" checked="checked"> | ||||||
|  | 			<label>Reboot system after installation</label> | ||||||
|  | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	 | 	 | ||||||
| 	<div style="height:80%" id="modal-log" class="ui modal"> | 	<div style="height:80%" id="modal-log" class="ui modal"> | ||||||
| 		<i class="close icon"></i> | 		<i class="close icon"></i> | ||||||
| 		<div class="header"> | 		<div class="header"> | ||||||
| 			Progress | 			Installation log | ||||||
| 		</div> | 		</div> | ||||||
| 		<div class="content"> | 		<div class="content"> | ||||||
| 			<div id="message-log" class="ui message hidden"> | 			<div id="message-log" class="ui message hidden"> | ||||||
|   | |||||||
| @@ -48,13 +48,34 @@ proc process {} { | |||||||
| 		} elseif {[lindex $path 1] == "get_firmware_info"} { | 		} elseif {[lindex $path 1] == "get_firmware_info"} { | ||||||
| 			return [rmupdate::get_firmware_info] | 			return [rmupdate::get_firmware_info] | ||||||
| 		} elseif {[lindex $path 1] == "start_install_firmware"} { | 		} elseif {[lindex $path 1] == "start_install_firmware"} { | ||||||
| 			regexp {^([\d\.]+)$} $data match version | 			regexp {\"version\"\s*:\s*\"([\d\.]+)\"} $data match version | ||||||
|  | 			regexp {\"reboot\"\s*:\s*(true|false)} $data match reboot | ||||||
| 			if { [info exists version] && $version != "" } { | 			if { [info exists version] && $version != "" } { | ||||||
| 				rmupdate::install_firmware_version $version | 				if { ![info exists reboot] } { | ||||||
| 				return "\"done\"" | 					set reboot "true" | ||||||
|  | 				} | ||||||
|  | 				if {$reboot == "true"} { | ||||||
|  | 					set reboot 1 | ||||||
|  | 				} else { | ||||||
|  | 					set reboot 0 | ||||||
|  | 				} | ||||||
|  | 				return "\"[rmupdate::install_firmware_version $version $reboot]\"" | ||||||
| 			} else { | 			} else { | ||||||
| 				error "Invalid version: ${data}" | 				error "Invalid version: ${data}" | ||||||
| 			} | 			} | ||||||
|  | 		} elseif {[lindex $path 1] == "delete_firmware_image"} { | ||||||
|  | 			regexp {\"version\"\s*:\s*\"([\d\.]+)\"} $data match version | ||||||
|  | 			if { [info exists version] && $version != "" } { | ||||||
|  | 				return "\"[rmupdate::delete_firmware_image $version]\"" | ||||||
|  | 			} else { | ||||||
|  | 				error "Invalid version: ${data}" | ||||||
|  | 			} | ||||||
|  | 		} elseif {[lindex $path 1] == "is_system_upgradeable"} { | ||||||
|  | 			if {[rmupdate::is_system_upgradeable]} { | ||||||
|  | 				return "true" | ||||||
|  | 			} else { | ||||||
|  | 				return "false" | ||||||
|  | 			} | ||||||
| 		} elseif {[lindex $path 1] == "read_install_log"} { | 		} elseif {[lindex $path 1] == "read_install_log"} { | ||||||
| 			variable content_type "text/html" | 			variable content_type "text/html" | ||||||
| 			return [rmupdate::read_install_log] | 			return [rmupdate::read_install_log] | ||||||
|   | |||||||
							
								
								
									
										64
									
								
								resize_image.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										64
									
								
								resize_image.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | #!/bin/bash -e | ||||||
|  |  | ||||||
|  | LOOP_DEV=4 | ||||||
|  | BOOT_SIZE=$((50*1024*1024)) | ||||||
|  | ROOT_SIZE=$((1000*1024*1024)) | ||||||
|  | USR_LOCAL_SIZE=$((2*1024*1024)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | if [[ $EUID -ne 0 ]]; then | ||||||
|  | 	echo "This script must be run as root." 1>&2 | ||||||
|  | 	exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | image_file="$1" | ||||||
|  | new_image_file="$1.resized" | ||||||
|  |  | ||||||
|  | echo "*** Creating new image file and partitions ***" | ||||||
|  | dd if=/dev/zero of=$new_image_file bs=1M count=$((((${BOOT_SIZE}+${ROOT_SIZE}+${USR_LOCAL_SIZE})/1024/1024)+1)) | ||||||
|  | parted --script $new_image_file \ | ||||||
|  | 	mklabel msdos \ | ||||||
|  | 	mkpart primary fat16 512B ${BOOT_SIZE}B \ | ||||||
|  | 	set 1 boot on \ | ||||||
|  | 	mkpart primary ext4 $((512+${BOOT_SIZE}))B $((${BOOT_SIZE}+${ROOT_SIZE}))B \ | ||||||
|  | 	mkpart primary ext4 $((512+${BOOT_SIZE}+${ROOT_SIZE}))B 100% | ||||||
|  |  | ||||||
|  | echo "*** Copying original partitons ***" | ||||||
|  | oIFS="$IFS" | ||||||
|  | IFS=$'\n' | ||||||
|  | for line in $(parted $image_file unit B print | grep primary); do | ||||||
|  | 	IFS=$oIFS | ||||||
|  | 	x=($line) | ||||||
|  | 	num=${x[0]} | ||||||
|  | 	start=$((${x[1]:0: -1}/512)) | ||||||
|  | 	size=$((${x[3]:0: -1}/512)) | ||||||
|  | 	echo $num - $start - $size | ||||||
|  | 	seek=0 | ||||||
|  | 	[ "$num" = "1" ] && seek=$start | ||||||
|  | 	[ "$num" = "2" ] && seek=$(((512+${BOOT_SIZE})/512)) | ||||||
|  | 	[ "$num" = "3" ] && seek=$(((512+${BOOT_SIZE}+${ROOT_SIZE})/512)) | ||||||
|  | 	dd if=$image_file of=$new_image_file bs=512 skip=$start count=$size seek=$seek conv=notrunc | ||||||
|  | done | ||||||
|  |  | ||||||
|  | echo "*** Resizing filesystems ***" | ||||||
|  | rm /dev/mapper/loop${LOOP_DEV}p 2>/dev/null || true | ||||||
|  | kpartx -d /dev/loop${LOOP_DEV} 2>/dev/null || true | ||||||
|  | losetup -d /dev/loop${LOOP_DEV} 2>/dev/null || true | ||||||
|  |  | ||||||
|  | losetup /dev/loop${LOOP_DEV} $new_image_file | ||||||
|  | kpartx -a /dev/loop${LOOP_DEV} | ||||||
|  | ln -s /dev/loop${LOOP_DEV} /dev/mapper/loop${LOOP_DEV}p | ||||||
|  |  | ||||||
|  | fsck.vfat -a /dev/mapper/loop${LOOP_DEV}p1 | ||||||
|  | fatresize --size $BOOT_SIZE /dev/mapper/loop${LOOP_DEV}p1 | ||||||
|  | fsck.ext4 -f -y /dev/mapper/loop${LOOP_DEV}p2 | ||||||
|  | resize2fs /dev/mapper/loop${LOOP_DEV}p2 | ||||||
|  | fsck.ext4 -f -y /dev/mapper/loop${LOOP_DEV}p3 | ||||||
|  | resize2fs /dev/mapper/loop${LOOP_DEV}p3 | ||||||
|  |  | ||||||
|  | rm /dev/mapper/loop${LOOP_DEV}p | ||||||
|  | kpartx -d /dev/loop${LOOP_DEV} | ||||||
|  | losetup -d /dev/loop${LOOP_DEV} | ||||||
|  |  | ||||||
|  | echo "*** Resized image successfully created ***" | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user