Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F35254567
format_disk.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
format_disk.py
View Options
#!/usr/bin/env python3
#
# Copyright VyOS maintainers and contributors <maintainers@vyos.io>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import
argparse
import
os
import
re
from
datetime
import
datetime
from
vyos.utils.io
import
ask_yes_no
from
vyos.utils.process
import
call
from
vyos.utils.process
import
cmd
from
vyos.utils.process
import
DEVNULL
from
vyos.utils.disk
import
device_from_id
def
list_disks
():
disks
=
set
()
with
open
(
'/proc/partitions'
)
as
partitions_file
:
for
line
in
partitions_file
:
fields
=
line
.
strip
()
.
split
()
if
len
(
fields
)
==
4
and
fields
[
3
]
.
isalpha
()
and
fields
[
3
]
!=
'name'
:
disks
.
add
(
fields
[
3
])
return
disks
def
is_busy
(
disk
:
str
):
"""Check if given disk device is busy by re-reading it's partition table"""
return
call
(
f
'blockdev --rereadpt /dev/{disk}'
,
stderr
=
DEVNULL
)
!=
0
def
backup_partitions
(
disk
:
str
):
"""Save sfdisk partitions output to a backup file"""
device_path
=
f
'/dev/{disk}'
backup_ts
=
datetime
.
now
()
.
strftime
(
'%Y%m
%d
-%H%M'
)
backup_file
=
f
'/var/tmp/backup_{disk}.{backup_ts}'
call
(
f
'sfdisk -d {device_path} > {backup_file}'
)
print
(
f
'Partition table backup saved to {backup_file}'
)
def
list_partitions
(
disk
:
str
):
"""List partition numbers of a given disk"""
parts
=
set
()
part_num_expr
=
re
.
compile
(
disk
+
'([0-9]+)'
)
with
open
(
'/proc/partitions'
)
as
partitions_file
:
for
line
in
partitions_file
:
fields
=
line
.
strip
()
.
split
()
if
len
(
fields
)
==
4
and
fields
[
3
]
!=
'name'
and
part_num_expr
.
match
(
fields
[
3
]):
part_idx
=
part_num_expr
.
match
(
fields
[
3
])
.
group
(
1
)
parts
.
add
(
int
(
part_idx
))
return
parts
def
delete_partition
(
disk
:
str
,
partition_idx
:
int
):
cmd
(
f
'parted /dev/{disk} rm {partition_idx}'
)
def
format_disk_like
(
target
:
str
,
proto
:
str
):
cmd
(
f
'sfdisk -d /dev/{proto} | sfdisk --force /dev/{target}'
)
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
()
group
=
parser
.
add_argument_group
()
group
.
add_argument
(
'-t'
,
'--target'
,
type
=
str
,
required
=
True
,
help
=
'Target device to format'
)
group
.
add_argument
(
'-p'
,
'--proto'
,
type
=
str
,
required
=
True
,
help
=
'Prototype device to use as reference'
)
parser
.
add_argument
(
'--by-id'
,
action
=
'store_true'
,
help
=
'Specify device by disk id'
)
args
=
parser
.
parse_args
()
target
=
args
.
target
proto
=
args
.
proto
if
args
.
by_id
:
target
=
device_from_id
(
target
)
proto
=
device_from_id
(
proto
)
target_disk
=
target
eligible_target_disks
=
list_disks
()
proto_disk
=
proto
eligible_proto_disks
=
eligible_target_disks
.
copy
()
eligible_proto_disks
.
remove
(
target_disk
)
if
proto_disk
==
target_disk
:
print
(
'The two disk drives must be different.'
)
exit
(
1
)
if
not
os
.
path
.
exists
(
f
'/dev/{proto_disk}'
):
print
(
f
'Device /dev/{proto_disk} does not exist'
)
exit
(
1
)
if
not
os
.
path
.
exists
(
'/dev/'
+
target_disk
):
print
(
f
'Device /dev/{target_disk} does not exist'
)
exit
(
1
)
if
target_disk
not
in
eligible_target_disks
:
print
(
f
'Device {target_disk} can not be formatted'
)
exit
(
1
)
if
proto_disk
not
in
eligible_proto_disks
:
print
(
f
'Device {proto_disk} can not be used as a prototype for {target_disk}'
)
exit
(
1
)
if
is_busy
(
target_disk
):
print
(
f
'Disk device {target_disk} is busy, unable to format'
)
exit
(
1
)
print
(
f
'
\n
This will re-format disk {target_disk} so that it has the same disk'
f
'
\n
partion sizes and offsets as {proto_disk}. This will not copy'
f
'
\n
data from {proto_disk} to {target_disk}. But this will erase all'
f
'
\n
data on {target_disk}.
\n
'
)
if
not
ask_yes_no
(
'Do you wish to proceed?'
):
print
(
f
'Disk drive {target_disk} will not be re-formated'
)
exit
(
0
)
print
(
f
'Re-formating disk drive {target_disk}...'
)
print
(
'Making backup copy of partitions...'
)
backup_partitions
(
target_disk
)
print
(
'Deleting old partitions...'
)
for
p
in
list_partitions
(
target_disk
):
delete_partition
(
disk
=
target_disk
,
partition_idx
=
p
)
print
(
f
'Creating new partitions on {target_disk} based on {proto_disk}...'
)
format_disk_like
(
target
=
target_disk
,
proto
=
proto_disk
)
print
(
'Done!'
)
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Tue, Dec 9, 12:21 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3063055
Default Alt Text
format_disk.py (4 KB)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment