Skip to content

Steps to update MC Hub to support MC 11

lefreud edited this page May 1, 2021 · 1 revision

This guide will go over the steps necessary to update MC Hub to use MC 11.

1. Setup

If you don't already have MC Hub setup locally, do the following steps.

1.1 Clone MC Hub locally

git clone https://github.com/ComputeCanada/mc-hub.git

1.2 Configure MC Hub

Follow the guide here.

2. Update MC Hub with your code

2.1 Updating the MC version number

Open the file app/models/constants.py and change the line containing the currently used version of Magic Castle.

For example, change the following line:

MAGIC_CASTLE_VERSION_TAG = "10.0"

To this:

MAGIC_CASTLE_VERSION_TAG = "11.0"

2.2 Updating the Terraform required version

If the version of Terraform required to run MC changed, do the following. Still in the file app/models/constants.py, change the line containing the Terraform required version.

For example, change the following line:

TERRAFORM_REQUIRED_VERSION = ">= 0.13.0"

To this:

TERRAFORM_REQUIRED_VERSION = ">= 0.14.5"

2.3 Changing the structure of the Magic Castle configuration (on the backend)

Note: an example of a small configuration schema change can be found in this commit.

To adapt the backend to MC 11, you need to make the MagicCastleConfiguration class match exactly the configuration defined in MC's migration guide and MC's configuration documentation. In order to make that transition, the MagicCastleConfigurationSchema class needs to be modified first.

Modify the instances parameter and storage parameter in the Marshmallow schema in app/models/magic_castle/magic_castle_configuration_schema.py. For instance, you will need to change these lines:

instances = fields.Dict(
    keys=fields.Str(validate=validate.OneOf(INSTANCE_CATEGORIES)),
    values=fields.Dict(type=fields.Str(), count=fields.Int()),
    required=True,
)
storage = fields.Nested(StorageSchema, required=True)

The new schema should match exactly the one in MC 11:

instances = {
    mgmt     = { type = "p4-6gb", tags = ["puppet", "mgmt", "nfs"], count = 1 }
    login    = { type = "p2-3gb", tags = ["login", "public", "proxy"], count = 1 }
    node     = { type = "p2-3gb", tags = ["node"], count = 1 }
    gpu-node = { type = "g1-8gb-c4-22gb", tags = ["node"], count = 1 }
}

where the tags should be validated against MC's permitted tags and the instance names could be validated with the existing function validate_cluster_name or another similar function. Furthermore, the count variable can be made optional (and have a default value of 1).

Regarding the storage, the StorageSchema class should be removed. Then, in MagicCastleConfigurationSchema, the attribute storage should be renamed to volumes and be assigned to a fields.Dict object, where the key would be the volume name (e.g. nfs) and the value would be a nested dictionary mapping a block device name (e.g. home) to a dictionary of attributes.

Now, the file app/models/magic_castle/magic_castle_configuration.py needs some editing.

  • MagicCastleConfiguration.get_from_main_tf_json_file

    This method needs a small modification. Simply remove the following lines:

    # "node" is the only instance category that is encapsulated in a list
    configuration["instances"]["node"] = configuration["instances"]["node"][0]

    This is no longer necessary because the node instances now have the same structure in the configuration as other types of instances.

  • MagicCastleConfiguration.update_main_tf_json_file

    As in the last method, the node instances don't need the structure conversion anymore. So, the following lines can be removed :

    # "node" is the only instance category that needs to be encapsulated in a list
    main_tf_configuration["module"]["openstack"]["instances"]["node"] = [
        main_tf_configuration["module"]["openstack"]["instances"]["node"]
    ]

