Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
pve-manager
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
pve-manager
Commits
f87a42de
Commit
f87a42de
authored
Nov 15, 2013
by
Dietmar Maurer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
allow to create OSD on unused disks
parent
69ba82e9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
287 additions
and
3 deletions
+287
-3
Ceph.pm
PVE/API2/Ceph.pm
+161
-1
Ceph.js
www/manager/node/Ceph.js
+126
-2
No files found.
PVE/API2/Ceph.pm
View file @
f87a42de
...
...
@@ -5,9 +5,11 @@ use warnings;
use
File::
Basename
;
use
File::
Path
;
use
POSIX
qw (LONG_MAX);
use
Cwd
qw(abs_path)
;
use
IO::
Dir
;
use
PVE::
SafeSyslog
;
use
PVE::
Tools
qw(extract_param run_command)
;
use
PVE::
Tools
qw(extract_param run_command
file_get_contents file_read_firstline dir_glob_regex dir_glob_foreach
)
;
use
PVE::
Exception
qw(raise raise_param_exc)
;
use
PVE::
INotify
;
use
PVE::
Cluster
qw(cfs_lock_file cfs_read_file cfs_write_file)
;
...
...
@@ -246,6 +248,112 @@ my $ceph_service_cmd = sub {
run_command
(['
service
',
'
ceph
',
'
-c
',
$ceph_cfgpath
,
@_
]);
};
sub
list_disks
{
my
$disklist
=
{};
my
$fd
=
IO::
File
->
new
("
/proc/mounts
",
"
r
")
||
die
"
unable to open /proc/mounts - $!
\n
";
my
$mounted
=
{};
while
(
defined
(
my
$line
=
<
$fd
>
))
{
my
(
$dev
,
$path
,
$fstype
)
=
split
(
/\s+/
,
$line
);
next
if
!
(
$dev
&&
$path
&&
$fstype
);
next
if
$dev
!~
m|^/dev/|
;
my
$real_dev
=
abs_path
(
$dev
);
$mounted
->
{
$real_dev
}
=
$path
;
}
close
(
$fd
);
my
$dev_is_mounted
=
sub
{
my
(
$dev
)
=
@_
;
return
$mounted
->
{
$dev
};
};
my
$dir_is_epmty
=
sub
{
my
(
$dir
)
=
@_
;
my
$dh
=
IO::
Dir
->
new
(
$dir
);
return
1
if
!
$dh
;
while
(
defined
(
my
$tmp
=
$dh
->
read
))
{
next
if
$tmp
eq
'
.
'
||
$tmp
eq
'
..
';
$dh
->
close
;
return
0
;
}
$dh
->
close
;
return
1
;
};
dir_glob_foreach
('
/sys/block
',
'
.*
',
sub
{
my
(
$dev
)
=
@_
;
return
if
$dev
eq
'
.
';
return
if
$dev
eq
'
..
';
return
if
$dev
=~
m|^ram\d+$|
;
# skip ram devices
return
if
$dev
=~
m|^loop\d+$|
;
# skip loop devices
return
if
$dev
=~
m|^md\d+$|
;
# skip md devices
return
if
$dev
=~
m|^dm-.*$|
;
# skip dm related things
return
if
$dev
=~
m|^fd\d+$|
;
# skip Floppy
return
if
$dev
=~
m|^sr\d+$|
;
# skip CDs
my
$devdir
=
"
/sys/block/
$dev
/device
";
return
if
!
-
d
$devdir
;
my
$size
=
file_read_firstline
("
/sys/block/
$dev
/size
");
return
if
!
$size
;
$size
=
$size
*
512
;
my
$info
=
`
udevadm info --path /sys/block/
$dev
--query all
`;
return
if
!
$info
;
return
if
$info
!~
m/^E: DEVTYPE=disk$/m
;
return
if
$info
=~
m/^E: ID_CDROM/m
;
my
$serial
=
'
unknown
';
if
(
$info
=~
m/^E: ID_SERIAL_SHORT=(\S+)$/m
)
{
$serial
=
$1
;
}
my
$vendor
=
file_read_firstline
("
$devdir
/vendor
")
||
'
unknown
';
my
$model
=
file_read_firstline
("
$devdir
/model
")
||
'
unknown
';
my
$used
=
&
$dir_is_epmty
("
/sys/block/
$dev
/holders
")
?
0
:
1
;
$used
=
1
if
&
$dev_is_mounted
("
/dev/
$dev
");
$disklist
->
{
$dev
}
=
{
vendor
=>
$vendor
,
model
=>
$model
,
size
=>
$size
,
serial
=>
$serial
,
};
my
$osdid
=
-
1
;
dir_glob_foreach
("
/sys/block/
$dev
",
"
$dev
.+
",
sub
{
my
(
$part
)
=
@_
;
if
(
!&
$dir_is_epmty
("
/sys/block/
$dev
/
$part
/holders
"))
{
$used
=
1
;
}
if
(
my
$mp
=
&
$dev_is_mounted
("
/dev/
$part
"))
{
$used
=
1
;
if
(
$mp
=~
m|^/var/lib/ceph/osd/ceph-(\d+)$|
)
{
$osdid
=
$1
;
}
}
});
$disklist
->
{
$dev
}
->
{
used
}
=
$used
;
$disklist
->
{
$dev
}
->
{
osdid
}
=
$osdid
;
});
return
$disklist
;
}
__PACKAGE__
->
register_method
({
name
=>
'
index
',
path
=>
'',
...
...
@@ -279,11 +387,51 @@ __PACKAGE__->register_method ({
{
name
=>
'
crush
'
},
{
name
=>
'
config
'
},
{
name
=>
'
log
'
},
{
name
=>
'
disks
'
},
];
return
$result
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
disks
',
path
=>
'
disks
',
method
=>
'
GET
',
description
=>
"
List local disks.
",
proxyto
=>
'
node
',
protected
=>
1
,
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{
node
=>
get_standard_option
('
pve-node
'),
},
},
returns
=>
{
type
=>
'
array
',
items
=>
{
type
=>
"
object
",
properties
=>
{
dev
=>
{
type
=>
'
string
'
},
used
=>
{
type
=>
'
boolean
'
},
size
=>
{
type
=>
'
integer
'
},
osdid
=>
{
type
=>
'
integer
'
},
vendor
=>
{
type
=>
'
string
',
optional
=>
1
},
model
=>
{
type
=>
'
string
',
optional
=>
1
},
serial
=>
{
type
=>
'
string
',
optional
=>
1
},
},
},
# links => [ { rel => 'child', href => "{}" } ],
},
code
=>
sub
{
my
(
$param
)
=
@_
;
&
$check_ceph_inited
();
my
$res
=
list_disks
();
return
PVE::RESTHandler::
hash_to_array
(
$res
,
'
dev
');
}});
__PACKAGE__
->
register_method
({
name
=>
'
config
',
path
=>
'
config
',
...
...
@@ -744,6 +892,18 @@ __PACKAGE__->register_method ({
-
b
$param
->
{
dev
}
||
die
"
no such block device '
$param
->{dev}'
\n
";
my
$disklist
=
list_disks
();
my
$devname
=
$param
->
{
dev
};
$devname
=~
s
|
/dev/
||
;
my
$diskinfo
=
$disklist
->
{
$devname
};
die
"
unable to get device info for '
$devname
'
\n
"
if
!
$diskinfo
;
die
"
device '
$param
->{dev}' is in use
\n
"
if
$diskinfo
->
{
used
};
my
$monstat
=
ceph_mon_status
(
1
);
die
"
unable to get fsid
\n
"
if
!
$monstat
->
{
monmap
}
||
!
$monstat
->
{
monmap
}
->
{
fsid
};
my
$fsid
=
$monstat
->
{
monmap
}
->
{
fsid
};
...
...
www/manager/node/Ceph.js
View file @
f87a42de
Ext
.
define
(
'
PVE.node.CephDiskList
'
,
{
extend
:
'
Ext.grid.GridPanel
'
,
alias
:
'
widget.pveNodeCephDiskList
'
,
initComponent
:
function
()
{
var
me
=
this
;
var
nodename
=
me
.
pveSelNode
.
data
.
node
;
if
(
!
nodename
)
{
throw
"
no node name specified
"
;
}
var
sm
=
Ext
.
create
(
'
Ext.selection.RowModel
'
,
{});
var
rstore
=
Ext
.
create
(
'
PVE.data.UpdateStore
'
,
{
interval
:
3000
,
storeid
:
'
ceph-disk-list
'
,
model
:
'
ceph-disk-list
'
,
proxy
:
{
type
:
'
pve
'
,
url
:
"
/api2/json/nodes/
"
+
nodename
+
"
/ceph/disks
"
}
});
var
store
=
Ext
.
create
(
'
PVE.data.DiffStore
'
,
{
rstore
:
rstore
});
PVE
.
Utils
.
monStoreErrors
(
me
,
rstore
);
var
create_btn
=
new
PVE
.
button
.
Button
({
text
:
gettext
(
'
Create
'
)
+
'
: OSD
'
,
selModel
:
sm
,
disabled
:
true
,
handler
:
function
()
{
var
rec
=
sm
.
getSelection
()[
0
];
console
.
log
(
"
CREATEOSD
"
+
rec
.
data
.
dev
);
PVE
.
Utils
.
API2Request
({
url
:
"
/nodes/
"
+
nodename
+
"
/ceph/osd
"
,
method
:
'
POST
'
,
params
:
{
dev
:
"
/dev/
"
+
rec
.
data
.
dev
},
failure
:
function
(
response
,
opts
)
{
Ext
.
Msg
.
alert
(
gettext
(
'
Error
'
),
response
.
htmlStatus
);
}
});
}
});
Ext
.
apply
(
me
,
{
store
:
store
,
selModel
:
sm
,
stateful
:
false
,
tbar
:
[
create_btn
],
columns
:
[
{
header
:
gettext
(
'
Device
'
),
width
:
100
,
sortable
:
true
,
dataIndex
:
'
dev
'
},
{
header
:
gettext
(
'
used
'
),
width
:
50
,
sortable
:
false
,
renderer
:
function
(
v
,
metaData
,
rec
)
{
if
(
rec
&&
(
rec
.
data
.
osdid
>=
0
))
{
return
"
osd.
"
+
rec
.
data
.
osdid
;
}
return
PVE
.
Utils
.
format_boolean
(
v
);
},
dataIndex
:
'
used
'
},
{
header
:
gettext
(
'
Size
'
),
width
:
100
,
sortable
:
false
,
renderer
:
PVE
.
Utils
.
format_size
,
dataIndex
:
'
size
'
},
{
header
:
gettext
(
'
Vendor
'
),
width
:
100
,
sortable
:
true
,
dataIndex
:
'
vendor
'
},
{
header
:
gettext
(
'
Model
'
),
width
:
200
,
sortable
:
true
,
dataIndex
:
'
model
'
},
{
header
:
gettext
(
'
Serial
'
),
flex
:
1
,
sortable
:
true
,
dataIndex
:
'
serial
'
}
],
listeners
:
{
show
:
rstore
.
startUpdate
,
hide
:
rstore
.
stopUpdate
,
destroy
:
rstore
.
stopUpdate
}
});
me
.
callParent
();
}
},
function
()
{
Ext
.
define
(
'
ceph-disk-list
'
,
{
extend
:
'
Ext.data.Model
'
,
fields
:
[
'
dev
'
,
'
used
'
,
{
name
:
'
size
'
,
type
:
'
number
'
},
{
name
:
'
osdid
'
,
type
:
'
number
'
},
'
vendor
'
,
'
model
'
,
'
serial
'
],
idProperty
:
'
dev
'
});
});
Ext
.
define
(
'
PVE.CephCreateMon
'
,
{
extend
:
'
PVE.window.Edit
'
,
alias
:
[
'
widget.pveCephCreateMon
'
],
...
...
@@ -107,7 +226,7 @@ Ext.define('PVE.node.CephMonList', {
}
});
var
add
_btn
=
new
Ext
.
Button
({
var
create
_btn
=
new
Ext
.
Button
({
text
:
gettext
(
'
Create
'
),
handler
:
function
(){
var
win
=
Ext
.
create
(
'
PVE.CephCreateMon
'
,
{
...
...
@@ -144,7 +263,7 @@ Ext.define('PVE.node.CephMonList', {
store
:
store
,
selModel
:
sm
,
stateful
:
false
,
tbar
:
[
start_btn
,
stop_btn
,
add
_btn
,
remove_btn
],
tbar
:
[
start_btn
,
stop_btn
,
create
_btn
,
remove_btn
],
columns
:
[
{
header
:
gettext
(
'
Name
'
),
...
...
@@ -449,6 +568,11 @@ Ext.define('PVE.node.Ceph', {
title
:
'
Monitor
'
,
itemId
:
'
monlist
'
},
{
xtype
:
'
pveNodeCephDiskList
'
,
title
:
'
Disks
'
,
itemId
:
'
disklist
'
},
{
title
:
'
OSD
'
,
itemId
:
'
test3
'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment