Android Xamarin App- Sign your app using a keystore in a Release Pipeline

keystore secure file uploaded

To sign your Xamarin Android app using Visual Studio, you can use the keystore setings in the project properties. This will generate a jks file for Windows.

See Compile steps: https://docs.microsoft.com/en-us/xamarin/android/deploy-test/release-prep/?tabs=windows#compile

Then continue to these steps to export the JKS file: https://docs.microsoft.com/en-us/xamarin/android/deploy-test/signing/?tabs=windows

Once you export the app, you can copy the file: C:\Users\EricSchrader\AppData\Local\Xamarin\Mono for Android\Keystore\DevOps

android xamarin keystore file

 

Click Secure Files in Azure DevOps pipeline for your project:

azure devops secure file tab

Select your keystore file

pick keystore file

Now you can upload the keystore file to Azure DevOps Pipeline:

keystore secure file uploaded

Then you can update the build pipeline to use the keystore file and password (password stored in Library variable for security)

add build with keystore

 

Then simply run the build and grant access to the Variables group.

Azure App Center- Android Xamarin test run error on Windows fix

Microsoft Azure App Center appcenter test run uitest

There are quite a few steps to run apps on the App Center while configuring Test Runs in Xamarin.

First, install the following:

  1. Android SDK https://developer.android.com/studio
  2. Visual Studio 2019 with the Xamarin addon in the Visual Studio Installer:
    1. visual studio xamarin install
  3. Java SDK http://java.sun.com/javase/downloads/index.jsp

Once everything was installed, I restarted my command prompt, opened my Xamarin Android app project in VS and did a Debug build to demo the app. Once I did this, that triggered the build for the APK file.

