PowerShell Create HAImage

Software-based VM-centric and flash-friendly VM storage + free version

Moderators: anton (staff), art (staff), Max (staff), Anatoly (staff)

Post Reply
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Thu May 03, 2018 12:44 pm

I tested the new build 12146 and creating an HA Image works fine for the most part...

In the PowerShell example CreateHA_....ps1 there are some lines that do not work:

$firstNode.CreateImage = $true
$secondNode.CreateImage = $true

If I set one of them false and I have an existing image it will fail.

As I see it is an unused parameter in the module (HA.ps1) "function Add-HADevice(...)" : "function TranslateParams(...)"

Is there a parameter which I can add to HA.ps1 to fix it like this:

$params.AppendParam("CreateImage","0")

Other question how can I set more than one "SyncInterface"/"HBInterface"

there was an example in the previous versions where I could add more than one interface like this:

$firstNode.SyncInterface = "#p2=192.168.0.72:3260,192.168.0.73:3260;#p3=192.168.0.54:3260,192.168.0.55:3260"

It might be changed since then so I might need a different separator for this.

What is the correct format to create more than one interface?
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Tue May 08, 2018 10:34 am

As for multiple interfaces for the same type of connection (sync, heartbeat), this is a known issue and it is expected to be fixed in the next build. I have drawn the attention of the R&D team to this and they are taking care of it.
As for the remaining question about the unused parameters, I would need a bit more time to check this. Will keep you posted.
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Tue May 08, 2018 12:35 pm

well thanks for your reply, then I just create it with the 1-1 interface than add the rest after the creation with server control request. (I can post a code for that if you anyone interested)

I am currently working on the existing device problem but it is much more complicated, I have a question about that:

I run a server control request
"sendTo":"HAImage"
"CreateHeader":""

Then I start to fill the rest of the parameters. If I add a parameter which name is before the "CreateHeader" than the request fail.

Before:
control HAImage -CreateHeader:"" -DeviceHeaderPath:....
200 Failed: invalid partner info..

After:
control HAImage -AuthChapLogin:"#p1=0b" -CreateHeader:"" -DeviceHeaderPath:...
101 Failed: operation cannot be completed..

As I see the -CreateHeader:"" must be the first but the Parameters class sort all the parameters so I can not get it right.

Is there a way to fix this problem or it is not possible with the current StarWindX?
(technically I should be able to send a direct TCP request but that would overcomplicate the problem)
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Tue May 08, 2018 3:44 pm

Which sample script are you trying to modify?
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Tue May 08, 2018 4:35 pm

Well there is no such sample, I only used samples to learn the basics, then I gain information from the server log to modify them, there is one example in the C# library which uses the server control request, but I do it like this add some parameres than try it if it fails I try to modify some of them.

Instead of the PowerShell, I use C# but in the forum, there is not really any C# content so I say PowerShell but the COM components are same for both of them so it should not matter.

So far I managed to do a function for mounting lsfs snapshots, and the previously mentioned HA Interface Adder/Remover.

Basically, the Create HA Device function (not in the ps module but in the COM components) go like this:

1. Create an image file for the new device
2. Create a header for the previous image
3. Create HA header file (..._HA.swdsk)
4. Create HA Device from the previous header
5. Create Target

Do each five steps on all node than initialize (synchronize) the device.

I want to skip the 1, 2 so I have to manually do 3, 4 and for that, I want to write a script.

I know each parameter for 3, (4) but I have the problem mention in the previous comment.


Note:

I like C# more it is easier to work with a GUI :)
Here is a picture of my program with the actual error message: https://imgur.com/a/B0GwiYo
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Wed May 09, 2018 8:47 am

I will try to request more information on C# from the developers, as it is not that popular among the community, as you noticed and mentioned in your previous post.
Just one brief question: did you see the APIPA addresses for the Sync channel in the error message? To the most of my knowledge, it should not be like that. Can you try fixing the IPs and run that once again?
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Wed May 09, 2018 11:53 am

