Skip to content

Commit 6716da9

Browse files
authored
Merge pull request #42 from cloudsoft/feature/arm-initialize-disk-win
Initialize attached disk in windows ARM
2 parents 4eccc25 + 3932f43 commit 6716da9

2 files changed

Lines changed: 91 additions & 46 deletions

File tree

blockstore/src/main/java/brooklyn/location/blockstore/AbstractVolumeManager.java

Lines changed: 69 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
import org.apache.brooklyn.location.jclouds.JcloudsMachineLocation;
1414
import org.apache.brooklyn.location.jclouds.JcloudsMachineNamer;
1515
import org.apache.brooklyn.location.ssh.SshMachineLocation;
16+
import org.apache.brooklyn.location.winrm.WinRmMachineLocation;
1617
import org.apache.brooklyn.util.collections.MutableMap;
18+
import org.apache.brooklyn.util.core.internal.winrm.WinRmToolResponse;
1719
import org.jclouds.compute.domain.NodeMetadata;
1820
import org.slf4j.Logger;
1921
import org.slf4j.LoggerFactory;
@@ -73,58 +75,79 @@ public MountedBlockDevice attachAndMountVolume(JcloudsMachineLocation machine, B
7375
@Override
7476
public void createFilesystem(AttachedBlockDevice attachedDevice, FilesystemOptions filesystemOptions) {
7577
JcloudsMachineLocation machine = attachedDevice.getMachine();
76-
if (!(machine instanceof SshMachineLocation)) {
77-
throw new IllegalStateException("Cannot create filesystem for "+machine+" of type "+machine.getClass().getName()+"; expected "+SshMachineLocation.class.getSimpleName());
78-
}
79-
80-
String osDeviceName = getOSDeviceName(attachedDevice.getDeviceSuffix());
81-
String filesystemType = filesystemOptions.getFilesystemType();
82-
LOG.debug("Creating filesystem: device={}; osDeviceName={}, config={}", new Object[]{attachedDevice, osDeviceName, filesystemOptions});
83-
84-
// NOTE: also adds an entry to fstab so the mount remains available after a reboot.
85-
Map<String, ?> flags = MutableMap.of("allocatePTY", true);
86-
87-
int exitCode = ((SshMachineLocation)machine).execCommands(flags, "Creating filesystem on volume", ImmutableList.of(
88-
dontRequireTtyForSudo(),
89-
waitForFileCmd(osDeviceName, 60),
90-
installPackage(ImmutableMap.of("yum", "e4fsprogs"), null),
91-
sudo("/sbin/mkfs -F -t " + filesystemType + " " + osDeviceName)));
92-
93-
if (exitCode != 0) {
94-
throw new RuntimeException(format("Failed to create file system. machine=%s; osDeviceName=%s; filesystemType=%s",
95-
machine, osDeviceName, filesystemType));
78+
if (machine instanceof SshMachineLocation) {
79+
String osDeviceName = getOSDeviceName(attachedDevice.getDeviceSuffix());
80+
String filesystemType = filesystemOptions.getFilesystemType();
81+
LOG.debug("Creating filesystem: device={}; osDeviceName={}, config={}", new Object[]{attachedDevice, osDeviceName, filesystemOptions});
82+
83+
// NOTE: also adds an entry to fstab so the mount remains available after a reboot.
84+
Map<String, ?> flags = MutableMap.of("allocatePTY", true);
85+
86+
int exitCode = ((SshMachineLocation)machine).execCommands(flags, "Creating filesystem on volume", ImmutableList.of(
87+
dontRequireTtyForSudo(),
88+
waitForFileCmd(osDeviceName, 60),
89+
installPackage(ImmutableMap.of("yum", "e4fsprogs"), null),
90+
sudo("/sbin/mkfs -F -t " + filesystemType + " " + osDeviceName)));
91+
92+
if (exitCode != 0) {
93+
throw new RuntimeException(format("Failed to create file system. machine=%s; osDeviceName=%s; filesystemType=%s",
94+
machine, osDeviceName, filesystemType));
95+
}
96+
} else if (machine instanceof WinRmMachineLocation) {
97+
String driveLetter = filesystemOptions.getMountPoint();
98+
String driveLetterParam = Strings.isNullOrEmpty(driveLetter) ? "-AssignDriveLetter" : "-DriveLetter " + driveLetter;
99+
String volumeLabel = filesystemOptions.getVolumeLabel();
100+
String volumeLabelParam = Strings.isNullOrEmpty(volumeLabel) ? "datadisk" : volumeLabel;
101+
WinRmToolResponse response = ((WinRmMachineLocation)machine).executePsScript("Get-Disk | Where partitionstyle -eq 'raw' | " +
102+
// AWS May create an instance store volume, which we need to exclude
103+
// See https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-volumes.html#instance-store-volume-map
104+
"Where {$_.SerialNumber -As [int] -NotIn 78..89 -Or $_.FriendlyName -Ne \"AWS PVDISK\"} | " +
105+
"Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition " + driveLetterParam + " -UseMaximumSize | " +
106+
"Format-Volume -FileSystem " + filesystemOptions.getFilesystemType() +" -NewFileSystemLabel \"" + volumeLabelParam + "\" -Confirm:$false");
107+
if (response.getStatusCode() != 0) {
108+
throw new RuntimeException(format("Failed to initialize disk. machine=%s; filesystemType=%s; stdErr=%s;",
109+
machine, filesystemOptions.getFilesystemType(), response.getStdErr()));
110+
}
111+
} else {
112+
throw new IllegalStateException("Cannot create filesystem for " + machine + " of type "
113+
+ machine.getClass().getName() + "; expected " + SshMachineLocation.class.getSimpleName()
114+
+ " or " + WinRmMachineLocation.class.getSimpleName());
96115
}
97116
}
98117

99118
@Override
100119
public MountedBlockDevice mountFilesystem(AttachedBlockDevice attachedDevice, FilesystemOptions options) {
101120
JcloudsMachineLocation machine = attachedDevice.getMachine();
102-
if (!(machine instanceof SshMachineLocation)) {
103-
throw new IllegalStateException("Cannot mount filesystem for "+machine+" of type "+machine.getClass().getName()+"; expected "+SshMachineLocation.class.getSimpleName());
104-
}
105-
106-
LOG.debug("Mounting filesystem: device={}; options={}", attachedDevice, options);
107-
String osDeviceName = getOSDeviceName(attachedDevice.getDeviceSuffix());
108-
String mountPoint = options.getMountPoint();
109-
String filesystemType = options.getFilesystemType();
110-
111-
// NOTE: also adds an entry to fstab so the mount remains available after a reboot.
112-
Map<String, ?> flags = MutableMap.of("allocatePTY", true);
113-
int exitCode = ((SshMachineLocation)machine).execCommands(flags, "Mounting EBS volume", ImmutableList.of(
114-
dontRequireTtyForSudo(),
115-
"echo making dir",
116-
sudo("mkdir -p -m 755 " + mountPoint),
117-
"echo updating fstab",
118-
waitForFileCmd(osDeviceName, 60),
119-
"echo \"" + osDeviceName + " " + mountPoint + " " + filesystemType + " noatime 0 0\" | " + sudo("tee -a /etc/fstab"),
120-
"echo mounting device",
121-
sudo("mount " + mountPoint),
122-
"echo device mounted"
123-
));
124-
125-
if (exitCode != 0) {
126-
throw new RuntimeException(format("Failed to mount file system. machine=%s; osDeviceName=%s; mountPoint=%s; filesystemType=%s",
127-
attachedDevice.getMachine(), osDeviceName, mountPoint, filesystemType));
121+
if (machine instanceof SshMachineLocation) {
122+
LOG.debug("Mounting filesystem: device={}; options={}", attachedDevice, options);
123+
String osDeviceName = getOSDeviceName(attachedDevice.getDeviceSuffix());
124+
String mountPoint = options.getMountPoint();
125+
String filesystemType = options.getFilesystemType();
126+
127+
// NOTE: also adds an entry to fstab so the mount remains available after a reboot.
128+
Map<String, ?> flags = MutableMap.of("allocatePTY", true);
129+
int exitCode = ((SshMachineLocation)machine).execCommands(flags, "Mounting EBS volume", ImmutableList.of(
130+
dontRequireTtyForSudo(),
131+
"echo making dir",
132+
sudo("mkdir -p -m 755 " + mountPoint),
133+
"echo updating fstab",
134+
waitForFileCmd(osDeviceName, 60),
135+
"echo \"" + osDeviceName + " " + mountPoint + " " + filesystemType + " noatime 0 0\" | " + sudo("tee -a /etc/fstab"),
136+
"echo mounting device",
137+
sudo("mount " + mountPoint),
138+
"echo device mounted"
139+
));
140+
141+
if (exitCode != 0) {
142+
throw new RuntimeException(format("Failed to mount file system. machine=%s; osDeviceName=%s; mountPoint=%s; filesystemType=%s",
143+
attachedDevice.getMachine(), osDeviceName, mountPoint, filesystemType));
144+
}
145+
} else if (machine instanceof WinRmMachineLocation) {
146+
LOG.debug("Ignoring mounting of filesystem on WinRmMachineLocation: device={}; options={}", attachedDevice, options);
147+
} else {
148+
throw new IllegalStateException("Cannot mount filesystem for " + machine + " of type "
149+
+ machine.getClass().getName() + "; expected " + SshMachineLocation.class.getSimpleName()
150+
+ " or " + WinRmMachineLocation.class.getSimpleName());
128151
}
129152

130153
return attachedDevice.mountedAt(options.getMountPoint());

blockstore/src/main/java/brooklyn/location/blockstore/FilesystemOptions.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@
55
import java.util.Map;
66

77
import com.google.common.base.MoreObjects;
8+
import com.google.common.base.Optional;
89

910
public class FilesystemOptions {
1011

1112
private String mountPoint;
1213
private String filesystemType;
14+
private String volumeLabel;
1315

1416
// For more convenient yaml input
1517
public static FilesystemOptions fromMap(Map<String, ?> map) {
1618
FilesystemOptions result = new FilesystemOptions();
1719
result.mountPoint = (String) map.get("mountPoint");
1820
result.filesystemType = (String) map.get("filesystemType");
21+
result.volumeLabel = (String) map.get("volumeLabel");
1922
return result;
2023
}
2124

@@ -31,23 +34,42 @@ public FilesystemOptions(String mountPoint) {
3134
}
3235

3336
public FilesystemOptions(String mountPoint, String filesystemType) {
37+
this(mountPoint, filesystemType, "");
38+
}
39+
40+
public FilesystemOptions(String mountPoint, String filesystemType, String volumeLabel) {
3441
this.filesystemType = checkNotNull(filesystemType, "filesystemType");
3542
this.mountPoint = checkNotNull(mountPoint, "mountPoint");
43+
this.volumeLabel = Optional.fromNullable(volumeLabel).or("");
3644
}
3745

46+
/*
47+
For Linux machines, this will be the mount point, e.g. /data. For Windows systems, this is the drive letter, e.g. "G". A colon should not be included
48+
*/
3849
public String getMountPoint() {
3950
return mountPoint;
4051
}
4152

53+
/*
54+
For Linux machines, this will be the file system type, e.g. ext3. For Windows system, this is the `-FileSystem` parameter passed to the `Format-Volume` cmdlet, e.g. NTFS
55+
*/
4256
public String getFilesystemType() {
4357
return filesystemType;
4458
}
4559

60+
/*
61+
Windows only. The volume label to be assigned to the volume, e.g. "MyDataDrive"
62+
*/
63+
public String getVolumeLabel() {
64+
return volumeLabel;
65+
}
66+
4667
@Override
4768
public String toString() {
4869
return MoreObjects.toStringHelper(this)
4970
.add("mountPoint", mountPoint)
5071
.add("filesystemType", filesystemType)
72+
.add("volumeLabel", volumeLabel)
5173
.toString();
5274
}
5375
}

0 commit comments

Comments
 (0)