Then I do the commands the over in the web browser Microsoft App Center (https://appcenter.ms), but I add a bug fix parameter to the end of the Running Tests command (–uitest with path).

Microsoft Azure App Center appcenter test run uitest

appcenter login

appcenter test run uitest --app "DevOps-Training-1/Android-xamarin" --devices "DevOps-Training-1/both" --app-path C:\vs\MobileDevOps\MobileDevOps\bin\Debug\com.companyname.MobileDevOps.apk --test-series "master" --locale "en_US" --build-dir C:\vs\MobileDevOps\UIAndroidTest\bin\Debug --uitest-tools-dir C:\Users\EricSchrader\.nuget\packages\xamarin.uitest\3.0.3\tools

You will get an ANDOID_HOME error,

(No path) - Not set. [ Source: ANDROID_HOME ]

Then, set the ANDOID_HOME Windows Android SDK location (make sure you replace the user desktop account with your current user path)

set JAVA_HOME=C:\Users\EricSchrader\AppData\Local\Android\Sdk
set PATH=%PATH%;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools

 

That should get you to the next error, JAVA_HOME.

If you see this error:

Java Development Kit (JDK) not found. Please make sure that it is installed and if it's still not located, please set the JAVA_HOME environment variable to point to the directory.

Then, set the JAVA_HOME path (and make sure your JDK version matches)

  • Overview: https://docs.oracle.com/cd/E19182-01/821-0917/inst_jdk_javahome_t/index.html
  • Actual commands I used (NOTE YOUR VERSION and make sure that path exists, otherwise replace with your jdk- version number)
set JAVA_HOME=C:\Program Files\Java\jdk-14.0.2
set PATH=%PATH%;%JAVA_HOME%\bin

Once all is done, the app test will be submitted and complete without issues:

app center andoid xamarin

 

Check out Donovan Browns post as well for an alternative way of doing this in VS. I was using CMDer, https://www.donovanbrown.com/post/Migrating-from-Xamarin-Test-Cloud-to-App-Center-Test

SharePoint Online- Bad service principal breaks SharePoint Admin API Access “Global Service Principal ID Error: Error: {}” Resolved

Could not retrieve Global Service Principal ID Error

We recently ran into an issue when creating SPFX Azure Active Directory App registrations using an O-Auth Implicit flow that our SharePoint Admin Center API Access page then gave an error:

Could not retrieve Global Service Principal ID Error: Error: {}
Could not retrieve Global Service Principal ID Error: Error: {}
Could not retrieve Global Service Principal ID Error: Error: {}

And when using O365 CLI, I was getting the same error trying to add a new serviceprincipal or list them:

o365$ spo serviceprincipal grant list
Error: Another object with the same value for property identifierUris already exists.

Error: Another object with the same value for property identifierUris already exists.
Error: Another object with the same value for property identifierUris already exists.

So now I am completely locked out of interacting with SharePoint Online to Azure AD Applications until this is fixed.

I opened a case with SharePoint Online MS Support and they said its on the Azure side but they would look into it for me.

After a few days they got back to me and said it was due to a bad Azure AD App Registration tagged under SharePoint that is causing the error. GREAT! I now have a place to start.

  1. Go into Azure Active Directory and go to App Registrations and search for “SharePoint”. Your “broken app” is somewhere in one of these two registrations.

    App registrations for SharePoint
    App registrations for SharePoint
  2. Big thanks to this article where it says how to find the bad one, https://github.com/SharePoint/sp-dev-docs/issues/3891#issuecomment-494868401 
    In the API Access admin page of SP admin https://yourcompany-admin.sharepoint.com/_layouts/15/online/AdminHome.aspx#/webApiPermissionManagement, go to view source and search for spfx3rdPartyServicePrincipalId. You will find a GUID, THIS IS THE GOOD ONE. The other application is bad.
    Good one (found in view source of Admin page- “spfx3rdPartyServicePrincipalId”:”ebxxxx-xxxxx-xxxxxxx899d1
  3. No go back into app registrations and map out what GUIDs belong where
    Good ID: “SharePoint Online Client Extensibility Web Application Principal
  4. That means the other one is bad! “SharePoint Online Client Extensibility Web Application Principal Helper
    According to the above article, deleting this one fixes it. AND IT DID!
    Object ID 218 is the good one, and the top one 421 is BAD!
  5. Sure enough, after removing the bad application I can now access the API Access page!

So after removing every single bad VM, app registration or enterprise app, it all comes down to removing the bad “SharePoint Online Client Extensibility Web Application Principal Helper” app registration above. Now everything works as expected and I can approve my app requests!

Big lesson learned!

Now I can do a Enable-SPOTenantServicePrincipal without errors:

Hope this helps and leave any comments below on your experience with this error.

Microsoft Teams cloud phone system and Skype for Business deployment

Our VoIP solution here at the office was previously Ooma. They are great, and rarely did we have issues with their service. However, we wanted to consolidate our VoIP phonelines with Skype for Business/Microsoft Teams. So here is the process of how we ported the numbers.

I believe this article is unique because I do not come from a VoIP telephony background, but rather an O365/SharePoint background. I love PowerShell but try to avoid it deep into very old Legacy and Skype commands where Teams has not developed a UI around it yet. I could not find an article or articles quite like what I am sharing. If that is because I am doing it wrong, please post some comments on any improvements or new-released features that may make everyone lives easier.

Changing our Phone system to Skype steps:

  1. Purchase O365 phone/voice licenses (This is important)
  2. Purchase any “hard phones” for your office (I picked a Skype for Business compatible Polycom phone because of previous issues with the new Microsoft Teams YeaLink phones, read more about this below)
  3. Put in phone number porting request in Skype for Business Legacy Portal (plan a date a week out or they will bump you a week out randomly)
  4. Setup your infrastructure (whatever that means)
  5. Conference Room Physical Phone configuration
  6. The big day- your numbers are being transferred
  7. End results
  8. Future steps/improvements

Purchase O365 phone/voice licenses (This step is important)

Its not easy to purchase licenses. Why? Because you need to know EXACTLY what to search for, AND choose “Addon” for the filter on the Purchase Services page.

Auto Attendant (for your main line)- Free

Add-on license when you search for “Phone System–Virtual User” per this article: https://docs.microsoft.com/en-us/microsoftteams/teams-add-on-licensing/virtual-user

  1. The UI for getting to these is terrible. Its like they hide a ton of products that are not E3 or E5, but hey, that’s what we have to work with….
  2. You have to perform these 3 steps. Go to O365 Admin portal > Billing > Purchase Services, then type this in search “Phone System–Virtual User” and hit enter. Then this is the crazy UI piece, click “Show all 1” itself (don’t expand it) to get to way more licenses…
  3. One more step to click “Add-ons” below under Other categories (yea… I know this is nuts…)
  4. And FINALLY you can find the EXACT string you searched for (terrible search results display on the last 2 pages. I am scarred this is the “new” admin center). Click on the  Phone System Virtual User header text to be taken to a cart checkout. Since its free I added 4 for my Main line numbers

User calling plans/licenses

Do they need to dial out to other numbers from Skype for Business?

If so, they will need a Domestic Calling Plan license

All users with a phone number in the Cloud will require a “Common Area Phone” license on top of their Office 365 license (E3, F1, Office Essentials, etc.)

If users want a Skype for Business conference bridge dial in number to be added to Skype invites, they can purchase a Audio Conferencing license.

Here is how we licensed our users:

  • Remote employees or contractors without a need for a phone line:Free
    • Office 365 E3 plan- $20/user/mo or free with MPN
    • They can use Teams and Skype for Business clients just fine to collaborate
  • Onsite/remote Employees that require a phone line$20/user/mo
    • Office 365 E3 $20/mo (consider E5 at $35/mo if you don’t have free E3’s like we do as a MS Partner. This might save you $10-$20/mo)
    • Common Area Phone $8/user/mo
    • Domestic Calling Plan $12/user/mo (International is $20)
  • Employees who schedule conference calls regularly$24/user/mo
  • Conference Room Phone $20/mo
    • Office 365 E3 (I could have used a cheaper license but I wanted an Exchange calendar for an interim Conference Room scheduling solution)
    • Common Area Phone $8/user/mo
    • Domestic Calling Plan $12/user/mo (International is $20)

The costs add up quick but considering Ooma costs $30/user/mo O365 can save about $10/user/mo and have one less separate system to manage.

Purchase any “hard phones” for your office

I picked a Skype for Business compatible Polycom phone because of previous issues with the new Microsoft Teams YeaLink phones.

$129 on Amazon https://www.amazon.com/dp/B01IF4VH6I/ref=cm_sw_em_r_mt_dp_U_mm1xDb4MTXRY9

Hooked it up with a single cat6 cable over PoE (power over ethernet) which I placed on the other side of this cable $20. Less wires and cords always creates a clean experience. https://www.amazon.com/gp/product/B001PS9E5I/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

Put in phone number porting request in Skype for Business Legacy Portal

Tip: plan a date a week out or they will bump you a week out randomly by the O365 number porting team

  1. Create a schedule of the numbers you want to transfer over if you are not doing them all at once.
  2. Navigate to the O365 Admin Portal > Teams Admin > Skype for Business Legacy Admin Portal> Voice > Port Orders and create a new Port Order https://webdir2a.online.lync.com/LSCP/PortOrderNew/NewPortOrderWizard
    1. Specify your old VoIP provider account number (probably the billing phone number). All this info should match the old VoIP provider info:
    2. Create a helpful name for 1 or more numbers that are being ported. Or, you can just port over everything at once and not test 1 number.
    3. Pick a date at least 1 week out. If you pick a sooner date they will just reschedule.
    4. Just agree with the billing persons name.
    5. Done!
  3. Now wait until the numbers are ported over.

One final tip, assign your licenses to users then assign the numbers BEFORE the port finishes (give the new request a day to get scheduled then do it). The Skype team adds your numbers in early, so you can set up everything before the transfer, then Boom once the transfer happens the users number will still work without you having to jump into the Admin Portal and assign the number.

Setup your infrastructure

Assigning phone numbers to users

The easiest way I have been able to do this is through the classic Skype For Business Admin Portal. You might be able to do this from Teams Admin center but I think I was just missing user licenses then.

  1. Once a user has a license assigned (if they dont they do NOT show up here, even if you filter to “All”. Fix the licenses first if the user shows up funky here, or as on-premises PSTN.
  2. Assign the user a number an an Emergency Location. Emergency locations are super important for your business VoIP. If someone calls 911 Emergency, they do not know your company location, suite number, name, etc. This saves first responders valuable time and could save your our your co-workers life. Safety first admins. Save a life! Its just 1 tab over.
  3. Then assign the number to the user:

Thats it! Give it a few minutes and the user can receive calls.

Adding Audio Conferencing to users

This one is super easy, just buy and assign the license to an existing user. All of their existing Skype for Business meetings will auto-update with a dial in magically after a restart or a day.

This is managed in the Classic Skype Admin Center

Auto Attendant- Main line greeting and directory

This is the “you have reached _____ business name here ____ . Press 0 for reception or 1 for blah, etc.”

You can upload your own audio recording or translate the text to a robot voice.

First, add a “resource account” (basically a name/number association for caller ID and license features) that we can associate to our greeting in the next step.

Resource Account

  1. Go to Teams Admin > Org wide settings > Resource Accounts
    1. Create a new Auto Attendant account and give it a good username. This is what shows up when a call is transferred to your Skype users. This ugly one was auto generated because I created it from the Auto Attendant screen instead of here. Lesson learned. I an now naming the username SileoMainLine234 or whatever my numbers are.
    2. Repeat creating these 1 per number you have for the Auto Attendant (not user phone numbers)
    3. Assign a license back in the Office 365 Admin > users section of the top level portal. I assigned my Resource Accounts a Phone System – Virtual User free license:
    4. More information can be found here on the process: Assigning a number to a Resource Account: https://docs.microsoft.com/en-us/microsoftteams/manage-resource-accounts#create-a-resource-account-in-microsoft-teams-admin-center (This one was hard to find)

Back to creating a new Auto Attendant

  1. Go to Teams Admin > Voice > Auto Attendants
  2. Add a new Auto Attendant
  3. Select your resource accounts to assign to the greeting
  4. For security, you might want to lock down directory access only to a certain group. I have not seen any guidance on this, but I don’t want someone being able to guess ALL of my users.

Conference Room Physical Phone configuration

Here I go through how to configure the Polycom VVX411 phone for SKype for Business as a “user account” but will be in a shared conference room. This is where my post becomes non-traditional. I would have preferred to use a YeaLink conference speaker phone but it just was not ready for prime time and required a ton of PowerShell to configure. Simple for now until Microsoft Team Rooms get a UI for configuration.

The big day- your numbers are being transferred

Hopefully you have already associated your numbers to users before the cutover. Now you can sit back and make sure the phone number works. Inbound, outbound, etc.

End results

Conference Room Phone that I can send Skype meeting invites to and join with 1 click.

Skype for Business soft phone capabilities for my team

  • Visual voicemail
  • Teams Phone app interface
  • Call forwarding and simultaneous ring
  • Domestic/international calling plans
  • Tip for 1 touch join. Format your numbers so you can click on them to join a web meeting, pause and enter the access code automatically. Example:
tel:+180012345678,,00112233#

Then, you and other users can just click on the link to join a meeting rather than write it down or try to memorize the dial in.

Main line auto attendant recording and “operator”

Future steps/improvements

I hope someday to get a sweet Microsoft Teams Room system setup, but those are a few thousand dollars. They also require a ton of custom PowerShell scripts to setup. The fact that there is no UI and its pure PowerShell to configure tells me I will be one of the first pioneers to set it up. Thats a big investment for a small business, so I am holding off.

Future hopes:

  • PowerShell-less configuration
    • Teams physical phones
    • Team rooms
    • Meeting Room license
      • Exchange calendar for conference rooms

 

Azure VM Remote Desktop error- CredSSP encryption oracle remediation

I ran into an issue where I could not Remote Desktop to my Azure VM and was getting this error:

Remote Desktop Connection
An authentication error has occurred.
The function requested is not supported

Remote computer: 13.64.xx.xxx
This could be due to CredSSP encryption oracle remediation.
For more information, see https://go.microsoft.com/fwlink/?linkid=866660

The issue was a March 2018 security update patch that was applied to my CLIENT computer, so I cannot connect to the Azure SERVER Windows Server 2012 R2 Datacenter VM that has not had updates applied recently.

https://blogs.technet.microsoft.com/mckittrick/unable-to-rdp-to-virtual-machine-credssp-encryption-oracle-remediation/

Examples:
1.       If the client is updated and you try to RDP to an Azure VM that was not updated, then it will be blocked and see the error message.
2.       If the client is not patched while server is updated, RDP can still work. But the session will be exposed to the attack.
3.       If both client & server are patched with default setting (Mitigated), RDP will work in a secure way.

I really could not find a solution anywhere that worked. Just a bunch of links to archaic Windows Updates websites from the early 2000’s (reminds me how far we came)

Solution

The solution is to Uninstall the KB on your CLIENT computer so you can install the KB on your SERVER VMs, then you can reinstall the KB on your CLIENT if you would like.

 

Detailed Steps

  1. I UNINSTALLED the KB4103721 from my Windows 10 machine, so I could patch my VM’s and rebooted.
  2. I RDP’ed from my CLIENT to each SERVER that was not patched, and installed the patch (note a different OS so a different KB patch)
  3. Applied Installed a KB on each SERVER and rebooted http://www.catalog.update.microsoft.com/Search.aspx?q=KB4103715
  4. On my CLIENT Windows 10 PC, I reinstalled the KB
    1. Go to https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2018-0886 and find your OS, then click Security Update
    2. Continue to download the appropriate patch (https://www.catalog.update.microsoft.com/Search.aspx?q=KB4103721)
    3. Once downloaded, install the KB

That’s it! I could not find an easy explanation of what KB to uninstall and which one to install.

A side note, if I enabled automatic updates, I think this wouldn’t have happened. My SharePoint VMs are not patched automatically since they are Dev machines.

Hope this helps.

Using Visual Studio Team Services build tasks for Linux over SSH

We use Visual Studio Team Services for source code on a LAMP stack Azure VM. When deploying via VS TS and copying the files over SSH through VS TS, I had a few challenges to automate the build/deployment process. Here is how I set things up.

  1. Check your files into source control (PHP files, web assets, etc.)
    1. I manually configured the deployment of 4 environment VMs for Dev, INT, STG, PRD using 4 instances of Azure Ubuntu Linux VMs.
    2. I manually deployed machine specific content, such as config files to the server. I later filter these files out of the deployment if they are in the web root. For security, I keep these files outside of the web root.
  2. Create Build definition (one for each environment, DEV, INT, STG, PRD)
    1. Use an Empty Process
      1. Under Get Sources, say This Project and chose the repository.
      2. Add a task to Copy files securely over SSH
      3. On the SSH endpoint, click the gear to configure your endpoints:
      4. Add SSH endpoints with your key file and IP, etc.
      5. Select your endpoint and apply chose your web root from your project under Source Folder. Also, under Contents, apply any filters: (below, ** is everything, then we filter out files/folders using !**/)

        I use the following filter examples:
        **
        !**/old_code/*
        !**/old/file.txt

    2. I added two SSH commands to set permissions before/after the copy
    3. You can choose a Shell Script and provide environment specific variables, such as a user.
    4. I have my resetperms.sh script in Source Control as well. This uses the same user as VS uses to overwrite files, then after the deployment, I use a second script to set my special permissions. The second script I will not post since it is specific to my application, and for security reasons. $1 is the argument I pass in for the user, who I set as owner recursively for all web files during deployment.
    #!/bin/bash
    # Reset permissions before TFS deployment
    echo “Reset permissions before TFS deployment”
    if [ “$1” != “” ]; then
    echo “Ready, Positional parameter 1 contains user $1”
    echo “Resetting permissions to $1 for TFS deployment”
        sudo chown -R “$1″:”$1” /var/www/html
    else
    echo “Fail, Positional parameter 1 is empty. Please pass in the environments user”
    fi
    1. One important note, on Windows when I created the script as resetperms.sh in NotePad++, you have to go to Edit -> EOL Conversion (thanks to this article http://stackoverflow.com/questions/8195839/choose-newline-character-in-notepad )
    2. Otherwise, you will get the following error:

      Build
      ./resetperms.sh: line 2: $’\r’: command not found
      ./resetperms.sh: line 10: syntax error: unexpected end of file
      Command failed with errors on remote machine.

That’s it, then save and queue a new build!

Much easier than copying files via FTP. Now I can click a button and update my application in each environment. Next steps are to automate the testing, release process.

More on SSH with Visual Studio Team Services https://www.visualstudio.com/en-us/docs/build/steps/deploy/ssh

Note: you can also have a build definition trigger the release definition to copy the files over SSH, etc. This is the way the Azure Portal sets up Continuous Delivery for Web Apps.

 

 

Azure Linux Ubuntu disk space full

I noticed our dev team had some issues with our disk space on an Azure VM saying the disk was full. I saw something in Linux called dev/sba1 that was taking up all my space and my disk was full. Why was my Linux storage space low?

Our website is only 5-6GB in size, so I knew something was wrong. Our VM in Azure is a DS12v2 with 56GB ram and 128GB SSD.

We are running the Ubuntu 14 OS image from Azure and are using it as an Apache web host.

When I ran a “df” (Disk Filesystem) command to check the free space, one of the volumes was huge and at 97%

$ sudo df -h

Filesystem Size Used Avail Use% Mounted on

udev 28G 12K 28G 1% /dev

tmpfs 5.6G 432K 5.6G 1% /run

/dev/sda1 29G 27G 1.1G 97% /

none 4.0K 0 4.0K 0% /sys/fs/cgroup

none 5.0M 0 5.0M 0% /run/lock

none 28G 0 28G 0% /run/shm

none 100M 0 100M 0% /run/user

none 64K 0 64K 0% /etc/network/interfaces.dynamic.d

/dev/sdb1 111G 60M 105G 1% /mnt

Run a sudo df -h (h stands for human readable)

I am still not 100% clear on this, but some of these above results are different disk partitions that are mounted via symbolic names, similar to how a disk in Windows can be partitioned into C, D drives, etc.

The Azure VM had one OS VHD assigned to it, which should be 128GB.

So, I focused in on the /dev/sda1 filesystem. I had no clue what this was at first, but after looking into it, it might be my VHD mounted to my VM’s primary root drive (/). (Please correct me if I am wrong). In “sda1“, The “sd” stands for SCSI device (which is now any attached device, could be USB, SATA, IDE, etc.), the “a” stands for the attached device order (a is first, b is the second device, etc.) and the “1” indicates the partition on that device (think of a hard drive partitioned into 1, 2, 3 different partitions.) (thanks to this article for the explanation http://superuser.com/questions/558156/what-does-dev-sda-for-linux-mean)

For me, I only have one sd device and one partition, so I assume that’s my Azure VM OS VHD that should have been 128GB. But why was it only 29GB?

WELL! All Linux OS vm partitions come as 30GB allocated.

How do I get all my GB’s? Add a second drive for my data? No, just resize the primary partition.

I read this article (https://blogs.msdn.microsoft.com/cloud_solution_architect/2016/05/24/step-by-step-how-to-resize-a-linux-vm-os-disk-in-azure-arm/) about resizing an Azure VHD and thought “ooh God, I am going to scrap my entire OS partitions data if this goes wrong or if I get stuck in these steps…” but after reading the top, UBUNTU automatically resizes the Linux partition on boot! YES! All I have to do is reboot! But, I just rebooted and that didn’t resize the partition….

The Problem: When browsing the Azure portal, I noticed my VM disk size was blank, and where I could select 128/256 or 512GB, none were selected. So, I thought “maybe Azure doesn’t automatically define a default OS disk size of 128GB since machine sizes can go up or down dynamically.”

These machines will have 128GB OS disks allocated to them, so I wanted to set them to the full 128GB (I can go up in size, but not down).

Problem: my OS disk size is not selected, so Ubuntu cannot automatically resize the partition (I think the VHD is dynamically allocated at this point)

Solution: How to add more space in the Azure Portal easily with a Linux Ubuntu VM

  1. Turn off the VM
  2. Select the disk size for the OS disk (I used 128GB)
  3. Turn it on.

BAM! You now have more space.

Run the “df -h” command again after the VM comes back online and see a 126GB of space at the root! Done!

$ sudo df -h

Filesystem Size Used Avail Use% Mounted on

udev 28G 12K 28G 1% /dev

tmpfs 5.6G 416K 5.6G 1% /run

/dev/sda1 126G 5.8G 116G 5% /

none 4.0K 0 4.0K 0% /sys/fs/cgroup

none 5.0M 0 5.0M 0% /run/lock

none 28G 0 28G 0% /run/shm

none 100M 0 100M 0% /run/user

none 64K 0 64K 0% /etc/network/interfaces.dynamic.d

/dev/sdb1 111G 60M 105G 1% /mnt

If you don’t have Ubuntu, you have more steps to do to resize the Linux OS partition. I haven’t done it, but this seems like a good place to start: https://blogs.msdn.microsoft.com/cloud_solution_architect/2016/05/24/step-by-step-how-to-resize-a-linux-vm-os-disk-in-azure-arm/

Please leave any comments if you know more about the df command results, the sda1, Azure VM OS disk sizes, Linux partitions, etc. I am always learning.

References that helped me get here:

Search Result preview images in SharePoint Online

SharePoint search results OOTB do not display image previews until you hover. We wanted to have a baseball card type approach to display certain items.

Here is an unfinished example of the results displayed as cards with image previews and the OOTB hover panel:

  1. Make sure the site is a publishing portal and publishing features are enabled at the site collection and site level. In order to get the Search Display templates to display the *.html files in the masterpage gallery, some of these features have to be on. Otherwise you just have *.JS files which can limit you. Just ask me under comments if you have any questions.
  2. Modify your Search display template for result items:
    1. /_catalogs/masterpage/Forms/Display%20Templates.aspx
    2. I modified Item_CommonItem_Body.html.
  3. Edit Item_CommonItem_Body.html properties and add the following property:
    1. ServerRedirectedPreviewURL
    2. (properties are separated by a comma, and surrounded by single quotes. So the exact text I added to the end was ,’ ServerRedirectedPreviewURL’ (but replace my blog posts fancy quotes)
  4. Edit the Item_CommonItem_Body.html file (I open with Explorer and edit the file in notepad++)
    1. Verify the property was added:

    2. Next, add a JavaScript tag to store the Preview Image URL as a web safe string:

      imageurlpreview = $htmlEncode(ctx.CurrentItem.ServerRedirectedPreviewURL)

    3. Now, let’s add in our custom HTML. This is kinda “hacky” since I am using this site for a proof of concept and I don’t care if these customizations exist everywhere in my test site collection. Ask me below in comments if you want to know how to copy this file and isolate the results to use this custom template using result types or a custom search results page.
        1. I scrolled down to the first HTML div I found, “ms-srch-item-body”. Right above this, I added my custom Baseball Card HTML. Then I moved the rest of this stuff in except for the closing div tag.
        2. The main thing was this line to add the new JavaScript for the image:

          <img src=”_#= imageurlpreview =#_” alt=”Preview” />

          Here is my baseball card HTML (including the preview image)

          [code language=”html” highlight=”7,30″]
          <div class="cbs-PictureCardsContainer">
          <div class="cbs-PictureCardsImageContainer">
          <a title="Title here" class="cbs-pictureImgLink" href="#">
          <div class="cbs-PictureCardsImage">
          <img src="_#= imageurlpreview =#_" alt="Preview" /></div>
          <div class="sts-cardtype sts-cardtypeidea">
          Type</div>
          </a></div>
          <div title="" class="cbs-pictureCardsCategory ms-noWrap">
          Category</div>
          <div class="cbs-PictureCardsDataContainer">
          <a title="Title here" class="cbs-PictureCardsLine1Link" href="#">
          <div class="cbs-PictureCardsTitle ms-noWrap">
          Pic title</div>
          </a>

          Move all of the OOTB stuff here, starting with the div ms-srch-item-body
          <div title="" class="cbs-PictureCardsDesc">
          Description of image</div>
          </div>
          </div>
          [/code]

        3. Now Save the display template HTML file and publish ONLY the HTML file from the browser (the JS file gets automatically updated instantly):

      Add the baseball card CSS to your result page and you should be good. Again, the element selector (ms-srch-item) for floating these elements is a bit hokey, I could have modified the Control_SearchResults and individual Item templates but this is just a POC.

      [code language=”css” highlight=”2″]
      /* Cards */
      .ms-srch-item {
      width:240px;
      display:inline;
      float:left;
      margin:11px;
      border: 1px solid #DDD;
      clear:none;
      }
      .cbs-PictureCardsImageContainer{
      height:240px;
      border-top-left-radius: 9px;
      border-top-right-radius: 9px;
      width:240px;

      }
      .cbs-PictureCardsImage {
      height:240px;
      overflow:hidden;
      width:240px;

      }
      .cbs-noImageContainer-ContentWrapperLarge {
      display:none;
      }
      .cbs-PictureCardsDataContainer {
      padding: 8px 22px 0px 22px;
      background-color: #f8f8f8;
      color: #212121;
      }
      .cbs-PictureCardsDataContainer a, .cbs-PictureCardsDataContainer a:active, .cbs-PictureCardsDataContainer a:hover, .cbs-PictureCardsDataContainer a:visited {
      color: #212121;
      }
      .cbs-pictureCardsCategory {
      background-color:#666;
      color: #FFF;
      font-weight: bold;
      font-size: 12px;
      padding: 8px 22px 8px 22px;
      border-top:1px solid #FFF;
      }
      .cbs-PictureCardsTitle {
      font-weight: bold;
      }
      .cbs-PictureCardsDesc {
      height: 75px;
      overflow:hidden;

      }

      .sts-cardtype {
      position:relative;
      top:-18px;
      left:120px;
      text-align:center;
      height: 18px;
      width: 120px;
      color:#000;
      font-weight:bold;
      }

      .sts-cardtypeidea {
      background-color:#a8da69;

      }

      .cbs-PictureCardsIconSection {
      float:left;
      margin-top:8px;
      margin-bottom:8px;
      }
      [/code]

    4. Check in and publish your custom result page (the custom ASPX page with all of your search refiners, result web part, search box, above CSS, etc.) and you should be good.

Azure VM PowerShell audit VHD disk information

I was having trouble getting a list of VHDs that are in use by my Azure VMs for OS and Data disks. I wanted to list them in a single line CSV to audit each VMs configuration. The issue was I had 3 commands with different objects:

  • Get-AzureVM
  • Get-AzureOSDisk
  • Get-AzureDataDisk

I wanted each output on the same line. I was able to rename the conflicting properties and output them to a single CSV, with each VM on a new line.

Script: (download)

$vms = Get-AzureVM -ServiceName mycloudservicenamehere
foreach($vm in $vms) {

#get-azurevm
$obj1 = $vm | Select-Object Name,InstanceSize,AvailabilitySetName,DNSName,deploymentname
#get VM Data disk, rename same properties to prevent output conflicts
$obj2 = $vm | Get-AzureDataDisk | Select-Object @{Name=’DataDiskName’; Expression={$_.DiskName}},@{Name=’DataDiskLabel’; Expression={$_.DiskLabel}},@{Name=’DataMediaLink’; Expression={$_.MediaLink}},@{Name=’DataDiskSizeGB’; Expression={$_.LogicalDiskSizeInGB}},@{Name=’DataLUN’; Expression={$_.Lun}}
#same as above VM data disk, but with OS disk
$obj3 = $vm | Get-AzureOSDisk | Select-Object  @{Name=’OSDiskName’; Expression={$_.DiskName}},@{Name=’OSMediaLink’; Expression={$_.MediaLink}},@{Name=’OSDiskLabel’; Expression={$_.DiskLabel}}, OS

#combine these outputs into a single row CSV per VM
$combined = New-Object -TypeName PSObject
$obj1,$obj2,$obj3|%{
$CurObj = $_;
$_|gm|?{$_.MemberType -match “NoteProperty”}|%{
$NewMember = $_.Name;
$Combined|Add-Member -MemberType NoteProperty -Name $NewMember -Value $CurObj.$NewMember
}
}
#write each VM output to CSV
$Combined|Export-CSV -Path c:\Users\administrator\Desktop\output.csv -NoTypeInfo -Append -Force
}

Output csv:

Output properties: Notice how I renamed conflicting disk properties to be prefixed with “Data” or “OS”.

  1. AvailabilitySetName
  2. DeploymentName
  3. DNSName
  4. InstanceSize
  5. Name
  6. DataDiskLabel
  7. DataDiskName
  8. DataDiskSizeGB
  9. DataLUN
  10. DataMediaLink
  11. OS
  12. OSDiskLabel
  13. OSDiskName
  14. OSMediaLink

Now I can look at VM Instance Size, Labels, OS/Data disk information, etc. and make any changes. Our team has about 40+ SharePoint development VMs in multiple cloud services, so provisioning/management can be a bit of work. In a perfect world I would use PowerShell DSC or Azure Automation, but that is quite a bit of work to setup for VMs we scrap every few months once projects are complete.

Next steps:

  • Split VMs into unique cloud services so multiple developers can start/stop VMs at the same time (worker process conflict) (using same site-to-site VPN)
  • Audit OS/Data disk configuration and possible move between storage accounts
  • Set affinity groups for disks/VMs

Links:

Running MS Office Demo VMs in Azure

UPDATE: If you are a MS employee, Visit https://demomonkey.cloudapp.net/. There is a complete Azure VM deployment script for this in your Azure subscription. I had limited success getting this to work on my own.

If you have used the Microsoft Office Demos website Office 365 environment, you know it’s quite handy for client demos. It used to be similar to the SharePoint Information Worker Demo or SDPS demo. This new environment runs on Windows Server 2012 and features SharePoint 2013, Exchange, Lync, and Office web apps. These demos can be spun up on Office 365, or downloaded as Hyper-V virtual machines for on premise demos. They are HUGE VMs and resource hogs. I think you need 50+ GB of ram to host all 9 VMs, as well as probably 1TB of hard drive space to even consider starting these VMs. Remember, having everything run on the same disk will create major throughput issues with your storage and run unbearably slow (tried on four 1TB Raid 10 7200 SATA drives and could only get a few going before hitting huge performance walls).

So, let’s host it in Azure!

There are plenty of performance considerations in Azure, such as use an E drive for your data, turn on or off disk caching, using separate storage accounts, etc. I will NOT be covering that. This is a POC for a client demo, so my goal is just to get SharePoint 2013 with the Contoso users and content working on premise so we can demo Web Content Management (WCM) features of SharePoint, along with the Content by Search web part and Taxonomy driven navigation for product sites.

I will only require SharePoint and the Domain Controller for this effort. My farm does not require Search live preview, Outgoing/incoming email, Lync presence, etc. So hosting this on

Here are the major steps:

  • Downloading the template
  • Convert VHDX to VHD before uploading to Azure
  • MakeCert
  • Connect Azure to PowerShell
  • Start conversion while waiting (VHDX to VHD)
  • Upload VHDs:
  • Add VHD to VM Image
  • Create VM
  • Repeat and create the SharePoint VM
  • Add VHD to VM Image
  • Create VM
  • Resources and Links

Downloading the template VMs

First, download the VHDX zip files from www.microsoftofficedemos.com

I chose to download mine with content.

  1. 2013-DC v4 (Complete)
  2. 2013-EXCH v4 (Complete)
  3. 2013-LYNC-SE1 v4 (Complete)
  4. 2013-PCHAT v4 (Complete)
  5. 2013-SP v4 (Complete)
  6. 2013-SP-AFCache v4 (Complete)
  7. 2013-VPN v4 (Complete)
  8. 2013-WAC v4 (Complete)
  9. Office Demos 2013 VHD EULA

I downloaded #1, #5 and #7. These 3 files required ~31GB of disk space and extract to ~175GB

Extract each VM to your computer.

Convert VHDX to VHD before uploading to Azure

If you have Windows 8.1 or Windows PowerShell 4.0, Windows Server 2012 R2, Run PowerShell Convert-VHD command: http://technet.microsoft.com/en-us/library/hh848454.aspx

Convert-VHD -path “D:\temp\MS-Office-Demo-VMs\2013-DC v4 (Complete)\2013-DC Complete v4\Virtual Hard Disks\2013DC.VHDX” -destinationpath “D:\temp\MS-Office-Demo-VMs\2013-DC v4 (Complete)\2013-DC Complete v4\Virtual Hard Disks\2013DC.VHD”

MakeCert

Visual Studio command prompt

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\x64

makecert -sky exchange -r -n “CN=MSDNAzure6scport06” -pe -a sha1 -len 2048 -ss My “MSDNAzure6scport06.cer”

Connect Azure to PowerShell

MMC- add snap-in Certificate. Navigate to Personal certificates. If you are not a local administrator and run CMD as administrator, they will not appear for you. I just exported another Azure cert from the management tools for testing and it worked for me.

Export again as CER – DER 509 CRT to Desktop

Upload CER file to Azure:

Get-AzurePublishSettingsFile

Save Certificate from Azure when prompted to download: C:\temp\

Import-AzurePublishSettingsFile “C:\temp\Windows Azure MSDN – Visual Studio Premium-12-3-2013-credentials.publishsettings”

Test a random command to verify PowerShell is connected: (Your storage account name below):

Get-AzureStorageAccount portalvhdsfz7h5hgfmhh4k

Start conversion while waiting (VHDX to VHD)

convert-vhd -path “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-DC v4 (Complete)\2013-DC Complete v4\Virtual Hard Disks\2013-DC.VHDX” -DestinationPath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-DC v4 (Complete)\2013-DC Complete v4\Virtual Hard Disks\2013-DC.VHD”

convert-vhd -path “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-SP v4 (Complete)\2013-SP Complete v4\Virtual Hard Disks\2013-SP.VHDX” -DestinationPath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-SP v4 (Complete)\2013-SP Complete v4\Virtual Hard Disks\2013-SP.VHD”

convert-vhd -path “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-VPN v4 (Complete)\2013-VPN Complete v4\Virtual Hard Disks\2013-VPN.VHDX” -DestinationPath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-VPN v4 (Complete)\2013-VPN Complete v4\Virtual Hard Disks\2013-VPN.VHD”

Upload VHDs:

Add-AzureVhd -Destination http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-dc.vhd -LocalFilePath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-DC v4 (Complete)\2013-DC Complete v4\Virtual Hard Disks\2013-DC.VHD” -NumberOfUploaderThreads 32 -OverWrite

Add-AzureVhd -Destination http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-SP.vhd -LocalFilePath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-SP v4 (Complete)\2013-SP Complete v4\Virtual Hard Disks\2013-SP.VHD” -NumberOfUploaderThreads 32 -OverWrite

Add-AzureVhd -Destination http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-VPN.vhd -LocalFilePath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-VPN v4 (Complete)\2013-VPN Complete v4\Virtual Hard Disks\2013-VPN.VHD” -NumberOfUploaderThreads 32 -OverWrite?

Add VHD to VM Image

Add-AzureVMImage -ImageName SP2013-DC -MediaLocation http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-dc.vhd -OS Windows -Label SP2013-DC -ImageFamily “Microsoft Office Demo SharePoint 2013 w content” -Eula http://go.microsoft.com/fwlink/?LinkID=324375 -PrivacyUri http://go.microsoft.com/fwlink/?LinkID=282418 -RecommendedVMSize Medium -Verbose

VERBOSE: 2:20:55 PM – Begin Operation: Add-AzureVMImage

VERBOSE: 2:21:03 PM – Completed Operation: Add-AzureVMImage

AffinityGroup :

Category : User

Location : West US

LogicalSizeInGB : 41

Label : SP2013-DC

MediaLink : http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-dc.vhd

ImageName : SP2013-DC

OS : Windows

Eula : http://go.microsoft.com/fwlink/?LinkID=324375

Description :

ImageFamily : Microsoft Office Demo SharePoint 2013 w content

PublishedDate :

IsPremium : False

IconUri :

PrivacyUri : http://go.microsoft.com/fwlink/?LinkID=282418

RecommendedVMSize : Medium

PublisherName : User

OperationDescription : Add-AzureVMImage

OperationId : 4e871f30-af08-3f06-95e3-ef9b72913288

OperationStatus : Succeeded

Create VM

Go to Azure, Create new Virtual Machine. Choose My Images. Choose SP2013-DC

Chose a unique local user account (probably wont be used) and non-common password.

Select a region or affinity group (I have an affinity Group)

Open Port for RDP and PS for now. Later we might have to add more for the DC, etc.

Wait for the VM to provision.

Connect using contoso\administrator. Password is pass@word1

Repeat and create the SharePoint VM

Add VHD to VM Image

Add-AzureVMImage -ImageName SP2013-SP -MediaLocation http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-SP.vhd -OS Windows -Label SP2013-SP -ImageFamily “Microsoft Office Demo SharePoint 2013 w content” -Eula http://go.microsoft.com/fwlink/?LinkID=324375 -PrivacyUri http://go.microsoft.com/fwlink/?LinkID=282418 -RecommendedVMSize Medium -Verbose

If you get an error, its because the dynamic disk on the SP box is an issue: http://social.msdn.microsoft.com/Forums/windowsazure/en-US/e5feddff-7fee-49b4-86e2-751a1903e852/the-blob-is-not-a-valid-vhd

My error turned out that the VHD was not uploaded correctly. Retried uploading and it worked.

Add-AzureVMImage : “An exception occurred when calling the ServiceManagement API. HTTP Status Code: 400. Service

Management Error Code: BadRequest. Message: The blob is not a valid VHD.. Operation Tracking ID:

9db3a37a1da33d75ba569ee062f63936.”

At line:1 char:1

+ Add-AzureVMImage -ImageName SP2013-SP -MediaLocation http://portalvhdsfz7h5hgfmh …

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ CategoryInfo : CloseError: (:) [Add-AzureVMImage], ServiceManagementClientException

+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Management.ServiceManagement.IaaS.DiskRepository.AddAzureVMImage

Back to square 1. Its takes 6 hours to upload this VHD at 30mbps.

Reupload:

Add-AzureVhd -Destination http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-SP.vhd -LocalFilePath “E:\Hyper-V\Virtual Hard Disks\MS Office Demo\2013-SP v4 (Complete)\2013-SP Complete v4\Virtual Hard Disks\2013-SP.VHD” -NumberOfUploaderThreads 32 -OverWrite

Convert VHD to VM template:

Add-AzureVMImage -ImageName SP2013-SP -MediaLocation http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-SP.vhd -OS Windows -Label SP2013-SP -ImageFamily “Microsoft Office Demo SharePoint 2013 w content” -Eula http://go.microsoft.com/fwlink/?LinkID=324375 -PrivacyUri http://go.microsoft.com/fwlink/?LinkID=282418 -RecommendedVMSize Medium -Verbose

VERBOSE: 7:26:47 AM – Begin Operation: Add-AzureVMImage
VERBOSE: 7:26:53 AM – Completed Operation: Add-AzureVMImage

AffinityGroup :
Category : User
Location : West US
LogicalSizeInGB : 127
Label : SP2013-SP
MediaLink : http://portalvhdsfz7h5hgfmhh4k.blob.core.windows.net/vhds/2013-SP.vhd
ImageName : SP2013-SP
OS : Windows
Eula : http://go.microsoft.com/fwlink/?LinkID=324375
Description :
ImageFamily : Microsoft Office Demo SharePoint 2013 w content
PublishedDate :
IsPremium : False
IconUri :
PrivacyUri : http://go.microsoft.com/fwlink/?LinkID=282418
RecommendedVMSize : Medium
PublisherName : User
OperationDescription : Add-AzureVMImage
OperationId : e493b45b-d214-3fe1-a5b8-6c21a349f670
OperationStatus : Succeeded

Create VM

Go to Azure, Create new Virtual Machine. Choose My Images. Choose SP2013-SP

Chose a unique local user account (probably wont be used) and non-common password.

Select a Cloud Service from previous DC vm:

Open Port for RDP and PS for now. Later we might have to add more for SP, etc.

Wait for the VM to provision.

Connect using contoso\administrator. Password is pass@word1

Fixing the SharePoint VM

Looks like Central Admin (CA) loads, but not the DNS host names for http://intranet.contoso.com. This is not a big deal but let’s trace the issue.

Let’s trace the DNS. SP2013-DC is the DNS/DHCP/AD server.

Log in to the SP2013-DC VM.

Try to ping SP2013-SP, we can’t. That means Azure is taking over our DNS.

You can configure Azure to use your VM as a DC, but it looks complicated: http://msdn.microsoft.com/en-us/library/windowsazure/jj156088.aspx#bkmk_BYODNS

I will just update my hosts file for now under C:\Windows\System32\Drivers\etc:

127.0.0.1        intranet.contoso.com

127.0.0.1        2013-sp

127.0.0.1        www.contoso.com

127.0.0.1        www.contoso.de

10.76.86.2        2013-dc

Be sure to update your DC IP under 2013-DC. Just do an IPConfig from the DC box.

Update: I just realized the VM image is called 2013-x, not SP2013-x. I don’t think Azure needs this info to match from what I can gather at this moment.

Open Internet Explorer from the 2013-SP box and go to www.contoso.com and intranet.contoso.com

Its pretty slow, but I get a SharePoint start page. www.contoso.de challenges me for credentials, I think its because I am rebooting the DC.

I made the DC an Extra Small CPU, since its only at 3% CPU on a Medium footprint.

The SP box is 97% cpu in the past hour, so I want to make it a Large footprint, but its still provisioning.

I also want to open some incoming ports for mydomain.cloudapp.net so users can come in using their web browser.

Resources:

Storage issues

Using Azure disks not sysprepped (DC, SP farm, etc) http://blog.aditi.com/cloud/guide-to-azure-iaas-vhds-disks-images/

Uploading a VHD to Azure (Latest instructions from Official Azure site) http://www.windowsazure.com/en-us/manage/windows/common-tasks/upload-a-vhd/

Azure VHD dynamic disk error: http://social.msdn.microsoft.com/Forums/windowsazure/en-US/e5feddff-7fee-49b4-86e2-751a1903e852/the-blob-is-not-a-valid-vhd

VHDX

Lessons learned uploading a VHDX to Azure: (see step #27) http://blogs.catapultsystems.com/cmoore/archive/2013/04/30/one-does-not-simply-upload-a-vm-to-azure.aspx

Converting VHDX to VHD http://blogs.technet.com/b/cbernier/archive/2013/08/29/converting-hyper-v-vhdx-to-vhd-file-formats-for-use-in-windows-azure.aspx

Convert-VHD command http://technet.microsoft.com/en-us/library/hh848454.aspx

Azure PowerShell trust certs

Add Certificates to MMC: http://social.technet.microsoft.com/wiki/contents/articles/2167.how-to-use-the-certificates-console.aspx

Convert PFX to CER: http://stackoverflow.com/questions/403174/convert-pfx-to-cer

Visual Studio: makecert- http://msdn.microsoft.com/en-us/library/bfsktky3(v=vs.110).aspx

Add-AzureVHD http://msdn.microsoft.com/en-us/library/dn205185.aspx

Networking

Azure DNS- http://msdn.microsoft.com/en-us/library/windowsazure/jj156088.aspx#bkmk_BYODNS