One place for hosting & domains

      Linode

      How to Resell Linode Services


      Updated by Linode Contributed by Linode

      Linode warmly welcomes and encourages the reselling of our services to third-party customers. Anyone can resell Linode services. This guide will walk you through the process of becoming a reseller.

      Note

      While Linode encourages reselling, we do not currently have a special reseller program. Linode does not offer discounted pricing for resellers at this time, nor do we directly offer white-label software, like WHMCS plugins, to aid in reselling. It is possible to create such software of your own via the Linode API.

      However, Linode does have a referral program. For more information on Linode’s referral program, read the referral codes section.

      What is a Reseller

      A reseller is any person or entity that charges a third party for Linode services, acting as a kind of middleman. Resellers are free to charge clients for full or partial access to Linode services, either through the use of the Linode API, or by giving a client access to Linode services provisioned on their behalf.

      There are a variety of reasons one might want to resell Linode services. One of the most common reasons developers and engineers become resellers is that they use Linode to test, develop, and/or host their client’s websites and apps, and in doing so need to bill those clients for charges accrued by the Linode services that power this business. Specific examples of this pattern include:

      • An agency that creates custom WordPress installations for their customers on Linode.

      • An app developer that uses Linode to host their customer’s database.

      • A business which operates a fully-fledged hosting platform based on Linode services, using tools like the Linode API. One such example is Cloudnet Sweden, a platform-as-a-service (PaaS) that uses Linode as a cloud host for their managed platform. Read our case study on Cloudnet Sweden for an in-depth look at why they chose to partner with Linode.

      Referral Codes

      As mentioned above, Linode does not offer a discount on re-sold Linode services. However, Linode does offer a referral program. If you feel like Linode is a good choice for another person, you can send them your referral code (or referral URL) to receive $20 per sign up.

      The credit for your referral will be applied to your account if the referral stays active as a Linode customer for 90 days. Specifically, the referred account will need to have at least one active, billed Linode service on their account throughout the 90 day period.

      Advertising your referral code to others is not the same as reselling Linode services. When someone else uses your referral code, they create an entirely separate Linode account with their own billing.

      Things Resellers Should Keep in Mind

      There are a few stipulations that resellers should keep in mind:

      • All resellers, and the customers of resellers, are bound to Linode’s Terms of Service (ToS). If for any reason a customer of a Linode reseller breaks Linode’s ToS, it is the reseller who will be held accountable. If you are planning on becoming a reseller it is a good idea to carefully craft a ToS of your own that is in accordance with Linode’s ToS.

      • All resellers, and the customers of resellers, are bound to Linode’s Acceptable Use Policy (AUP). If for any reason a customer of a Linode reseller breaks Linode’s AUP, it is the reseller who will be held accountable.

      • Payments are to be made directly to Linode by the reseller. If a customer of a reseller fails to pay the reseller for their services, the reseller is still responsible for their monthly payment to Linode.

      • Linode Support can help with issues related to the physical operation of your Linode services, but issues related to your software configuration are outside of the scope of Linode Support. Linode offers a number of resources to help with configuration questions. Linode Support is only available to people with access to a Linode Cloud Manager user. If your customers do not have their own Linode users, they will not be able to contact Linode Support.

      How to Resell Linode Service

      Linode API

      The best way to resell Linode services is through the use of the Linode API. The Linode API provides robust, programmatic access to the full suite of Linode services. Using the API, a reseller could set up a custom user interface to only allow the select features they want available for their customers. For example, it’s possible to create a UI that only enables 4GB Linode deployments and that automatically provisions those Linodes with a StackScript. For a tutorial on how to use the Linode API, check out our Getting Started with the Linode API guide. For a comprehensive view of the Linode API, see Linode’s API documentation. For a list of Linode API libraries and tools, head over to our developer portal.

      Limited Cloud Manager Users

      If a reseller wants to be able to give reseller customers access to parts of the Linode Cloud Manager without developing a new user interface, they can create a limited Manager user in the Cloud Manager. A user is a set of credentials that can access your Linode account, and your Linode account can have multiple users. A user can be restricted to have a limited set of permissions, such as only being able to access certain Linodes and not having access to your billing information. To create a limited user in the Cloud Manager, review the Users and Permissions section of the Accounts and Passwords guide.

      Note

      Cloud Manager users are not related to the Linux users on your Linodes. If you need to revoke a customer’s account access, you should remove access to both their Cloud Manager users and their Linux users. Read the Linux Users and Groups guide for more information on this subject.

      Limited Linux User Accounts

      A reseller might provide a customer with limited access to a Linode by creating an account for them at the operating system level. This provides the customer with access to their server, without access to the features of the Linode API or the Cloud Manager. For a hosting reseller that offers access to a pre-defined Linux environment, this is often a good solution. Read the Linux Users and Groups guide for more information on this subject. You may also want to limit users’ access to the filesystem with SFTP jails.

      Frequently Asked Questions

      Can I Show Linode’s Logos on My Site?

      Yes. Please use the official Linode logo assets.

      What Payment Methods are Available?

      Automatic payments can be made with a credit card. All Linode accounts are required to have a credit card on file. Manual PayPal payments can also be made, so you can add credit to your Linode account with PayPal. For more information on Linode’s billing, review the Billing and Payments guide.

      Does Linode Have a White-Label Interface?

      Linode does not offer a white-label interface, but you could create one via the Linode API.

      Can I Model my Terms of Service on Linode’s ToS?

      Yes, you can refer to Linode’s ToS and AUP when authoring your own, and your business and your customers need to comply with Linode’s ToS and AUP.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      How to Choose a Linode Plan


      Updated by Linode Written by Linode

      Linode offers four instance types: Nanode, Standard, High Memory, and Dedicated CPU. For the Standard, High Memory, and Dedicated CPU types there are several hardware resource tiers, or plans, that you can choose from.

      When selecting a plan, it is important to understand the hardware resources allocated to your instance, like CPU, transfer, storage, and RAM. An understanding of your project’s own needs and requirements is also useful. This guide provides an overview of all Linode instance types and plans, their corresponding use cases, and how to choose which one is right for you.

      Note

      You can easily change between instance types and plans on an existing Linode at any time. Review the Resizing a Linode for instructions.

      Hardware Resource Definitions

      Start by reviewing what each resource means for your application. If you’re confident in your understanding of these concepts, please feel free to skip ahead.

      Resource Description
      RAM The working memory available for your server’s processes. Your server stores information in memory that is needed to carry out its functions. Or, it caches data in memory for fast retrieval in the future, if it is likely that the data will be needed. Data stored in RAM is accessed faster than data stored in your Linode’s disks, but it is not persistent storage.
      CPU The number of virtual CPUs (vCPUs) available to your server. Your software is often designed to execute its tasks across multiple CPUs in parallel. The higher your vCPU count, the more work you can perform simultaneously.
      Storage Your server’s built-in persistent storage. Large databases, media libraries, and other stores of files will require more storage space. Your Linode’s storage is maintained on high-performance SSDs for fast access. You can also supplement your Linode’s disks with extra Block Storage Volumes.
      Transfer The total amount of traffic your server can emit over the course of a month. Inbound traffic sent to your Linode does not count against your transfer quota. If you exceed your quota, your service will not be shut off; instead, an overage will be billed. Review the Network Transfer Quota guide for more information about how transfer works.
      Network In The maximum bandwidth for inbound traffic sent to your Linode. The bandwidth you observe will also depend on other factors, like the geographical distance between you and your Linode and the bandwidth of your local ISP. For help with choosing a data center that will feature the lowest latency and best bandwidth, review the How to Choose a Data Center guide.
      Network Out The maximum bandwidth for outbound traffic emitted by your Linode. The bandwidth you observe will also depend on other factors, like the geographical distance between you and your Linode and the bandwidth of your local ISP. For help with choosing a data center that will feature the lowest latency and best bandwidth, review the How to Choose a Data Center guide.

      General Principles when Choosing a Plan

      The different Linode instance types represent different balances of the above resources. Nanode and Standard instances offer a general-purpose array of resources, High Memory instances favor higher memory allocations, and Dedicated CPU instances reserve physical CPU cores for you.

      At the same time, different kinds of applications have different resource requirements. Some applications may need to store a lot of data but require less processing power, some may need more memory than CPU, and some may be especially CPU-intensive. As a result, certain instance types can better serve certain applications. When creating your instances, consider what resources your application needs and then compare it with the resources specified by each of the instance types. The following sections include common use cases for each type, and one of these may resemble your needs.

      Finally, a common strategy when setting up a new server is to start with a smaller instance and then resize your Linode if needed. At a minimum, you will need to choose a plan that offers enough disk space to store your data. You can then monitor the CPU, memory, and network usage of your application to determine if you need more of those resources.

      1. Nanode

      The Nanode instance is great place to begin if you are new to the world of cloud hosting and are unsure of your requirements. The Nanode offers the essentials and costs $5/month. With this instance you have a fully functioning server with your preferred Linux distribution.

      Use Cases

      Resource Specifications

      Resource Value
      RAM 1GB
      CPU 1 vCPU
      Storage 25 GB SSD Storage
      Transfer 1 TB
      Network In 40 Gbps
      Network Out 1000 Mbps

      2. Standard

      Standard instances start with 2GB of RAM and 1 vCPU and can go all the way up to 192GB of RAM with 32 vCPUs. These instances offer a balanced array of resources and can support a wide range of modern cloud applications, from personal projects to production deployments of an enterprise application.

      Use Cases

      Base Plan

      Resource Value
      RAM 2GB
      CPU 1 vCPU
      Storage 50 GB SSD Storage
      Transfer 2 TB
      Network In 40 Gbps
      Network Out 2000 Mbps

      To view a full list of the Standard instance plans, visit the Linode Pricing page.

      3. High Memory

      High Memory instances feature higher RAM allocations and relatively fewer vCPUs and less storage. This keeps your costs down and provides power to memory-intensive applications.

      Use Cases

      Two primary applications for High Memory instances are in-memory caches and in-memory databases, like Memcached and Redis. These applications offer very fast retrieval of data, but they store data in a non-persistent manner (with some caveats). So, they are usually used in conjunction with another persistent database server running on a separate instance.

      The kinds of data you might store in one of these applications includes: information about your users’ sessions; frequently-requested pages on your website; and data that needs to be computed (for example, the average rating of a product on a retail store’s site).

      Base Plan

      Resource Value
      RAM 24GB
      CPU 1 vCPU
      Storage 20 GB SSD Storage
      Transfer 5 TB
      Network In 40 Gbps
      Network Out 5000 Mbps

      To view a full list of the High Memory instance plans, visit the Linode Pricing page.

      4. Dedicated CPU

      Dedicated CPU instances offer entire dedicated CPU cores for your own Linode’s use. No other instances can run processes on the same cores that you’re using, which means that your software can run at peak speed and efficiency.

      Under the Nanode, Standard, and High Memory instances, your processes are scheduled on the same CPU cores as the processes from other servers. This shared scheduling is done in a secure and performant manner, and Linode works to minimize competition for CPU resources between your server and other servers, but the Dedicated CPU instances provide an environment with zero competition. With Dedicated CPU instances, you can run your software for prolonged periods of maximum CPU usage, and you can ensure the lowest latency possible for latency-sensitive operations.

      Dedicated CPUs and the Linode API

      Some data analysis and processing tasks are well-suited for Dedicated CPU instances. For these workloads, you may only need your Dedicated CPU instance until the task is finished, at which point you can remove the instance.

      Furthermore, some CPU-intensive tasks may be triggered from other events in your workflow. For example, if you’re a software developer that uses continuous integration and delivery (CI/CD) tools, those tools are generally run whenever you push code to your repository. By leveraging the Linode API, you can programmatically create a Dedicated CPU instance, run these tools, and destroy the instance on every code push.

      Use Cases

      Base Plan

      Resource Value
      RAM 4GB
      vCPU 2 vCPUs
      Storage 25 GB SSD Storage
      Transfer 4 TB
      Network In 40 Gbps
      Network Out 4000 Mbps

      To view a full list of the Dedicated CPU instance plans, visit the Linode Pricing page.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      How To Create an OAuth App with the Linode Python API Library


      Updated by Linode

      Contributed by

      Linode

      Linode supports the OAuth 2 authorization protocol. OAuth 2 allows a user to safely grant a third-party app permission to act on their behalf. This means that a user could authorize an app to access data and / or make changes to their Linode account and services that are exposed by the Linode APIv4. For example, an app could create or destroy Linodes, manage a NodeBalancer, or alter a domain.

      This guide will show you how to create a simple OAuth application using Flask and the Linode Python API library. This app allows a user to log in with their Linode account and create a Linode with a StackScript. The complete code for this example is available in the Linode APIv4 Python library example repository.

      Before You Begin

      1. Normally, in order to create an OAuth app with Linode your server must have HTTPS enabled. The only exceptions to this rule are localhost addresses, which can use HTTP. As this guide is just a primer and is not intended to supply production ready code, we will be working with a local workstation, using localhost. If you choose to create an app for production, you will need to generate SSL certificates for HTTPS access.

      2. Ensure that Python 3 is installed on your workstation.

      Obtaining a Client ID and a Client Secret

      In order for Linode to verify the identity of your app, called a client, you will need to generate a set of credentials, specifically a client ID and a client secret.

      1. Log in to the Linode Cloud Manager and navigate to your Account Profile.

        OAuth Account Profile

      2. From there, click on the My Apps tab and select Create My App. You will be prompted to supply a label for your app and a callback URL. We will discuss the role of the callback URL in depth later in this guide. For now you can supply the following URL:

        http://localhost:5000/auth_callback
        

        Leave Public unchecked and click Submit.

        OAuth Account Profile

      3. A window will appear with your client secret. Copy this down somewhere secure, as once you exit this window you will not be able to retrieve the client secret again, and will be forced to generate a new one.

        OAuth Account Profile

      4. Once you exit the client secret window your app will appear as part of a list of apps. Note your client ID, as this is the last piece of information you will need to verify your app’s identity.

        OAuth Account Profile

      In summary, you should have these three bits of information, with values similar to the ones provided here:

      OAuth 2 Authentication Exchange

      The OAuth 2 workflow is a series of exchanges between your third-party app and Linode. Below is an explanation of these exchanges.

      1. The end user visits your client application’s website and attempts to login.
      2. Your client application redirects the end user to the authentication server (https://login.linode.com) with your client application’s client ID and requested OAuth scopes, which appear in the URL of the login page.
      3. The end user inputs their username and password to the authorization server and authorizes the login.
      4. The authorization server redirects the end user back to your client application with a temporary authorization code (sometimes called an exchange code) in the URL.
      5. The client application issues a POST request to the authentication server containing the authorization code and the client application’s client secret.
      6. The authentication server responds to the client application with a newly issued OAuth access token.

      In the following sections you will write the code to perform each one of these steps, using the Linode Python API library.

      Setup Your Development Environment

      1. Create a project folder and move into that folder.

        mkdir ~/linode-oauth-project && cd ~/linode-oauth-project
        
      2. For this project, you will need to use pip to download and install the required Python libraries. Install pip if you do not already have it:

        apt install python-pip
        
      3. Install the required Python libraries:

        pip install flask flask-session linode_api4
        

      Configure Your App

      In a text editor, create a file named config.py. Add the following variables and values, being sure to change the values to your own.

      The StackScript used in this example is for demo purposes. To explore other available StackScripts, visit the Linode StackScript Library. Note that the stackscript_id does not have quotation marks around it. The secret key is used for serializing session data, and should be a value only you know.

      config.py
      1
      2
      3
      4
      5
      
      client_id = 'ce571a8cdad1ba4a0a7d'
      client_secret = 'fab8e2222e83b9b2f50a76012122ec20a5acb005ed088f3fccda2c9c2c4e1cbd'
      stackscript_id = 320826
      application_name = 'my-application-name'
      secret_key = 'my-secret-key'

      Author an OAuth2 App

      In this section, you will write the code for the app.

      Include Imports

      Ensure you are in the linode-oauth-project directory and create and open a file called app.py in the text editor of your choice. Include the following libraries:

      app.py
      1
      2
      3
      4
      5
      6
      
      import re
      from flask import Flask, redirect, request, render_template, session, send_from_directory
      from flask_session import Session
      from linode_api4 import (LinodeClient, LinodeLoginClient, StackScript, Image, Region, Type, OAuthScopes)
      
      import config

      Set Up Flask and Session Key

      Copy in the following code to set up Flask and the session secret key:

      app.py
      1
      2
      3
      4
      
      ...
      
      app=Flask(__name__)
      app.config['SECRET_KEY'] = config.secret_key

      Create a Function to Return the Linode Login Client

      In app.py add the following function to return the LinodeLoginClient class. The LinodeLoginClient class is the library’s OAuth interface. Note that we are passing the client_id and client_secret parameters from our config.py file to the class:

      ~/linode-oauth-project/app.py
      1
      2
      3
      4
      
      ...
      
      def get_login_client():
          return LinodeLoginClient(config.client_id, config.client_secret)

      Create an Index Route

      In Flask you can create HTTP endpoints with routes. The index route, defined in the code below at the document root /, will be the route the user will see when they navigate to http://localhost:5000/. This route will be responsible for displaying the available Linode plan types, the available regions, and the StackScript-compatible images that a user will choose from when creating their new Linode.

      To query a list of available plan types and regions you can use the LinodeClient class, which is an interface for Linode’s APIv4. Viewing the Linode plan types and regions does not require any sort of authorization, so you can provide a dummy value of no-token to instantiate the class:

      ~/linode-oauth-project/app.py
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      ...
      
      @app.route('/')
      def index():
          client = LinodeClient('no-token')
          types = client.linode.types(Type.label.contains("Linode"))
          regions = client.regions()
          stackscript = StackScript(client, config.stackscript_id)
          return render_template('configure.html',
              types=types,
              regions=regions,
              application_name=config.application_name,
              stackscript=stackscript
          )

      It is important to note that the two API queries in the above code are slightly different from one another. The client.regions method is a top-level method, just as it appears in the Linode API. The client.linode.types method, on the other hand, is part of the Linode group, which is a collection of methods that deal with Linodes. Again, this is because Linode endpoints are grouped that way in the API. Some methods in the Linode Python library are top level, such as domain_create, while others, like networking.ip_assign, are part of a group. For more information on the top-level methods and groupings, consult the library documentation.

      In addition to querying the API, the above route also renders the configure.html template by passing it the types, regions, application name, and StackScript object. The StackScript object contains a list of StackScript compatible images. We will cover templating in a later section.

      Create a Login Route

      Next, create a login route in app.py. This route will perform two functions. First, it will serialize the user’s plan type, region, and image selections into the session.

      Second, this route will redirect the user to Linode’s login page where they will be prompted to authorize your client app and the scopes you have requested for it. Scopes are sets of permissions that define the access level of your client app. For instance, to create a Linode, your end user must authorize the OAuthScopes.Linodes.create scope.

      ~/linode-oauth-project/app.py
      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      ...
      
      @app.route('/', methods=["POST"])
      def start_auth():
          login_client = get_login_client()
          session['dc'] = request.form['region']
          session['distro'] = request.form['distribution']
          session['type'] = request.form['type']
          return redirect(login_client.generate_login_url(scopes=OAuthScopes.Linodes.create))

      When the user returns to your app from the Linode login page, they will be directed to the callback URL.

      Note

      Below is a list of available scopes:

      • OAuthScopes.Linodes
      • OAuthScopes.Domains
      • OAuthScopes.StackScripts
      • OAuthScopes.Users
      • OAuthScopes.NodeBalancers
      • OAuthScopes.Tokens
      • OAuthScopes.IPs
      • OAuthScopes.Tickets
      • OAuthScopes.Clients
      • OAuthScopes.Account
      • OAuthScopes.Events
      • OAuthScopes.Volumes

      Each scope is broken into five permissions: view, create, modify, delete, and all. The all permission encompasses the other four permissions.

      Manage the OAuth 2 Callback URL

      The OAuth 2 callback URL has two main responsibilities. Its first responsibility is to help prove the identity of the client application. When a user attempts to log in to Linode through OAuth, instead of redirecting the user back to the page they came from, Linode’s OAuth implementation matches the client ID to the callback URL you have registered with your app on Linode’s system. This ensures that a nefarious third party can’t just steal the client ID, which is public, and attempt to authorize their own app with it.

      The callback URL’s second responsibility is to kick off the process of exchanging an authorization code for an access token. This second process is done over POST, and so it doesn’t require the user to physically leave the page they are returned to after they log in to Linode. Now you will write the code that satisfies this second responsibility.

      In app.py, add the following lines:

      ~/linode-oauth-project/app.py
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      
      ...
      
      @app.route('/auth_callback')
      def auth_callback():
          code = request.args.get('code')
          login_client = get_login_client()
          token, scopes, _, _ = login_client.finish_oauth(code)
      
          # ensure we have sufficient scopes
          if not OAuthScopes.Linodes.create in scopes:
              return render_template('error.html', error='Insufficient scopes granted to deploy {}'
                      .format(config.application_name))
      
          (linode, password) = make_instance(token, session['type'], session['dc'], session['distro'])
      
          get_login_client().expire_token(token)
          return render_template('success.html',
              password=password,
              linode=linode,
              application_name=config.application_name
          )

      Let’s take a look at what each of the parts of this section does.

      First, a route is defined for the callback with @app.route(), then a function called auth_callback is defined that will run whenever this route is accessed:

      ~/linode-oauth-project/app.py
      1
      2
      3
      4
      
      ...
      @app.route('/auth_callback')
      def auth_callback():
      ...

      When the user is returned to the callback URL, an authorization code is appended to the URL. The variable code is set to retrieve this value from the URL’s request arguments:

      ~/linode-oauth-project/app.py
      1
      2
      3
      
      ...
          code = request.args.get('code')
      ...

      Then you retrieve an instance of the LinodeLoginClient class:

      ~/linode-oauth-project/app.py
      1
      2
      3
      
      ...
          login_client = get_login_client()
      ...

      Once you have the LinodeLoginClient class, you can pass the authorization code to the finish_oauth method, which is a helper method that will manage the authorization code to OAuth token exchange. This method returns an OAuth token, and the scopes the user has agreed upon.

      ~/linode-oauth-project/app.py
      1
      2
      3
      
      ...
          token, scopes, _, _ = login_client.finish_oauth(code)
      ...

      The next section compares the scopes your app requested from the user to the scopes returned by Linode’s OAuth login page. If the returned scopes do not include the correct scopes, in this case the OAuthScopes.Linode.create scope, then an error template is rendered and an error message is displayed:

      ~/linode-oauth-project/app.py
      1
      2
      3
      4
      5
      6
      
      ...
          # ensure we have sufficient scopes
          if not OAuthScopes.Linodes.create in scopes:
              return render_template('error.html', error='Insufficient scopes granted to deploy {}'
                      .format(config.application_name))
      ...

      Once your app has determined that it has the correct permissions, it creates the Linode using the Linode plan type, the region, and the image that the app serialized into session storage. You will create the make_instance function in the next step. The make_instance function returns the linode object, which contains the Linode’s label, group, and IP address, and the function also returns a randomly generated password:

      ~/linode-oauth-project/app.py
      1
      2
      3
      
      ...
          (linode, password) = make_instance(token, session['type'], session['dc'], session['distro'])
      ...

      Once the Linode has been created, the app expires the OAuth access token. Expiring tokens after use is a strong security measure but if your app is performing many actions on behalf of the user, you might find that time-based expiration scheme is more suitable to your needs. The app then renders the success template by passing it the linode object, the password, and application name:

      ~/linode-oauth-project/app.py
      1
      2
      3
      4
      5
      6
      7
      
      ...
          get_login_client().expire_token(token)
          return render_template('success.html',
              password=password,
              linode=linode,
              application_name=config.application_name
          )

      Create a Function to Deploy a Linode

      Now, create the make_instance function that you referenced above:

      ~/linode-oauth-project/app.py
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      
      ...
      
      def make_instance(token, type_id, region_id, distribution_id):
          client = LinodeClient('{}'.format(token))
          stackscript = StackScript(client, config.stackscript_id)
          (linode, password) = client.linode.instance_create(type_id, region_id,
                  group=config.application_name,
                  image=distribution_id, stackscript=stackscript.id)
      
          if not linode:
              raise RuntimeError("it didn't work")
          return linode, password

      The make_instance function takes an OAuth access token, the type ID, the region ID, and the image (Linux distribution) ID as parameters. It creates an instance of the LinodeClient class, and unlike the instance of LinodeClient used earlier in the guide, this one requires an OAuth token because you will be using it to create a Linode. The function then creates a Linode using the linode.instance_create method, returning the linode object and the password.

      Finally, if there was an error with the creation of the Linode, the if not linode statement will raise a runtime error.

      Set the name Variable

      At the end of your app.py, paste in the following code to make sure you can run your app:

      ~/linode-oauth-project/app.py
      1
      2
      3
      
      if __name__ == '__main__':
          app.debug=True
          app.run()

      Create App Templates

      Now that you have written the backend code for your app, you’ll need to create a frontend user interface. Begin by creating a templates directory in your project directory and moving into it:

      mkdir ~/linode-oauth-project/templates && cd ~/linode-oauth-project/templates
      

      Using your preferred text editor, create and open base.html. This will be the base template from which your other templates will inherit their stylesheets and JavaScript files:

      ~/linode-oauth-project/templates/base.html
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      
      <html>
      <head>
          <title>Install On Linode</title>
          <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
              integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
          <style>
              body{
                  text-align: center;
                  background-color: #333333;
              }
              .form-group{
                  display: inline-block;
                  text-align: left;
                  width: 250px;
                  border: 1px solid #cccccc;
                  margin: 5px;
                  padding: 5px;
              }
              .form-group label{
                  color: #337ab7;
              }
              .form-group select{
                  font-size: 16px;
                  outline: none;
                  border: 0px solid #000000;
                  box-shadow: inset 0 1px 1px rgba(0,0,0,0);
                  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0);
              }
              .form-group select:focus{
                  box-shadow: inset 0 1px 1px rgba(0,0,0,0);
                  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0);
              }
              .btn-lg{
                  border-radius: 0px;
                  margin-top: 20px;
              }
              .row{
                  margin-bottom: 20px
              }
              .pop{
                  color: #337ab7;
                  font-weight: bold
              }
              code{
                  color: #337ab7;
                  background-color: #eeeeee
              }
              .boxy{
                  border: 1px solid #cccccc;
                  width: 400px;
                  background-color: #f9f9f9;
                  margin: auto;
                  padding: 10px;
              }
          </style>
      </head>
      <body>
          <div class='container' style='background-color: white; border-left: grey; border-right: grey; height: 100%; padding: 20px;'>
              {% block content %}
              {% endblock %}
          </div>
      
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
          <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
              integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
              crossorigin="anonymous"></script>
      </body>

      The important thing to note in the above template is the Jinja2 templating tags. They are:

      {% block content %}
      {% endblock %}
      

      As you will see, any template that extends the base.html template and includes code between the opening and closing content block, will render the code laid out by base.html.

      Create a file called configure.html, which will be the UI a user will see when they reach the document root endpoint (/). Copy in the following code:

      templates/configure.html
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      
      {% extends 'base.html' %}
      {% block content %}
          <form method="POST">
              <div class='row'>
                  <h1>Deploy <span style="color: #337ab7;">{{application_name}}</span> to a Linode</h1>
                  <p>
                      This will create a brand new Linode running {{application_name}} on your
                      account and give you the credentials.
                  </p>
              </div>
              <div class='row'>
                  <div class='form-group'>
                      <label for='type'>Type</label>
                      <select name='type'i id='type' class='form-control'
                          onblur="blurring(this)" onfocus="focusing(this)">
                          {% for s in types %}
                              <option value="{{s.id}}">{{s.label}}</option>
                          {% endfor %}
                      </select>
                  </div>
                  <div class='form-group'>
                      <label for='region'>Region</label>
                      <select name='region' id='region' class='form-control'
                          onblur="blurring(this)" onfocus="focusing(this)">
                          {% for o in regions %}
                              <option value="{{o.id}}">{{o.id}}</option>
                          {% endfor %}
                      </select>
                  </div>
                  <div class='form-group'>
                      <label for='distribution'>Images</label>
                      <select name='distribution' id='distribution' class='form-control'
                          onblur="blurring(this)" onfocus="focusing(this)">
                          {% for d in stackscript.images %}
                              <option value="{{d.id.id}}">{{d.id.id}}</option>
                          {% endfor %}
                      </select>
                  </div>
              </div>
              <div class='row'>
                  <input type="submit" value="Deploy Linode" class='btn btn-primary btn-lg'/>
              </div>
          </form>
          <script>
              function focusing(ele){
                  ele.parentElement.style.borderColor = "#337ab7";
              }
              function blurring(ele){
                  ele.parentElement.style.borderColor = "#cccccc";
              }
          </script>
      {% endblock %}

      Here the template begins with two statements: {% extends 'base.html' %} and a {% block content %} statement. These two tags tell Jinja2 to extend the code within base.html, and to place everything within {% block content %} ... {% endblock %} in configure.html between the corresponding {% block content %} ... {% endblock %} tags in base.html.

      configure.html includes Jinja2 logic, with the inclusion of for statements like {% for o in regions %}. These statements are like for statements in other languages, and are used to iterate over an array or list. In this example, it is iterating over the regions that we passed to the template from the index route. configure.html also contains variables, which are denoted by double curly brackets: {{ s.id }}.

      Create another file called error.html. This will be the template that appears whenever there is an error in the Linode deployment. Copy in the following code:

      templates/error.html
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      
      {% extends 'base.html' %}
      {% block content %}
          <div class='row'>
              <h1 class="pop">Error</h1>
              <p>{{error}}</p>
          </div>
          <div class='row' style='margin-top: 20px'>
              <a href='/' class='btn btn-lg btn-default'>Try Again</a>
          </div>
      {% endblock %}

      This template works the same way that configure.html does, by extending base.html and providing its own content block.

      Lastly, create another file called success.html. This file follows the pattern set by configure.html and error.html, and will present the user with a confirmation message whenever a Linode is successfully created. This message includes the Linode’s label, group, IP address, and password:

      templates/success.html
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      
      {% extends 'base.html' %}
      {% block content %}
          <div class='row'>
              <h1>Success!</h1>
              <p>{{application_name}} has been deployed to <span class="pop">{{linode.label}}</span> in the {{linode.group}} group.</p>
          </div>
          <div class='row'>
              <div class='boxy'>
                  <p>You can access your Linode with the following command:</p>
                  <code>ssh root@{{linode.ipv4[0]}}</code>
                  <br />
                  <br />
                  <p>Your root password is:</p>
                  <code>{{password}}</code>
              </div>
          </div>
      {% endblock %}

      Run Your App

      You are now ready to run your app. Change back to your project’s main directory:

      cd ~/linode-oauth-project
      

      Run the app.py script:

      python3 app.py
      

      Open your browser to the following URL:

      http://localhost:5000/
      

      You should be greeted with your new app. Select a plan, a region, and an image to deploy a Linode using the Linode API Python library.

      Next Steps

      The app you’ve created shows off some of the aspects of the Linode API Python library. You can use LinodeLoginClient to authorize your OAuth app with the appropriate scopes, and can create Linodes through the use of LinodeClient.

      In extending this app, you might want to add multiple functionalities, like creating NodeBalancers from a list of available Linodes, or managing domains. To achieve this goal you’ll probably want to separate the login logic from the Linode creation logic. One way to do this would be store the OAuth token in the session, implementing a time-based expiration mechanism to expire your tokens instead.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link