简体   繁体   中英

Runtime error while trying to create VM through Azure REST API

I've been following these instructions to create a VM on Azure with python. However Azure is returning an error:

 <!DOCTYPE html> <html> <head> <title>Runtime Error</title> <meta name=viewport content=width=device-width /> <style> body {font-family:Verdana;font-weight:normal;font-size: .7em;color:black;} p {font-family:Verdana;font-weight:normal;color:black;margin- b {font-family:Verdana;font-weight:bold;color:black;margin- H1 { font-family:Verdana;font-weight:normal;font-size:18pt;color:red } H2 { font-family:Verdana;font-weight:normal;font-size:14pt;color:maroon } pre {font-family:Consolas,Lucida Console,Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt} .marker {font-weight: bold; color: black;text-decoration: none;} .version {color: gray;} .error {margin-bottom: 10px;} .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; } @media screen and (max-width: 639px) { pre { width: 440px; white-space: pre-wrap; word-wrap: break-word; } } @media screen and (max-width: 479px) { pre { width: 280px; } } </style> </head> <body bgcolor=white> <span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1> <h2> <i>Runtime Error</i> </h2></span> <font face=Arial, Helvetica, Geneva, SunSans-Regular, sans-serif > <b> Description: </b>An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine. <br><br> <b>Details:</b> To enable the details of this specific error message to be viewable on remote machines, please create a &lt;customErrors&gt; tag within a &quot;web.config&quot; configuration file located in the root directory of the current web application. This &lt;customErrors&gt; tag should then have its &quot;mode&quot; attribute set to &quot;Off&quot;.<br><br> <table width=100% bgcolor=#ffffcc> <tr> <td> <code><pre> &lt;!-- Web.Config Configuration File --&gt; &lt;configuration&gt; &lt;system.web&gt; &lt;customErrors mode=&quot;Off&quot;/&gt; &lt;/system.web&gt; &lt;/configuration&gt;</pre></code> </td> </tr> </table> <br> <b>Notes:</b> The current error page you are seeing can be replaced by a custom error page by modifying the &quot;defaultRedirect&quot; attribute of the application&#39;s &lt;customErrors&gt; configuration tag to point to a custom error page URL.<br><br> <table width=100% bgcolor=#ffffcc> <tr> <td> <code><pre> &lt;!-- Web.Config Configuration File --&gt; &lt;configuration&gt; &lt;system.web&gt; &lt;customErrors mode=&quot;RemoteOnly&quot; defaultRedirect=&quot;mycustompage.htm&quot;/&gt; &lt;/system.web&gt; &lt;/configuration&gt;</pre></code> </td> </tr> </table> <br> </body> </html> 

The part that's confusing me is I'm not interacting with the API through any sort of web application, I'm running this python script locally, and it (ideally) runs with no user interaction once it starts. So I'm not sure how I'd modify any web config file to get a more useful error unless it's referring to something on my Azure account, and in that case, I'm not sure what it's referring to.

I have authenticated programmatically using OAUTH2 token authentication, and that has previously allowed me to create/update resource groups, virtual networks, etc using the same python script (I actually do all of that immediately proceeding the creation of the VM). Also, while using the REST API to create resource groups and virtual networks, it returned useful errors detailing what went wrong. So it's entirely possible I have a typo in the part of the script that creates the request to create a VM, but without a more useful error, I'm not sure what it is.

If anyone has any suggestions on how to get a more useful error, or a better way to do this, I would be eternally grateful

The relevant parts of the python script are:

def get_token(self):
    url = self._auth_url[:(self._auth_url.find('/'))]
    uri = self._auth_url[(self._auth_url.find('/')):]

    conn = httplib.HTTPSConnection( url, 443 )
    conn.request( 'POST', uri, body = "grant_type=client_credentials&client_id=%s&client_secret=%s&resource=https://management.azure.com/" % (self._app_id, self._app_secret), headers = { 'Content-Type' : 'application/x-www-form-urlencoded' } )
    resp = conn.getresponse()

    if not resp.status == 200:
        logger.error( resp.read() )
        raise Error( "Getting azure token failed with givein parameters. Check the _auth_url, _app_id, or _app_secret")
    self._connection = httplib.HTTPSConnection( "management.azure.com", 443 )
    return json.loads( resp.read() )[ "access_token" ]

def create_virtual_machine( self, resource_group_name, vm_name, os_type, role_size, disk_size, nic):
    body = self.generate_linux_virtual_machine_json( vm_name, role_size, disk_size, os_type, resource_group_name, nic )
    token = self.get_token()
    uri = "https://management.azure.com/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s&api-version=2016-08-30" % (self._subscription_id, resource_group_name, vm_name)

    self._connection.request( 'PUT', uri, body = body, headers = { 'Content-Type' : 'application/json', 'Authorization' : 'Bearer %s' % token } )
    resp = self._connection.getresponse()
    if not resp.status == 200:
        logger.error("status: %s, error: %s" % (resp.status, resp.read() ) )

def generate_linux_virtual_machine_json( self, vm_name, role_size, disk_size, os_type, resource_group_name, nic ):
    (publisher_name, publisher_offer, sku) = self.get_image_info( os_type )
    create_linux_virtual_machine_json = '''
    {
        "name": "%s",
        "location": "%s", 
        "properties":{
            "hardwareProfile": {
                "vmSize": "%s"
            },
            "storageProfile": {
                "imageReference": {
                    "publisher": "%s",
                    "offer": "%s",
                    "sku": "%s",
                    "version": "latest"
                },
                "osDisk": {
                    "name": "osdisk",
                    "osType": "Linux",
                    "createOption": "fromImage",
                    "diskSizeGB": "%s",
                    "caching": "ReadWrite"
                }
            },
            "osProfile": {
                "computerName": "%s",
                "adminUsername": "********",
                "adminPassword": "********",
                "customData": "",
                "linuxConfiguration": {
                    "disablePasswordAuthentication": false
                }
            },
            "networkProfile": {
                "networkInterfaces": [
                    {
                        "id": "%s",
                        "properties": {
                            "primary": true
                        } 
                    }
                ]
            }
        }
    }
    '''%(vm_name, self._location, role_size, publisher_name, publisher_offer, sku, disk_size, vm_name, nic)

    return create_linux_virtual_machine_json

I believe I figured out the issue. On the documentation I was using, it specified the request URI as:

".../providers/Microsoft.Compute/virtualMachines/{vm}&api-version={apiVersion}"

However, it should be:

".../providers/Microsoft.Compute/virtualMachines/{vm} ? api-version={apiVersion}" with a question mark rather than an ampersand

I've updated that in my code and everything seems to be working correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM