<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="Asciidoctor 2.0.18"> <meta name="author" content="Perforce Professional Services"> <title>SDP Windows to Linux Migration Guide</title> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> <style> /*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */ /* Uncomment the following line when using as a custom stylesheet */ /* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */ html{font-family:sans-serif;-webkit-text-size-adjust:100%} a{background:none} a:focus{outline:thin dotted} a:active,a:hover{outline:0} h1{font-size:2em;margin:.67em 0} b,strong{font-weight:bold} abbr{font-size:.9em} abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none} dfn{font-style:italic} hr{height:0} mark{background:#ff0;color:#000} code,kbd,pre,samp{font-family:monospace;font-size:1em} pre{white-space:pre-wrap} q{quotes:"\201C" "\201D" "\2018" "\2019"} small{font-size:80%} sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} sup{top:-.5em} sub{bottom:-.25em} img{border:0} svg:not(:root){overflow:hidden} figure{margin:0} audio,video{display:inline-block} audio:not([controls]){display:none;height:0} fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} legend{border:0;padding:0} button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} button,input{line-height:normal} button,select{text-transform:none} button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer} button[disabled],html input[disabled]{cursor:default} input[type=checkbox],input[type=radio]{padding:0} button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} textarea{overflow:auto;vertical-align:top} table{border-collapse:collapse;border-spacing:0} *,::before,::after{box-sizing:border-box} html,body{font-size:100%} body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} a:hover{cursor:pointer} img,object,embed{max-width:100%;height:auto} object,embed{height:100%} img{-ms-interpolation-mode:bicubic} .left{float:left!important} .right{float:right!important} .text-left{text-align:left!important} .text-right{text-align:right!important} .text-center{text-align:center!important} .text-justify{text-align:justify!important} .hide{display:none} img,object,svg{display:inline-block;vertical-align:middle} textarea{height:auto;min-height:50px} select{width:100%} .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0} a{color:#2156a5;text-decoration:underline;line-height:inherit} a:hover,a:focus{color:#1d4b8f} a img{border:0} p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} p aside{font-size:.875em;line-height:1.35;font-style:italic} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} h1{font-size:2.125em} h2{font-size:1.6875em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} h4,h5{font-size:1.125em} h6{font-size:1em} hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em} em,i{font-style:italic;line-height:inherit} strong,b{font-weight:bold;line-height:inherit} small{font-size:60%;line-height:inherit} code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} ul,ol{margin-left:1.5em} ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0} ul.circle{list-style-type:circle} ul.disc{list-style-type:disc} ul.square{list-style-type:square} ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit} ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} dl dt{margin-bottom:.3125em;font-weight:bold} dl dd{margin-bottom:1.25em} blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} @media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} h1{font-size:2.75em} h2{font-size:2.3125em} h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} h4{font-size:1.4375em}} table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal} table thead,table tfoot{background:#f7f8f7} table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} table tr.even,table tr.alt{background:#f8f8f7} table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6} h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} .center{margin-left:auto;margin-right:auto} .stretch{width:100%} .clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} .clearfix::after,.float-group::after{clear:both} :not(pre).nobreak{word-wrap:normal} :not(pre).nowrap{white-space:nowrap} :not(pre).pre-wrap{white-space:pre-wrap} :not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed} pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed} pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit} pre>code{display:block} pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal} em em{font-style:normal} strong strong{font-weight:400} .keyseq{color:rgba(51,51,51,.8)} kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} .keyseq kbd:first-child{margin-left:0} .keyseq kbd:last-child{margin-right:0} .menuseq,.menuref{color:#000} .menuseq b:not(.caret),.menuref{font-weight:inherit} .menuseq{word-spacing:-.02em} .menuseq b.caret{font-size:1.25em;line-height:.8} .menuseq i.caret{font-weight:bold;text-align:center;width:.45em} b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} b.button::before{content:"[";padding:0 3px 0 2px} b.button::after{content:"]";padding:0 2px 0 3px} p a>code:hover{color:rgba(0,0,0,.9)} #header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} #header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} #header::after,#content::after,#footnotes::after,#footer::after{clear:both} #content{margin-top:1.25em} #content::before{content:none} #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf} #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px} #header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap} #header .details span:first-child{margin-left:-.125em} #header .details span.email a{color:rgba(0,0,0,.85)} #header .details br{display:none} #header .details br+span::before{content:"\00a0\2013\00a0"} #header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} #header .details br+span#revremark::before{content:"\00a0|\00a0"} #header #revnumber{text-transform:capitalize} #header #revnumber::after{content:"\00a0"} #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} #toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em} #toc>ul{margin-left:.125em} #toc ul.sectlevel0>li>a{font-style:italic} #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} #toc li{line-height:1.3334;margin-top:.3334em} #toc a{text-decoration:none} #toc a:active{text-decoration:underline} #toctitle{color:#7a2518;font-size:1.2em} @media screen and (min-width:768px){#toctitle{font-size:1.375em} body.toc2{padding-left:15em;padding-right:0} #toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} #toc.toc2>ul{font-size:.9em;margin-bottom:0} #toc.toc2 ul ul{margin-left:0;padding-left:1em} #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} body.toc2.toc-right{padding-left:0;padding-right:15em} body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}} @media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} #toc.toc2{width:20em} #toc.toc2 #toctitle{font-size:1.375em} #toc.toc2>ul{font-size:.95em} #toc.toc2 ul ul{padding-left:1.25em} body.toc2.toc-right{padding-left:0;padding-right:20em}} #content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px} #content #toc>:first-child{margin-top:0} #content #toc>:last-child{margin-bottom:0} #footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em} #footer-text{color:hsla(0,0%,100%,.8);line-height:1.44} #content{margin-bottom:.625em} .sect1{padding-bottom:.625em} @media screen and (min-width:768px){#content{margin-bottom:1.25em} .sect1{padding-bottom:1.25em}} .sect1:last-child{padding-bottom:0} .sect1+.sect1{border-top:1px solid #e7e7e9} #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} #content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} details{margin-left:1.25rem} details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent} details>summary::-webkit-details-marker{display:none} details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)} details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)} details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem} .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} .paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} .admonitionblock>table td.icon{text-align:center;width:80px} .admonitionblock>table td.icon img{max-width:none} .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere} .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} .exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px} .exampleblock>.content>:first-child{margin-top:0} .exampleblock>.content>:last-child{margin-bottom:0} .sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px} .sidebarblock>:first-child{margin-top:0} .sidebarblock>:last-child{margin-bottom:0} .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} .literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em} @media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}} @media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}} .literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8} .literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)} .listingblock>.content{position:relative} .listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5} .listingblock:hover code[data-lang]::before{display:block} .listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5} .listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} .listingblock pre.highlightjs{padding:0} .listingblock pre.highlightjs>code{padding:1em;border-radius:4px} .listingblock pre.prettyprint{border-width:0} .prettyprint{background:#f7f7f8} pre.prettyprint .linenums{line-height:1.45;margin-left:2em} pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0} pre.prettyprint li code[data-lang]::before{opacity:1} pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none} table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none} table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal} table.linenotable td.code{padding-left:.75em} table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} pre.pygments span.linenos{display:inline-block;margin-right:.75em} .quoteblock{margin:0 1em 1.25em 1.5em;display:table} .quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em} .quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} .quoteblock blockquote{margin:0;padding:0;border:0} .quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} .quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right} .verseblock{margin:0 1em 1.25em} .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} .verseblock pre strong{font-weight:400} .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} .quoteblock .attribution br,.verseblock .attribution br{display:none} .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} .quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none} .quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0} .quoteblock.abstract{margin:0 1em 1.25em;display:block} .quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} .quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf} .quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0} .quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem} .quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0} p.tableblock:last-child{margin-bottom:0} td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere} td.tableblock>.content>:last-child{margin-bottom:-1.25em} table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} table.grid-all>*>tr>*{border-width:1px} table.grid-cols>*>tr>*{border-width:0 1px} table.grid-rows>*>tr>*{border-width:1px 0} table.frame-all{border-width:1px} table.frame-ends{border-width:1px 0} table.frame-sides{border-width:0 1px} table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0} table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0} table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0} table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0} table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7} th.halign-left,td.halign-left{text-align:left} th.halign-right,td.halign-right{text-align:right} th.halign-center,td.halign-center{text-align:center} th.valign-top,td.valign-top{vertical-align:top} th.valign-bottom,td.valign-bottom{vertical-align:bottom} th.valign-middle,td.valign-middle{vertical-align:middle} table thead th,table tfoot th{font-weight:bold} tbody tr th{background:#f7f8f7} tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} p.tableblock>code:only-child{background:none;padding:0} p.tableblock{font-size:1em} ol{margin-left:1.75em} ul li ol{margin-left:1.5em} dl dd{margin-left:1.125em} dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} ul.unstyled,ol.unstyled{margin-left:0} li>p:empty:only-child::before{content:"";display:inline-block} ul.checklist>li>p:first-child{margin-left:-1em} ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em} ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} ul.inline>li{margin-left:1.25em} .unstyled dl dt{font-weight:400;font-style:normal} ol.arabic{list-style-type:decimal} ol.decimal{list-style-type:decimal-leading-zero} ol.loweralpha{list-style-type:lower-alpha} ol.upperalpha{list-style-type:upper-alpha} ol.lowerroman{list-style-type:lower-roman} ol.upperroman{list-style-type:upper-roman} ol.lowergreek{list-style-type:lower-greek} .hdlist>table,.colist>table{border:0;background:none} .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} td.hdlist1{font-weight:bold;padding-bottom:1.25em} td.hdlist2{word-wrap:anywhere} .literalblock+.colist,.listingblock+.colist{margin-top:-.5em} .colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} .colist td:not([class]):first-child img{max-width:none} .colist td:not([class]):last-child{padding:.25em 0} .thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd} .imageblock.left{margin:.25em .625em 1.25em 0} .imageblock.right{margin:.25em 0 1.25em .625em} .imageblock>.title{margin-bottom:0} .imageblock.thumb,.imageblock.th{border-width:6px} .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} .image.left{margin-right:.625em} .image.right{margin-left:.625em} a.image{text-decoration:none;display:inline-block} a.image object{pointer-events:none} sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} sup.footnote a,sup.footnoteref a{text-decoration:none} sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} #footnotes .footnote:last-of-type{margin-bottom:0} #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} div.unbreakable{page-break-inside:avoid} .big{font-size:larger} .small{font-size:smaller} .underline{text-decoration:underline} .overline{text-decoration:overline} .line-through{text-decoration:line-through} .aqua{color:#00bfbf} .aqua-background{background:#00fafa} .black{color:#000} .black-background{background:#000} .blue{color:#0000bf} .blue-background{background:#0000fa} .fuchsia{color:#bf00bf} .fuchsia-background{background:#fa00fa} .gray{color:#606060} .gray-background{background:#7d7d7d} .green{color:#006000} .green-background{background:#007d00} .lime{color:#00bf00} .lime-background{background:#00fa00} .maroon{color:#600000} .maroon-background{background:#7d0000} .navy{color:#000060} .navy-background{background:#00007d} .olive{color:#606000} .olive-background{background:#7d7d00} .purple{color:#600060} .purple-background{background:#7d007d} .red{color:#bf0000} .red-background{background:#fa0000} .silver{color:#909090} .silver-background{background:#bcbcbc} .teal{color:#006060} .teal-background{background:#007d7d} .white{color:#bfbfbf} .white-background{background:#fafafa} .yellow{color:#bfbf00} .yellow-background{background:#fafa00} span.icon>.fa{cursor:default} a span.icon>.fa{cursor:inherit} .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} .admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} .admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} .admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} .admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} .admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} .conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} .conum[data-value] *{color:#fff!important} .conum[data-value]+b{display:none} .conum[data-value]::after{content:attr(data-value)} pre .conum[data-value]{position:relative;top:-.125em} b.conum *{color:inherit!important} .conum:not([data-value]):empty{display:none} dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em} p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem} p{margin-bottom:1.25rem} .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} .exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc} .print-only{display:none!important} @page{margin:1.25cm .75cm} @media print{*{box-shadow:none!important;text-shadow:none!important} html{font-size:80%} a{color:inherit!important;text-decoration:underline!important} a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} abbr[title]{border-bottom:1px dotted} abbr[title]::after{content:" (" attr(title) ")"} pre,blockquote,tr,img,object,svg{page-break-inside:avoid} thead{display:table-header-group} svg{max-width:100%} p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} #header,#content,#footnotes,#footer{max-width:none} #toc,.sidebarblock,.exampleblock>.content{background:none!important} #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important} body.book #header{text-align:center} body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} body.book #header .details{border:0!important;display:block;padding:0!important} body.book #header .details span:first-child{margin-left:0!important} body.book #header .details br{display:block} body.book #header .details br+span::before{content:none!important} body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} .listingblock code[data-lang]::before{display:block} #footer{padding:0 .9375em} .hide-on-print{display:none!important} .print-only{display:block!important} .hide-for-print{display:none!important} .show-for-print{display:inherit!important}} @media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem} .sect1{padding:0!important} .sect1+.sect1{border:0} #footer{background:none} #footer-text{color:rgba(0,0,0,.6);font-size:.9em}} @media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> </head> <body class="book"> <div id="header"> <h1>SDP Windows to Linux Migration Guide</h1> <div class="details"> <span id="author" class="author">Perforce Professional Services</span><br> <span id="email" class="email"><a href="mailto:consulting@perforce.com">consulting@perforce.com</a></span><br> <span id="revnumber">version v2023.2,</span> <span id="revdate">2024-03-25</span> </div> <div id="toc" class="toc"> <div id="toctitle">Table of Contents</div> <ul class="sectlevel1"> <li><a href="#_draft_notice">DRAFT NOTICE</a></li> <li><a href="#_preface">Preface</a></li> <li><a href="#_overview">1. Overview</a></li> <li><a href="#_migration_planning">2. Migration Planning</a> <ul class="sectlevel2"> <li><a href="#_planning_for_user_impact">2.1. Planning for User Impact</a></li> <li><a href="#_failover_migration">2.2. Failover Migration</a></li> <li><a href="#_custom_triggers_and_extensions">2.3. Custom Triggers and Extensions</a></li> <li><a href="#_other_custom_automation_on_windows_server_machine">2.4. Other Custom Automation on Windows Server Machine</a></li> <li><a href="#_find_incompatible_configuration_settings">2.5. Find Incompatible Configuration Settings</a> <ul class="sectlevel3"> <li><a href="#_sample_procedure_to_replace_p4log_configurable">2.5.1. Sample Procedure to replace P4LOG configurable</a></li> <li><a href="#_other_windows_paths_in_configuration">2.5.2. Other Windows Paths in Configuration</a></li> </ul> </li> <li><a href="#_depot_root_and_depot_spec_map_fields">2.6. Depot Root and Depot Spec Map Fields</a></li> <li><a href="#_the_journalprefix">2.7. The journalPrefix</a></li> <li><a href="#_uncompressed_journals">2.8. Uncompressed Journals</a></li> <li><a href="#_helix_core_components">2.9. Helix Core Components</a></li> <li><a href="#_helix_core_topology">2.10. Helix Core Topology</a></li> <li><a href="#_moving_archive_files">2.11. Moving Archive Files</a></li> <li><a href="#_avoid_case_conversion">2.12. Avoid Case Conversion</a></li> <li><a href="#_combining_upgrade_with_migration">2.13. Combining Upgrade with Migration</a></li> <li><a href="#_dry_run">2.14. DRY RUN</a></li> <li><a href="#_setup_linux_replica_serverid">2.15. Setup Linux Replica ServerID</a></li> </ul> </li> <li><a href="#_migration_preparation">3. Migration Preparation</a> <ul class="sectlevel2"> <li><a href="#_provision_new_linux_server_machines">3.1. Provision New Linux Server Machines</a> <ul class="sectlevel3"> <li><a href="#_select_operating_system">3.1.1. Select Operating System</a></li> </ul> </li> </ul> </li> <li><a href="#_install_perforce_helix_on_linux">4. Install Perforce Helix on Linux</a> <ul class="sectlevel2"> <li><a href="#_install_helix_core_software">4.1. Install Helix Core Software</a></li> <li><a href="#_create_the_linux_replica">4.2. Create the Linux replica.</a></li> </ul> </li> <li><a href="#_sample_cutover_procedure">Appendix A: Sample Cutover Procedure</a> <ul class="sectlevel2"> <li><a href="#_sample_migration_scenarion">A.1. Sample Migration Scenarion</a></li> <li><a href="#_one_week_prior_to_cutover_procedure">A.2. One Week Prior to Cutover Procedure</a></li> <li><a href="#_one_day_prior_to_cutover_procedure">A.3. One Day Prior to Cutover Procedure</a></li> <li><a href="#_cutover_procedure">A.4. Cutover Procedure</a></li> </ul> </li> <li><a href="#_why_migrate">Appendix B: Why Migrate?</a></li> <li><a href="#_draft_notice_2">5. DRAFT NOTICE</a></li> </ul> </div> </div> <div id="content"> <div class="sect1"> <h2 id="_draft_notice">DRAFT NOTICE</h2> <div class="sectionbody"> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <i class="fa icon-warning" title="Warning"></i> </td> <td class="content"> This document is in DRAFT status and should not be relied on yet. It is a preview of a document to be completed in a future release. </td> </tr> </table> </div> </div> </div> <div class="sect1"> <h2 id="_preface">Preface</h2> <div class="sectionbody"> <div class="paragraph"> <p>This guide documents the process for migrating a Helix Core (P4D) service from a Windows server machine to Linux. A migration can be minimally disruptive to users if planned and executed properly. This document informs the planning and execution of a Windows to Linux migration.</p> </div> <div class="paragraph"> <p>Because P4D on Linux can run in the same case-insensitive mode that is familiar to users operating on P4D on Windows, the migration can be nearly seamless to users. After preparations,tthe eventual cutover is done with a <code>p4 failover</code> operation in a scheduled maintenance window (or a series of failovers if edge servers are involved). A failover smoothly transitions the P4D service from one machine to another, with no loss of data and minimal disruption.</p> </div> <div class="paragraph"> <p>The preparation effort typically involves straightforward (though potentially long-running) tasks for the administrator. If the Windows P4D runs with custom triggers, there will be some degree of compleixty depending on how custom triggers are handled. Typical options include porting or ditching (temporarily or permanently) the custom triggers. If any additional custom automation operates on the Windows P4D server directly, similar handling may be required.</p> </div> <div class="paragraph"> <p>Regardless of the effort and potential complexity handling customization for admins, the migration can culminate in a nearly seamless transition for users.</p> </div> <div class="paragraph"> <p><strong>Please Give Us Feedback</strong></p> </div> <div class="paragraph"> <p>Perforce welcomes feedback from our users. Please send any suggestions for improving this document to <a href="mailto:consulting@perforce.com">consulting@perforce.com</a>.</p> </div> </div> </div> <div class="sect1"> <h2 id="_overview">1. Overview</h2> <div class="sectionbody"> <div class="paragraph"> <p>A Windows to Linux Migration has these elements:</p> </div> <div class="ulist"> <ul> <li> <p>Planning</p> </li> <li> <p>Provision New Linux Server machines.</p> </li> <li> <p>Install Perforce Helix on Linux.</p> </li> <li> <p>Setup Linux Replica server spec on Windows.</p> </li> <li> <p>Pull and verify archives. This may take a long while if there is a lot of data to pull, potentially requiring multiple iterations of the pull/verify process.</p> </li> <li> <p>Do a Dry Run of the cutover.</p> </li> <li> <p>Port and/or Test Triggers</p> </li> <li> <p>Test, Test, Test.</p> </li> <li> <p>Correct data issues identified in planning.</p> </li> <li> <p>Adjust configurables.</p> </li> <li> <p>Craft a Cutover Procedure.</p> </li> <li> <p>Execute the Cutover Procedure.</p> </li> </ul> </div> <div class="paragraph"> <p>For purposes of this document, it does not matter if the servers are on-premises ("on-prem") or in a private or public cloud environment such as AWS, Azure, or GCP.</p> </div> <div class="paragraph"> <p>Each of these components is covered in detail in this guide.</p> </div> </div> </div> <div class="sect1"> <h2 id="_migration_planning">2. Migration Planning</h2> <div class="sectionbody"> <div class="paragraph"> <p>This section covers things to be aware of when planning.</p> </div> <div class="paragraph"> <p>First, it is helpful to review the related document <a href="https://swarm.workshop.perforce.com/view/guest/perforce_software/sdp/main/doc/SDP_MigrationAndUpgradeGuide.html">SDP Migration and Upgrade Guide</a>. This document discusses a Big Blue Green Cutover (BBGC) style of migration. For a Windows to Linux migration, use a special type of BBGC called a Failover Migration: After preparations are complete, a <code>p4 failover</code> completes the migration to Linux (or a series of failovers if edge servers are involved).</p> </div> <div class="paragraph"> <p>The Windows service may or may not be operated using <a href="https://swarm.workshop.perforce.com/view/guest/perforce_software/sdp/main/doc/SDP_Guide.Windows.html">Server Deployment Package (SDP) for Windows</a>. Regardless of whether the Windows service is managed with SDP, the Windows service is largely left alone during the migration. The target environment will always be setup per best practices as implemented with the <a href="https://swarm.workshop.perforce.com/view/guest/perforce_software/sdp/main/doc/SDP_Guide.Unix.html">Linux Server Deployment Package (SDP)</a>.</p> </div> <div class="sect2"> <h3 id="_planning_for_user_impact">2.1. Planning for User Impact</h3> <div class="paragraph"> <p>The migration can be nearly seamless. Typical impacts to users (humans and automation/bots) for a Windows to Linux migration include:</p> </div> <div class="ulist"> <ul> <li> <p>Possibly needing to login again after the Linux server becomes the commit (depending on whether certain configurables like <code>auth.id</code> are adjusted during migration).</p> </li> <li> <p>If SSL is enabled, needing to trust the Linux server after it becomes the commit.</p> </li> <li> <p>Depending on how user traffic is directed to the Windows server, there may be an impact:</p> <div class="ulist"> <ul> <li> <p>If users connect using a P4PORT that includes an an IP address, users will need to change the P4PORT they use.</p> </li> <li> <p>If the failover plan involves changing a DNS name (as opposed to some instantansous method of traffic redirection), there will be delays associated with DNS changes and DNS cache flushing.</p> </li> </ul> </div> </li> <li> <p>If the migration is planned to include a change in authentication mechanism, e.g. standard LDAP → SAML/SSO with the <a href="https://github.com/perforce/helix-authentication-service">Helix Authentication Service (HAS)</a>, users will need to adapt to this.</p> </li> </ul> </div> <div class="paragraph"> <p>Other than being aware of the above, users to not need to do any special preparation for the cutover. For example, users <em>do not</em> need to be concerned about the state of files in their workspaces. Whatever state files in workspaces are in at the time of cutover — checked out to default or numbered pending changelists, shelved or not, etc. — is not affected by the cutover.</p> </div> </div> <div class="sect2"> <h3 id="_failover_migration">2.2. Failover Migration</h3> <div class="paragraph"> <p>This document focuses on the failover style strategy. This entails creating a server spec (ServerID) for a standby server we’ll call <code>p4d_fs_linux</code>, that will operate for a time as a Linux standby replica of the current production Windows commit server. Depending on various factors such as data scale, project priority and complexity, etc. this Linux replica of the Windows commit server may operate for days, weeks or even months before it is ready for the planned and scheduled failover that will promote the Linux standby server to become the new commit server.</p> </div> <div class="paragraph"> <p>This Failover strategy has several benefits:</p> </div> <div class="ulist"> <ul> <li> <p>Minimum disruption to end users for the cutover.</p> </li> <li> <p>Allows for extensive testing of the new Linux server(s) and infrastructure prior to cutover.</p> </li> <li> <p>The effect on the original Windows server(s) and infrastructure is minimal.</p> </li> <li> <p>Rollback, while hopefully unnecessary, is straightforward.</p> </li> </ul> </div> <div class="paragraph"> <p>While planning and preparation will take time and effort, the disruption to end users can be minimal.</p> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> <td class="content"> If your current method of operating Helix Core on Windows does not produce a regular metadata <strong>checkpoint</strong>, a change is required to get at least some basic form of checkpoint process in place. (If you are not sure what a checkpoint is, see: <a href="https://www.perforce.com/manuals/p4sag/Content/P4SAG/backup-recovery-concepts.html">backup and recovery concepts</a>.) </td> </tr> </table> </div> <div class="paragraph"> <p>The Failover strategy requires that the Windows Helix Core P4D service be at version 2019.1 (latest patch) or later. If it is not already at the latest patch available of 2019.1 or a later major version, than the plan should account for first upgrading the Windows service in place to a more recent version, such as 2023.1.</p> </div> <div class="paragraph"> <p>Other strategies could be considered that would not require upgrading in place if avoiding an in-place upgrade is a priority. That would entail longer downtime and other complexity. Such options are not explored in this document.</p> </div> </div> <div class="sect2"> <h3 id="_custom_triggers_and_extensions">2.3. Custom Triggers and Extensions</h3> <div class="paragraph"> <p>The largest single variable in terms of effort estimation in planning for a Windows to Linux migration is the effort required to port any custom <a href="https://EDITME_TRIGGERS_DOC_URL">triggers</a> or <a href="https://EDITME_EXTENSIONS_DOC_URL">extensions</a>. This can be literally zero effort if you have no custom triggers or extensions (or none that need to survive the migration). If porting and/or testing is required, that becomes a software development and testing project on its own that folkds into the larger migration project.</p> </div> <div class="paragraph"> <p>Any custom Triggers or Extensions will need to be reviewed. Any that can’t be discarded will need to evaluated for porting and testing needs.</p> </div> <div class="paragraph"> <p>Triggers written in a native Windows langage such as batch or PowerShell, or operated as compiled .exe files, will need to be ported. Even triggers written in more portably languages such as Python or Perl will need testing and may need adjustment to operate in the Linux environment.</p> </div> <div class="paragraph"> <p>Extensions are written in Lua, the interpreter for which is entirely containdd in the Helix Core p4d binary itself. As such, custom extensions are less likely to require porting. However, they should still be evaluated and/or tested to be sure they have no Windows OS depenencies in their implementation.</p> </div> <div class="paragraph"> <p>Extensions provided by Perforce Software, such as those assoicated with Helix Swarm and the Helix Authentication Service, are inherently cross-platform and do not need to be ported.</p> </div> </div> <div class="sect2"> <h3 id="_other_custom_automation_on_windows_server_machine">2.4. Other Custom Automation on Windows Server Machine</h3> <div class="paragraph"> <p>Determine whether you have any custom softawre that runs directly on the Windows server machine. Custom automation that executes directly on the Windows server machine itself needs to be evaluated for porting and testing needs.</p> </div> <div class="paragraph"> <p>Because the migration is transparent, any automation that merely connects as a client to the Windows p4d server, such as build server farms, need not be considered (other than possibly needing to login or trust p4d again and/or possibly change the P4PORT, as noted in <a href="#_planning_for_user_impact">Section 2.1, “Planning for User Impact”</a>).</p> </div> </div> <div class="sect2"> <h3 id="_find_incompatible_configuration_settings">2.5. Find Incompatible Configuration Settings</h3> <div class="paragraph"> <p>Using the <code>p4 configure</code> command to interact with <code>db.config</code> is a good way, and in many cases the only way, to set various configuration items with a Helix Core server. However, there are certain settings that must not be defined with <code>p4 configure</code>, as they conflict with settings the SDP defines with shell environment variables on Linux.</p> </div> <div class="paragraph"> <p>Review the output of the command <code>p4 configure show allservers</code> and see if any of the following are set:</p> </div> <div class="ulist"> <ul> <li> <p><code>P4JOURNAL</code></p> </li> <li> <p><code>P4PORT</code></p> </li> <li> <p><code>P4LOG</code></p> </li> </ul> </div> <div class="paragraph"> <p>If any of these are set with <code>p4 configure</code>, the migration plan will need to deal with unsetting them after first ensuring they are set in some other way on the Windows service. Following is an example of how to replace how P4LOG is set displays in the output of <code>p4 configure show all servers</code>. Note that changing this requires a brief service restart to take effect.</p> </div> <div class="sect3"> <h4 id="_sample_procedure_to_replace_p4log_configurable">2.5.1. Sample Procedure to replace P4LOG configurable</h4> <div class="paragraph"> <p>This is an example of how this might be done if the Windows service name is <code>Perforce</code>:</p> </div> <div class="literalblock"> <div class="content"> <pre>p4 set -S Perforce P4LOG=L:\p4logs\p4d.log</pre> </div> </div> <div class="paragraph"> <p>That will set the P4LOG variable so that it is associated with the Windows service named <code>Perforce</code>. Once that is done, it can be unset as a configurable, such as in this example:</p> </div> <div class="literalblock"> <div class="content"> <pre>p4d.exe -r E:\PerforceRoot "-cunset P4LOG"</pre> </div> </div> <div class="paragraph"> <p>Next, stop and then start the Windows service as you normally would.</p> </div> </div> <div class="sect3"> <h4 id="_other_windows_paths_in_configuration">2.5.2. Other Windows Paths in Configuration</h4> <div class="paragraph"> <p>Also scan for things like Windows paths, such as Structured Logs defined to reference a Windows path. Such things will need to be be overridden in the server spec for the Linux replica. For example, if you see:</p> </div> <div class="literalblock"> <div class="content"> <pre>any: serverlog.file.11=E:\PerforceRoot\triggers.csv</pre> </div> </div> <div class="paragraph"> <p>You’ll want to create an override for the Linux replica by doing:</p> </div> <div class="literalblock"> <div class="content"> <pre>p4 configure set p4d_fs_linux#serverlog.file.11=/p4/1/logs/triggers.csv</pre> </div> </div> </div> </div> <div class="sect2"> <h3 id="_depot_root_and_depot_spec_map_fields">2.6. Depot Root and Depot Spec Map Fields</h3> <div class="paragraph"> <p>Perforce Helix depot specs have a field named <code>Map:</code> that, if used, must be eliminated prior to the deployment of a Linux replica. Further, the <code>server.depot.root</code> configurable must be set on the commit server.</p> </div> <div class="paragraph"> <p>If done carefully, the changes to set <code>server.depot.root</code> and clear the <code>Map:</code> field of each depot spec can be done non-disruptively on the live running Windows Perforce Helix Core service, and must be done before creating the checkpoint used to seed the Linux replica.</p> </div> <div class="paragraph"> <p>The key to making the change non-disruptively is to understand that the p4d server will use the <code>Map:</code> field value to see if it is set to anything other than the default, and otherwise will fall back to the <code>server.depot.root</code> configurable to find depots. If the value of the <code>Map:</code> field of any given depot is <code><em>TheDepotName</em>/…​</code>, that means the value is not explicitly set.</p> </div> <div class="paragraph"> <p>Before making changes, the singular <code>server.depot.root</code> value must be made to work for all depots. A common goal early on is to make the single <code>server.depot.root</code> path work without actually moving any files, but by using Windows directory symlinks. If individual depots are on different drives, put symlinks to all depots in the directory pointed to by the <code>server.depot.root</code> configurable so that p4d can find all depot files from that path. You may also find the Map fields use Windows UNC paths or if Windows junctions.</p> </div> <div class="paragraph"> <p>Special planning may be required if there are any depots of type <code>archive</code>.</p> </div> </div> <div class="sect2"> <h3 id="_the_journalprefix">2.7. The journalPrefix</h3> <div class="paragraph"> <p>The Windows commit server must have the <code>journalPrefix</code> value be set in order to set up the Linux replica. It can be set to any value that works to enable the p4d service to find its archives, but cannot be unset.</p> </div> </div> <div class="sect2"> <h3 id="_uncompressed_journals">2.8. Uncompressed Journals</h3> <div class="paragraph"> <p>Examine how checkpoints and journals are currently taken on the Windows environment (or of they are taken at all).</p> </div> <div class="paragraph"> <p>If journals on the Windows service are compressed, replication will not work. Replicas require uncompressed journals.</p> </div> <div class="paragraph"> <p>As a general rule, the <code>p4d -jc</code> command is best done with <code>-Z</code>, which compresses the checkpoint file, but not the numbered journal files. Changes to any custom scripts that manage checkpoints in the Windows environment may be warranted.</p> </div> </div> <div class="sect2"> <h3 id="_helix_core_components">2.9. Helix Core Components</h3> <div class="paragraph"> <p>Consider what Perforce Helix systems are in your environment that may need to be handled, such as:</p> </div> <div class="ulist"> <ul> <li> <p>Helix Core Server (P4D)</p> <div class="ulist"> <ul> <li> <p>Commit Server</p> </li> <li> <p>Edge Servers</p> </li> <li> <p>Filtered Replicas</p> </li> <li> <p>Unfiltered Replicas</p> </li> <li> <p>Standby Servers</p> </li> </ul> </div> </li> <li> <p>Helix Broker (P4Broker)</p> </li> <li> <p>Helix Proxy (P4P)</p> </li> <li> <p>Helix Swarm</p> </li> <li> <p>P4DTG</p> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_helix_core_topology">2.10. Helix Core Topology</h3> <div class="paragraph"> <p>Is your server a single machine, or are there many server machines? In any case, you’ll want to think in terms of a "Big Blue/Green Deploy." Every active Windows server machine in the current production topology (the "Blue" servers), including all replicas, edges, and proxies, will all need equivalent Linux server machines to replace them (the "Green" servers). Replicas are straightforward to handle. Handling edges is more complex but doable. Don’t forget proxies — they need to do the Windows → Linux thing too. (Proxies could have been Linux all along even with a Windows P4D, but don’t forget to check that).</p> </div> </div> <div class="sect2"> <h3 id="_moving_archive_files">2.11. Moving Archive Files</h3> <div class="paragraph"> <p>Once the Linux replicas are setup, a variety of strategies can be used to transfer archive files.</p> </div> <div class="paragraph"> <p>Plan 3 cycles of <code>p4verify.sh</code>, to get p4d to pull the archives. The first, starting with no archive files, is to start a bulk pull. That could take days or weeks depending on data scale. The second to fill in gaps, and the 3rd should be clean.</p> </div> <div class="paragraph"> <p>Depending on scale of data, you may want to consider using outside-p4d mechanisms for transferring some archives (especially the <code>.gz</code> files, <code>,v</code> files should be transferred with <code>p4 pull</code> ideally).</p> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> <td class="content"> Lots of variations on how to get the archives files there. Using <code>p4 pull</code> has an advantage better that, if the Linux p4d writes the archive, it can always find it, even it it’s funky with Unicode cruft in the path. By contrast, files copied outside p4d may not be found by the Linux p4d. However, for bulk pulls of Terabytes of data, a Windows port of rsync, at least for <code>.gz</code> files, will be much faster. You’ll need a live running rsync service on Linux for the Windows port of rsync to talk to. There are many options here; somehow or other get the files in place so p4verify.sh is happy. </td> </tr> </table> </div> </div> <div class="sect2"> <h3 id="_avoid_case_conversion">2.12. Avoid Case Conversion</h3> <div class="paragraph"> <p>If there is a desire to convert the case to become case-sensitive, that should be deferred and done as a separate project. A Windows to Linux migration that preserves the original Windows case-insensitive behavior is minimally disruptive. A case conversion is likely to be disruptive to users and workflows, and is complex enough that it should be relegated to a separate project from a Windows to Linux migration. The case conversion should be done after the Windows to Linux migration is complete.</p> </div> </div> <div class="sect2"> <h3 id="_combining_upgrade_with_migration">2.13. Combining Upgrade with Migration</h3> <div class="paragraph"> <p>If the priority is to avoid upgrading or touching the Windows environment, an upgrade to a modern Helix Core version can be done to the Linux server during the cutover, as part of the Windows to Linux migration project.</p> </div> <div class="paragraph"> <p>Alternately, you can upgrade the Windows P4D in place first, and then set up the Linux replica on the same modern P4D version. If the starting Windows version is 2019.1+, a Failover style migration is possible; otherwise a different strategy is needed.</p> </div> <div class="paragraph"> <p>Typically we recommend doing the failover-then-upgrade in the same maintenance window as the Windows to Linux migration. That is, failover to the new server on Linux on the same p4d version as Windows was initially. Then once on Linux, do the standard SDP upgrade procedure for Linux, using <code>upgrade.sh</code>.</p> </div> </div> <div class="sect2"> <h3 id="_dry_run">2.14. DRY RUN</h3> <div class="paragraph"> <p>At least one Dry Run is required to confidently execute a migration. Plan to have at least one.</p> </div> <div class="paragraph"> <p>In the dry run, the <code>p4 failover</code> command is NOT used. Instead, the Linux service is stopped, and the <code>$P4ROOT/server.id</code> file is simply hand-edited to be the ServerId the the commit server. Then the service is restarted.</p> </div> <div class="paragraph"> <p>At that point, the Linux commit server will believe itself to be the new commit server, even though users will still be using the Windows server for real work. Then the Linux server can be tested in various ways:</p> </div> <div class="ulist"> <ul> <li> <p>Test connectivity from all user access points.</p> </li> <li> <p>Test connectivity from all server access points, including replicas, proxies, and any integrated systems such as Jenkins, Swarm, P4DTG, etc.</p> </li> <li> <p>If there are any <code>ldap</code> specs, ensure the targeted LDAP servers can be reached from the Linux server. (This may require firewall adjustments).</p> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_setup_linux_replica_serverid">2.15. Setup Linux Replica ServerID</h3> <div class="paragraph"> <p>On the Windows commit server, create a server spec to represent p4d on Linux. Call it <code>p4d_fs_linux</code>.</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_migration_preparation">3. Migration Preparation</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_provision_new_linux_server_machines">3.1. Provision New Linux Server Machines</h3> <div class="paragraph"> <p>EDITME - Add content here.</p> </div> <div class="sect3"> <h4 id="_select_operating_system">3.1.1. Select Operating System</h4> <div class="paragraph"> <p>As of this writing, the best options are:</p> </div> <div class="ulist"> <ul> <li> <p>Ubuntu 22.04 (or 20.04)</p> </li> <li> <p>RHEL/Rocky Linux 9 (or 8)</p> </li> </ul> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_install_perforce_helix_on_linux">4. Install Perforce Helix on Linux</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_install_helix_core_software">4.1. Install Helix Core Software</h3> <div class="paragraph"> <p>On the Green Linux server machines that do not yet have any data, use the Helix Installer, do a Configured Install.</p> </div> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <i class="fa icon-warning" title="Warning"></i> </td> <td class="content"> The Helix Installer is only to be used on truly "green" server machines, those with no Helix Core data on them yet. </td> </tr> </table> </div> <div class="literalblock"> <div class="content"> <pre>su - mkdir -p /hxdepots/reset cd /hxdepots/reset curl -L -s -O https://swarm.workshop.perforce.com/download/guest/perforce_software/helix-installer/main/src/reset_sdp.sh chmod +x reset_sdp.sh ./reset_sdp.sh -C > settings.cfg</pre> </div> </div> <div class="paragraph"> <p>In <code>settings.cfg</code>, change these settings:</p> </div> <div class="ulist"> <ul> <li> <p>DNS_name_of_master_server=</p> </li> <li> <p>P4_PORT=</p> </li> <li> <p>Instance=</p> </li> <li> <p>Password=</p> </li> <li> <p>CaseSensitive=0</p> </li> <li> <p>P4USER=</p> </li> <li> <p>ServerID=</p> </li> <li> <p>ServerType=</p> </li> <li> <p>P4BinRel=</p> </li> <li> <p>P4APIRel=</p> </li> </ul> </div> <div class="paragraph"> <p>Then run the script:</p> </div> <div class="literalblock"> <div class="content"> <pre>./reset_sdp.sh -no_sd -c settings.cfg 2>&1 | tee log.reset_sdp.txt</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>su - perforce p4 set</pre> </div> </div> <div class="literalblock"> <div class="content"> <pre>cd /p4/common/site [[ -d config ]] || mkdir config cd config</pre> </div> </div> </div> <div class="sect2"> <h3 id="_create_the_linux_replica">4.2. Create the Linux replica.</h3> <div class="paragraph"> <p>Temporary Hack:</p> </div> <div class="paragraph"> <p>vi /p4/common/site/config/p4_N.vars.local</p> </div> <div class="literalblock"> <div class="content"> <pre>export P4MASTER_ID=windows.p4d export P4MASTERPORT=192.168.1.5:1666 export P4PORT=$P4MASTERPORT</pre> </div> </div> <div class="paragraph"> <p>p4login -v</p> </div> <div class="paragraph"> <p>cd /p4/common/config vi SiteTags.cfg</p> </div> <div class="paragraph"> <p>azwestus2: Azure data center</p> </div> <div class="paragraph"> <p>Add to Protections:</p> </div> <div class="literalblock"> <div class="content"> <pre>super group ServiceUsers * //...</pre> </div> </div> <div class="paragraph"> <p>mkrep.sh -t fs -s usw2 -r p4d-commit-wus2</p> </div> <div class="paragraph"> <p>Undo Temporary Hack:</p> </div> <div class="paragraph"> <p>vi /p4/common/site/config/p4_N.vars.local</p> </div> <div class="literalblock"> <div class="content"> <pre>#export P4MASTER_ID=Master #export P4PORT=$P4MASTERPORT export P4MASTERPORT=10.0.0.4:</pre> </div> </div> </div> </div> </div> <div class="sect1"> <h2 id="_sample_cutover_procedure">Appendix A: Sample Cutover Procedure</h2> <div class="sectionbody"> <div class="sect2"> <h3 id="_sample_migration_scenarion">A.1. Sample Migration Scenarion</h3> <div class="paragraph"> <p>The following is a sample cutover procedure for a topology with a commit server and an edge server, with custom triggers that have been ported to Linux.</p> </div> <div class="paragraph"> <p>The sample instructions assume the <code>perforce</code> OS user on the Linux servers has been setup with the proper shell environment, specifically that the <code>~/.bashrc</code> has sourced the <code>/p4/common/bin/p4_vars</code> file with the appropriate SDP instance parameter.</p> </div> <div class="paragraph"> <p>The preparation for this sample cutover scenario would have included:</p> </div> <div class="ulist"> <ul> <li> <p>As set of ported and tested Linux custom triggers (replacing former custom triggers on Windows) deployed on all Linux servers as <code>/p4/common/site/bin/triggers</code> folder.</p> </li> <li> <p>A triggers table suited for operation on the Linux server after it becomes th commit server.</p> </li> </ul> </div> </div> <div class="sect2"> <h3 id="_one_week_prior_to_cutover_procedure">A.2. One Week Prior to Cutover Procedure</h3> <div class="paragraph"> <p><strong>STEP 1: Verify Replication</strong></p> </div> <div class="paragraph"> <p>Verify that replication is healthy on the Linux replica, the Windows edge, and the Linux replica of the Windows edge server.</p> </div> </div> <div class="sect2"> <h3 id="_one_day_prior_to_cutover_procedure">A.3. One Day Prior to Cutover Procedure</h3> <div class="paragraph"> <p><strong>STEP 1: Verify Replication</strong></p> </div> <div class="paragraph"> <p>Verify that replication is healthy on the Linux replica, the Windows edge, and the Linux replica of the Windows edge server.</p> </div> <div class="paragraph"> <p><strong>STEP 2: Checkpoint Linux Replicas</strong></p> </div> <div class="paragraph"> <p>On the Linux standby of the Windodws commit server, and separately and in parallel on any Linux standbys of Windows edge servers, request a checkpoint:</p> </div> <div class="literalblock"> <div class="content"> <pre>p4 admin checkpiont -Z</pre> </div> </div> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <i class="fa icon-warning" title="Warning"></i> </td> <td class="content"> Do a <code>p4 info</code> first and confirm that the target ServerID is that of the Linux edge server, to avoid taking an unintentional "live checkpoint" of the commit server. </td> </tr> </table> </div> <div class="paragraph"> <p>Next, on the Windows commit server, execute a journal rotation:</p> </div> <div class="literalblock"> <div class="content"> <pre>p4 admin journal</pre> </div> </div> <div class="paragraph"> <p>Once this command has been run, it will trigger the Linux server to start taking a checkpoint. On the Linux server, a checkpoint should immediately appear in the checkpoints directory.</p> </div> <div class="admonitionblock tip"> <table> <tr> <td class="icon"> <i class="fa icon-tip" title="Tip"></i> </td> <td class="content"> The checkpoints directory is '/p4/<em>N</em>/checkpoints' for the standby of the commit server, `/p4/N/checkpoints.ShortServerID </td> </tr> </table> </div> <div class="paragraph"> <p>Monitor the checkpoints directory and await the appearance of a *.md5 with the same number as the checkpoint. The existence of the MD5 file incidates the successful completion of the checkpoint process.</p> </div> <div class="paragraph"> <p>Use the <code>watch</code> utility and wait until the *.md5 file appaers.</p> </div> <div class="paragraph"> <p><strong>STEP 3</strong>: Replay Checkpoint to offline_db.</p> </div> <div class="paragraph"> <p>On the Linux commit and edge servers, replay the checkpoint to the offline_db. This can be done regardless of whether the local p4d service is replicating or even online at all, and is nether affected by nor disruptive the p4d service.</p> </div> <div class="literalblock"> <div class="content"> <pre>nohup recreate_offline_db.sh < /dev/null > /dev/null 2>&1 &</pre> </div> </div> <div class="paragraph"> <p>Monitor until completion with:</p> </div> <div class="literalblock"> <div class="content"> <pre>tail -f $LOGS/recreate_offline_db.log</pre> </div> </div> </div> <div class="sect2"> <h3 id="_cutover_procedure">A.4. Cutover Procedure</h3> <div class="paragraph"> <p><strong>STEP 1: Verify Replication</strong></p> </div> <div class="paragraph"> <p>Verify that replication is healthy on the Linux replica, the Windows edge, and the Linux replica of the Windows edge server.</p> </div> <div class="paragraph"> <p><strong>STEP 2: Disabled Scheduled Tasks</strong></p> </div> <div class="paragraph"> <p>On the old Windows commit and edge server machines, disable any Scheduled Tasks related to backups or checkpoints. Also ensure no long-running checkpoint or backup opreations are in progress that won’t be complete by the time of the intended cutover.</p> </div> <div class="paragraph"> <p><strong>STEP 3: Disable Crontabs</strong></p> </div> <div class="paragraph"> <p>On the new Linux commit and edge server machines, save and then disable all crontabs intended for routine produdction operation (and they may have been left on during dry runs).</p> </div> <div class="paragraph"> <p><strong>STEP 4: Lockout Users with Protections</strong></p> </div> <div class="paragraph"> <p><strong>STEP 5: Stop Services</strong></p> </div> <div class="paragraph"> <p><strong>STEP 6: Start Services</strong></p> </div> <div class="paragraph"> <p><strong>STEP 7: Rotate Journal</strong></p> </div> <div class="paragraph"> <p><strong>STEP 8: Verify Replication</strong></p> </div> <div class="paragraph"> <p><strong>STEP 9: Failover Edge Server</strong></p> </div> <div class="paragraph"> <p><strong>STEP 10: Apply Metadata Changes for Linux</strong></p> </div> <div class="paragraph"> <p>Apply metadata changes required for operation on Linux and commit server now being on SDP.</p> </div> <div class="paragraph"> <p><strong>STEP 11: Failover Commit Server</strong></p> </div> <div class="paragraph"> <p><strong>STEP 12: Do Sanity Tests</strong></p> </div> <div class="paragraph"> <p><strong>STEP 13: Decide: GO/NO GO</strong></p> </div> <div class="paragraph"> <p><strong>STEP 14: Restore Default Protections</strong></p> </div> <div class="paragraph"> <p><strong>STEP 15: Direct User Traffic to Linux</strong></p> </div> <div class="paragraph"> <p><strong>STEP 16: Enable crontabs</strong></p> </div> <div class="paragraph"> <p>EDITME</p> </div> </div> </div> </div> <div class="sect1"> <h2 id="_why_migrate">Appendix B: Why Migrate?</h2> <div class="sectionbody"> <div class="paragraph"> <p>Migrations from Windows to Linux have been the single most consistent theme in Perforce Consulting in over two decades, for many reasons. The procedures have evolved over time, with the modern "failvoer style" replication being the latest in seamless cutover.</p> </div> <div class="paragraph"> <p>EDITME Add some of the many reasons.</p> </div> </div> </div> <div class="sect1"> <h2 id="_draft_notice_2">5. DRAFT NOTICE</h2> <div class="sectionbody"> <div class="admonitionblock warning"> <table> <tr> <td class="icon"> <i class="fa icon-warning" title="Warning"></i> </td> <td class="content"> This document is in DRAFT status and should not be relied on yet. It is a preview of a document to be completed in a future release. </td> </tr> </table> </div> </div> </div> </div> <div id="footer"> <div id="footer-text"> Version v2023.2<br> Last updated 2024-03-25 14:25:02 -0400 </div> </div> </body> </html>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#14 | 30385 | C. Thomas Tyler | Regnerated docs for release. | ||
#13 | 30294 | C. Thomas Tyler | Updated docs for release. | ||
#12 | 30207 | C. Thomas Tyler | Doc work WIP | ||
#11 | 30206 | C. Thomas Tyler | WIP. | ||
#10 | 30204 | C. Thomas Tyler | Doc work in progress ... | ||
#9 | 30202 | C. Thomas Tyler | Doc work in progress ... | ||
#8 | 30201 | C. Thomas Tyler | Doc work in progress ... | ||
#7 | 30178 | C. Thomas Tyler | Doc in progress updates. | ||
#6 | 30159 | C. Thomas Tyler | Documentation work in progress. | ||
#5 | 30000 | C. Thomas Tyler |
Refined Release Notes and top-level README.md file in preparation for coming 2023.2 release. Adjusted Makefile in doc directory to also generate top-level README.html from top-level README.md file so that the HTML file is reliably updated in the SDP release process. Updated :revnumber: and :revdate: docs in AsciiDoc files to indicate that the are still current. Avoiding regen of ReleaseNotes.pdf binary file since that will need at least one more update before shipping SDP 2023.2. |
||
#4 | 29953 | C. Thomas Tyler | Regeneratd docs. | ||
#3 | 29743 | C. Thomas Tyler | WIP. | ||
#2 | 29741 | C. Thomas Tyler | WIP. | ||
#1 | 29740 | C. Thomas Tyler | Bootstrapped empty doc. |