Then, the file app/models/terraform/terraform_state_parser.py needs the following changes.

  • TerraformStateParser.__get_storage

    The returned dictionary needs to be updated in order to match MC 11's volumes structure. It will probably contain a single volume entry named nfs at first. These would be the lines to change:

    storage = {
        f"{space}_size": get_external_storage_size(space)
        for space in STORAGE_SPACES
    }
    storage["type"] = "nfs"

    Also, the line containing openstack_blockstorage_volume_v2 needs to be updated to openstack_blockstorage_volume_v3. Finally, the name of the function should be renamed to __get_volumes to keep things clean.

  • TerraformStateParser.__get_instances

    The parsing in the nested functions get_instance_type and get_instance_count will probably need to change because the instance categories (mgmt, login, node) are now expressed differently in MC 11 and the name attribute can't be used anymore to filter instance categories. The best way to figure out how to update the parsing is by looking at the structure of openstack_compute_instance_v2 resources in the terraform.tfstate file of a cluster created in MC 11.

    Also, the structure of the return value of __get_instances will need to be updated to match the one in the MagicCastleConfigurationSchema class (e.g. adding support for tags).

  • The parsing will need to be updated in __get_nb_users, __get_domain, __get_cluster_name, get_freeipa_passwd and __get_guest_passwd because the hieradata resource doesn't seem to be present anymore in the state file. Therefore, we will need to look for other places in the state file where the information is present.

  • TerraformStateParser.get_partial_configuration

    Simply change the "storage" key to "volumes".

You will also need to update the tests to use the new configuration parameter. This includes the following files:

  • app/tests/integration/test_api_no_auth.py
  • app/tests/integration/test_api_with_auth.py
  • app/tests/unit/magic_castle/test_magic_castle.py
  • app/tests/unit/magic_castle/test_magic_castle_configuration.py

See also Testing locally.

2.4 Changing the structure of the Magic Castle configuration (on the frontend)

You will need to update the frontend Vue Js code to the new MC configuration structure.

First, you will need to update the following in frontend/src/components/cluster/ClusterDisplay.vue to the new structure (should match the one in MagicCastleConfigurationSchema):

const DEFAULT_MAGIC_CASTLE = Object.freeze({
  cluster_name: "phoenix",
  domain: null,
  image: null,
  nb_users: 10,
  instances: {
    mgmt: {
      type: null,
      count: 1
    },
    login: {
      type: null,
      count: 1
    },
    node: {
      type: null,
      count: 1
    }
  },
  storage: {
    type: "nfs",
    home_size: 100,
    project_size: 50,
    scratch_size: 50
  },
  public_keys: [""],
  guest_passwd: "",
  hieradata: "",
  os_floating_ips: []
});

Then, the ClusterEditor form will need to be updated so that the input fields update the right attributes in the configuration. At first, to keep things simple, the structure in MC 10 (where there are only three instance categories: mgmt, login, node) could be kept the same in the frontend and tags would be set automatically to match the respective roles. Also, there could be a button below the "Compute" node section to add other instances of different categories (with the choice between Management, Login and Compute or others for example). Make sure to look for all references to the this.magicCastle object in the code and verify that the attributes have been updated correctly.

2.5 Last changes

Update the CHANGELOG:

## [v7.5.1] 2021-03-05

### Changed
- Bumped MC to 11.0

Before pushing the changes, you can should verify that all tests from the basic test suite are passed.

cd app
python -m pytest

Then, you can run the full test suite, which includes tests that build a real cluster on the cloud. These will take a few minutes to complete.

python -m pytest --build-live-cluster

3. Publish a new release of MC Hub

If the tests pass and you are satisfied by your changes, you can push the changes and add the tag v7.5.1 to your git commit. Adding a tag to the commit will have the effect of triggering the creation of a Docker image on Docker Hub.

git tag v7.5.1
git push --follow-tags origin master

Now, you will have to wait for Travis CI to build the MC Hub Docker image and run the tests on it. This includes the creation of a live cluster on the ipm-500 project on Arbutus (make sure that the quotas are respected). Finally, if all tests pass, Travis CI will automatically deploy the built image on the Docker Hub repository. When this is done, you should be able to see the new version tag on Docker Hub.

Then, go to GitHub to publish a new release associated with the version tag v7.5.1. Go to https://github.com/ComputeCanada/mc-hub/releases/new.

The release title should have the format MC Hub v7.5.1 and the release description should match exactly the CHANGELOG for the latest release. Then, click on Publish release.

4. Deploying MC Hub with Ansible

Warning: When updating MC Hub, all existing cluster clusters that get modified will be automatically upgraded to the new version of MC you are using.

If you are an administrator of mc.computecanada.dev, follow the instructions to run the Ansible playbook.

Otherwise, if you have your own deployment, you can follow the instructions here.

In both cases, you will need to update the attribute mc_hub_version with the new MC Hub tag in the hosts.yml file.

all:
  hosts:
    example.com:
      ...
      mc_hub_version: "v7.5.1"