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
b6c4b9ca
Commit
b6c4b9ca
authored
Dec 21, 2011
by
Dietmar Maurer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
start adding HA Config
parent
f9e2a4c2
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
829 additions
and
0 deletions
+829
-0
Cluster.pm
PVE/API2/Cluster.pm
+8
-0
HAConfig.pm
PVE/API2/HAConfig.pm
+512
-0
Makefile
PVE/API2/Makefile
+1
-0
Makefile
www/manager/Makefile
+1
-0
Config.js
www/manager/dc/Config.js
+5
-0
HAConfig.js
www/manager/dc/HAConfig.js
+302
-0
No files found.
PVE/API2/Cluster.pm
View file @
b6c4b9ca
...
...
@@ -5,9 +5,11 @@ use warnings;
use
PVE::
SafeSyslog
;
use
PVE::
Tools
qw(extract_param)
;
use
PVE::
INotify
;
use
PVE::
Cluster
qw(cfs_register_file cfs_lock_file cfs_read_file cfs_write_file)
;
use
PVE::
Storage
;
use
PVE::API2::
Backup
;
use
PVE::API2::
HAConfig
;
use
JSON
;
use
PVE::
RESTHandler
;
use
PVE::
RPCEnvironment
;
...
...
@@ -19,6 +21,11 @@ __PACKAGE__->register_method ({
path
=>
'
backup
',
});
__PACKAGE__
->
register_method
({
subclass
=>
"
PVE::API2::HAConfig
",
path
=>
'
ha
',
});
my
$dc_schema
=
PVE::Cluster::
get_datacenter_schema
();
my
$dc_properties
=
{
delete
=>
{
...
...
@@ -58,6 +65,7 @@ __PACKAGE__->register_method ({
{
name
=>
'
resources
'
},
{
name
=>
'
tasks
'
},
{
name
=>
'
backup
'
},
{
name
=>
'
ha
'
},
];
return
$result
;
...
...
PVE/API2/HAConfig.pm
0 → 100644
View file @
b6c4b9ca
package
PVE::API2::
HAConfig
;
use
strict
;
use
warnings
;
use
PVE::
SafeSyslog
;
use
PVE::
Tools
;
use
PVE::
Cluster
qw(cfs_lock_file cfs_read_file cfs_write_file)
;
use
PVE::
RESTHandler
;
use
PVE::
RPCEnvironment
;
use
PVE::
JSONSchema
qw(get_standard_option)
;
use
PVE::
Exception
qw(raise_param_exc)
;
use
base
qw(PVE::RESTHandler)
;
__PACKAGE__
->
register_method
({
name
=>
'
index
',
path
=>
'',
method
=>
'
GET
',
description
=>
"
Directory index.
",
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Audit
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{},
},
returns
=>
{
type
=>
'
array
',
items
=>
{
type
=>
"
object
",
properties
=>
{
id
=>
{
type
=>
'
string
'
},
},
},
links
=>
[
{
rel
=>
'
child
',
href
=>
"
{id}
"
}
],
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$res
=
[
{
id
=>
'
config
'
},
{
id
=>
'
changes
'
},
{
id
=>
'
groups
'
},
];
return
$res
;
}});
my
$load_cluster_conf
=
sub
{
my
$oldconf
;
my
$newconf
;
my
$code
=
sub
{
$oldconf
=
PVE::Cluster::
cfs_read_file
('
cluster.conf
');
$newconf
=
PVE::Cluster::
cfs_read_file
('
cluster.conf.new
');
};
cfs_lock_file
('
cluster.conf
',
undef
,
$code
);
die
$@
if
$@
;
if
(
!
$newconf
->
{
children
})
{
return
wantarray
?
(
$oldconf
,
undef
)
:
$oldconf
;
}
return
$newconf
if
!
wantarray
;
# test if there is different content
my
$oldstr
=
PVE::Cluster::
write_cluster_conf
("
fake.cfg
",
$oldconf
);
my
$newstr
=
PVE::Cluster::
write_cluster_conf
("
fake.cfg
",
$newconf
);
return
(
$oldconf
,
undef
)
if
$oldstr
eq
$newstr
;
# same content
# comput diff to display on GUI
my
$oldfn
=
'
/etc/pve/cluster.conf
';
my
$newfn
=
'
/etc/pve/cluster.conf.new
';
my
$diff
=
PVE::INotify::
ccache_compute_diff
(
$oldfn
,
$newfn
);
return
(
$newconf
,
$diff
);
};
__PACKAGE__
->
register_method
({
name
=>
'
get_config
',
path
=>
'
config
',
method
=>
'
GET
',
description
=>
"
Read cluster configuartion (cluster.conf). If you have any uncommitted changes in cluster.conf.new that content is returned instead.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Audit
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{},
},
returns
=>
{
type
=>
"
object
",
properties
=>
{},
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$rpcenv
=
PVE::RPCEnvironment::
get
();
my
(
$conf
,
$diff
)
=
&
$load_cluster_conf
();
$rpcenv
->
set_result_attrib
('
changes
',
$diff
);
return
$conf
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
get_changes
',
path
=>
'
changes
',
method
=>
'
GET
',
description
=>
"
Get pending changes (unified diff between cluster.conf and cluster.conf.new
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Audit
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{},
},
returns
=>
{
type
=>
"
string
",
optional
=>
1
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
(
$conf
,
$diff
)
=
&
$load_cluster_conf
();
return
$diff
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
revert_changes
',
path
=>
'
changes
',
method
=>
'
DELETE
',
description
=>
"
Revert pending changes (remove cluster.conf.new)
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Modify
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{},
},
returns
=>
{
type
=>
"
null
"
},
code
=>
sub
{
my
(
$param
)
=
@_
;
if
(
!
unlink
("
/etc/pve/cluster.conf.new
"))
{
die
"
unlink failed - $!
\n
";
}
return
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
commit_config
',
path
=>
'
changes
',
method
=>
'
POST
',
description
=>
"
Commit cluster configuartion. Pending changes from cluster.conf.new are written to cluster.conf. This triggers a CMan reload on all nodes.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Modify
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{},
},
returns
=>
{
type
=>
"
object
",
properties
=>
{},
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$rpcenv
=
PVE::RPCEnvironment::
get
();
die
"
not implemented
";
}});
my
$read_cluster_conf_new
=
sub
{
my
$conf
=
PVE::Cluster::
cfs_read_file
('
cluster.conf.new
');
if
(
!
$conf
->
{
children
})
{
$conf
=
PVE::Cluster::
cfs_read_file
('
cluster.conf
');
}
return
$conf
;
};
my
$update_cluster_conf_new
=
sub
{
my
(
$conf
)
=
@_
;
$conf
->
{
children
}
->
[
0
]
->
{
config_version
}
++
;
cfs_write_file
('
cluster.conf.new
',
$conf
);
};
my
$lookup_cluster_sec
=
sub
{
my
(
$conf
)
=
@_
;
die
"
no cluster defined
\n
"
if
!
PVE::Cluster::
cluster_conf_version
(
$conf
);
my
$cluster
=
$conf
->
{
children
}
->
[
0
];
die
"
invalid root node
\n
"
if
$cluster
->
{
text
}
ne
'
cluster
';
return
$cluster
;
};
my
$lookup_rm_sec
=
sub
{
my
(
$conf
,
$create
,
$noerr
)
=
@_
;
my
$cluster
=
&
$lookup_cluster_sec
(
$conf
);
my
$rmsec
;
foreach
my
$child
(
@
{
$cluster
->
{
children
}})
{
if
(
$child
->
{
text
}
eq
'
rm
')
{
$rmsec
=
$child
;
}
}
if
(
!
$rmsec
)
{
if
(
!
$create
)
{
return
undef
if
$noerr
;
die
"
no resource manager section
\n
";
}
$rmsec
=
{
text
=>
'
rm
'
};
push
@
{
$cluster
->
{
children
}},
$rmsec
;
}
return
$rmsec
;
};
my
$lookup_pvevm
=
sub
{
my
(
$conf
,
$create
,
$vmid
)
=
@_
;
my
$rmsec
=
&
$lookup_rm_sec
(
$conf
,
$create
);
my
$vmref
;
foreach
my
$child
(
@
{
$rmsec
->
{
children
}})
{
if
(
$child
->
{
text
}
eq
'
pvevm
'
&&
$child
->
{
vmid
}
eq
$vmid
)
{
$vmref
=
$child
;
}
}
return
$vmref
if
!
$create
;
if
(
!
$vmref
)
{
$vmref
=
{
text
=>
'
pvevm
',
vmid
=>
$vmid
};
push
@
{
$rmsec
->
{
children
}},
$vmref
;
}
else
{
die
"
resource group 'pvevm:
$vmid
' already exists
\n
";
}
return
$vmref
;
};
__PACKAGE__
->
register_method
({
name
=>
'
list_groups
',
path
=>
'
groups
',
method
=>
'
GET
',
description
=>
"
List resource groups.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Audit
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{},
},
returns
=>
{
type
=>
'
array
',
items
=>
{
type
=>
"
object
",
properties
=>
{},
},
links
=>
[
{
rel
=>
'
child
',
href
=>
"
{id}
"
}
],
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$conf
=
&
$read_cluster_conf_new
();
my
$res
=
[]
;
my
$rmsec
=
&
$lookup_rm_sec
(
$conf
,
0
,
1
);
return
$res
if
!
$rmsec
;
foreach
my
$child
(
@
{
$rmsec
->
{
children
}})
{
if
(
$child
->
{
text
}
eq
'
pvevm
')
{
push
@$res
,
{
id
=>
"
$child
->{text}:
$child
->{vmid}
"
};
}
elsif
(
$child
->
{
text
}
eq
'
service
')
{
push
@$res
,
{
id
=>
"
$child
->{text}:
$child
->{name}
"
};
}
}
return
$res
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
create_group
',
path
=>
'
groups
',
method
=>
'
POST
',
description
=>
"
Create a new resource groups.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Modify
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{
vmid
=>
get_standard_option
('
pve-vmid
'),
autostart
=>
{
optional
=>
1
,
type
=>
'
boolean
',
description
=>
"
Service is started when a quorum forms.
",
}
},
},
returns
=>
{
type
=>
"
null
"
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$vmlist
=
PVE::Cluster::
get_vmlist
();
raise_param_exc
({
id
=>
"
no such vmid '
$param
->{vmid}'
"})
if
!
(
$vmlist
&&
$vmlist
->
{
ids
}
&&
$vmlist
->
{
ids
}
->
{
$param
->
{
vmid
}});
my
$code
=
sub
{
my
$conf
=
&
$read_cluster_conf_new
();
my
$pvevm
=
&
$lookup_pvevm
(
$conf
,
1
,
$param
->
{
vmid
});
$pvevm
->
{
autostart
}
=
$param
->
{
autostart
}
?
1
:
0
;
&
$update_cluster_conf_new
(
$conf
);
};
cfs_lock_file
('
cluster.conf
',
undef
,
$code
);
die
$@
if
$@
;
return
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
update_group
',
path
=>
'
groups/{id}
',
method
=>
'
PUT
',
description
=>
"
Update resource groups settings.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Modify
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{
id
=>
{
type
=>
'
string
',
description
=>
"
The resource group ID (for example 'pvevm:200').
",
},
autostart
=>
{
optional
=>
1
,
type
=>
'
boolean
',
description
=>
"
Service is started when a quorum forms.
",
}
},
},
returns
=>
{
type
=>
"
null
"
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$vmid
;
if
(
$param
->
{
id
}
=~
m/^pvevm:(\d+)$/
)
{
$vmid
=
int
(
$1
);
}
else
{
raise_param_exc
({
id
=>
"
unsupported group type '
$param
->{id}'
"});
}
my
$code
=
sub
{
my
$conf
=
&
$read_cluster_conf_new
();
my
$pvevm
=
&
$lookup_pvevm
(
$conf
,
0
,
$vmid
);
$pvevm
->
{
autostart
}
=
$param
->
{
autostart
}
?
1
:
0
;
&
$update_cluster_conf_new
(
$conf
);
};
cfs_lock_file
('
cluster.conf
',
undef
,
$code
);
die
$@
if
$@
;
return
;
}});
__PACKAGE__
->
register_method
({
name
=>
'
read_group
',
path
=>
'
groups/{id}
',
method
=>
'
GET
',
description
=>
"
List resource groups.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Audit
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{
id
=>
{
type
=>
'
string
',
description
=>
"
The resource group ID (for example 'pvevm:200').
",
}
},
},
returns
=>
{
type
=>
"
object
",
properties
=>
{},
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$conf
=
&
$read_cluster_conf_new
();
if
(
my
$rmsec
=
&
$lookup_rm_sec
(
$conf
,
0
,
1
))
{
foreach
my
$child
(
@
{
$rmsec
->
{
children
}})
{
if
(
$child
->
{
text
}
eq
'
pvevm
')
{
my
$id
=
"
$child
->{text}:
$child
->{vmid}
";
if
(
$id
eq
$param
->
{
id
})
{
$child
->
{
id
}
=
$id
;
return
$child
;
}
}
elsif
(
$child
->
{
text
}
eq
'
service
')
{
my
$id
=
"
$child
->{text}:
$child
->{name}
";
if
(
$id
eq
$param
->
{
id
})
{
$child
->
{
id
}
=
$id
;
return
$child
;
}
}
}
}
raise_param_exc
({
id
=>
"
no such group
"});
}});
__PACKAGE__
->
register_method
({
name
=>
'
delete_group
',
path
=>
'
groups/{id}
',
method
=>
'
DELETE
',
description
=>
"
Delete resource group.
",
protected
=>
1
,
permissions
=>
{
path
=>
'
/
',
privs
=>
[
'
Sys.Modify
'
],
},
parameters
=>
{
additionalProperties
=>
0
,
properties
=>
{
id
=>
{
type
=>
'
string
',
description
=>
"
The resource group ID (for example 'pvevm:200').
",
}
},
},
returns
=>
{
type
=>
"
null
"
},
code
=>
sub
{
my
(
$param
)
=
@_
;
my
$code
=
sub
{
my
$conf
=
&
$read_cluster_conf_new
();
my
$found
;
if
(
my
$rmsec
=
&
$lookup_rm_sec
(
$conf
,
0
,
1
))
{
my
$oldlist
=
$rmsec
->
{
children
};
$rmsec
->
{
children
}
=
[]
;
foreach
my
$child
(
@$oldlist
)
{
if
(
$child
->
{
text
}
eq
'
pvevm
')
{
if
("
$child
->{text}:
$child
->{vmid}
"
eq
$param
->
{
id
})
{
$found
=
1
;
next
;
}
}
elsif
(
$child
->
{
text
}
eq
'
service
')
{
if
("
$child
->{text}:
$child
->{name}
"
eq
$param
->
{
id
})
{
$found
=
1
;
next
;
}
}
push
@
{
$rmsec
->
{
children
}},
$child
;
}
}
raise_param_exc
({
id
=>
"
no such group
"})
if
!
$found
;
&
$update_cluster_conf_new
(
$conf
);
};
cfs_lock_file
('
cluster.conf
',
undef
,
$code
);
die
$@
if
$@
;
return
;
}});
1
;
PVE/API2/Makefile
View file @
b6c4b9ca
...
...
@@ -4,6 +4,7 @@ PERLSOURCE = \
VZDump.pm
\
Backup.pm
\
Cluster.pm
\
HAConfig.pm
\
Nodes.pm
\
Tasks.pm
\
Network.pm
\
...
...
www/manager/Makefile
View file @
b6c4b9ca
...
...
@@ -121,6 +121,7 @@ JSSRC= \
dc/AuthView.js
\
dc/AuthEdit.js
\
dc/Backup.js
\
dc/HAConfig.js
\
dc/Config.js
\
Workspace.js
...
...
www/manager/dc/Config.js
View file @
b6c4b9ca
...
...
@@ -48,6 +48,11 @@ Ext.define('PVE.dc.Config', {
xtype
:
'
pveAuthView
'
,
title
:
gettext
(
'
Authentication
'
),
itemId
:
'
domains
'
},
{
xtype
:
'
pveDcHAConfig
'
,
title
:
'
HA
'
,
itemId
:
'
ha
'
}
]
});
...
...
www/manager/dc/HAConfig.js
0 → 100644
View file @
b6c4b9ca
Ext
.
define
(
'
PVE.dc.vmHAServiceEdit
'
,
{
extend
:
'
PVE.window.Edit
'
,
initComponent
:
function
()
{
var
me
=
this
;
me
.
create
=
me
.
vmid
?
false
:
true
;
if
(
me
.
vmid
)
{
me
.
create
=
false
;
me
.
url
=
"
/cluster/ha/groups/pvevm:
"
+
me
.
vmid
;
me
.
method
=
'
PUT
'
;
}
else
{
me
.
create
=
true
;
me
.
url
=
"
/cluster/ha/groups
"
;
me
.
method
=
'
POST
'
;
}
Ext
.
apply
(
me
,
{
title
:
gettext
(
'
HA managed VM/CT
'
),
width
:
350
,
items
:
[
{
xtype
:
me
.
create
?
'
pveVMIDSelector
'
:
'
displayfield
'
,
name
:
'
vmid
'
,
validateExists
:
true
,
value
:
me
.
vmid
||
''
,
fieldLabel
:
"
VM ID
"
},
{
xtype
:
'
pvecheckbox
'
,
name
:
'
autostart
'
,
checked
:
true
,
fieldLabel
:
'
autostart
'
}
]
});
me
.
callParent
();
if
(
!
me
.
create
)
{
me
.
load
()
}
}
});
Ext
.
define
(
'
PVE.dc.HAConfig
'
,
{
extend
:
'
Ext.panel.Panel
'
,
alias
:
'
widget.pveDcHAConfig
'
,
clusterInfo
:
{},
// reload store data here
reload
:
function
()
{
var
me
=
this
;
var
getClusterInfo
=
function
(
conf
)
{
var
info
=
{};
if
(
!
(
conf
&&
conf
.
children
&&
conf
.
children
[
0
]))
{
return
info
;
}
var
cluster
=
conf
.
children
[
0
];
if
(
cluster
.
text
!==
'
cluster
'
||
!
cluster
.
config_version
)
{
return
info
;
}
info
.
version
=
cluster
.
config_version
;
Ext
.
Array
.
each
(
cluster
.
children
,
function
(
item
)
{
if
(
item
.
text
===
'
fencedevices
'
)
{
// fixme: make sure each node uses at least one fence device
info
.
fenceDevices
=
true
;
}
else
if
(
item
.
text
===
'
rm
'
)
{
info
.
ha
=
true
;
}
});
return
info
;
};
PVE
.
Utils
.
API2Request
({
url
:
'
/cluster/ha/config
'
,
waitMsgTarget
:
me
,
method
:
'
GET
'
,
failure
:
function
(
response
,
opts
)
{
me
.
clusterInfo
=
{};
me
.
setLoading
(
response
.
htmlStatus
);
},
success
:
function
(
response
,
opts
)
{
me
.
clusterInfo
=
getClusterInfo
(
response
.
result
.
data
);
console
.
dir
(
me
.
clusterInfo
);
me
.
setDisabled
(
!
me
.
clusterInfo
.
version
);
me
.
addMenu
.
setDisabled
(
!
me
.
clusterInfo
.
version
);
// note: this modifies response.result.data
me
.
treePanel
.
setRootNode
(
response
.
result
.
data
);
me
.
treePanel
.
expandAll
();
if
(
response
.
result
.
changes
)
{
me
.
commitBtn
.
setDisabled
(
false
);
me
.
revertBtn
.
setDisabled
(
false
);
me
.
diffPanel
.
setVisible
(
true
);
me
.
diffPanel
.
update
(
"
<pre>
"
+
Ext
.
htmlEncode
(
response
.
result
.
changes
)
+
"
</pre>
"
);
}
else
{
me
.
commitBtn
.
setDisabled
(
true
);
me
.
revertBtn
.
setDisabled
(
true
);
me
.
diffPanel
.
setVisible
(
false
);
me
.
diffPanel
.
update
(
''
);
}
}
});
},
initComponent
:
function
()
{
var
me
=
this
;
me
.
commitBtn
=
new
PVE
.
button
.
Button
({
text
:
gettext
(
'
Commit
'
),
disabled
:
true
,
confirmMsg
:
function
()
{
return
gettext
(
'
Are you sure you want to commit your changes
'
);
},
handler
:
function
(
btn
,
event
)
{
PVE
.
Utils
.
API2Request
({
url
:
'
/cluster/ha/changes
'
,
method
:
'
POST
'
,
waitMsgTarget
:
me
,
callback
:
function
()
{
me
.
reload
();
},
failure
:
function
(
response
,
opts
)
{
Ext
.
Msg
.
alert
(
gettext
(
'
Error
'
),
response
.
htmlStatus
);
}
});
}
});
me
.
revertBtn
=
new
PVE
.
button
.
Button
({
text
:
gettext
(
'
Revert changes
'
),
disabled
:
true
,
confirmMsg
:
function
()
{
return
gettext
(
'
Are you sure you want to revert (undo) your changes
'
);
},
handler
:
function
(
btn
,
event
)
{
PVE
.
Utils
.
API2Request
({
url
:
'
/cluster/ha/changes
'
,
method
:
'
DELETE
'
,
waitMsgTarget
:
me
,
callback
:
function
()
{
me
.
reload
();
},
failure
:
function
(
response
,
opts
)
{
Ext
.
Msg
.
alert
(
gettext
(
'
Error
'
),
response
.
htmlStatus
);
}
});
}
});
me
.
addMenu
=
new
Ext
.
button
.
Button
({
text
:
gettext
(
'
Add
'
),
disabled
:
true
,
menu
:
new
Ext
.
menu
.
Menu
({
items
:
[
{
text
:
gettext
(
'
HA managed VM/CT
'
),
handler
:
function
()
{
if
(
!
me
.
clusterInfo
.
fenceDevices
)
{
Ext
.
Msg
.
alert
(
gettext
(
'
Error
'
),
gettext
(
"
Please configure fencing first!
"
));
return
;
}
var
win
=
Ext
.
create
(
'
PVE.dc.vmHAServiceEdit
'
,
{});
win
.
show
();
win
.
on
(
'
destroy
'
,
me
.
reload
,
me
);
}
},
{
text
:
gettext
(
'
Failover Domain
'
),
handler
:
function
()
{
Ext
.
Msg
.
alert
(
gettext
(
'
Error
'
),
"
not implemented - sorry
"
);
}
}
]
})
});
me
.
treePanel
=
Ext
.
create
(
'
Ext.tree.Panel
'
,
{
rootVisible
:
false
,
animate
:
false
,
region
:
'
center
'
,
border
:
false
,
fields
:
[
'
text
'
,
'
id
'
,
'
vmid
'
,
'
name
'
],
columns
:
[
{
xtype
:
'
treecolumn
'
,
text
:
'
Tag
'
,
dataIndex
:
'
text
'
,
width
:
200
},
{
text
:
'
Attributes
'
,
dataIndex
:
'
id
'
,
renderer
:
function
(
value
,
metaData
,
record
)
{
var
text
=
''
;
Ext
.
Object
.
each
(
record
.
raw
,
function
(
key
,
value
)
{
if
(
key
===
'
id
'
||
key
===
'
text
'
)
{
return
;
}
text
+=
Ext
.
htmlEncode
(
key
)
+
'
="
'
+
Ext
.
htmlEncode
(
value
)
+
'
"
'
;
});
return
text
;
},
flex
:
1
}
]
});
var
run_editor
=
function
()
{
var
rec
=
me
.
treePanel
.
selModel
.
getSelection
()[
0
];
if
(
rec
&&
rec
.
data
.
text
===
'
pvevm
'
)
{
var
win
=
Ext
.
create
(
'
PVE.dc.vmHAServiceEdit
'
,
{
vmid
:
rec
.
data
.
vmid
});
win
.
show
();
win
.
on
(
'
destroy
'
,
me
.
reload
,
me
);
}
};
me
.
editBtn
=
new
Ext
.
button
.
Button
({
text
:
gettext
(
'
Edit
'
),
disabled
:
true
,
handler
:
run_editor
});
me
.
removeBtn
=
new
Ext
.
button
.
Button
({
text
:
gettext
(
'
Remove
'
),
disabled
:
true
,
handler
:
function
()
{
var
rec
=
me
.
treePanel
.
selModel
.
getSelection
()[
0
];
if
(
rec
&&
rec
.
data
.
text
===
'
pvevm
'
)
{
var
groupid
=
'
pvevm:
'
+
rec
.
data
.
vmid
;
PVE
.
Utils
.
API2Request
({
url
:
'
/cluster/ha/groups/
'
+
groupid
,
method
:
'
DELETE
'
,
waitMsgTarget
:
me
,
callback
:
function
()
{
me
.
reload
();
},
failure
:
function
(
response
,
opts
)
{
Ext
.
Msg
.
alert
(
gettext
(
'
Error
'
),
response
.
htmlStatus
);
}
});
}
}
});
me
.
diffPanel
=
Ext
.
create
(
'
Ext.panel.Panel
'
,
{
border
:
false
,
hidden
:
true
,
region
:
'
south
'
,
autoScroll
:
true
,
itemId
:
'
changes
'
,
tbar
:
[
gettext
(
'
Pending changes
'
)
],
split
:
true
,
bodyPadding
:
5
,
flex
:
0.6
});
Ext
.
apply
(
me
,
{
layout
:
'
border
'
,
tbar
:
[
me
.
addMenu
,
me
.
removeBtn
,
me
.
editBtn
,
me
.
revertBtn
,
me
.
commitBtn
],
items
:
[
me
.
treePanel
,
me
.
diffPanel
]
});
me
.
callParent
();
me
.
on
(
'
show
'
,
me
.
reload
);
me
.
treePanel
.
on
(
"
selectionchange
"
,
function
(
sm
,
selected
)
{
var
rec
=
selected
[
0
];
if
(
rec
&&
rec
.
data
.
text
===
'
pvevm
'
)
{
me
.
editBtn
.
setDisabled
(
false
);
me
.
removeBtn
.
setDisabled
(
false
);
}
else
{
me
.
editBtn
.
setDisabled
(
true
);
me
.
removeBtn
.
setDisabled
(
true
);
}
});
me
.
treePanel
.
on
(
"
itemdblclick
"
,
function
(
v
,
record
)
{
run_editor
()
});
}
});
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