Optimising WordPress for Running in Azure

Now that you have WordPress running in Azure there are a few housekeeping tasks that you may want to look at prior to switching over from your existing site.

Managing Storage

In a previous post we discussed the different types of deployment available in Azure. One thing to be aware of is that storage is managed differently with these and if you decide to scale-out then things change again. If you deploy WordPress in PaaS or a container then scaling is easy but each new web service needs to be able to access both the database and the file repository.

You may have noticed that our instructions on how to deploy WordPress using hybrid containers that we also deployed a storage service. This is what we will be using to store all of those objects so that any web server can access them. Luckily WordPress has a plugin that makes this functionality easy as well. This should be one of the first plugins that you install. No point in having any data saved to the wrong place after all.
Once this is added you need to configure the storage account that it will use. In order to do this you need to create a storage account key, which will be used by the plugin to access the blob storage. Log in to the Azure portal and open the storage account that you want to use. Under Blobs you need to create a new container then go to Access Keys to get one of the API keys. This information can then be put into the plugin configuration. In the WordPress admin go to settings|Microsoft Azure and copy in the name of the storage account and the API key. If the authentication is successful you will then see the container that you created.
Make sure that Azure Storage is then selected as the default upload source and save the settings. At this point you can restore your old site into WordPress. When you do this you will see that all of the images are automatically saved in the Azure storage account and when you go to upload a file it will automatically save to the Azure storage account.

Stopping the spam

When we stood up the site it took 4 hours before some spammer noticed that they could use a bot to send spam to the contact form. Luckily email wasn’t configured so no one really got spammed but still it was a lesson that we are running our own WordPress site and need to do some things ourselves now. So first up let’s make it harder to spam the contact form. I settled on installing the Contact Form 7 plugin. This has an integration with reCAPTCHA which is a free google service. You will need to sign up for an account at whic will give you a site key and secret key. Put these into the Integration page for the contact plugin and then create a new contact form. We simply added the recaptcha to the bottom of the form.
Once you’re happy with the form you can copy the short code for the form directly onto your page. Have a play with it and make sure that it’s working before you fix the email integration. For this we used the WP Mail SMTP plugin. This allows a way to modify the SMTP settings for WordPress. Now WordPress is not an SMTP server so you need to have some external SMTP service that you can use. This plugin supports Google, Mailgun and Sendgrid, but you can also manually specify SMTP server settings. Since we have an Office 365 account we use that. For Office 365 the SMTP host will be your tenant name, which may be different from your domain name with at the end. For some reason the TLS option wasn’t working with Office 365 so we used SMTP on port 25 but enabled the Auto TLS option.
If you want to relay mail outside the organisation then it would be a good idea to set up an account in Office 365 and use authentication. If you don’t want to do this then remember that you will need to set up a receive connector in Exchange Online to authorise the web server to relay based on it’s IP address. If you just want to receive alerts yourself then no changes are required.

Configuring HTTPS

