DCSIMG
July 2008 - Posts - Gadi's Blog

Gadi's Blog

SBC, Application Delivery, Scripting ושאר ירקות

July 2008 - Posts

Processor Check for 64-Bit Compatibility

למי שלא יודע, VMware Server ו- VMware Workstation מאפשרים הרצת מכונות וירטואליות עם מערכת הפעלה 64 ביט על גבי מחשב מארח אשר מריץ מערכת הפעלה 32 ביט.
כדי לתמוך בתצורה שכזאת על המעבד לעמוד בתנאים הבאים:

  • AMD Athlon 64, revision D or later
  • AMD Opteron, revision E or later
  • AMD Turion 64, revision E or later
  • AMD Sempron, 64-bit-capable revision D or later
  • Intel EM64T VT-capable processors

כדי להקל על חיינו, VMware הוציאו כלי אשר בודק האם המעבד אכן תומך בהרצת מכונות וירטואליות של 64 ביט - דרך אגב, גם אם הכלי אומר שאכן המעבד תומך, חשוב לבדוק שה feature מאופשר ב BIOS.

פרטים, הורדה ושלל פעילויות - כאן

סדר בפרופילים

דרך מעניינת לעשות סדר בפרופילים, להמיר את ה Roaming Profiles למאין שילוב של Roaming Profile ו- Redirection של תיקיות מסוימות. המטרה של כל העניין היא להפעיל quota על הנתונים שנשמרים ע"י המשתמשים בעבודת על גבי חוות ה Citrix\TS.

מצב קיים

כל המשתמשים עובדים עם Roaming Profile היושב על גבי ה storage המרכזי של הארגון (netapp), אין מחיקת פרופילים ביציאה ואין הגבלה על גודל הפרופיל.

הבעיה

הפרופילים גודלים בלי שליטה. נעשה נסיון להפעיל את ההגדרה של Limit Profile Size ב GPO, אבל ההגדרה דרך ה GPO היא בעיתית, ואני אסביר.
ניקח לדוגמא שהגבלתי את הפרופילים ל 10mb, כל עוד הוא ב session, המשתמש יוכל להוסיף לפרופיל שלו כל כמות מידע שהוא רק רוצה, הוא רק  ייקבל הודעה כאשר הוא יחרוג מההגבלה הנ"ל, בנוסף לכך, הוא לא יהיה מסוגל לעשות logoff מה session כל עוד הוא עובר את ההגבלה. אבל, יש כאן דרך להתחכמות (וכידוע לכולנו, המשתמשים רכשו לעצמם שם לא רע בתחום הזה עם השנים), נגיד ובאמת המשתמש רושם לפרופיל שלו מעבר להגבלה שמוגדרת לו ב GPO - למשל מעתיק קובץ של 40mb ל Desktop - הוא באמת יקבל הודעה שהוא חרג מההגבלה שלו וכמובן שלא יהיה מסוגל לבצע logoff, אבל הוא כן יוכל לעשות disconnect מה session שלו, לחכות את פרק הזמן שבו ה session ינותק מהשרת ולהכנס בחזרה. כמובן שהפרופיל שלו יכיל את כל המידע (כולל המידע מעבר להגבלה) והוא יוכל לכתוב עוד חומר נוסף, ולחזור כמובן על הקומבינה בפעם הבאה.
אבל אם נעזוב לרגע את זה שאפשר לאכוף את ההגבלה, מה שיותר מפריע זה שכל עוד המשתמש נמצא ב session הוא יכול לכתוב כמה שהוא רק רוצה לתיקיית הפרופיל שלו. כאמור, זה רק מתריע ומונע logoff.

הגדרת הפיתרון

