Not able to mount VHD drive on azure server - c#

Please help me. I am writing following code to mount the vhd file. But I am not able to mount it. It works fine locally but when I deploy it on azure server the webrole remains offline. I tried by removing foreach block below but in vain. But when I removed the code "Global.driveLetter = drive.Mount(localCache.MaximumSizeInMegabytes - 20, DriveMountOptions.Force);" role got ready on server. But I can't do this because this is the key statement to mount the drive.
What would be the problem?
private static void MountAzureDrive()
{
string connectionStringSettingName = "AzureConnectionString";
string azureDriveContainerName = "azuredrives";
string azureDrivePageBlobName = Guid.NewGuid().ToString("N").ToLowerInvariant();
string azureDriveCacheDirName = Path.Combine(Environment.CurrentDirectory, "cache");
CloudStorageAccount.SetConfigurationSettingPublisher((a, b) =>
{
b(RoleEnvironment.GetConfigurationSettingValue(connectionStringSettingName));
});
//CloudStorageAccount storageAccount=CloudStorageAccount.FromConfigurationSetting(connectionStringSettingName);
CloudStorageAccount storageAccount=CloudStorageAccount.DevelopmentStorageAccount;
LocalResource localCache=RoleEnvironment.GetLocalResource("InstanceDriveCache");
CloudDrive.InitializeCache(localCache.RootPath + "cache", localCache.MaximumSizeInMegabytes);
// Just checking: make sure the container exists
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
blobClient.GetContainerReference("drives").CreateIfNotExist();
// Create cloud drive
//WebRole.drive=storageAccount.CreateCloudDrive(blobClient.GetContainerReference("drives").GetPageBlobReference("Test.VHD").Uri.ToString());
WebRole.drive = storageAccount.CreateCloudDrive("drives/Test.VHD");
try
{
WebRole.drive.CreateIfNotExist(512);
}
catch (CloudDriveException ex)
{
// handle exception here
// exception is also thrown if all is well but the drive already exists
}
foreach (var d in CloudDrive.GetMountedDrives())
{
var mountedDrive = storageAccount.CreateCloudDrive(d.Value.PathAndQuery);
mountedDrive.Unmount();
}
//Global.driveLetter = drive.Mount(25, DriveMountOptions.Force);
Global.driveLetter = drive.Mount(localCache.MaximumSizeInMegabytes - 20, DriveMountOptions.Force);
}
Thanks in advance.

Maybe this is stating the obvious, but... when you deploy to Windows Azure, did you change the storage account from dev storage? You have the dev storage emulator hard-coded:
CloudStorageAccount storageAccount=CloudStorageAccount.DevelopmentStorageAccount;

Related

Google DriveService Files.List() not returning results

Edit:
I've tried granting the SA access to my personal drive (within the organization Workspace) to do some troubleshooting. After granting rights to the SA to a particular folder and rewriting the code to examine that folder, it successfully returned information about files within the test folder. The conclusion is the SA has been set-up correctly by our IT department and does have adequate scope and rights to read files in our organizations Workspace. So, the questions remain: why can't it return information about files in a Shared Drive? What other parameters need to be set in order to get it to return those files? Are there entirely other functions that need to be used? I did notice the deprecated TeamDrives.List() function, but the guidance when trying to use it was to use Files.List() as I had written originally.
--- end edit ---
We have a Google Workspace environment. I've been granted a Service Account (SA) by our IT department and am trying to use it to help maintain access rights. The SA has been granted Content Manager rights to a shared drive instance.
I've tried following along this YouTube tutorial. In stepping through the code execution, it appears to log in correctly, but it is not returning any files. I've tried substituting the full URL for the file ID of the root folder I'd like to examine, but then it returns a 404 error, so I think it is finding the correct folder.
If the file ID is used the code runs without errors, it simply returns no files (and there are hundreds of folders and files within the root).
Any suggestions?
namespace DriveQuickstart
{
class Program
{
static string[] Scopes = { DriveService.Scope.DriveReadonly };
private const string PathToServiceAccountKeyFile = #"<path to jason Service Account file>";
private const string ServiceAccountEmail = #"<Service Account "email">";
static void Main(string[] args)
{
MainAsync().Wait();
}
static async Task MainAsync()
{
var credential = GoogleCredential.FromFile(PathToServiceAccountKeyFile)
.CreateScoped(new[] { DriveService.ScopeConstants.Drive });
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential
});
var request = service.Files.List();
request.IncludeItemsFromAllDrives = true;
request.SupportsAllDrives = true;
request.Q = "parents in '<id of "root" folder in shared drive>'";
FileList results = await request.ExecuteAsync();
foreach (var driveFile in results.Files)
{
Console.WriteLine($"{driveFile.Name} {driveFile.MimeType} {driveFile.Id}");
}
}
}
}
OK, it appears the #DAIMTO example is specific to personal drives. The Q() parameter syntax is incorrect for Team drives in the example. To make it work in Team environment:
IncludeItemsFromAllDrives parameter must be set to true
SupportsAllDrives parameter must be set to true
the Q search parameter syntax for finding specific directories is:
Q = "'folder_ID' in parents and mimeType = 'application/vnd.google-apps.folder'"; -- or mimeType of your choice
(note: this is reversed from the youtube example of "parents in 'folder_ID'")

