2018-04-04 15:36:44 +03:00
Ext . define ( 'PVE.ClusterCreateWindow' , {
extend : 'Proxmox.window.Edit' ,
xtype : 'pveClusterCreateWindow' ,
title : gettext ( 'Create Cluster' ) ,
width : 600 ,
method : 'POST' ,
url : '/cluster/config' ,
isCreate : true ,
subject : gettext ( 'Cluster' ) ,
showTaskViewer : true ,
2019-07-11 21:12:00 +03:00
onlineHelp : 'pvecm_create_cluster' ,
2019-07-11 21:16:20 +03:00
items : {
xtype : 'inputpanel' ,
items : [ {
2018-04-04 15:36:44 +03:00
xtype : 'textfield' ,
fieldLabel : gettext ( 'Cluster Name' ) ,
allowBlank : false ,
2020-01-29 13:27:19 +03:00
maxLength : 15 ,
2021-01-19 19:31:03 +03:00
name : 'clustername' ,
2018-04-04 15:36:44 +03:00
} ,
{
2020-03-23 15:41:13 +03:00
xtype : 'fieldcontainer' ,
2020-05-05 19:23:01 +03:00
fieldLabel : gettext ( "Cluster Network" ) ,
2020-03-23 15:41:13 +03:00
items : [
{
xtype : 'pveCorosyncLinkEditor' ,
2020-05-05 19:23:01 +03:00
infoText : gettext ( "Multiple links are used as failover, lower numbers have higher priority." ) ,
2021-01-19 19:31:03 +03:00
name : 'links' ,
2020-03-23 15:41:13 +03:00
} ,
2021-01-19 19:31:03 +03:00
] ,
} ] ,
} ,
2018-04-04 15:36:44 +03:00
} ) ;
2018-04-04 15:36:45 +03:00
Ext . define ( 'PVE.ClusterInfoWindow' , {
extend : 'Ext.window.Window' ,
xtype : 'pveClusterInfoWindow' ,
mixins : [ 'Proxmox.Mixin.CBind' ] ,
width : 800 ,
modal : true ,
resizable : false ,
title : gettext ( 'Cluster Join Information' ) ,
joinInfo : {
ipAddress : undefined ,
fingerprint : undefined ,
2021-01-19 19:31:03 +03:00
totem : { } ,
2018-04-04 15:36:45 +03:00
} ,
items : [
{
xtype : 'component' ,
border : false ,
padding : '10 10 10 10' ,
2021-01-19 19:31:03 +03:00
html : gettext ( "Copy the Join Information here and use it on the node you want to add." ) ,
2018-04-04 15:36:45 +03:00
} ,
{
xtype : 'container' ,
layout : 'form' ,
border : false ,
padding : '0 10 10 10' ,
items : [
{
xtype : 'textfield' ,
fieldLabel : gettext ( 'IP Address' ) ,
2020-05-08 14:31:25 +03:00
cbind : {
value : '{joinInfo.ipAddress}' ,
} ,
editable : false ,
2018-04-04 15:36:45 +03:00
} ,
{
xtype : 'textfield' ,
fieldLabel : gettext ( 'Fingerprint' ) ,
2020-05-08 14:31:25 +03:00
cbind : {
value : '{joinInfo.fingerprint}' ,
} ,
editable : false ,
2018-04-04 15:36:45 +03:00
} ,
{
xtype : 'textarea' ,
inputId : 'pveSerializedClusterInfo' ,
fieldLabel : gettext ( 'Join Information' ) ,
grow : true ,
2020-05-08 14:31:25 +03:00
cbind : {
joinInfo : '{joinInfo}' ,
} ,
2018-04-04 15:36:45 +03:00
editable : false ,
listeners : {
afterrender : function ( field ) {
if ( ! field . joinInfo ) {
return ;
}
var jsons = Ext . JSON . encode ( field . joinInfo ) ;
var base64s = Ext . util . Base64 . encode ( jsons ) ;
field . setValue ( base64s ) ;
2021-01-19 19:31:03 +03:00
} ,
} ,
} ,
] ,
} ,
2018-04-04 15:36:45 +03:00
] ,
dockedItems : [ {
dock : 'bottom' ,
xtype : 'toolbar' ,
items : [ {
xtype : 'button' ,
handler : function ( b ) {
var el = document . getElementById ( 'pveSerializedClusterInfo' ) ;
el . select ( ) ;
document . execCommand ( "copy" ) ;
} ,
2021-01-19 19:31:03 +03:00
text : gettext ( 'Copy Information' ) ,
} ] ,
} ] ,
2018-04-04 15:36:45 +03:00
} ) ;
2018-04-04 15:36:46 +03:00
Ext . define ( 'PVE.ClusterJoinNodeWindow' , {
extend : 'Proxmox.window.Edit' ,
xtype : 'pveClusterJoinNodeWindow' ,
title : gettext ( 'Cluster Join' ) ,
width : 800 ,
method : 'POST' ,
url : '/cluster/config/join' ,
defaultFocus : 'textarea[name=serializedinfo]' ,
isCreate : true ,
2020-01-30 18:08:07 +03:00
bind : {
submitText : '{submittxt}' ,
} ,
2018-04-04 15:36:46 +03:00
showTaskViewer : true ,
2019-11-11 13:10:50 +03:00
onlineHelp : 'pvecm_join_node_to_cluster' ,
2018-04-04 15:36:46 +03:00
viewModel : {
parent : null ,
data : {
info : {
fp : '' ,
ip : '' ,
2021-01-19 19:31:03 +03:00
clusterName : '' ,
2020-05-08 14:33:06 +03:00
} ,
hasAssistedInfo : false ,
2018-11-27 17:22:24 +03:00
} ,
formulas : {
2020-01-30 18:08:07 +03:00
submittxt : function ( get ) {
let cn = get ( 'info.clusterName' ) ;
if ( cn ) {
2020-03-23 15:41:12 +03:00
return Ext . String . format ( gettext ( 'Join {0}' ) , ` ' ${ cn } ' ` ) ;
2020-01-30 18:08:07 +03:00
}
return gettext ( 'Join' ) ;
} ,
2020-05-08 14:33:06 +03:00
showClusterFields : ( get ) => {
let manualMode = ! get ( 'assistedEntry.checked' ) ;
return get ( 'hasAssistedInfo' ) || manualMode ;
} ,
2020-01-30 18:08:07 +03:00
} ,
2018-04-04 15:36:46 +03:00
} ,
controller : {
xclass : 'Ext.app.ViewController' ,
control : {
2018-04-04 15:36:47 +03:00
'#' : {
close : function ( ) {
delete PVE . Utils . silenceAuthFailures ;
2021-01-19 19:31:03 +03:00
} ,
2018-04-04 15:36:47 +03:00
} ,
2018-04-27 16:46:16 +03:00
'proxmoxcheckbox[name=assistedEntry]' : {
2021-01-19 19:31:03 +03:00
change : 'onInputTypeChange' ,
2018-04-04 15:36:46 +03:00
} ,
'textarea[name=serializedinfo]' : {
change : 'recomputeSerializedInfo' ,
2021-01-19 19:31:03 +03:00
enable : 'resetField' ,
2018-04-04 15:36:46 +03:00
} ,
'textfield' : {
2021-01-19 19:31:03 +03:00
disable : 'resetField' ,
} ,
2018-04-04 15:36:46 +03:00
} ,
resetField : function ( field ) {
field . reset ( ) ;
} ,
onInputTypeChange : function ( field , assistedInput ) {
2020-03-23 15:41:13 +03:00
let linkEditor = this . lookup ( 'linkEditor' ) ;
// this also clears all links
linkEditor . setAllowNumberEdit ( ! assistedInput ) ;
2018-04-04 15:36:46 +03:00
if ( ! assistedInput ) {
2020-03-23 15:41:13 +03:00
linkEditor . setInfoText ( ) ;
linkEditor . setDefaultLinks ( ) ;
2018-04-04 15:36:46 +03:00
}
} ,
recomputeSerializedInfo : function ( field , value ) {
2020-03-23 15:41:13 +03:00
let vm = this . getViewModel ( ) ;
let assistedEntryBox = this . lookup ( 'assistedEntry' ) ;
2020-05-08 13:30:37 +03:00
2020-03-23 15:41:13 +03:00
if ( ! assistedEntryBox . getValue ( ) ) {
// not in assisted entry mode, nothing to do
2020-05-08 14:33:06 +03:00
vm . set ( 'hasAssistedInfo' , false ) ;
2020-03-23 15:41:13 +03:00
return ;
}
let linkEditor = this . lookup ( 'linkEditor' ) ;
let jsons = Ext . util . Base64 . decode ( value ) ;
let joinInfo = Ext . JSON . decode ( jsons , true ) ;
2018-04-04 15:36:46 +03:00
2020-03-23 15:41:13 +03:00
let info = {
2018-04-04 15:36:46 +03:00
fp : '' ,
2020-01-29 13:27:20 +03:00
ip : '' ,
2021-01-19 19:31:03 +03:00
clusterName : '' ,
2018-04-04 15:36:46 +03:00
} ;
if ( ! ( joinInfo && joinInfo . totem ) ) {
field . valid = false ;
2020-03-23 15:41:13 +03:00
linkEditor . setLinks ( [ ] ) ;
linkEditor . setInfoText ( ) ;
2020-05-08 14:33:06 +03:00
vm . set ( 'hasAssistedInfo' , false ) ;
2018-04-04 15:36:46 +03:00
} else {
2020-03-23 15:41:13 +03:00
let interfaces = joinInfo . totem . interface ;
let links = Object . values ( interfaces ) . map ( iface => {
2020-03-23 15:41:14 +03:00
let linkNumber = iface . linknumber ;
let peerLink ;
if ( joinInfo . peerLinks ) {
peerLink = joinInfo . peerLinks [ linkNumber ] ;
}
2020-03-23 15:41:13 +03:00
return {
2020-03-23 15:41:14 +03:00
number : linkNumber ,
2020-03-23 15:41:13 +03:00
value : '' ,
2020-03-23 15:41:14 +03:00
text : peerLink ? Ext . String . format ( gettext ( "peer's link address: {0}" ) , peerLink ) : '' ,
2021-01-19 19:31:03 +03:00
allowBlank : false ,
2020-03-23 15:41:13 +03:00
} ;
} ) ;
linkEditor . setInfoText ( ) ;
2021-05-18 11:04:17 +03:00
if ( links . length === 1 && joinInfo . ring _addr !== undefined &&
joinInfo . ring _addr [ 0 ] === joinInfo . ipAddress
) {
2020-03-23 15:41:13 +03:00
links [ 0 ] . allowBlank = true ;
2020-05-05 19:21:44 +03:00
links [ 0 ] . emptyText = gettext ( "IP resolved by node's hostname" ) ;
2018-11-27 17:22:24 +03:00
}
2020-03-23 15:41:13 +03:00
linkEditor . setLinks ( links ) ;
2018-04-04 15:36:46 +03:00
info = {
ip : joinInfo . ipAddress ,
fp : joinInfo . fingerprint ,
2021-01-19 19:31:03 +03:00
clusterName : joinInfo . totem . cluster _name ,
2018-04-04 15:36:46 +03:00
} ;
field . valid = true ;
2020-05-08 14:33:06 +03:00
vm . set ( 'hasAssistedInfo' , true ) ;
2018-04-04 15:36:46 +03:00
}
vm . set ( 'info' , info ) ;
2021-01-19 19:31:03 +03:00
} ,
2018-04-04 15:36:46 +03:00
} ,
2018-04-04 15:36:47 +03:00
submit : function ( ) {
// joining may produce temporarily auth failures, ignore as long the task runs
PVE . Utils . silenceAuthFailures = true ;
this . callParent ( ) ;
} ,
2018-04-04 15:36:46 +03:00
taskDone : function ( success ) {
2018-04-04 15:36:47 +03:00
delete PVE . Utils . silenceAuthFailures ;
2018-04-04 15:36:46 +03:00
if ( success ) {
2020-03-26 17:20:54 +03:00
// reload always (if user wasn't faster), but wait a bit for pveproxy
Ext . defer ( function ( ) {
window . location . reload ( true ) ;
} , 5000 ) ;
2021-05-18 11:04:17 +03:00
let txt = gettext ( 'Cluster join task finished, node certificate may have changed, reload GUI!' ) ;
2018-04-04 15:36:46 +03:00
// ensure user cannot do harm
Ext . getBody ( ) . mask ( txt , [ 'pve-static-mask' ] ) ;
// TaskView may hide above mask, so tell him directly
Ext . Msg . show ( {
title : gettext ( 'Join Task Finished' ) ,
icon : Ext . Msg . INFO ,
2021-01-19 19:31:03 +03:00
msg : txt ,
2018-04-04 15:36:46 +03:00
} ) ;
}
} ,
items : [ {
xtype : 'proxmoxcheckbox' ,
reference : 'assistedEntry' ,
2018-04-27 16:46:16 +03:00
name : 'assistedEntry' ,
2020-03-23 15:41:13 +03:00
itemId : 'assistedEntry' ,
2018-04-04 15:36:46 +03:00
submitValue : false ,
value : true ,
autoEl : {
tag : 'div' ,
2021-01-19 19:31:03 +03:00
'data-qtip' : gettext ( 'Select if join information should be extracted from pasted cluster information, deselect for manual entering' ) ,
2018-04-04 15:36:46 +03:00
} ,
2021-01-19 19:31:03 +03:00
boxLabel : gettext ( 'Assisted join: Paste encoded cluster join information and enter password.' ) ,
2018-04-04 15:36:46 +03:00
} ,
{
xtype : 'textarea' ,
name : 'serializedinfo' ,
submitValue : false ,
allowBlank : false ,
fieldLabel : gettext ( 'Information' ) ,
emptyText : gettext ( 'Paste encoded Cluster Information here' ) ,
validator : function ( val ) {
2021-05-18 11:04:17 +03:00
return val === '' || this . valid || gettext ( 'Does not seem like a valid encoded Cluster Information!' ) ;
2018-04-04 15:36:46 +03:00
} ,
bind : {
disabled : '{!assistedEntry.checked}' ,
2021-01-19 19:31:03 +03:00
hidden : '{!assistedEntry.checked}' ,
2018-04-04 15:36:46 +03:00
} ,
2021-01-19 19:31:03 +03:00
value : '' ,
2018-04-04 15:36:46 +03:00
} ,
{
2020-03-23 15:41:13 +03:00
xtype : 'panel' ,
width : 776 ,
layout : {
type : 'hbox' ,
2021-01-19 19:31:03 +03:00
align : 'center' ,
2020-03-23 15:41:13 +03:00
} ,
2020-05-08 14:33:06 +03:00
bind : {
hidden : '{!showClusterFields}' ,
} ,
2020-03-23 15:41:13 +03:00
items : [
2018-04-04 15:36:46 +03:00
{
xtype : 'textfield' ,
2020-03-23 15:41:13 +03:00
flex : 1 ,
margin : '0 5px 0 0' ,
2018-04-04 15:36:46 +03:00
fieldLabel : gettext ( 'Peer Address' ) ,
allowBlank : false ,
bind : {
value : '{info.ip}' ,
2020-05-08 14:31:25 +03:00
readOnly : '{assistedEntry.checked}' ,
2018-04-04 15:36:46 +03:00
} ,
2021-01-19 19:31:03 +03:00
name : 'hostname' ,
2018-04-04 15:36:46 +03:00
} ,
{
xtype : 'textfield' ,
2020-03-23 15:41:13 +03:00
flex : 1 ,
margin : '0 0 10px 5px' ,
2018-04-04 15:36:46 +03:00
inputType : 'password' ,
emptyText : gettext ( "Peer's root password" ) ,
fieldLabel : gettext ( 'Password' ) ,
allowBlank : false ,
2021-01-19 19:31:03 +03:00
name : 'password' ,
2018-04-04 15:36:46 +03:00
} ,
2021-01-19 19:31:03 +03:00
] ,
2020-03-23 15:41:13 +03:00
} ,
{
xtype : 'textfield' ,
fieldLabel : gettext ( 'Fingerprint' ) ,
allowBlank : false ,
bind : {
value : '{info.fp}' ,
2020-05-08 14:33:06 +03:00
readOnly : '{assistedEntry.checked}' ,
hidden : '{!showClusterFields}' ,
2020-03-23 15:41:13 +03:00
} ,
2021-01-19 19:31:03 +03:00
name : 'fingerprint' ,
2020-03-23 15:41:13 +03:00
} ,
{
xtype : 'fieldcontainer' ,
2020-05-05 19:23:01 +03:00
fieldLabel : gettext ( "Cluster Network" ) ,
2020-05-08 13:30:37 +03:00
bind : {
2020-05-08 14:33:06 +03:00
hidden : '{!showClusterFields}' ,
2020-05-08 13:30:37 +03:00
} ,
2020-03-23 15:41:13 +03:00
items : [
2018-04-04 15:36:46 +03:00
{
2020-03-23 15:41:13 +03:00
xtype : 'pveCorosyncLinkEditor' ,
itemId : 'linkEditor' ,
reference : 'linkEditor' ,
2021-01-19 19:31:03 +03:00
allowNumberEdit : false ,
2020-03-23 15:41:13 +03:00
} ,
2021-01-19 19:31:03 +03:00
] ,
} ] ,
2018-04-04 15:36:46 +03:00
} ) ;