לאחר מחשבה מעמיקה (אני רוצה refill לוויינשטפן בבקשה) החלטנו לפצל את הפרופיל לשני חלקים מרכזיים. Desktop, My Documents, Favorites, Cookies, אותן תיקיות שלמשתמש יש אינטרקציה ישירה איתן, כלומר, כל הכתיבות לתיקיות הנ"ל נעשות ע"י המשתמש ולא ע"י תהליכים השקופים לו (טוב נו, חוץ מה Cookies). אותן ארבעת התיקיות ישבו ב share משלהם על גבי ה storage בו יוגדר quota (ב netapp) ויהיו מוגדרות ב redirection לפרופיל, ישבו ב netapp\ctx_redirect\\. תצורה זו לא תאפשר למשתמש לחרוג מהגדרת ה quota שלו גם אם הוא ב session.
כל שאר חלקי הפרופיל (application data, ntuser.dat וכו') ימשיכו לעבוד כ roaming profile (אשר קטן בצורה דרסטית עקב ה redirection של ארבעת התיקיות הנ"ל) במקום חדש, netapp\ctx_profiles\\.

מה תכלס עשינו

במצב ההתחלתי כל ה Roaming profiles ישבו ב Share הבא: netapp\ctx_profiles\\ ומתחת ישבו התיקיות של כל משתמש. כמובן, שהיסטורית סרר שם בלגן לא קטן (פרופילים ישנים, גדולים מדי, דפוקים ועוד).
כדי להגדיר את חלוקת הפרופיל לתצורה החדשה, הגדרנו את ההגדרות הבאות ב GPO (יצרנו חדש, אשר יכיל רק את ההגדרות האלה):


User Configuration-->Windows Settings-->Folder Redirection
כאמור, מיפוי של Desktop ו- My Documents ל- netapp\ctx_redirect\username\\.

מכיוון שתיקיית Favorites ו- Cookies לא כלולות בתיקיות הניתנות ל redirection ב default הינו צריכים להוסיף Policy Template בו הוספנו את התיקיות Cookies ו- Favorites:

CLASS USER
   CATEGORY "Citrix Redirection"
   CATEGORY "System"
    POLICY "+ User Shell Folders"
            KEYNAME "Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
             PART "--------------------------------------------------------------------------" TEXT
            END PART

            PART "Cookies" EDITTEXT
                VALUENAME "Cookies"
                DEFAULT "%USERPROFILE%\Cookies"
                REQUIRED
                #if VERSION >= 2
                EXPANDABLETEXT
                #endif
            END PART

            PART "Favorites" EDITTEXT
                VALUENAME "Favorites"
                DEFAULT "%USERPROFILE%\Favorites"
                REQUIRED
                #if VERSION >= 2
                EXPANDABLETEXT
                #endif
            END PART

     END POLICY ; + User Shell Folders
   END CATEGORY ; System
END CATEGORY ; Citrix Extension

כמובן, שגם התי התיקיות האלה הופנו ל netapp\ctx_redirect\username\\.

את הקישור לתיקיית ה Roaming Profiles החדשה עשינו ע"י הפוליסי הבא:

Computer Configuration-->Administrative Templates-->Windows Components-->Terminal Services-->Set path for TS Roaming Profiles: \\netapp\ctx_profiles\username

מכיוון שרצינו מעבר חלק של המשתמשים בין התצורה הישנה (Roaming profile פשוט) לתצורה החדשה (שילוב של Redirection ו- Roaming profile) הינו צריכים להעתיק את התיקיות הרלוונטיות מה Roaming Profile הקיים לתיקיות החדשות, כאמור, Desktop, Favorites, Cookies, My Documents ל- netapp\ctx_redirect\username\\ וכל שאר הפרופיל ל- netapp\ctx_profiles\username\\.
כל זה נעשה ע"י הסקריפט הבא:

 

<package>
            <job id="Sessions">
                        <comment>
                        </comment>
                        <runtime>
                                    <description>
                                    </description>
                                    <example>
                    </example>
                        </runtime>
                        <reference object="MetaFrameCOM.MetaFrameFarm"/>
                        <script language="VBScript">
           Dim theFarm, aSession, SessionState, users

            SessionState = Array("Unknown", _
                                 "Active", _
                                 "Connected", _
                                 "Connecting", _
                                 "Shadowing", _
                                 "Disconnected", _
                                 "Idle", _
                                 "Listening", _
                                 "Resetting", _
                                 "Down", _
                                 "Init")

            '
            ' Create MetaFrameFarm object
            '
                Set fs = WScript.CreateObject("Scripting.filesystemobject")
                Set users = fs.opentextfile("c:\users.txt",1)

            Set theFarm = CreateObject("MetaFrameCOM.MetaFrameFarm")
            if Err.Number <> 0 Then
                WScript.Echo "Can't create MetaFrameFarm object"
                WScript.Echo "(" & Err.Number & ") " & Err.Description
                WScript.Echo ""
                WScript.Quit Err.Number
            End if

            '
            ' Initialize the farm object.
            '

            theFarm.Initialize(MetaFrameWinFarmObject)
            if Err.Number <> 0 Then
                WScript.Echo "Can't  Initialize MetaFrameFarm object"
                WScript.Echo "(" & Err.Number & ") " & Err.Description
                WScript.Echo ""
                WScript.Quit Err.Number
            End if

            '
            ' Are you Citrix Administrator?
            '

            if theFarm.WinFarmObject.IsCitrixAdministrator = 0 then
                WScript.Echo "You must be a Citrix admin to run this script"
                WScript.Echo ""
                WScript.Quit 0
            End If

            '
            ' Print out the farm name.
            '

            WScript.Echo "MetaFrame Farm Name: " & theFarm.FarmName
            WScript.Echo ""

            '
            ' Display all sessions in the farm.
            '

            WScript.Echo "All sessions in the farm (" & Now & ")"
            WScript.Echo "------------------------------------------------"

                Do
                b_temp = false             
                u_temp = users.ReadLine
                For Each aSession In theFarm.Sessions

                if Err.Number <> 0 Then
                    WScript.Echo "Can't enumerate sessions"
                    WScript.Echo "(" & Err.Number & ") " & Err.Description
                    WScript.Echo ""
                    WScript.Quit Err.Number
                End if        

                                                If u_temp = aSession.username Then
                                                            b_temp = True
                                                End if
            Next
        If not b_temp Then
            wscript.echo u_temp & " are not logged in"
            Call Find_folder(u_temp)
                                    'Return = WshShell.Run(ROBO, 0, true)
        End If
        loop While users.AtEndOfStream <> true


Function Find_folder (user)
            Set fs = WScript.CreateObject("Scripting.filesystemobject")
            Set objFolder = fs.GetFolder("\\netapp\ctx_profiles\")
            Set colSubfolders = objFolder.Subfolders
            Set WshShell = WScript.CreateObject("WScript.Shell")
            For Each objSubfolder In colSubfolders

                        If InStr(objSubfolder.name, user)And NOT InStr(objSubfolder.name, (user & ".TESTDOMAIN")) Then
                                    date1 = objSubfolder.DateLastModified
                                    folder1 = objSubfolder.name
                                    'WScript.echo objSubfolder.name & "  "  & objSubfolder.DateLastModified
                                    'WScript.Echo InStr(objSubfolder.name, user)
                        End If
                        If InStr(objSubfolder.name, (user & ".TESTDOMAIN")) = 1 Then
                                    date2 = objSubfolder.DateLastModified
                                    folder2 = objSubfolder.name
                                    'WScript.echo " blabla " & objSubfolder.name & "  "  & objSubfolder.DateLastModified
                                    'WScript.Echo InStr(objSubfolder.name, (user & ".TESTDOMAIN"))
                        End If
            Next
            If date1>date2 Then
                        WScript.Echo user & "  " & date1 & "without TESTDOMAIN"
                        rob = "c:\robocopy.exe \\netapp\ctx_profiles\" & folder1 & " \\netapp\ctx_profiles\" & user & ".TESTDOMAIN /E /SEC /XD dirs desktop Favorites ""My Documents"" Cookies"
                        return = WshShell.run(rob , 0, True)
                        return = WshShell.run("c:\robocopy.exe \\netapp\ctx_profiles\" & folder1 & "\Desktop \\netapp\ctx_riderect\" & user & ".TESTDOMAIN\Desktop /E /COPYALL" , 0, True)
                        return = WshShell.run("c:\robocopy.exe \\netapp\ctx_profiles\" & folder1 & "\Favorites \\netapp\ctx_riderect\" & user & ".TESTDOMAIN\Favorites /E /COPYALL" , 0, True)
                        return = WshShell.run("c:\robocopy.exe \\netapp\ctx_profiles\" & folder1 & "\Cookies \\netapp\ctx_riderect\" & user & ".TESTDOMAIN\Cookies /E /COPYALL" , 0, True)
                        return = WshShell.run("c:\robocopy.exe ""\\netapp\ctx_profiles\" & folder1 & "\My Documents"" ""\\netapp\ctx_riderect\" & user & ".TESTDOMAIN\My Documents"" /E /COPYALL" , 0, True)
            End If
            If date2>date1 Then
                        WScript.Echo user & "  " &  date2 & " TESTDOMAIN"
                        rob = "c:\robocopy.exe \\netapp\ctx_profiles\" & folder2 & " \\netapp\ctx_profiles\" & user & ".TESTDOMAIN /E /COPYALL /XD dirs desktop Favorites ""My Documents"" Cookies"
                        return = WshShell.run(rob , 0, True)
                        return = WshShell.run("c:\robocopy.exe \\netapp\ctx_profiles\" & folder2 & "\Desktop \\netapp\ctx_riderect\" & user & ".TESTDOMAIN\Desktop /E /COPYALL" , 0, True)
                        return = WshShell.run("c:\robocopy.exe \\netapp\ctx_profiles\" & folder2 & "\Favorites \\netapp\ctx_riderect\" & user & ".TESTDOMAIN\Favorites /E /COPYALL" , 0, True)
                        return = WshShell.run("c:\robocopy.exe \\netapp\ctx_profiles\" & folder2 & "\Cookies \\netapp\ctx_riderect\" & user & ".TESTDOMAIN\Cookies /E /COPYALL" , 0, True)
                        return = WshShell.run("c:\robocopy.exe ""\\netapp\ctx_profiles\" & folder2 & "\My Documents"" ""\\netapp\ctx_riderect\" & user & ".TESTDOMAIN\My Documents"" /E /COPYALL" , 0, True)
            End If
End Function
                        </script>
            </job>
</package>

 

הסבר קצר על מה קורה כאן בכלל, הסקריפט עובר על כל השורות בקובץ users.txt המכיל את המשתמשים אשר עשו logoff מהחווה.
כל משתמש הרשום בקובץ נבדק האם הוא כרגע נמצא ב login בחווה, אם לא, נעשת העתקה של התיקיות המדוברות למיקומים החדשים. לא מבוצעת שום העתקה אם המשתמש ב login.
מכיוון שחלק מהמשתמשים מחזיקים ב Roaming Profile עם סיומת שם הדומיין (כל אלה שקיבלו את ההגדרה מה GPO) וחלק בלי סיומת (כאלה שמקבלים את ההגדרה מה AD) הינו צריכים למצוא את הפרופיל המעודכן ביותר (בגלל זה ההשוואה בין date1 לבין date2).

אחרי פעולת הסקריפט, הנתיבים החדשים יהיו מעודכנים עם הנתונים הרלוונטיים של המשתמשים, מה שיאפשר החלפה חלקה של ה GPO לתצורה החדשה.

*תודה למושי על ההשקעה.

 

Logoff disconnected sessions at Citrix XenApp farm

או למעשה, די נמאס לי מכל אלה שבממתינה, למאזין הבא.

סקריפט קטן, אשר מבוסס בעיקרו על סקריפט של Citrix הנותן מידע על sessions בחווה.
הטריק היחיד כאן הוא לדעת איך מצבי session שונים מוצגים בחווה:
0 - unknown
1 - active
2 - connected
3 - connecting
4 - shadowing
5 - disconnected
6 - idle
7 - listening
8 - resetting
9 - down

ואחרי שהטריק ידוע, הנה הסקריפט המלא:

<package>
    <job id="Sessions">

        <comment>

        File:           logoff_dis_sessions.wsf
        Description:    Logoff disconnected sessions.
        Requirements:   WSH 5.5 or higher.
        Author:        Gadi Feldman (based on Citrix template).
        Version:    1.1
        Date:    13/7/08
        </comment>
        <runtime>
            <description>
                Logoff disconnected sessions.
            </description>
            <example>
                CScript //nologo logoff_dis_sessions.wsf
            </example>
        </runtime>
        <reference object="MetaFrameCOM.MetaFrameFarm"/>
        <script language="VBScript">
            Dim theFarm, aSession, SessionState

            '
            ' Create MetaFrameFarm object
            '

            Set theFarm = CreateObject("MetaFrameCOM.MetaFrameFarm")
            if Err.Number <> 0 Then
                WScript.Echo "Can't create MetaFrameFarm object"
                WScript.Echo "(" & Err.Number & ") " & Err.Description
                WScript.Echo ""
                WScript.Quit Err.Number
            End if

            '
            ' Initialize the farm object.
            '

            theFarm.Initialize(MetaFrameWinFarmObject)
            if Err.Number <> 0 Then
                WScript.Echo "Can't  Initialize MetaFrameFarm object"
                WScript.Echo "(" & Err.Number & ") " & Err.Description
                WScript.Echo ""
                WScript.Quit Err.Number
            End if

            '
            ' Are you Citrix Administrator?
            '

            if theFarm.WinFarmObject.IsCitrixAdministrator = 0 then
                WScript.Echo "You must be a Citrix admin to run this script"
                WScript.Echo ""
                WScript.Quit 0
            End If

            '
            ' Print out the farm name.
            '

            'WScript.Echo "MetaFrame Farm Name: " & theFarm.FarmName
            'WScript.Echo ""

            '
            ' Display all sessions in the farm.
            '

            'WScript.Echo "All sessions in the farm (" & Now & ")"
            'WScript.Echo "------------------------------------------------"

            For Each aSession In theFarm.Sessions

                if Err.Number <> 0 Then
                    WScript.Echo "Can't enumerate sessions"
                    WScript.Echo "(" & Err.Number & ") " & Err.Description
                    WScript.Echo ""
                    WScript.Quit Err.Number
                End if

                        ' To logoff sessions from specific servers
                        'if aSession.ServerName = "VMSERVER04" or aSession.ServerName = "VMSERVER01" Then
                                    if aSession.SessionState = 5 then
                                                aSession.logoff(2)
                                    End if
                        'End if
            Next
        </script>
    </job>
</package>

מנכ"לית VMware, דיאן גרין עוזבת את הממלכה

עיתונאי מחשבים למיניהם אוהבים להלל ולשבח את VMware - ואו, תראו איזה מוצלחים הם, איך המניה שלהם עלתה כ"כ (ונפלה כמובן אחרי זה). או, ואו, הם הכי טובים בעולם, VMware שולטתתתת!!1 - אבל עזבו אותכם שטויות - או בעצם מעיתונאים חסרי הבנה עמוקה בטכנולוגיות - נכון, VMware עושים עבודה מעולה, בלעדי הדחיפה שלהם, עולם הוירטואליזציה (או בעצם הבאז) לא היה מה שהוא עכשיו, אבל לא הכל כ"כ ורוד מסתבר (צרות בגן עדן?).
אתמול יצאה ההודעה לעיתונות בדבר שינויים בהנהלת החברה, דיאן גרין OUT, פול מאריץ IN.

אולי זה מאין מחלת הסגמ"ת - שכולנו למדנו להכיר בשירותינו הצבאי - בצורתה החדשה, או שההצלחה עלתה להם לראש יותר מדי, לא יודע, אבל VMware תמיד התנהגה במאין אליטיסטיות מסוימת ולא שמה יותר מדי על המתחרים, אפילו גרין עצמה התבטאה פעם שהיא לא ממש מודאגת מהתחרות החדשה מצד מיקרוסופט. ותסלחו לי, אבל מנכ"ל של חברה לא יכול להגיד אמירות כאלה, אפילו אם הוא באמת חושב ככה - וכן, אסור לו לחשוב ככה, אפילו לשניה -  כל מתחרה חדש, כל מתחרה קיים, צריך להטריד את מנהלי ועובדי החברה. להטריד כמובן מהכיוון החיובי, של לחפש כל הזמן איך להתבלט על אותם המתחרים, לעשות מוצרים טובים יותר, לספק פתרונות טובים יותר, לשווק טוב יותר, להיות זול יותר. כל דבר. ואם המנכ"לית מזלזלת במתחרים, אז מה בעצם יותר אלטיסטי מזה, איזה ליגיטימציה זה נותן לעובדים להשקיע בלשפר את המוצרים הקיימים ולפתח חדשים.

קראתי פה ושם דעות של כמה מעובדי VMware שכתבו דווקא שהם רואים במהלך משהו חיובי, שהם באמת קיבלו את הרושם שדיאן הגיעה לגבול התרומה שלה לחברה. כנראה שזה גם היה הלך הרוח במועצת המנהלים שהחליטה על המהלך להיפרד מגרין (ככה לפי השמועות, שגורסות בתוקף שהיא פוטרה, או בעצם התפוטרה) ולמנות במקומה את פול מאריץ שהיה עד עכשיו נשיא מחלקת Cloud Computing ב EMC ובעל עבר של 14 שנים במתחרה הכי גדולה אולי של VMware, מיקרוסופט.

ד"א, כמה שאני חושב על זה יותר, זה נראה לי יותר ויותר כמו הנחתה של EMC. משהו פה נראה מוזר, יש הרבה התייחסויות של מנכ"ל EMC, ג'ו טוצ'י על החדשות המסעירות, הוא טוען בכל מקום שגרין היא זאת שיום אחד בהיר נמאס לה והיא הודיעה על עזיבה. יכול להיות, אבל קשה לי להאמין שמקים של חברה ונושא תפקיד כ"כ חשוב בחברה כ"כ מצליחה קם יום אחד והולך וכל זה בלי לדבר יותר מדי.
ואם ממשיכים עוד קצת בתאוריית הקונספירציה שאני רוקם פה, אז איך זה שמועצת המנהלים בוחרת ישר מחליף, בלי לדון אחרי שהמנכ"לית הודיעה על עזיבתה, כלומר, האם הם כבר דנו בזה קודם?? ועוד איזה עניין משעשע שקראתי בקשר לזה, מסתבר שערך הויקיפדיה של פול מאריץ - המנכ"ל החדש - עודכן עם התפקיד החדש שלו זמן מה לפני ההודעה על כל הסיפור (מישהו לא התאפק?)

ועוד משהו קטן, מנדל רוזנבלום, המדען הראשי ואחד ממקימיי VMware וגם בין השאר בעלה של דיאן גרין, נמצא בימים אלה בארץ לרגל פתיחת הסניף הישראלי של VMware, יהיה מעניין לשמוע מה אומר על כל העניין - למרות שקשה לי להאמין שהוא ייבחר להתייחס לזה כל עוד הוא כאן.