How to fix "request error" from google cloud storage?

I used google.cloud.storage for .mp3 files. I tried it before and it worked.
now I writed another new function that uses the existing storage function.
everything was suppose to work but I get this weird error:
"Google.Apis.Requests.RequestError
text-to-speach#XXXXXXXXXXX.iam.gserviceaccount.com does not have storage.objects.create access to objectsound/voiceAnimals20.mp3. [403]"
I dont know what to begin with. can anybody help me?
the Ok storage function is here:
public static string VoiceStorage(int catId, string URL,
Dictionary<string, int> voicesCounter)
{
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
#"C:\wordproject-XXXXXXXXXX.json");
// upload the image storage
//----------------
string voiceName;
voiceName = "voice" + BLLcategory.GetCategoryById(catId).CategoryName
+ voicesCounter[BLLcategory.GetCategoryById(catId).CategoryName]++ +
".mp3";
string bucketName = "XXXXXXXX";
var storage = StorageClient.Create();
using (var f = File.OpenRead(URL))
{
try
{
var res = storage.UploadObject(bucketName, voiceName, null,
f);
URL = "https://storage.cloud.google.com/" + bucketName + "/" +
voiceName;
}
catch (Exception e)
{
throw e;
}
}
return URL;
}
the new not working function is:
private void button12_Click(object sender, EventArgs e)
{
foreach (COMimageObject obj in BLLobject.GetObjects())
{
if(obj.VoiceURL==null)
{
try
{
string url=BLLtextToSpeach.TextToSpeach(obj.Name);
url=BLLtextToSpeach.VoiceStorage(
BLLimage.GetImageById(obj.ImageID).CategoryID,
url, voicesCounter);
BLLobject.UpdateVoiceURL(obj.ObjectId, url);
}
catch (Exception)
{
throw;
}
}
}
}
the catch happening after the line with url=BLLtextToSpeach.VoiceStorage
tnx!!
What the error mean is that the service account of the text-to-speach api doesn't have create access on the objectsound bucket. Go to the bucket permissions and add the text-to-speach service account with storage creator rights.
When you get this error:
[403] Errors [ Message[.................iam.gserviceaccount.com does
not have storage.buckets.list access to the Google Cloud project.
you need to have permissions in your service account from the IAM to read the buckets
storage.buckets.get Read bucket metadata, excluding IAM policies.
storage.buckets.list List buckets in a project. Also read bucket
metadata,
https://cloud.google.com/storage/docs/access-control/iam-permissions
The "Firebase Admin" will enable all necessary permissions.

Copy file from one Azure storage account to another

I am trying to copy a file from one storage account to another account using StartCopy method to copy the file. Check the below code.
CloudStorageAccount sourceStorageAccount = CloudStorageAccount.Parse(#"source storage account connection string");
CloudStorageAccount destStorageAccount = CloudStorageAccount.Parse(#"destination storage account connection string");
CloudBlobClient sourceBlobClient = sourceStorageAccount.CreateCloudBlobClient();
CloudBlobClient destBlobClient = destStorageAccount.CreateCloudBlobClient();
var sourceContainer = sourceBlobClient.GetContainerReference("sourceContainer");
var destContainer = destBlobClient.GetContainerReference("destContainer");
CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference("copy.txt");
CloudBlockBlob targetBlob = destContainer.GetBlockBlobReference("copy.txt");
targetBlob.StartCopy(sourceBlob);
But it always return the following error.
Microsoft.WindowsAzure.Storage.StorageException: 'The remote server
returned an error: (404) Not Found.'
What am I missing here ?
Note, the same code works perfectly if I try to copy files from one container to another within same storage account.
Take a look at the following example on how a copy should be performed (taken from Introducing Asynchronous Cross-Account Copy Blob):
public static void CopyBlobs(
CloudBlobContainer srcContainer,
string policyId,
CloudBlobContainer destContainer)
{
// get the SAS token to use for all blobs
string blobToken = srcContainer.GetSharedAccessSignature(
new SharedAccessBlobPolicy(), policyId);
var srcBlobList = srcContainer.ListBlobs(true, BlobListingDetails.None);
foreach (var src in srcBlobList)
{
var srcBlob = src as CloudBlob;
// Create appropriate destination blob type to match the source blob
CloudBlob destBlob;
if (srcBlob.Properties.BlobType == BlobType.BlockBlob)
{
destBlob = destContainer.GetBlockBlobReference(srcBlob.Name);
}
else
{
destBlob = destContainer.GetPageBlobReference(srcBlob.Name);
}
// copy using src blob as SAS
destBlob.StartCopyFromBlob(new Uri(srcBlob.Uri.AbsoluteUri + blobToken));
}
}
Hope it helps!
Here is another way to do this using TransferManager.CopyAsync Method
CloudStorageAccount sourceStorageAccount = CloudStorageAccount.Parse(#"source storage account connection string");
CloudStorageAccount destStorageAccount = CloudStorageAccount.Parse(#"destination storage account connection string");
CloudBlobClient sourceBlobClient = sourceStorageAccount.CreateCloudBlobClient();
CloudBlobClient destBlobClient = destStorageAccount.CreateCloudBlobClient();
var sourceContainer = sourceBlobClient.GetContainerReference("sourceContainer");
var destContainer = destBlobClient.GetContainerReference("destContainer");
CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference("copy.txt");
CloudBlockBlob targetBlob = destContainer.GetBlockBlobReference("copy.txt");
TransferManager.CopyAsync(sourceBlob, targetBlob, true).Wait();
TransferManager is under the namespace Microsoft.WindowsAzure.Storage.DataMovement. To get the reference install Microsoft.Azure.Storage.DataMovement in nuget manager.
i recently ran into this error trying to copy from /uploads to /raw within a single blob account.
The issue was that the container /raw didn't exist on the destination side within the test environment.
(ie, this error is actually thrown by the destination, not the source)

Connecting to SQLite Database on Azure File Storage

Problem:
I cannot figure out what connection string to use to connect a WPF desktop application to a SQLite database on Azure File Storage. Thanks to the MSDN Documentation I am able to access the CloudFile from the app (so I have access to the URI), but when I pass the URI to a connection string to create a connection and then try to open the connection, I get an error message that my URI is invalid. The connection works fine when I try to connect to a SQLite database on my hard drive. Do I need to pass a key or something to the SQLite connection string to connect to a database on Azure File Storage? Is it even possible?
/// <summary>
/// Add all online (Azure file storage) data sources
/// </summary>
private void FindOnlineDataSources()
{
var accountName = "myAccountName";
var keyValue = "myKeyValue";
var useHttps = true;
var exportSecrets = true;
var storageCredentials = new StorageCredentials(accountName, keyValue);
var storageAccount = new CloudStorageAccount(storageCredentials, useHttps);
var connString = storageAccount.ToString(exportSecrets);
// Create a CloudFileClient object for credentialed access to Azure Files.
CloudFileClient fileClient = storageAccount.CreateCloudFileClient();
// Get a reference to the file share we created previously.
CloudFileShare share = fileClient.GetShareReference("myShare");
// Ensure that the share exists.
if (share.Exists())
{
// Get a reference to the root directory for the share.
CloudFileDirectory rootDir = share.GetRootDirectoryReference();
// Get a reference to the directory we created previously.
CloudFileDirectory sampleDir = rootDir.GetDirectoryReference("myDirectory");
// Ensure that the directory exists.
if (sampleDir.Exists())
{
// Get a reference to the file we created previously.
var fileList = sampleDir.ListFilesAndDirectories();
foreach (var fileTemp in fileList)
{
if (fileTemp is CloudFile && TestConnection(SQLiteOnlineConnectionBuilder(fileTemp.StorageUri.PrimaryUri.AbsoluteUri)))
{
// Store reference to data source
}
}
}
}
}
/// <summary>
/// Test data source connection to determine if it is accessible
/// </summary>
private bool TestConnection(DbConnection connection)
{
bool retval = false;
try
{
connection.Open();
connection.Close();
retval = true;
}
catch { }
return retval;
}
/// <summary>
/// Create SQLite connection from URI string
/// </summary>
private DbConnection SQLiteOnlineConnectionBuilder(string uri)
{
return new SQLiteConnection
{
ConnectionString = new SQLiteConnectionStringBuilder
{
Uri = uri,
ForeignKeys = true,
BinaryGUID = false,
}.ConnectionString
};
}
Background:
I am building a desktop app for use within my company. The data for the app is held in a SQLite database. We will only have a maximum of 5 users accessing the data at one time so I decided it would be unnecessary to try to set up a full server - SQLite seems like a great option.
However, I am trying to put the SQLite database into our Azure File Storage account so that multiple users can access it thru the desktop app wherever they have internet access. We don't have a central company network so I figured Azure File Storage would be the way to go.
Hey so one option with Azure File Share that is not very secure but might suit your needs is to map the azure file share to where the desktop app resides. Then you can just point to the sqlite *db file inside the mapped drive.
https://learn.microsoft.com/en-us/azure/storage/files/storage-how-to-use-files-windows - how to make the mapping.

Azure Storage API "StartCopyFromBlob"

I am trying to copy a blob from one location to another and it seems like this method is obsolete. Everything I've read says I should use "StartCopy". However, when I try this it doesn't copy the blob. I just get a 404 error at the destination.
I don't seem to be able to find any documentation for this. Can anyone advise me on how to do this in the latest version of the API or point me in the direction of some docs.
Uri uploadUri = new Uri(destinationLocator.Path);
string assetContainerName = uploadUri.Segments[1];
CloudBlobContainer assetContainer =
cloudBlobClient.GetContainerReference(assetContainerName);
string fileName = HttpUtility.UrlDecode(Path.GetFileName(model.BlockBlob.Uri.AbsoluteUri));
var sourceCloudBlob = mediaBlobContainer.GetBlockBlobReference(fileName);
sourceCloudBlob.FetchAttributes();
if (sourceCloudBlob.Properties.Length > 0)
{
IAssetFile assetFile = asset.AssetFiles.Create(fileName);
var destinationBlob = assetContainer.GetBlockBlobReference(fileName);
destinationBlob.DeleteIfExists();
destinationBlob.StartCopyFromBlob(sourceCloudBlob);
destinationBlob.FetchAttributes();
if (sourceCloudBlob.Properties.Length != destinationBlob.Properties.Length)
model.UploadStatusMessage += "Failed to copy as Media Asset!";
}
I'm just posting my comment as the answer to make it easier to see.
It wasn't the access level of the container. It wasn't anything to do with StartCopy either. It turned out to be these lines of code.
var mediaBlobContainer = cloudBlobClient.GetContainerReference(cloudBlobClient.BaseUri + "temporarymedia");
mediaBlobContainer.CreateIfNotExists();
Apparently I shouldn't be supplying the cloudBlobClient.BaseUri, just the name temporarymedia.
var mediaBlobContainer = cloudBlobClient.GetContainerReference("temporarymedia");
There was no relevant error message though. Hopefully it'll save another Azure newbie some time in future.

Categories

Resources