You really need to use HTTPS for your new site. The default site already has a valid SSL certificate but if you want to use a custom name this will require additional work. First you need to set up the custom domain name by going to the app service and opening the custom domain properties. The process for adding a custom name differs depending on whether the site is live or not. If it isn’t then you create a new CNAME pointing to the default Azure name. This is the that was assigned when you first created the site. If the site is already live then you don’t really want to redirect it to the new Azure site just to add the custom domain. You may still have more work to do before you’re ready to go live after all. To cater for this you need to create a txt record in your DNS which has the name awverify with the data containing your If you want to have a host name for the site (eg then you will also need to create a record for this. (eg awverify.www) with the data referring to the Azure site. Once this is done you can upload a public certificate and bind it to the custom domain. If you went down the Windows PaaS route then you can use a Let’s Encrypt extension which will manage acquiring and renewing Let’s Encrypt certificates. This will result in a free cert associated with your custom domain. If you went down the container route then this is a little more difficult. There are solution out there which involves deploying multiple containers. The first container has a nginx reverse proxy which publishes the second container running WordPress. The nginx reverse proxy also has has the Let’s encrypt integration. In the end we went a different way. We use Cloudflare to publish our site. This already has SSL but things get a little funky with WordPress. If we configure the custom domain on CloudFlare but don’t use this name in WordPress then pages will break. If we set both to the same name and require SSL, well don’t do that. WordPress will stop responding. We added another plugin called CloudFlare Flexible SSL. This makes sure that all pages will display correctly to the end user. You then use CloudFlare to control the HTTPS configuration. You can then disable HTTP access from within CloudFlare if this is the route you want to go down.

Oh crap I changed the WordPress settings and now I can’t access my site!!!!

Yeah we’ve been there. Fortunately there is an easy way to fix this. You will need to change the setting on the database to get things back again. You can do this using the Azure cloud shell. Log on to it using the built in mysql command.
mysql -h -u [email protected] -p
Then convert the site details back to using HTTP.

UPDATE wp_options SET option_value = replace(option_value, '', '') WHERE option_name = 'home' OR option_name = 'siteurl';
Reconnect to your site and breath.

Deploying WordPress on Azure using Hybrid Containers

In the last post we looked at the different architectures that can be used to deploy WordPress in Azure. We decided to deploy our site using a hybrid container environment. This has the web service running in a docker container but the database running as a separate resource. This makes the web service a simple component which can be easily replaced if problems are experienced or scaled in response to load changes. If you haven’t already deployed any Azure services then you will need to start by deploying a resource group. This will group the WordPress resources together. Give this a name select the subscription you will be using to pay for the service and select the Azure region that you want to use.

MySQL Server Installation

Next deploy a Azure Database for MySQL Server. This will be used to host the WordPress database and will allow us to deploy additional web services connected to the same database.
You’ll need to define some basic settings as part of this deployment and you will need to record some of the details for later. The server name needs to unique across Azure and will ultimately end up with a fully qualified domain name of servername. The server admin name and password should be something complex and will be used to remotely access the database. Finally you may want to modify the pricing plan which is designed for significant production systems.
Once the database server has successfully deployed you need to create the WordPress database to the MySQL server. If you already have the MySQL tools installed you can use these to connect to the server. Otherwise you can connect using the cloud shell directly from the Azure portal. This is the command prompt in the toolbar.
If you haven’t used this before it may prompt to create a storage account. This will likely be deployed in a different Azure regions from your WordPress services but this won’t cause any problems. Once you are at the prompt you can use the following command to connect to your new MySQL server
mysql -h -u [email protected] -p
Then run the following script to create a wordpress user account in the database and create a new database.
create user 'wordpress' IDENTIFIED BY "Sup3r53crEtP455w0rd";

create database wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress';
WordPress doesn’t support connecting to a MySQL database using SSL connections out of the box. There are ways to patch this behaviour by updating the code but otherwise you will need to change the connection settings of the MySQL Server. You will also want to allow Azure resources to communicate with the server.

Web Service Installation

There are two parts to the web service. The billing component is called the App Service Plan. We’re going to be using docker containers for the web service using a Linux App Service Plan. Give the Service Plan a name, assign it to your resource group and subscription. Then make sure that it’s a Linux service plan in the same location as your database. Finally make sure that you’re happy with the billing for the site.
Now you can create the Web Application and associate it with the new service plan. Again make sure that you set the OS to linux and then select configure container.
Change to the docker tab and then enter wordpress:latest. This is the public wordpress repository and will mean that you get the latest wordpress setup whenever you update the container.
Once the web service deploys and starts you will be able to access the web service using the address. This will show the WordPress quickstart page. Select the correct language before proceeding to the database setup page.
Next fill in the connection settings for your MySQL server. you need to make sure that you use the full names in this section so the username needs to be [email protected] and the database host needs to be¬† if you don’t use this syntax then you will end up with a connection error.
All going well you should now see the WordPress welcome page.
There’s still more to do before you have everything ready to go into production but with just a few steps you’ve got a serverless web server. this is what makes public cloud so powerful.

Options for deploying WordPress to Azure

We’ve been using to host our site. This is a cost effect solution, particularly with the cheaper subscription levels, but we decided that we really needed to drink our own kool-aid and migrate to our own public cloud. This even resulted in a saving for us as we have a Microsoft Partner account which has monthly Azure credits. Finally since we are now running our own WordPress site there are no functionality restrictions as is the case with the sites. With Azure there are a few different ways to deploy WordPress:
  1. Deploy WordPress using a VM in IaaS. This could be done using either one or several Windows or Linux VM. Using this model you need to think about whether you want to scale up or out and design this capability. You’re also running a full blown operating system so you are paying to run this as well as having to maintain it yourself.
  2. Next you could deploy everything into a container This would result in both the database and the web site running inside a container. This will have the smallest footprint but scaling the solution will be a little harder as the database is contained inside the docker container as well.
  3. You could also use the PaaS Web App service to run WordPress. This again can be either a Windows or Linux web service. In this case you will also need to deploy a database service which does allow for the web service to be scaled out if required.
  4. Finally you can also use containers but with an external database. This will use a docker image for the web service which connects to a dedicated database service. This solution actually runs on the Linux PaaS Web App so the difference between the two is how you stand up your solution. Is it pulled in from a docker image repository or do you push the web code using git into the web service?
In the end we decided on a WordPress docker image connecting to a Azure Database for mySQL server. This allowed for a shockingly quick deployment while still allowing some flexibility and the ability to expand. In the next article we’ll go through the process of how we set up this site.

This week in the cloud – 18th June 2018

There’s so much happening in the cloud space at the moment that I thought it would be good for my own reference as much as anyone else’s to produce a summary of some of the big changes that have happened this week. This week has been particularly busy with the Microsoft Build Conference.

The compute decision tree

The first resource that I found wasn’t new this week but will be quite useful. There’s so many different types of compute services but choosing the wrong one can be catastrophic when migrating on-premises resources to the Azure cloud.

This and additional information is located at

The new DEV lab

Next up is a look at the DEVTest Lab function in Azure. If you haven’t heard of this it’s a great way to spin up a new environment to do some testing without having that old hardware around or having to bother with building all the boring stuff.

With this you can deploy templates with multiple machines which can include different components. This allows you to do things like deploy an SCCM environment , even though these include multiple servers and services. Deploy multiple VMs with domain controllers (including standing up a new forest) SQL services and the SCCM services all using a automated process.

Then you can minimise costs by automating the shutdown of the environment so that an idle DEV machine isn’t costing money for idling.

A great resource about this is found here.

PSTN Services in Teams getting closer

Here in NZ we will be holding our breaths for a while longer before PSTN services are available in Office 365 but things are looking a little easier with the introduction in preview of Direct Routing. This is only available in teams *sigh* but will allow a on-premises telephony gateway to directly integrate with Teams. No more Skype for Business on-premises environment or multi-VM cloud connector. Just install a supported physical or even virtual telephony gateway and away you go.

Let’s just hope that Teams can improve to the point that we will all accept them taking Skype for Business off us in the future.

Linux Everywhere even in your Azure AD

Microsoft now loves Linux. Really loves it. Loves it so much that they have now released a Linux distro in the form of Azure Sphere. This is a new IoT operating system which Microsoft will support for 10 years, While it has built-in integration with Azure there appears nothing to stop it from connecting to another cloud service or even a on-premises environment.

Next up is a boring old Linux VM running in Azure. Fairly boring now but now you can integrate it with Azure AD as the Identity Provider. This will enable you to log on to a Linux machine in Azure using on-premises credentials.

Another Azure AD Service

Just because there are not enough ways to use the words Azure Active and Directory in a product name there is now also Azure Active Directory Domain Services. This isn’t a really new service but I have to admit I totally missed it and must have thought it was just one of the other Azure Active Directory services.

This time though it’s a full on Active Directory service without the VM. This Azure service uses the Azure AD directory service to stand up a full Active Directory service in Azure complete with the features that Azure AD doesn’t include such as Group Policy, Organisational Units and NTLM/Kerberos Authentication.

To be clear this is still NOT your on-premises domain but another domain with the same users, passwords and groups.

Details can be found here.

This is just a taster of some of the changes that have been introduced recently. Microsoft announced at Build that they had introduced 170 different new functions in Azure in the last year. Keeping up with these changes is going to get very difficult without even including AWS.



LastPass on Firefox – The missing copy password function

Ever since Firefox removed the legacy plugin functionality I’ve been annoyed that the new LastPass plugin didn’t have the copy username and copy password option.


It’s fine if you are just using the browser to log in but what about when you need to log in using actual applications?

This required you to find the entry and select to edit it, then unhide the password and manually copy it to the clipboard. ūüė©

I finally went looking for a solution and it appears that the firefox addon now needs both the addon and a native messaging component. I guess this wasn’t available when the addon was first releases and LastPass doesn’t tell you to go get it.

So how do you know if you need it? Well other than the copy username and copy password not being available you can go to the lastpass addon and select more options and then about LastPass


If you have the native messaging components then you should see this

LastPass with Native Components

If you don’t have them installed then there will be a button to go to the LastPass web site to install them. This just seems to me to be re-running the LastPass installer but I could be wrong about that.

Once done all the functions will be available again. Ya!!!


Office 365 Hybrid Send-As Functionality – Not quite there yet.

Recently Microsoft announced that mailbox delegation would be available between Cloud and On-Premises accounts. This would allow for a cloud mailbox user to send-as an on-premises mailbox.

Looking at the documentation ( it appears that this should now be working in early May 2018. In particular.

As of February 2018 the feature to support Full Access, Send on Behalf and folder rights cross forest is being rolled out and expected to be complete by April 2018.

This feature requires the latest Exchange 2010 RU, Exchange 2013 CU10, Exchange 2016 or above but otherwise should just work.

Unfortunately when a user tried to use this feature it didn’t work.

This message could not be sent. Try sending the message again later, or contact your network administrator. You do not have the permission to send the message on behalf of the specified user. Error is [0x80070005-0x0004dc-0x000524].

Notice that this mentions the send on behalf rights. Well in this case the user didn’t have those but instead had the more powerful Send-As rights.

Well it looks like Microsoft are running a bit late on the rollout with this other article ( now shifting the rollout completion to Q2 2018.

As of February 2018 the feature to support Full Access and Send on Behalf Of is being rolled out and expected to be complete by the second quarter of 2018.

Either way it’s not much longer but in the interim you may need to keep assigning send on behalf rights prior to migrating mailboxes. This will save you having to use powershell to do this post-migration since the on-premises ECP interface doesn’t support granting these rights to cloud mailboxes.


Cisco UCS – Cisco Server Computing takes virtualisation a step further

I recently implemented a new Cisco UCS environment using Windows Server 2016 Hyper-V, managed by a MS VMM 2016 and SCCM Current Branch management environment. This was my first introduction to the Cisco UCS platform.

The Hardware

On first look it appeared to be just another blade enclosure environment.


In addition to the standard blade chassis, the Cisco UCS environment also requires external management controllers called Fabric Interconnects. This is where all the intelligent for the environment sites and can manage multiple chassis.


While the fabric interconnects can be installed as a single unit I can’t see why anyone would ever want to do this and so you can cluster multiple units. These are also not just the management controller for the environment but also the conduit for all external communications.

These are active/passive management clusters so just be aware that a management outage occurs when the active role changes. Blade traffic will continue to route as this uses both the active and passive nodes at all time. If a fabric interconnect goes offline then it will just mean that some of the paths are no longer available. As long as you have paths for all services via all fabric interconnects and the servers are configured correctly you won’t experience any issues.

There’s a few caveats there but unfortunately it is possible to install these units badly. This is not a unit to plug in quickly without any planning.


Cisco have produced validated designs which give step by step documentation to install an environment with specified hardware. The Windows 2016 Hyper-V with VMM validated design uses the following hardware:

  • UCS Blade Chassis
  • UCS Standalone Servers
  • UCS Fabric Interconnects
  • Nexus Switches
  • MDS Fibre Channel Switches
  • NetApp SAN

Put together this gives the following physical design

Cisco UCS Networking Design

It is absolutely possible to drop the MDS switches in this design and use the Nexus switches to provide the FibreChannel connectivity. Also worth noting is that in this design the NetApps are used for both FC and iSCSI/SMB storage thus requiring the connection to the Nexus switches.

Each blade chassis is connected via multiple connections to both fabric interconnects. This will provide all external connectivity including network and storage access as well as the management, which we will go into later.

Each port on the fabric interconnects will then be configured as either a server, network or FC port. Server ports will be used to discover chassis and standalone alone UCS Servers. Network ports will be configured using network templates for external connectivity.

FC ports can not be directly specified but are instead limited to a number of ports which are located in a location which differs depending on the fabric interconnects that you are using. The UCS 6248s that I used required the FC ports to be located at the top end of the ports on each fabric interconnect. If you wanted to have 2 FC ports per Fabric Interconnect then these ports would be assigned to port 31 and 32 on each unit.

The Virtualisation magic

This is reasonably standard so far so why did I say that it takes virtualisation a step further?

Well each server does not get directly configured. In fact Cisco would rather you forget that you even had servers and rather just think about resources.

Before you do anything you need to configure the external network configuration and external FC configuration as well as discover your servers.

Then everything is based on templates and service profiles. While it is possible to create a server from scratch without any templates this is not encouraged and would likely result in a giant mess. Instead you need to go through and create templates for everything.

You need to start with the addresses you will be using. This includes MAC addresses, FC Addresses, UUIDs. Next you need to create policies for the boot order, BIOS settings, power settings, and network configuration.

Then you need to configure all vLANs, vSANs which can then be assigned to vNICs and vHBAs which also have adapter configuration.

Then you need to create pools of servers which will be used to assign the configuration.

Next you create the service templates which takes all of the above information and creates a configuration template. You then assign this template to a server pool.

Finally you can configure your servers by deploying the service templates to your server pools. This will give the server a base name as well as a starting number which it will increment.

You would think that this would result in blade 1 in chassis 1 being assigned the first template but cisco really don’t want you to think that much about it. It will assign each service profile where-ever it sees fit. If you really need to know where the server is located physically then you can look it up but it’s definitely not front and centre.

Each blade will end up with what appears to be a physical NIC which is in fact the vNICs defined in the template as well as FCoE adapters to match the vHBA configuration.

Sounds like a lot of effort. Why bother?

It is a lot of effort up front, but once you’ve got your service templates expanding the environment is quite amazing. This is particularly the case if you also use SAN boot rather than local disk. Have a hardware failure? Just reassign the service profile to another blade in the environment. The server will reboot and be operational with ALL hardware configuration being identical.

Most other blade environments will allow you to switch out a blade, with the new blade having the same FC and MAC address, but this goes so much further. It also saves a trip to the data centre as you can move the configuration to a new slot rather than having to replace the server in the same slot.

Need to install a new chassis? Connect 4 cables and power, discover the chassis, potentially upgrade firmware and then add the new servers to the existing pools. Deploy 8 new servers with the existing service templates. Total time of stuff all.

Throw in the IPMI integration with VMM and you can deploy a new bare metal Hyper-V environment in no time at all.

Need to install a new network card? Sure that’s virtual. Change the service template and trigger a service profile update and all associated servers will now have the new vNIC.

What are the limitations

As so many facebook relationship status’ say. It’s complicated. Particularly when setting it up the first time you are almost guaranteed to be¬† left scratching your head asking why a template just refuses to deploy. Unfortunately the error messages can be a little vague too with “not enough compute error” and “not enough vNIC/vHBA error” plaguing me during my deployment.

This is definitely not the unit that you quickly install and have operational in an morning with the physical installation being just the start of the deployment process.

The Cisco environment really wants you to let go of where servers are located which can really be intuitive. If you are a bit too obsessive compulsive for this chaos then you can manually deploy each server to a service template and manually assign a name but you just know that someone at Cisco is shedding a tear.

You also have to understand just how much control you are handing over to the Cisco management environment. If you are deploying Hyper-V then you should be looking for how to configure jumbo frames on the physical network adapters. The problem is you just won’t find it on the physical adapters. This is because it’s configured on the vNIC template in the UCS management interface.

There are also still some rough edges in the environment. While vSphere 6.5 supports UEFI boot using secure boot this just wouldn’t work for me and ultimately had to be disabled. This was documented as a bug for the current release at the time.

Is it worth the effort?

As always it depends. If you do just want a quick build for a static environment then this may not be for you. It’s fancy but if the steep learning curve delays the deployment and then it’s never used again it’s a bit of a waste.

I actually really like this hardware for environments that are experiencing change or growth. Everything can be standardised while still allowing for huge growth. No longer will you have 5 different chassis configuration depending on the engineer assigned to the build.



Upgrading Bamboo results in HTTPS configuration disappearing

I recently upgraded bamboo within the 5.x version. The actual upgrade went well but when bamboo was restarted the site was only available on the default HTTP port. In this case it was a simple fix and it was a good thing that I had copied both the application files and the bamboo home.

Even though the Bamboo installer says that it’s going to “upgrade” what it’s really saying is that it will dump the new files in the old directory. This includes overwriting any files like the server.xml file.

Unfortunately this removed the HTTPS section of this file. Luckily this was a simple copy and paste from the old configuration file.

Yes this is in the upgrade guide but this guide also doesn’t say that an “upgrade” is possible so I figured this was a new function. Oh well.

Now that the server was available on HTTPS I still had another problem. The site wasn’t available via our F5 load balancer. This was a little harder to spot, but was again a simple solution.

When you connect to the root site ( it sends a 302 redirect to the web service address. Now the F5 load balancer is looking for a HTTP 200 message to say that the site is healthy so you can’t point it at the root so instead we used the location that it sends you to, which in the case of the old version was /userlogin!default.action?os_destination=%2Fstart.action.

Well of course as part of the upgrade this path was changed just a little bit to /userlogin!doDefault.action?os_destination=%2Fstart.action. If you went to the old path well no HTTP 200 for you and so the site was marked as being down.

Once the health monitor was updated to the new URL the site was available again.

Upgrading BitBucket using HTTPS on Windows from 4.x to 5.x

Just for a change I had to upgrade a Bitbucket 4.x server to 5.9. This is a major upgrade and Atlassian provided clear warning that the configuration file needed to be changed manually as part of this process.

The upgrade went well and I decided to start the service to see what state it would be in prior to the configuration file changes. This wasn’t so good with the service stopping almost immediately.

Checking the Bitbucket web server log I found the following error.

Caused by: java.lang.IllegalStateException: Failed to load property source from location ‘file:/D:/Atlassian/ApplicationData/Bitbucket/shared/’

This seemed strange as the service had been running fine but after checked the file permissions sure enough the Bitbucket service account had no access to the file. Simple fix so I started the service again.

This time the service started but was using straight HTTP. That’s fine it showed that the service was all fine and talking to the database so now on to the configuration changes.

The configuration that needed to be replicated was below.

<Connector port=”443″
sslProtocol=”TLS” />

Looking at the new file the format was a little different and not what was expected based on the upgrade documentation. It seemed on first look to use semi-colons as separators rather than being line separated.


To replicate this the new configuration was set up using semi-colons. When the service was started it wasn’t too good.

Faulting application name: bserv64.exe, version:, time stamp: 0x51543b9d
Faulting module name: jvm.dll, version:, time stamp: 0x56ac212a
Exception code: 0xc0000005
Fault offset: 0x0000000000214f38
Faulting process id: 0xa70
Faulting application start time: 0x01d3dd132c763723
Faulting application path: C:\Atlassian\Bitbucket\5.9.1\bin\bserv64.exe
Faulting module path: c:\atlassian\bitbucket\4.6.0\jre\bin\server\jvm.dll
Report Id: 552e5d9f-4907-11e8-80db-001dd8b71d05
Faulting package full name:
Faulting package-relative application ID:

Well that didn’t work. After looking again I saw my mistake and removed the semi-colons and used line breaks instead. This didn’t work too well either with the Bitbucket log again recording an error.

Caused by: org.springframework.boot.context.embedded.tomcat.ConnectorStartFailedException: Connector configured to listen on port 443 failed to start

After more investigation I found that you need to specify the key-store and key password in this version even if the default password has been used.

Still the service wouldn’t start.

The other configuration items looked pretty clear so I looked at the key-store location parameter. In the old version this was keystoreFile=”D:\Atlassian\keystore\bitbucket.jks”

All of the examples provided were for linux which used the typical /dir/file format. This surely wouldn’t work for Windows but I didn’t find any examples of what to do.

Ultimately I removed the speech marks and converted the back slashes to forward slashes.

So the final working configuration for 5.x is below.


The service now started using HTTPS and we were back in service.

Unable to delete Hyper-V Host in VMM due to SQL statement failure

I had an odd failure when deleting a Hyper-V server from VMM 2016. The job failed with a very generic Error 20413.

So the next step was to check the log file which gave me an unexpected error.

——————- Error Report ——————-

Error report created 4/26/2018 7:29:26 AM
CLR is not terminating

————— Bucketing Parameters —————


SCVMM Version=4.0.2244.0
SCVMM flavor=C-buddy-RTL-AMD64
Default Assembly Version=4.0.2244.0
Executable Name=vmmservice.exe
Executable Version=4.0.2244.0
Base Exception Target Site=140717336435616
Base Exception Assembly name=System.Data.dll
Base Exception Method Name=System.Data.SqlClient.SqlConnection.OnError
Exception Message=Unable to connect to the VMM database because of a general database failure.
Ensure that the SQL Server is running and configured correctly, then try the operation again.
Build bit-size=64

Great!! The service can’t talk to SQL I thought but this message was also a little deceiving and the next section was actually more important.

———— exceptionObject.ToString() ————

Microsoft.VirtualManager.DB.CarmineSqlException: Unable to connect to the VMM database because of a general database failure.
Ensure that the SQL Server is running and configured correctly, then try the operation again. —> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the SAME TABLE REFERENCE constraint “FK_tbl_WLC_VHD_VHD”. The conflict occurred
The statement has been terminated.

Again they bury the lead. The first part again goes on about not being able to talk to SQL but then they give you the actual issue. “The DELETE statement conflicted with the SAME TABLE REFERENCE constraint “FK_tbl_WLC_VHD_VHD”. The conflict occurred. The statement has been terminated”

When VMM is trying to delete the server it’s hitting an issue due to references in the “FK_tbl_WLC_VHD_VHD” table. This is blocking the deletion of the server object.

I found that there were some mentioned that this may be due to the server belonging to a cluster, which it was, and that VMM may take some time to clean up the reference. Well this server had been removed from the cluster almost 12 hours ago so I doubted that just waiting longer would do it and decided to clean up the table.

This appeared to be caused by some orphaned objects that were still in the database as being present on the host even though they were long gone. These existed in the  tbl_WLC_PhysicalObject table.

VMM uses GUIDs to refer to objects in the database so I first needed to get the GUID for the server which could then be used to target these entries. This was simple with powershell.

(Get-SCVMHost Hyper-V-Server-Name).ID

We then pick up the GUID and insert it into the following SQL query after a quick DB backup.

DELETE FROM [tbl_WLC_PhysicalObject] WHERE [HostId]=’VM-Host-GUID’

Finally back to VMM Powershell and delete the Hyper-V server again. My Hyper-V server was already off the network so I used a -force to just remove the database references.

remove-vmhost Hyper-V-Server-Name -Force

This time the job succeeded.