This script is a bit different than the other CreateHa.ps1 scripts. This script does not call a server.CreateDevice() but instead the server.ExecuteCommand() it also does not create any device only the header file and only one of the nodes that way the syntax is a bit different instead of the "SyncInterface" and "HBInterface" param it only has a "PartnerIP" param which format: "ip:type:port:synchsessions" like in the error message: "#p1=169.254.229.198:sync:3260:1,169.254.16.3:sync:3260:1,192.168.6.170:heartbeat:3260:1"

as for the IP addresses they are fine I create HADevices with them previously (with the original script)

As for C# all of the HADevice Creating codes are broken (not updated for the current build) but the PowerShell example can be translated in C# easily so it is not a problem.

To me, it seems that the problem lies in "ParametersClass" [Guid("3C5F7E64-94D1-4DDD-B0E4-50E9AE42E7C8")] and or the IStarWindServer.ExecuteCommand() function:

void ExecuteCommand(cmdType, commandName, Parameters);

if I call the ExecuteCommand with cmdType = 1 (STARWIND_CONTROL_REQUEST)
then I have to have the command in the Parameters, not in the commandName and the command must be the first but when the underlying function is called the Parameters are sorted so it fails whenever I add a parameter which is before the actual command. Like in my script I have a command "CreateHeader" and I must add "AuthChapLogin" parameter as well which cause the control request to fail.
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Wed May 09, 2018 12:48 pm

I have got a confirmation from the developers regarding your question. According to them, that is an issue rather than any kind of expected behavior. They are taking care of it and should fix that soon.
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Tue May 22, 2018 1:23 pm

Thanks for the confirmation, I am waiting for the fix. Well, I kind of fixed it for myself it was not too hard to write a TCP client which only do the CONTROL_REQUEST now I have a function extension: IStarWindServer.Control(string sendTo, string request, IParameters pars) which connect with TCPClient than login than send the request then disconnect. While I was writing the previous function I tested some other simple commands and I have some question about them:

1.: Why are the SPTI Devices Hidden and not shown under IStarWindServer.Devices
2.: INetworkInterface could have a speed parameter which can be seen in the response of the "list -what:ipconfigports" command

There is some other useful information under IDevice / IHADeveice / ILSFSDevice which can only be seen via GetPropertyValue(string propertyName) function and unless you know what you are looking for they are hard to get such as:

"DeviceHeaderPath", "parent", "IsDeviceASnapshot", "SnapshotOffset", "BlockSize", "ha_tracker_status", "ha_sync_estimated_time" and many more.

After the 11456 build some interfaces are not included in the dll :
IDiskInfo [Guid("9D4812EA-C74A-40F6-85B5-E4F04D830231")]
IFileData [Guid("C1FDC5AC-0CB9-4D1C-B7B4-044ECBA03A53")]

These are not serious problems and can be fixed/figured out outside of StarWindX but it would nice to have a StarWindX with the same(similar) functionality as the GUI
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Thu May 24, 2018 1:43 pm

1. We are hiding devices that are not attached to any target to demonstrate the list of devices that is shown in GUI. We will add the possibility to get the list of physical devices.
2. OK, we will add it.

IDiskInfo, IFileData: please confirm. At the current time both interfaces are present.

In general, we are reworking the entire StarWindX library to make it more convenient to use and to include full functionality that is available via GUI.
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Sat May 26, 2018 11:57 am

Well, I add a reference for "C:\Program Files\StarWind Software\StarWind\StarWindX\x64\StarWindX.dll" in visual studio C# and I have a missing reference for IDiskInfo, IFileData: https://imgur.com/a/2aQf1RZ

maybe they are not missing in PowerShell.

Well as for the devices there are some additional devices. Devices with parent (fash-cache or HA child) are shown in the Devices while they are hidden in the GUI although I like that they are not hidden.

For me, the hardest part about the StarWindX library are the parameters so I tried to implement them in separate classes while keeping the code short and readable, here is an example of the image file creation:

