As you can read in the subject this is a huge step in the last period in Azure. Since I have been working with Azure there was a feature which always missed and caused some inconviniences during VMs administration. You have no console access to VMs so when something happened during the boot you were not able to manage by yourself. Merely you could cross your fingers and wait for the login prompt.
And now a new time begins becasue Serial console is here – in preview – for Linux and Windows VMs.
I suggest to try it and if you have any observations you can share with me or Microsoft to ensure this great feature will be available in production with full functionality. You can leave feedback about this feature when you click on Feedback button on top of the screen. (You can see here the opened bugs as well)
First impression
Username prompt is hidden
When you click on the Serial Console (Preview) button you have to wait 1-2 minutes for initialization then it seems it stops. And here I can see a small bug – I think this is acceptable now. So when you hit an enter it asks immediatelly the password.
Of course because you did not type account name you don’t know which password you should type here. So you just simply hit an other enter it says “Login incorrect” then you can type the username. 🙂
Then of course you can login with the right user and password.
Notes
The console work correctly. Not the best but this is only preview. 🙂
You can do everything you want. Nevertheless the copy/paste oprartions are not too comfortable.
<End> sometimes work sometimes not.
The WALinuxAgent sometimes lost the connection with console.
Summary
I am sure this is a great step and useful feature from Microsoft. I hope the Linux gurus also could appreciate this new function. My opinion is absolute positive regarding Serial Console
I suggest to test and open bugs because this is the best support for Microsoft and you. 🙂
In this week I would like to inform you about a bug in azure-cli 2.0.30 which can cause some inconveniences when you want to copy blobs in Azure storage accounts.
Some days ago I started to create a solution for copy files inside storage account (this is related a git pipeline solution) and I was facing an issue when I wanted to use ” az storage blob copy start” command with “–sas-token” parameter. The command was quite simple:
The specified resource does not exist.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>The specified resource does not exist.
RequestId:fe725383-701e-0002-5aae-ccdd02000000
Time:2018-04-05T07:20:26.8836489Z</Message></Error>
Traceback (most recent call last):
File "/usr/lib64/az/lib/python2.7/site-packages/knack/cli.py", line 197, in invoke
cmd_result = self.invocation.execute(args)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 347, in execute
six.reraise(*sys.exc_info())
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 319, in execute
result = cmd(params)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 180, in __call__
return super(AzCliCommand, self).__call__(*args, **kwargs)
File "/usr/lib64/az/lib/python2.7/site-packages/knack/commands.py", line 109, in __call__
return self.handler(*args, **kwargs)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/__init__.py", line 420, in default_command_handler
result = op(**command_args)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/multiapi/storage/v2017_07_29/blob/baseblobservice.py", line 3032, in copy_blob
False)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/multiapi/storage/v2017_07_29/blob/baseblobservice.py", line 3102, in _copy_blob
return self._perform_request(request, _parse_properties, [BlobProperties]).copy
File "/usr/lib64/az/lib/python2.7/site-packages/azure/multiapi/storage/v2017_07_29/common/storageclient.py", line 354, in _perform_request
raise ex
AzureMissingResourceHttpError: The specified resource does not exist.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>The specified resource does not exist.
RequestId:fe725383-701e-0002-5aae-ccdd02000000
Time:2018-04-05T07:20:26.8836489Z</Message></Error>
The specified resource does not exist.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>The specified resource does not exist.
RequestId:fe725383-701e-0002-5aae-ccdd02000000
Time:2018-04-05T07:20:26.8836489Z</Message></Error>
Traceback (most recent call last):
File "/usr/lib64/az/lib/python2.7/site-packages/knack/cli.py", line 197, in invoke
cmd_result = self.invocation.execute(args)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 347, in execute
six.reraise(*sys.exc_info())
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 319, in execute
result = cmd(params)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/commands/__init__.py", line 180, in __call__
return super(AzCliCommand, self).__call__(*args, **kwargs)
File "/usr/lib64/az/lib/python2.7/site-packages/knack/commands.py", line 109, in __call__
return self.handler(*args, **kwargs)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/cli/core/__init__.py", line 420, in default_command_handler
result = op(**command_args)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/multiapi/storage/v2017_07_29/blob/baseblobservice.py", line 3032, in copy_blob
False)
File "/usr/lib64/az/lib/python2.7/site-packages/azure/multiapi/storage/v2017_07_29/blob/baseblobservice.py", line 3102, in _copy_blob
return self._perform_request(request, _parse_properties, [BlobProperties]).copy
File "/usr/lib64/az/lib/python2.7/site-packages/azure/multiapi/storage/v2017_07_29/common/storageclient.py", line 354, in _perform_request
raise ex
AzureMissingResourceHttpError: The specified resource does not exist.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>The specified resource does not exist.
RequestId:fe725383-701e-0002-5aae-ccdd02000000
Time:2018-04-05T07:20:26.8836489Z</Message></Error>
@the1bit Thanks for bringing this to our attention. #6041 will apply the sas token specified by –sas-token for the source as well as the destination and will be available in our next release.
For now, please use –source-sas to apply the same sas towards your source, as –sas-token currently only applies towards the destination.
I tested again then I was sure there is a bug in the code. I used this command:
AzureHttpError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
AzureHttpError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
AzureHttpError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.ErrorCode: CannotVerifyCopySource
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
@the1bit I’ve raised a new issue for the bug you found: #6073
Thanks for finding this!
Workaround
There is a bug in “az storage blob copy start” with “–source-sas” parameter in azure-cli 2.0.30. I am sure they will fix this soon. MEanwhile you can apply the following workarounds:
use your sas token in “–source-sas” parameter without ‘?’
use storage account key instead of sas token.
I hope this helps to avoid some struggling until the fix will be here.
Since I am working with Azure one of biggest problem was the connection across subscriptions. Although you can use several features to achieve this state such as Site-To-Site VPN, vNet-To-vNet peering, they have some serious limitations.
From my side the most relevant is vNet-To-vNet peering whose biggest limitations the regions where you can make a connection between two subscriptions. I mean You weren’t able to create without any difficulties VNet peering between subscriptions in US and Europe. Additionally You cannot create VNet peering between a subscription in AzureCloud and a subscription in AzureGermany cloud.
This was a huge missing feature and I feel this is a beginning of a bright future where we do not need to create VPN connection – which is far expensive than VNet peering – between our worldwide subscriptions.
Of course at the moment this feature is available in some regions but I am sure this list will be expanded soon.
Automation. It is a nice topic and it is important day by day to make our life easier. There are several very good tools for automation such as Puppet, Chef, Ansible.
I would like to start a serie which covers several topics regarding Azure management with Ansible. This is the first article in this serie. Here I provide some external articles as fundamentals of knowledge. Then I will provide additional topics, scenarios, case studies and examples wit Ansible. Some of these articles will be published as Technical Thursday related articles and some of them will be published as standalone posts. 🙂
Why Ansible?
According to the official site: “Working in IT, you’re likely doing the same tasks over and over. What if you could solve problems once and then automate your solutions going forward? Ansible is here to help.”
Nevertheless during my tasks I often meet with Ansible related topics and solutions. In second hand Azure offers some options for this. For more information you can read the official documentation from Microsoft here.
Ansible articles
As I mentioned you can find some basic articles for Ansible which are great fundamentals for start learning.
In this week I would like to show a sensitive and important thing in GoLang which answers some questions and solve your problems if you just started development in Go(Lang).
When I started this – parellel with python – I was confused and I had some concerns about this language. (I still have some concerns…)
At first Iwould like to inform you this topic is not a brand new story and I am sure you can find many articles on internet on this area. Additionally there are severeal excellent documentation for Go.
We have a main file which will use our modules. Our modules contain many useful and reusable functions and codes for different goals. We wouldn’t like to put every and each functions to a file because that is not so professional and not so efficient for the future.
This contains the basic packages we would like to use during our implementation.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import(
"encoding/json"
"fmt"
)
import (
"encoding/json"
"fmt"
)
import (
"encoding/json"
"fmt"
)
We use here the JSON encoding and the “fmt”.
3. Result section – struct
We have to define a struct for result structure for JSON.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// FResult is a type of function results
type FResult struct {
Status string `json:"status"`
Message string `json:"message"`
}
// FResult is a type of function results
type FResult struct {
Status string `json:"status"`
Message string `json:"message"`
}
// FResult is a type of function results
type FResult struct {
Status string `json:"status"`
Message string `json:"message"`
}
4. Functions section
Now this will solve our business requirements which is a simple JSON result function according to string input.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// GetJSONResult for json management
func GetJSONResult(inputStr string) FResult {
result, err := json.Marshal(FResult{
Status: "success",
Message: fmt.Sprintf("%s", inputStr),
})
if err != nil {
panic(err)
}
var f FResult
err = json.Unmarshal(result, &f)
if err != nil {
panic(err)
}
return f
}
// GetJSONResult for json management
func GetJSONResult(inputStr string) FResult {
result, err := json.Marshal(FResult{
Status: "success",
Message: fmt.Sprintf("%s", inputStr),
})
if err != nil {
panic(err)
}
var f FResult
err = json.Unmarshal(result, &f)
if err != nil {
panic(err)
}
return f
}
// GetJSONResult for json management
func GetJSONResult(inputStr string) FResult {
result, err := json.Marshal(FResult{
Status: "success",
Message: fmt.Sprintf("%s", inputStr),
})
if err != nil {
panic(err)
}
var f FResult
err = json.Unmarshal(result, &f)
if err != nil {
panic(err)
}
return f
}
This waits a string and gives back a “FResult” type result. Of course this is not so easy. Before that you have to fill your FResult struct related data with the related data, check errors then convert the whole object from/to JSON. (I know this is not a real scenario) And the trick here is the following:
Use json.Marshall because Marshal returns the JSON encoding
Then use json.Unmarshall because Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by FResult If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.
Check the error during convert
Finally it returns with the required result:
return f
return f
Now we can use it from main.go
main.go
This is our main file with the main function which will call our core related function.
1. Package section
Package name
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package main
package main
package main
2. Import section
This contains the basic packages we would like to use during our implementation.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import(
"firstgo/lib"
"fmt"
)
import (
"firstgo/lib"
"fmt"
)
import (
"firstgo/lib"
"fmt"
)
IMPORTANT: For use an external library or function and include them you have to put here the related path from “src” directory. So if your project is in the “firstgo” directory and your module files inside the “lib” directory you have to import the “firstgo/lib” although your main file is also inside the “firstgo” directory.
3. Functions section
You have to define a main function which executed when you run your program. Here we have to put the module call part.
Because we imported “firstgo/lib” directory and our “core.go” module is inside it we can use our module as we use in other language. I mean: <module>.<function>(<parameter list>)
As you can see I put the function result (which is a JSON object) to a variable then we can check it immediatelly without any further converting.
Outputs, output formatting…this is a quite interesting topic during your development activities. Every time when you create a function you want to provide reusable code with excellent outputs…but how can you achieve this?
Maybe you feel this is a simple question and the answer is also simple. Nevertheless you realize some weeks later this is a little bit complex area. I mean when you choose a result type or solution you have some direction you can choose.
True/False
Simple string
Nothing 🙁
Result code (0, 1, …)
JSON
My personal choice is JSON because easy to manage and you can provide several important information for re-usage via that . For example in Azure-Cli every time you receive JSON object which contains the most important information for current activity. Moreover a JSON object is easily managed by Python.
And now I show some useful example for JSON output management by Python.
0. Use JSON in python
JSON management is very simple in Python. You merely need to import JSON module.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Import JSON module
import json
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# Convert string to JSON
myjson = json.loads(mystring)
# Use JSON data
print "{0}".format(myjson["name"])
# Import JSON module
import json
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# Convert string to JSON
myjson = json.loads(mystring)
# Use JSON data
print "{0}".format(myjson["name"])
# Import JSON module
import json
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# Convert string to JSON
myjson = json.loads(mystring)
# Use JSON data
print "{0}".format(myjson["name"])
1. Return from string
When you have a string in JSON format in your function and you would like to use it as a JSON object you need to convert the string to JSON.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# my Function
defmyFunction(inputString):
# Import JSON module
import json
# Try to convert to JSON
try:
# Convert string to JSON
myjson = json.loads(inputString)
# Return with result
return myjson["name"]
except:
# Error handling
returnFalse
# Call function
myFunction(mystring)
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# my Function
def myFunction(inputString):
# Import JSON module
import json
# Try to convert to JSON
try:
# Convert string to JSON
myjson = json.loads(inputString)
# Return with result
return myjson["name"]
except:
# Error handling
return False
# Call function
myFunction(mystring)
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# my Function
def myFunction(inputString):
# Import JSON module
import json
# Try to convert to JSON
try:
# Convert string to JSON
myjson = json.loads(inputString)
# Return with result
return myjson["name"]
except:
# Error handling
return False
# Call function
myFunction(mystring)
To convert string to JSON object you can use the “json.loads()” method.
2. Return from JSON
Sometimes you have a JSON object and you would like to give back it via your function in string format.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# my Function
defmyFunction(inputString):
# Import JSON module
import json
# Try to convert to JSON
try:
# Convert string to JSON
myjson = json.loads(inputString)
# Return with result
return json.dumps(myjson)
except:
# Error handling
returnFalse
# Call function
myFunction(mystring)
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# my Function
def myFunction(inputString):
# Import JSON module
import json
# Try to convert to JSON
try:
# Convert string to JSON
myjson = json.loads(inputString)
# Return with result
return json.dumps(myjson)
except:
# Error handling
return False
# Call function
myFunction(mystring)
# Define JSON format string
mystring = '{"name": "Python", "version": "2.7"}'
# my Function
def myFunction(inputString):
# Import JSON module
import json
# Try to convert to JSON
try:
# Convert string to JSON
myjson = json.loads(inputString)
# Return with result
return json.dumps(myjson)
except:
# Error handling
return False
# Call function
myFunction(mystring)
To convert JSON object to string you can use the “json.dumps()” method.
3. Return custom string
Finally you can create string output which is built by you.
# my Function
def myFunction(inputString):
# Return with result
return '{"status": "success", "message": "%s"}' % (inputString)
# Call function
myFunction("This is a string")
# my Function
def myFunction(inputString):
# Return with result
return '{"status": "success", "message": "%s"}' % (inputString)
# Call function
myFunction("This is a string")
Here you should not import json module to create JSON format output
Of course can combine them and use other formats…Let’s try them…
When you have many python scripts and several very useful feature inside them maybe you are thinking about it: whether can I make a WebUI over them? Then you realize you are not a web developer and you have never made WebUI. So you feel you have to spend hundreds of hours to learn web development or you should skip this option.
I was in this situation then I had found Bottle and I created a website over my python scripts. I know there are some other way to do it such as Django or Flask. For the very first usage the Bottle is a perfect choice.
In this article I would like to provide you a “getting started” guide for Bottle installation and configuration. (more or less this is a link collection)
Basics
When I started this I had three things in my mind:
I use Visual Studio for development
I would like to use it from Azure Web App
I would like to use it from a stand alone CentOS Linux
At first we are a very lucky situation because there are several article on Internet regarding this topic. Please kindly notes I am focus on Visual Studio related usage. 🙂
Then a page for Python web application project templates (this article contains that very useful information to install Python on App Service MS recommends using the site extensions. These extensions are copies of the official releases of Python, optimized and repackaged for Azure App Service.)
Note:
– Azure generally uses Windows machines under App services so your web application will be executed by an IIS
– You have to install the python extension under the App service where you would like to hosts your UI
– Bottle uses MVC modell
I know…this is another restore related post for unmanaged disk. I promise this is the last in this period… 🙂
So the concept is here for restore and you can find here the previous unmanaged disk related restore with several scripts. (the managed disk related steps are here) Now I would like to show you the amaretto related restore steps forl unmanaged disk based VM.
Some useful information before you start the restore:
Required naming convention
OS disk and Data disks related vhds must be in the following format:
OS disk:
[vmname]-osdisk.vhd
Data disk:
[vmname]-datadisk-[diskid].vhd (where the diskid represents the value of lun)
(example for 1st data disk: myvm-datadisk-0.vhd)
Prerequisites
Linux OS
Azure-Cli 2.x
Python 2.7
amaretto (Azure management tools by the1bit) package for python. You can download it from pypi and git as well.
Amaretto
In amaretto you can also find a restoreUnmanagedDiskFromVhd function in amarettorestore module which “do your job” regarding restore procedure.
What does this function do?
Get restore file from restored container
Download deploy file (generally this is a config.json with UTF-16 encoding(!))
Check file encoding – if necessary it converts from UTF-16 to UTF-8
Deallocate VM
Delete VM object (ONLY)
Get os disk information (restored vhd’s url)
Delete old unmanaged disk
Copy os disk to its original location
Get data disk information (restored vhds’ url)
Delete old unmanaged disk one-by-one
Copy data disk to its original location
Check restore result (whether all disks are restored or not)
And now let’s see the steps one-by-one:
1. Restore VM’s VHDs from backup vault
Choose the right restore point from Recovery Services vaults which belongs to target VM and Restore OSDisk and DataDisks to your storage account.
# Your VM name
vmName = "thisismyserver-1"
# resource group name where the VM is located
resourceGroup = "thisismyrg"
# location where the resources are located. (westeurope, germanycentral, ...)
location = "westeurope"
# storage account name where the VM's restored vhds are stored
sourceStorageAccount = "thisismystorage"
# 1st or 2nd access key for sourceStorageAccount
sourceSecretKey = "d22j/rr+a7br7LW6KDKV8KZkO2wCIe3m0MTKVr3Tt9B9NMZZsYxny8bvWvPwUGgZpDkE8gyAePjWCVu2IZ4LYw=="
# name of container where the restored vhds are stored
sourceContainer = "vhd6bdda0e88c88408299246c468784656546a"
# Execute restore function
amaretto.amarettorestore.restoreUnmanagedDiskFromVhd(vmName, resourceGroup, location, storageAccount, secretKey, sourceContainer)
# Your VM name
vmName = "thisismyserver-1"
# resource group name where the VM is located
resourceGroup = "thisismyrg"
# location where the resources are located. (westeurope, germanycentral, ...)
location = "westeurope"
# storage account name where the VM's restored vhds are stored
sourceStorageAccount = "thisismystorage"
# 1st or 2nd access key for sourceStorageAccount
sourceSecretKey = "d22j/rr+a7br7LW6KDKV8KZkO2wCIe3m0MTKVr3Tt9B9NMZZsYxny8bvWvPwUGgZpDkE8gyAePjWCVu2IZ4LYw=="
# name of container where the restored vhds are stored
sourceContainer = "vhd6bdda0e88c88408299246c468784656546a"
# Execute restore function
amaretto.amarettorestore.restoreUnmanagedDiskFromVhd(vmName, resourceGroup, location, storageAccount, secretKey, sourceContainer)
3. Re-create target VM with your ARM Template
In this step you merely redeploy your vm from that ARM template you had created for original vm creation.
Next week I will provide a new topic to you… 🙂
If you need some help regarding ARM Template for restore or other scenarios do not hesitate to contact me.
Last week I provided the unmanaged disk related restore description which based on the concept for restore and now I show the managed disk related restore steps on technical level.
Some useful information before you start the restore:
Required naming convention
OS disk and Data disks related vhds must be in the following format:
OS disk:
[vmname]-osdisk
Data disk:
[vmname]-datadisk-[diskid] (where the diskid represents the value of lun)
(example for 1st data disk: myvm-datadisk-0)
Prerequisites
Linux OS
Azure-Cli 2.x
Python 2.7
amaretto (Azure management tools by the1bit) package for python. You can download it from pypi and git as well.
For this type of restore we can use the previously introduced amaretto python package. This package contains the restore steps related functions one-by-one. Additionally you can also find a restoreManagedDiskFromVhd function in amarettorestore module which “do your job” regarding restore procedure.
What does this function do?
Get restore file from restored container
Download deploy file (generally this is a config.json with UTF-16 encoding(!))
Check file encoding – if necessary it converts from UTF-16 to UTF-8
Deallocate VM
Delete VM object (ONLY)
Get os disk information (size, tags – it is important from billing and categorization point of view)
Delete old managed disk
Convert vhd to managed disk (with tags and sizes from step 6)
Get data disks information (size, tags – it is important from billing and categorization point of view)
Delete old managed disks one-by-one
Convert vhds to managed disks (with tags and sizes from step 9)
Check restore result (whether all disks are restored or not)
And now let’s see the restore steps one-by-one:
1. Restore VM’s VHDs from backup vault
Choose the right restore point from Recovery Services vaults which belongs to target VM and Restore OSDisk and DataDisks to your storage account.
Note: In case of manage disk restore: Template based restore for managed disks is planned in June 2018. Thus far that we should identify the restored VHDs. This means after the restore you have vhd files instead of managed disks. 🙁
2. Configure and execute “restoreManagedDiskFromVhd” function from amaretto
You have to execute the following commands with your VM related parameters from python:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Your VM name
vmName = "thisismyserver-2"
# resource group name where the VM is located
resourceGroup = "thisismyrg"
# location where the resources are located. (westeurope, germanycentral, ...)
location = "westeurope"
# storage account name where the VM's restored vhds are stored
# Your VM name
vmName = "thisismyserver-2"
# resource group name where the VM is located
resourceGroup = "thisismyrg"
# location where the resources are located. (westeurope, germanycentral, ...)
location = "westeurope"
# storage account name where the VM's restored vhds are stored
sourceStorageAccount = "thisismystorage"
# 1st or 2nd access key for sourceStorageAccount
sourceSecretKey = "d22j/rr+a7br7LW6KDKV8KZkO2wCIe3m0MTKVr3Tt9B9NMZZsYxny8bvWvPwUGgZpDkE8gyAePjWCVu2IZ4LYw=="
# name of container where the restored vhds are stored
sourceContainer = "vhd6bdda0e88c88408299246c468784656546a"
# managedDiskAccountType (optional): sku of disk. Possible values: Standard_LRS or Premium_LRS. Default value: Standard_LRS
# managedDiskAccountType = "Standard_LRS"
# Execute restore function
amaretto.amarettorestore.restoreManagedDiskFromVhd(vmName, resourceGroup, location, sourceStorageAccount, sourceSecretKey, sourceContainer)
# Your VM name
vmName = "thisismyserver-2"
# resource group name where the VM is located
resourceGroup = "thisismyrg"
# location where the resources are located. (westeurope, germanycentral, ...)
location = "westeurope"
# storage account name where the VM's restored vhds are stored
sourceStorageAccount = "thisismystorage"
# 1st or 2nd access key for sourceStorageAccount
sourceSecretKey = "d22j/rr+a7br7LW6KDKV8KZkO2wCIe3m0MTKVr3Tt9B9NMZZsYxny8bvWvPwUGgZpDkE8gyAePjWCVu2IZ4LYw=="
# name of container where the restored vhds are stored
sourceContainer = "vhd6bdda0e88c88408299246c468784656546a"
# managedDiskAccountType (optional): sku of disk. Possible values: Standard_LRS or Premium_LRS. Default value: Standard_LRS
# managedDiskAccountType = "Standard_LRS"
# Execute restore function
amaretto.amarettorestore.restoreManagedDiskFromVhd(vmName, resourceGroup, location, sourceStorageAccount, sourceSecretKey, sourceContainer)
2018-02-2213:18:48 - Delete VM object: thisismyserver-2
2018-02-2213:18:50 - - OS DISK
2018-02-2213:18:50 - Get os disk information
2018-02-2213:18:50 - Delete old managed disk: thisismyserver-2-osdisk
2018-02-2213:18:54 - Convert os vhd to its original location
2018-02-2213:19:00 - - DATA DISKS
2018-02-2213:19:00 - Get data disks information
2018-02-2213:19:00 - Delete old data disk
2018-02-2213:19:05 - Convert data disk to its original location: thisismyserver-2-datadisk-0
2018-02-2213:19:11 - OS and Data disks are restored
True
>>> amaretto.amarettorestore.restoreManagedDiskFromVhd(vmName, resourceGroup, location, sourceStorageAccount, sourceSecretKey, sourceContainer)
2018-02-22 13:18:40 - FUNCTION Restore Managed disk based VM's vhds
2018-02-22 13:18:40 - Get restore file from restored container
2018-02-22 13:18:43 - Download deploy file
Finished[#############################################################] 100.0000%
2018-02-22 13:18:45 - Check config.json file encoding
2018-02-22 13:18:45 - Deallocate VM: thisismyserver-2
2018-02-22 13:18:48 - Delete VM object: thisismyserver-2
2018-02-22 13:18:50 - - OS DISK
2018-02-22 13:18:50 - Get os disk information
2018-02-22 13:18:50 - Delete old managed disk: thisismyserver-2-osdisk
2018-02-22 13:18:54 - Convert os vhd to its original location
2018-02-22 13:19:00 - - DATA DISKS
2018-02-22 13:19:00 - Get data disks information
2018-02-22 13:19:00 - Delete old data disk
2018-02-22 13:19:05 - Convert data disk to its original location: thisismyserver-2-datadisk-0
2018-02-22 13:19:11 - OS and Data disks are restored
True
>>> amaretto.amarettorestore.restoreManagedDiskFromVhd(vmName, resourceGroup, location, sourceStorageAccount, sourceSecretKey, sourceContainer)
2018-02-22 13:18:40 - FUNCTION Restore Managed disk based VM's vhds
2018-02-22 13:18:40 - Get restore file from restored container
2018-02-22 13:18:43 - Download deploy file
Finished[#############################################################] 100.0000%
2018-02-22 13:18:45 - Check config.json file encoding
2018-02-22 13:18:45 - Deallocate VM: thisismyserver-2
2018-02-22 13:18:48 - Delete VM object: thisismyserver-2
2018-02-22 13:18:50 - - OS DISK
2018-02-22 13:18:50 - Get os disk information
2018-02-22 13:18:50 - Delete old managed disk: thisismyserver-2-osdisk
2018-02-22 13:18:54 - Convert os vhd to its original location
2018-02-22 13:19:00 - - DATA DISKS
2018-02-22 13:19:00 - Get data disks information
2018-02-22 13:19:00 - Delete old data disk
2018-02-22 13:19:05 - Convert data disk to its original location: thisismyserver-2-datadisk-0
2018-02-22 13:19:11 - OS and Data disks are restored
True
3. Re-create target VM with your ARM Template
In this step you merely redeploy your vm from that ARM template you had created for original vm creation.
I hope it helps to solve your restore VM problem. 🙂
If you need some help regarding ARM Template for restore or other scenarios do not hesitate to contact me.
As I promised last week I provide some materials for unmanaged disk based VM restore from Recovery Services vault. Last week I posted the concept for restore and now I show the most important steps on technical level.
Some useful information before you start the restore:
Required naming convention
OS disk and Data disks related vhds must be in the following format:
OS disk:
[vmname]-osdisk.vhd
Data disk:
[vmname]-datadisk-[diskid].vhd (where the diskid represents the value of lun)
(example for 1st data disk: myvm-datadisk-0.vhd)
Prerequisites
Azure-Cli 2.x
Python 2.7
And now let’s see the steps one-by-one:
1. Stopped (deallocated) the target VM
This step is executable from PowerShell, Azure-Cli and Portal as well.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Stop (deallocated) vm from Azure-Cli 2.x
az vm deallocate --name <vm name> --resource-group <resource group name> --verbose
# Stop (deallocated) vm from Azure-Cli 2.x
az vm deallocate --name <vm name> --resource-group <resource group name> --verbose
# Stop (deallocated) vm from Azure-Cli 2.x
az vm deallocate --name <vm name> --resource-group <resource group name> --verbose
Be sure the VM is in Stopped (deallocated) status!
2.Delete necessary objects
In this step we have to delete target VM object (ONLY the virtual machine object) and vhd files which belong to target VM.
There is a sensitive topic which is important for business and IT as well. This is the BCM (Business Continuity Management). And its technical part the DRP (Disaster Recovery Plan) which related for us now. This is the topic which could cause some sleepless nights for us. Then you hear the cloud solve your and your company’s problem…so you decide to backup your on-premises and Azure VMs with a cloud solution especially Recovery Services vaults.
To get an overview you should start to read the following page: Azure Backup Documentation This is a very usefull and detailed documentation and contains the most important points such as Concepts, Samples, references. Regarding VMs you will find the following pages:
The backup is quite easy because you create Recovery Services vaults for your VMs then you configure the schedule of backup then retention time and it works independently you have unmanaged or managed disks under your VM. 😉
Restore is our fear because the consistency and the availability is critical in a disaster situation. Additionally we have to be ready to restore the unmanaged and managed disk based VMs as well.
Restore unmanaged disk based VM
This situation is that when you have VHD files on a storage account which is used by your VM as OS disk and/or Data disks. Although a simple scenario is written in Use the Azure portal to restore virtual machines article you should be ready on conceptual level to restore a VM which is a little bit complex (example: it uses multiple NICs or it was created from a labyrinthine ARM Template). In this case you cannot restore the whole VM from Recovery Services vaults. Your only one option is to restore the VM related VHD files to a storage account then recreate the VM.
The concept is here for this scenario:
Stop (deallocated) the target VM
Delete target VM object (ONLY the virtual machine object)
Delete vhd files which belong to target VM
Choose the right restorepoint from Recovery Services vaults which belongs to target VM
Restore OSDisk and DataDisks to dedicated storage account.
Move restored vhd files to original location
Re-create target VM with ARM Template
I will provide some materials for this scenario on next week.
Restore managed disk based VM
Here you do not have VHD files under VM but you have very good managed disks. These disks are standalone objects on Azure level so you can manage them on that way. Nevertheless when you restore the disks from Recovery Services vault you will realize that you will have one vhd files for each restored disks which belong to your restored VM. Why? The answer is in the article you can find above:
Templates are added as part of restore disks for recovery points taken after March 1, 2017. They’re applicable for nonmanaged disk VMs. Support for managed disk VMs is coming in upcoming releases.
Accordingly we have to wait some days or weeks until Microsoft fully supports managed disks related restore. No problem, we can apply some workarounds until that. 🙂
Managed disk restore steps (there is one additional steps here):
Stop (deallocated) the target VM
Delete target VM object (ONLY the virtual machine object)
Delete managed disks which belong to target VM
Choose the right restorepoint from Recovery Services vaults which belongs to target VM
Restore OSDisk and DataDisks to dedicated storage account. (Result will be VHDs)
Convert VHDs to Managed disk
Move restored managed disks to original location
Re-create target VM with ARM Template
I will provide some materials for this scenario on next week.
Today I would like to show you a cool feature of ARM Template which “changed the world”. Although this feature has been available since last September I felt I must say some words about it.
In the past when we wanted to make a little bit complex solution where we had to choose one or more options during deployment – according to the parameters or Customer’s requirements – we had to create separated ARM Templates for each scenario such as create a Standard or Premium storage account according to the chosen VM size.
Nevertheless the documentation says the usage is simple –
if(condition, trueValue, falseValue)
if(condition, trueValue, falseValue). If you start to make nested IF statements you would be struggling with the syntax. Therefore I would like to provide you a useful ARM Template and example which makes you life easier in this area.
Usage in template
Regarding the usage the documentation is quite simple so here is a simple example for usage in “variables” section. In this example I would like to show you how can you check that whether a string contains “s” or “S”. (the “s” inside the VM size name means that is SSD ready)
Hard to read, doesn’t it?…Here is the explanation in C#
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if(vmSizeProfile.Contains("S")){
/* Executes when the vmSizeProfile contains capital S */
if(vmSizeProfile.Contains("s")){
/* Executes when the vmSizeProfile contains lowercase s */
storageAccountType = "Premium_LRS";
}else{
/* Executes when the vmSizeProfile does not contain lowercase s */
storageAccountType = "Standard_LRS";
}else{
/* Executes when the vmSizeProfile does not contain capital S */
storageAccountType = "Standard_LRS";
}
if(vmSizeProfile.Contains("S")) {
/* Executes when the vmSizeProfile contains capital S */
if(vmSizeProfile.Contains("s")) {
/* Executes when the vmSizeProfile contains lowercase s */
storageAccountType = "Premium_LRS";
} else {
/* Executes when the vmSizeProfile does not contain lowercase s */
storageAccountType = "Standard_LRS";
} else {
/* Executes when the vmSizeProfile does not contain capital S */
storageAccountType = "Standard_LRS";
}
if(vmSizeProfile.Contains("S")) {
/* Executes when the vmSizeProfile contains capital S */
if(vmSizeProfile.Contains("s")) {
/* Executes when the vmSizeProfile contains lowercase s */
storageAccountType = "Premium_LRS";
} else {
/* Executes when the vmSizeProfile does not contain lowercase s */
storageAccountType = "Standard_LRS";
} else {
/* Executes when the vmSizeProfile does not contain capital S */
storageAccountType = "Standard_LRS";
}
I hope it helps.
Example
Finally I would like to provide you a working solution which can deploy a Storage Account according to the chosen Virtual Machine size. (I know we already use manage disks 🙂 )
In this week I would like to show you a cool feature of Azure Storage Account. A really useful function which makes our life easier if we want to store monster size files such as for blog, download. Additionally this is almost free… 🙂
Often you are facing that situation when you would like to share some large size files (zip, pdf, images) with someone. Of course you can share it via OneDrive, DropBox, Pendrive or some kind of stuff. There are many cloud solutions which support this on very secure way but you can see their capability is quite limited if you would like to use these files from your website (such as WordPress, Drupal, Joomla).
Therefore here you can see the almost free, secure and flexible solution. Now I show you how can integrate this with your WordPress site.
Here you can find the Azure and WordPress related configuration steps
Azure
Firstly you should (create a subscription in Azure and) login to your subscription (https://portal.azure.com)
Then you have to create a Storage Account inside your subscription
Click the “+ New” button on the top left corner on the screen
Then search for “storage account” expression
Choose the “Storage account – blob, file, table, queue” from the list then click to “Create” button on the blade.
Type a name which is unique on Azure level
Choose the followings to keep the cost low.
Deployment model: Resource manager
Performance: Standard
Replication: Locally-redundant storage (LRS)
Secure transfer required: Enabled
Subscription: chhose your PAY-AS-YOU-GO subscription
Resource group: Create new (type a name for here like: myresourcegroup)
Location: choose a location
Virtual networks: Disabled
Then click to “Create” button.
When you have created this account got to there and you can see the overview of it
In the storage account blade find the “Containers” options and click on it
Then click upper the “+ Container” button
Type the name for your public file container (this is same like a directory) and under the Public access level choose the “Container (anonymous access for containers and blobs)”
To create this container click to “OK” button
Now you step into this container and choose the “Upload” button to upload your large files
Then you upload the file via the panel which appears (browse the file then click “Upload”)
Great! We have a file in this container.
Click the file then a blade appears on the right side where you can find the url of the file
Copy this url and from now we can share this with anybody.
Let’s test it…
Paste the url to your browser
and hit enter and you or your friend can easily save the file
We are ready for the WordPress integration…
WordPress
We know the url of file and we can easily open or download it via our website.
Login to our WordPress site
“Add new” post
Then write your post and put a link with the file url inside it
Finally “Publish” the post.
Awesome…Anyone who visit your page can download your extra large file and this file does not “eat” your expensive WordPress disk space.
Bonus
There is a bonus at storage account side. I you would not like to use the Azure specified url you can use your own domain related url. The only thing which have to be configure the “Custom domain” inside storage account.
Briefly:
Click on “Custom domain” options at storage account
Then follow the instructions on the page
Then you can access to file via your custom url like: https://storage.yourdomain.com/mypublicfiles/exampleBigFile1.pdf