public void Install(RunningDeployment deployment) { if (deployment.Variables.GetFlag(SpecialVariables.Action.Azure.CloudServicePackageExtractionDisabled, false)) return; Log.Verbose("Re-packaging cspkg."); var workingDirectory = deployment.CurrentDirectory; var originalPackagePath = deployment.Variables.Get(SpecialVariables.Action.Azure.CloudServicePackagePath); var newPackagePath = Path.Combine(Path.GetDirectoryName(originalPackagePath), Path.GetFileNameWithoutExtension(originalPackagePath) + "_repacked.cspkg"); using (var originalPackage = Package.Open(originalPackagePath, FileMode.Open)) using (var newPackage = Package.Open(newPackagePath, FileMode.CreateNew)) { var originalManifest = AzureCloudServiceConventions.ReadPackageManifest(originalPackage); var newManifest = new PackageDefinition { MetaData = {AzureVersion = originalManifest.MetaData.AzureVersion} }; AddParts(newPackage, newManifest, Path.Combine(workingDirectory, AzureCloudServiceConventions.PackageFolders.ServiceDefinition), AzureCloudServiceConventions.PackageFolders.ServiceDefinition); AddParts(newPackage, newManifest, Path.Combine(workingDirectory, AzureCloudServiceConventions.PackageFolders.NamedStreams), AzureCloudServiceConventions.PackageFolders.NamedStreams); AddLocalContent(newPackage, newManifest, workingDirectory); AddPackageManifest(newPackage, newManifest); newPackage.Flush(); } fileSystem.OverwriteAndDelete(originalPackagePath, newPackagePath); }
void ExtractLayouts(Package package, PackageDefinition manifest, string workingDirectory) { var localContentDirectory = Path.Combine(workingDirectory, AzureCloudServiceConventions.PackageFolders.LocalContent); fileSystem.EnsureDirectoryExists(localContentDirectory); foreach (var layout in manifest.Layouts) { if (!layout.Name.StartsWith(AzureCloudServiceConventions.RoleLayoutPrefix)) continue; var layoutDirectory = Path.Combine(localContentDirectory, layout.Name.Substring(AzureCloudServiceConventions.RoleLayoutPrefix.Length)); fileSystem.EnsureDirectoryExists(layoutDirectory); foreach (var fileDefinition in layout.FileDefinitions) { var contentDefinition = manifest.GetContentDefinition(fileDefinition.Description.DataContentReference); var destinationFileName = Path.Combine(layoutDirectory, fileDefinition.FilePath.TrimStart('\\')); ExtractPart( package.GetPart(PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), contentDefinition.Description.DataStorePath)), destinationFileName); } } }
void ExtractContents(Package package, PackageDefinition manifest, string contentNamePrefix, string workingDirectory) { foreach (var namedStreamsContent in manifest.Contents.Where(x => x.Name.StartsWith(contentNamePrefix))) { var destinationFileName = Path.Combine(workingDirectory, ConvertToWindowsPath(namedStreamsContent.Description.DataStorePath.ToString()).TrimStart('\\')); ExtractPart(package.GetPart(PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), namedStreamsContent.Description.DataStorePath)), destinationFileName); } }
void AddLocalContent(Package package, PackageDefinition manifest, string workingDirectory) { foreach (var roleDirectory in fileSystem.EnumerateDirectories(Path.Combine(workingDirectory, "LocalContent"))) { var layout = new LayoutDefinition {Name = "Roles/" + new DirectoryInfo(roleDirectory).Name}; manifest.Layouts.Add(layout); AddLocalContentParts(package, manifest, layout, roleDirectory, ""); } }
void AddPackageManifest(Package package, PackageDefinition manifest) { var manifestPartUri = PackUriHelper.CreatePartUri(new Uri("/package.xml", UriKind.Relative)); var manifestPart = package.CreatePart(manifestPartUri, System.Net.Mime.MediaTypeNames.Application.Octet, CompressionOption.Maximum); using (var manifestPartStream = manifestPart.GetStream()) { manifest.ToXml().Save(manifestPartStream); } package.CreateRelationship(manifestPartUri, TargetMode.External, AzureCloudServiceConventions.CtpFormatPackageDefinitionRelationshipType); }
public void ShouldProduceValidManifestXml() { var manifest = new PackageDefinition {MetaData = {AzureVersion = "2.6"}}; manifest.Contents.Add( new ContentDefinition { Name = "ServiceDefinition/ServiceDefinition.csdef", Description = new ContentDescription { LengthInBytes = 688, HashAlgorithm = IntegrityCheckHashAlgorithm.Sha256, Hash = "NMkHuVQbi+g+ny+kvjiunBgt8rLQT8Jd9FGJvWsRtZE=", DataStorePath = new Uri("ServiceDefinition/ServiceDefinition.csdef", UriKind.Relative) } }); manifest.Contents.Add( new ContentDefinition { Name = "LocalContent/ab3574e8f52d4c939aa6ff065e8b7cfd", Description = new ContentDescription { LengthInBytes = 19469, HashAlgorithm = IntegrityCheckHashAlgorithm.Sha256, Hash = "UK4lyWPyRI6I8WNzlVP2dtiFZj+kjMIjyGieq5b4TiE=", DataStorePath = new Uri("LocalContent/ab3574e8f52d4c939aa6ff065e8b7cfd", UriKind.Relative) } }); var workerRoleLayout = new LayoutDefinition {Name = "Roles/WorkerRole1"}; workerRoleLayout.FileDefinitions.Add(new FileDefinition { FilePath = "\\Cloud.uar.csman", Description = new FileDescription { DataContentReference = "LocalContent/ab3574e8f52d4c939aa6ff065e8b7cfd", Created = DateTime.UtcNow, Modified = DateTime.UtcNow } }); manifest.Layouts.Add(workerRoleLayout); var manifestXml = new XDocument(new XDeclaration("1.0", "utf-8", "yes")); manifestXml.Add(manifest.ToXml()); var schemaSet = new XmlSchemaSet(); schemaSet.Add(null, XmlReader.Create(new StringReader(GetPackageManifestSchema()), XmlUtils.DtdSafeReaderSettings)); manifestXml.Validate(schemaSet, (o, e) => { Assert.Fail("Xml failed to validate: " + e.Message); }); }
void AddParts(Package package, PackageDefinition manifest, string directory, string baseDataStorePath) { foreach (var file in fileSystem.EnumerateFiles(directory)) { var partUri = new Uri(baseDataStorePath + "/" + Path.GetFileName(file), UriKind.Relative); AddContent(package, manifest, partUri, file); } foreach (var subDirectory in fileSystem.EnumerateDirectories(directory).Select(x => new DirectoryInfo(x))) { AddParts(package, manifest, subDirectory.FullName, baseDataStorePath + "/" + subDirectory.Name); } }
void AddLocalContentParts(Package package, PackageDefinition manifest, LayoutDefinition layout, string baseDirectory, string relativeDirectory) { var currentDirectory = Path.Combine(baseDirectory, relativeDirectory); foreach (var file in fileSystem.EnumerateFiles(currentDirectory)) { var uniqueFileName = Guid.NewGuid().ToString("N"); var partUri = new Uri("LocalContent/" + uniqueFileName, UriKind.Relative); AddContent(package, manifest, partUri, file); //add file definition var fileDate = DateTime.UtcNow; //todo: use original timestamps if un-modified layout.FileDefinitions.Add( new FileDefinition { FilePath = "\\" + Path.Combine(relativeDirectory, Path.GetFileName(file)), Description = new FileDescription { DataContentReference = partUri.ToString(), ReadOnly = false, Created = fileDate, Modified = fileDate } }); } foreach (var subDirectory in Directory.GetDirectories(currentDirectory).Select(x => new DirectoryInfo(x))) { AddLocalContentParts(package, manifest, layout, baseDirectory, Path.Combine(relativeDirectory, subDirectory.Name)); } }
void AddContent(Package package, PackageDefinition manifest, Uri partUri, string file) { var part = package.CreatePart( PackUriHelper.CreatePartUri(partUri), System.Net.Mime.MediaTypeNames.Application.Octet, CompressionOption.Maximum); using (var partStream = part.GetStream()) using (var fileStream = fileSystem.OpenFile(file, FileMode.Open)) { fileStream.CopyTo(partStream); partStream.Flush(); fileStream.Position = 0; var hashAlgorithm = new SHA256Managed(); hashAlgorithm.ComputeHash(fileStream); manifest.Contents.Add(new ContentDefinition { Name = partUri.ToString(), Description = new ContentDescription { DataStorePath = partUri, LengthInBytes = (int) fileStream.Length, HashAlgorithm = IntegrityCheckHashAlgorithm.Sha256, Hash = Convert.ToBase64String(hashAlgorithm.Hash) } }); } }