Code: Select all

    public class ImageFileCreator : ParameterAppender, IImageFileCreator {
        public STARWIND_FILE_TYPE FileType => STARWIND_FILE_TYPE.STARWIND_IMAGE_FILE;

        public string Path { get; set; }

        public string Name { get; set; }

        [Param]
        public int Size { get; set; } 
        [Param]
        [BoolToString("True", "False")]
        public bool Flat { get; set; } = true;
        [Param]
        [BoolToString("True", "False")]
        public bool ZeroOut { get; set; } = false;
        [Param]
        [BoolToString("True", "False")]
        public bool Compressed { get; set; } = false;
        [Param]
        [BoolToString("True", "False")]
        public bool DeferredInit { get; set; } = true;
        [Param]
        [BoolToString("True", "False")]
        [EnableParam("Username", "Password")]
        public bool Encrypted { get; set; } = false;
        [Param(false)]
        public string Username { get; set; } = "";
        [Param(false)]
        public string Password { get; set; } = "";
    }
I used attributes to make them simple and the ParameterAppender class will append an IParameters using reflections:

Code: Select all

    public abstract class ParameterAppender : IAppender {
        public void AppendParams(IParameters pars) {
            Append(pars, this);
        }

        protected static string ToString(PropertyInfo info, object obj) {
            if (obj is string str) {
                return str;
            } else if (obj is bool b) {
                if (info.GetCustomAttribute(typeof(BoolToStringAttribute), true) is BoolToStringAttribute attr) {
                    return b ? attr.TrueString : attr.FalseString;
                }
                return null;
            } else if (obj.GetType().BaseType == typeof(Enum)) {
                return EnumFormat.EnumToString(obj);
            } else {
                return obj.ToString();
            }
        }

        protected static void Append(IParameters pars, object obj, string prefix = "") {
            bool IsEnabled(IConditional attr) {
                if (attr.Enabled) { return true; }
                return (bool)obj.GetType().GetProperties().Single(info => (info.GetCustomAttribute(typeof(EnableParamAttribute), true) as EnableParamAttribute)?.CheckName(attr.Name) ?? false).GetValue(obj);
            }
            foreach (var info in obj.GetType().GetProperties()) {
                if (info.CanRead) {
                    if (info.GetCustomAttribute(typeof(ParamAttribute), true) is ParamAttribute attr) {
                        if (IsEnabled(attr) && ToString(info, info.GetValue(obj)) is string str) {
                            pars.AppendParam(prefix + attr.Name, str);
                        }
                    } else if (info.GetCustomAttribute(typeof(FlatParamAttribute), true) is FlatParamAttribute flat) {
                        if (IsEnabled(flat)) {
                            Append(pars, info.GetValue(obj), flat.Prefix);
                        }
                    }
                }
            }
        }
    }
this way I can use the "IImageFileCreator" interface instead of the params.AppendParam("string name", "string value") this way making the code more readable.
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Thu May 31, 2018 4:38 pm

Sekkmer,

We have found the reason for those not being visible in C#/.NET, and the fix is already introduced into the source code, so it is expected to be operating properly in the very next build.
Thank you for bringing this to our attention.
Sekkmer
Posts: 29
Joined: Thu Mar 08, 2018 12:11 pm

Thu Jun 07, 2018 10:19 am

I found another small problem when I call the CreateTarget function of the IStarWindServer and I add a "devices" parameter it won't be sent to the server.

param.AppendParam("devices", "RamDrive1")

with the parameter, the new target should attach the "RamDrive1" device (if it is detached) but the parameter gets filtered.

Note:
I am not sure that it is the best to post it here under "PowerShell Create HAImage", is there a place for issues specifically or just keep posting here?

I am planning to make a public GitHub repository for some of my classes that could help other people, mostly extensions for IDevice, IHADevice, ILSFSDevice and my previously mentioned Appender classes, is it ok post something like this? (these classes contain undocumented parameters)
Boris (staff)
Staff
Posts: 805
Joined: Fri Jul 28, 2017 8:18 am

Fri Jun 08, 2018 11:38 pm

If you work with the COM object directly, the parameter name is "Devices" (starting with the capital letter)
For PowerShell, there is a function called New-Target.

As far as the non-documented parameters are concerned, most likely they are going to be changed in the nearest time, according to the information from the R&D team.
Post Reply