Setting up Portworx on a Tanzu Kubernetes Grid aka TKG Cluster

First, this process works today on clusters made with the TKG tool that does not use the embedded management cluster. For clarity I call those clusters TKC or TKC Guest Clusters. The run as VM’s. You just can’t add block devices outside of the Cloud Native Storage (VMware’s CSI Driver). At least I couldn’t.

Now TKG deploys using a Photon 3.0 template. When I wrote this blog and recorded the demo the current latest version is TKG 1.2.1 and the k8s template is 1.19.3-vmware.

Check the release notes here: https://docs.portworx.com/reference/release-notes/portworx/#improvements-4

First generate base64 encoded versions of your user and password to vCenter.

# Update the following items in the Secret template below to match your environment:

VSPHERE_USER: Use output of printf <vcenter-server-user> | base64
VSPHERE_PASSWORD: Use output of printf <vcenter-server-password> | base64

The vsphere-secret.yaml save this to a file with your own user and password to vCenter (from above).


apiVersion: v1
kind: Secret
metadata:
  name: px-vsphere-secret
  namespace: kube-system
type: Opaque
data:
  VSPHERE_USER: YWRtaW5pc3RyYXRvckB2c3BoZXJlLmxvY2Fs
  VSPHERE_PASSWORD: cHgxLjMuMEZUVw==


kubectl apply the above spec after you update the above template with your user and password.

Follow these steps:

# create a new TKG cluster
tkg create cluster tkg-portworx-cluster -p dev -w 3 --vsphere-controlplane-endpoint-ip 10.21.x.x 

# Get the credentials for your config
tkg get credentials tkg-portworx-cluster

# Apply the secret and the operator for Portworx
kubectl apply -f vsphere-secret.yaml
kubectl apply -f 'https://install.portworx.com/2.6?comp=pxoperator'

#generate your spec first, you get this from generating a spec at https://central.portworx.com
kubectl apply -f tkg-px.yaml 

# Wait till it all comes up.
watch kubectl get pod -n kube-system

# Check pxctl status
PX_POD=$(kubectl get pods -l name=portworx -n kube-system -o jsonpath='{.items[0].metadata.name}')
kubectl exec $PX_POD -n kube-system -- /opt/pwx/bin/pxctl status

You can now create your own or use the premade storageClass

kubectl get sc
NAME                             PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
default (default)                csi.vsphere.vmware.com          Delete          Immediate           false                  7h50m
px-db                            kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-db-cloud-snapshot             kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-db-cloud-snapshot-encrypted   kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-db-encrypted                  kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-db-local-snapshot             kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-db-local-snapshot-encrypted   kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-replicated                    kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
px-replicated-encrypted          kubernetes.io/portworx-volume   Delete          Immediate           false                  7h44m
stork-snapshot-sc                stork-snapshot                  Delete          Immediate           false                  7h44m

Now Deploy Kube-Quake

The example.yaml is from my fork of the kube-quake repo on github where I redirected the data to be on a persistent volume.

kubectl apply -f https://raw.githubusercontent.com/2vcps/quake-kube/master/example.yaml
deployment.apps/quakejs created
service/quakejs created
configmap/quake3-server-config created
persistentvolumeclaim/quake3-content created

k get pod
NAME                      READY   STATUS              RESTARTS   AGE
quakejs-668cd866d-6b5sd   0/2     ContainerCreating   0          7s
k get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
quake3-content   Bound    pvc-6c27c329-7562-44ce-8361-08222f9c7dc1   10Gi       RWO            px-db          2m

k get pod
NAME                      READY   STATUS    RESTARTS   AGE
quakejs-668cd866d-6b5sd   2/2     Running   0          2m27s

k get svc
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                         AGE
kubernetes   ClusterIP      100.64.0.1     <none>        443/TCP                                         20h
quakejs      LoadBalancer   100.68.210.0   <pending>     8080:32527/TCP,27960:31138/TCP,9090:30313/TCP   2m47s

Now point your browser to: http://<some node ip>:32527
Or if you have the LoadBalancer up and running go to the http://<Loadbalancer IP>:8080

OpenStack Cinder Replication: Using Multiple ActiveCluster Pods to Increase Scale

Since the Mitaka release of OpenStack, the Pure Storage Cinder driver has supported Cinder replication, although this first iteration only supported asynchronous replication.

The Rocky release of OpenStack saw Pure’s Cinder driver support synchronous replication by integrating our ActiveCluster feature from the FlashArray.

This synchronous replication automatically created an ActiveCluster pod on the paired FlashArrays called cinder-pod. A pretty obvious name I would say.

While this provided a seamless integration for OpenStack users to create a synchronously replicated volume using a correctly configured volume type, there was one small limitation. ActiveCluster pods were limited to 3000 volumes.

Now you might think that is more than enough volumes for any single ActiveCluster environment. I certainly did until I received a request to be able to support 6000 volumes synchronously replicated.

After some scratching of my head, I remembered that from the OpenStack Stein release of the Pure Cinder driver there is an undocumented (well, not very well documented) parameter that allows the name of the ActiveCluster pod to be customizable and that gave me an idea….

Can you configure Cinder to use the same backend as separate stanzas in the Cinder config file with different parameters?

It turns out the answer is Yes.

So, here’s how to enable your Pure FlashArray Cinder driver to use a single ActiveCluster pair of FlashArrays to allow for 6000 synchronously replicated volumes.

First, we need to edit the cinder.conf file and create two different stanzas for the same array that is configured in an ActiveCluster pair and ensure we have enabled both of these backends:

enabled_backends = pure-1-1, pure-1-2
…
[pure-1-1]
volume_backend_name = pure
volume_driver = cinder.volume.drivers.pure.PureISCSIDriver
san_ip = 10.21.209.210
replication_device = backend_id:pure-2,san_ip:10.21.209.8,api_token:9c0b56bc-f941-f7a6-9f85-dcc3e9a8f6d6,type:sync
pure_api_token = bee464cc-24a9-f44c-615a-ae566082a1ae
pure_replication_pod_name = cinder-pod1
use_multipath_for_image_xfer = True
pure_eradicate_on_delete = true
image_volume_cache_enabled = True
volume_clear = none

[pure-1-2]
volume_backend_name = pure
volume_driver = cinder.volume.drivers.pure.PureISCSIDriver
replication_device = backend_id:pure-2,san_ip:10.21.209.8,api_token:9c0b56bc-f941-f7a6-9f85-dcc3e9a8f6d6,type:sync
pure_replication_pod_name = cinder-pod2
san_ip = 10.21.209.210
pure_api_token = bee464cc-24a9-f44c-615a-ae566082a1ae
use_multipath_for_image_xfer = True
pure_eradicate_on_delete = true
image_volume_cache_enabled = True
volume_clear = none

If we look at the two stanzas, the only difference is that the pure_replication_pod_name is different. I have also set the volume_backend_name to be the same for both configurations. There is a reason for this I will cover later.

After altering the configuration file, make sure to restart your Cinder Volume service to implement the changes.

After restarting the cinder-volume service, you will see on the FlashArray that two ActiveCluster pods now exist with the names defined in the configuration file.

This is the first step.

Now we need to enable volume types to be able to use these pods and also to load-balance across the two pods – why load-balance? It just seems to make more sense to make volumes evenly utilize the pods, but there is no specific reason for doing this. If you wanted to use each pod separately, then you would need to set a different volume_backend_name in the Cinder configuration file for each array stanza.

When creating a volume type to use synchronous replication you need to set some specific extra_specs in the type definition. These are the commands to use:

openstack volume type create pure-repl
openstack volume type set --property replication_type=’<in> sync’ pure_repl
openstack volume type set --property replication_enabled=’<is> True’ pure_repl
openstack volume type set --property volume_backend_name=’pure’ pure_repl 

The final configuration of the volume type would now look something like this:

 openstack volume type show pure-repl
 +--------------------+-------------------------------------------------------------------------------------------+
 | Field              | Value                                                                                     |
 +--------------------+-------------------------------------------------------------------------------------------+
 | access_project_ids | None                                                                                      |
 | description        | None                                                                                      |
 | id                 | 2b6fe658-5bbf-405c-a0b6-c9ac23801617                                                      |
 | is_public          | True                                                                                      |
 | name               | pure-repl                                                                                 |
 | properties         | replication_enabled='<is> True', replication_type='<in> sync', volume_backend_name='pure' |
 | qos_specs_id       | None                                                                                      |
 +--------------------+-------------------------------------------------------------------------------------------+ 

Now, all we need to do is use the volume type when creating our Cinder volumes.

Let’s create two volumes and see how they appear on the FlashArray:

 openstack volume create --type pure-repl --size 25 test_volume
 +---------------------+--------------------------------------+
 | Field               | Value                                |
 +---------------------+--------------------------------------+
 | attachments         | []                                   |
 | availability_zone   | nova                                 |
 | bootable            | false                                |
 | consistencygroup_id | None                                 |
 | created_at          | 2020-04-03T14:48:13.000000           |
 | description         | None                                 |
 | encrypted           | False                                |
 | id                  | 64ef0e40-ce89-4f4d-8c89-42e3208a96c2 |
 | migration_status    | None                                 |
 | multiattach         | False                                |
 | name                | test_volume                          |
 | properties          |                                      |
 | replication_status  | None                                 |
 | size                | 25                                   |
 | snapshot_id         | None                                 |
 | source_volid        | None                                 |
 | status              | creating                             |
 | type                | pure-repl                            |
 | updated_at          | None                                 |
 | user_id             | eca55bb4cd8c490197d8b9d2cdce29f2     |
 +---------------------+--------------------------------------+
 
 openstack volume create --type pure-repl --size 25 test_volume2
 +---------------------+--------------------------------------+
 | Field               | Value                                |
 +---------------------+--------------------------------------+
 | attachments         | []                                   |
 | availability_zone   | nova                                 |
 | bootable            | false                                |
 | consistencygroup_id | None                                 |
 | created_at          | 2020-04-03T14:48:22.000000           |
 | description         | None                                 |
 | encrypted           | False                                |
 | id                  | e494e233-b38a-4fb6-8f3d-0aab5c7c68ec |
 | migration_status    | None                                 |
 | multiattach         | False                                |
 | name                | test_volume2                         |
 | properties          |                                      |
 | replication_status  | None                                 |
 | size                | 25                                   |
 | snapshot_id         | None                                 |
 | source_volid        | None                                 |
 | status              | creating                             |
 | type                | pure-repl                            |
 | updated_at          | None                                 |
 | user_id             | eca55bb4cd8c490197d8b9d2cdce29f2     |
 +---------------------+--------------------------------------+ 

Looking at the FlashArray, we can see the two volumes we just created (I am filtering the volume name on cinder just so you only see the OpenStack related volumes on this array)

The volume naming convention we use at Pure shows that these volumes are in a pod due to the double colon (::) in the name and the pod name for each volume is cinder-pod1 and cinder-pod2 respectively.

The view of each pod also shows only one volume in each.

If you didn’t want to load-balance across the pods and needed the flexibility to specify the pod a volume exists in, all I need do is set the volume_backend_name to be different in the configuration file array stanzas and then create two volume types. Each would point to the different volume_backend_name setting.

Kubernetes on AWS with Cloud Block Store

Only a slight nudge at from @CodyHosterman to put this post together.

Kubernetes deployed into AWS is a method many organizations are using to get into using K8s. Whether you deploy K8s with Kubeadm, Kops, Kubespray, Rancher, WeaveWorks, OpenShift, etc the next big question is how do I do persistent volumes? While EBS has StorageClass integrations you may be interesting in getting better efficiency and reliability than traditional block in the cloud. That is one of the great uses of Cloud Block Store. Highly efficient and highly reliable storage built for AWS with the same experience as the on prem FlashArray. By utilizing Pure Service Orchestrator’s helm chart or operator you can now take advantage of Container Storage as a Service in the cloud. Are you using Kubernetes in AWS on EC2 and have questions about how to take advantage of Cloud Block Store? Please ask me here in the comments or @jon_2vcps on twitter.

  1. Persistent Volume Claims may will not always be 100% full. Cloud Block Store is Deduped, Compressed and Thin. Don’t pay for 100% of a TB if it is only 1% full. I do not want to be in the business of keeping developers from getting the resources they need, but I also do not want to be paying for when they over-estimate.
  2. Migrate data from on prem volumes such as K8s PVC, VMware vVols, Native physical volumes into the cloud and attach them to your Kubernetes environment. See the youtube demo below for an example. What we are seeing in the demo is creating an app in Kubernetes on prem, loading it with some data (photos), replicating that application to the AWS cloud and using Pure Service Orchestrator to attach the data to the K8s orchestrated application using Cloud Block Store. This is my re-working of Simon’s tech preview demo from the original launch of Cloud Block Store last November.

3. Simple. Make storage simple. One common tweet I see on twitter from the Kubernetes detractors is how complicated Kubernetes can be. Pure Service Orchestrator makes the storage layer amazingly simple. A single command line to install or upgrade. Pooling across multiple devices.

Get Started today:
Below I will include some links on the different installs of PSO. Now don’t let the choices scare you. Container Storage Interface or CSI is the newest API for common interaction with all storage providers. While flexvol was the original storage solution it makes sense to move forward with CSI. This is very true for newer versions of kubernetes that include CSI by default. So if you are starting to use K8s for the first time today or your cluster is K8s 1.11 we have you covered. Use the links below to see the install process and prerequisites for PSO.

FlexVol Driver:
Pure Service Orchestrator Helm Chart
Pure Service Orchestrator Operator

CSI Driver:
Pure Service Orchestrator CSI Helm
Pure Service Orchestrator CSI Operator

Talking Pure and K8s on the Virtually Speaking Podcast at #PureAccelerate

Start with Applications

I have been revisiting my work towards some advanced datacenter certifications and decided to journal some of the thoughts I have during the process. After a 3 year break I decided it was time to start pushing toward some of these goals.

 This may sound eerily similar to something I have said before. It is a constant fight in the infrastructure technology field to get so weighed down by speeds and feeds and features. You begin to lose sight as to why you actually put servers, switches, storage and software together in the first place. While looking at the requirements guide for the VCAP-DCD the very first thing that is mentioned is getting the business requirements. How do I actually do that? What does the business actually require?

  1. Know what the applications actually do.
    Ask! What does this Microsoft SQL database do? How does email relate to our business doing deals? Find out how money goes in and out of the business. How does your company pay bills? How do you charge for whatever it is you produce? How do the MBA types make decisions about who, what, when, where and why for your business? In IT we often get so involved in rolling out a new widget from vendor X, Y and Z we often don’t realize what is the purpose to the business. Understand this from a high level first.
  2. Map technology to the impact on the business.
    Who cares if I can do a million IOPS if all I do is check email all day? How do I consolidate servers with no plan on how they impact the bottom line? How do I provide cloud like capabilities if no one really needs them? So start to map the capabilities to the benefits to the business. If the decisions being made can be done with data that is 5 minutes old instead of a 24 hours how can that change the landscape of your business? Does this give an advantage over competitors?
  3. Know something about the Apps.
    If your answer is I don’t know how are business runs or anything about SQL or Oracle I just make empty VM’s for people to put the apps on. I make sure they turn on and I move them around when they need performance or more capacity. Guess what? Those functions can be done by VMware Orchestrator. If you don’t know why you put 4 vCPU’s on a SQL VM because the batch jobs don’t ever use more than that and why, you need to learn. If you need tools to decipher the differences then get them. At least get the trial versions so you can see what happens. Get close to the queries that run at night. Do you know if they are CPU, Memory or Storage bound? Find out. Get off of reddit and check it out. Do you know if you put in faster servers will the app improve in a way that makes things better for business? Are you really going to gamble your budget on marginal improvements?

WhyInfraexists

Can you connect how all of these things relate and benefit the business?

Just some small things I have been thinking about. In my job it is a constant temptation to push how many IOPS you can do with this thing or that. When I need to say “what process needs the performance? If that process is faster AND you get additional benefits of data reduction, floor tile reduction, power usage reduction what will it mean to your business users?”

 

 

Book Review: Automating vSphere with VMware vCenter Orchestrator

So to be 100% honest I have had this book on my desk for several months. Just staring at me. Calling my name. VMware press provided this copy to me along with Mike Laverick’s SRM book and so I am finally going to review the first one.

Cody Bunch does an amazing job of breaking down one of the most mystifying yet powerful products hidden in the VMware portfolio. VMware vCenter Orchestrator is almost mythical in the promises of automation of typical tasks of a vSphere administrator. While you can bang your head against the wall for weeks trying to figure out how to properly setup the vOrchestrator server and client I was able to use Cody’s guidance to have to operational and running test workflows in just a few hours (I am a slow reader).

I can’t stress enough the need for automation and orchestration in today’s virtual machine environment. The business is demanding more and more from the Virtualization team and in order to deliver vCenter Orchestrator is a good start since you probably already OWN it.

Hopefully soon there will be an update with information on the vApp version of Orchestrator. Check it out here on Amazon or your favorite book reseller.

Thanks again

Leadership in the Cloud (And everywhere else)

This is really a post about leadership in general, but I like to apply it to our industry. I am totally cool if you take these concepts and apply them elsewhere.

In any work environment there is constant posturing, politicing, conflicting, that has nothing to do with the actual cause of the workplace. I am going to offer a few leadership tips for everyone, not just for managers, vp’s and directors. Tips that we can all put to use.

1. It is not all about you. We all know that “guy” (or girl). Using every oppurtunity to push others down and himself up. Using others backs to climb on never lasts. Being the MVP of a losing team is never my goal, make everyone around you better. The skills involved in doing that will take you further than your daily task knowledge. No one ever says, “Wow, Jon sure can deploy a sweet VM.” If you are known for adding value, contributing and making everyone better that is how what you do will last. Valuing your team as something more than tools to make you look good is a good start.

2. Have a Purpose/Mission. I am here to change the world. Personally and Professionally. I have done jobs and have volunteered with people and organizations where no one knows why they do what they do. If you are making Pizza, make life changing pizza. If you are building next-gen datacenters, do it in a way that will alter life for someone.

3. Lead, Even if you aren’t supposed to. Don’t sit around and wait to be asked to do something leadershippy.

4. Have a Strategy. If you don’t know why you do what you do get that first. Then decide how the world will look when you are done. Impact (well good impact) on people will not happen on accident.

5. If you see a problem be part of the Solution. Stop complaining. There is only so much time in the day. Personally, it is natural for me to complain. I am very good at pointing out faults in everything. I have to consciously make the decision to work on the solutions for things I can change and shut up about the other stuff (for now). Some things just need the proper timing.

6. Community. Jump into the deep end of the pool of community. Make this a core tenant of everything you participate in. You can not do it all by yourself. Community substitues like Twitter and Facebook are a start but go meet in person with some real people. Just an idea.

The most cynical of my readers never started reading this. If you got this far, I hope in your mind you see how this applies to you. Of course any comments are welcome.

Some Reality for us Infrastructure Peeps or Apps are cool too

Don’t’ you just love double titles?

For many years I have been an infrastructure guy. I really liked how the cables, and processors and Memory and blinking lights worked. Applications were often the necessary evil tolerated so that I can play with cool technology. During my own journey toward learning about the cloud it becomes increasingly important to consider the function of the application. Six years ago me would totally punch me in the face right now. Traitor. J

1 – Don’t get your App messed up in my resource buckets of awesomeness

 

So the reality check to the Infrastructure geek in me is this: The application teams really think of what you do as the network. That is why when anything is ever wrong it is always “the network’s” fault. What we love to do is getting abstracted more and more. I will still contend that is very important and very hard to do. Whether you are building reference architectures or deploying a converged infrastructure appliance almost no one but us cares. They just want the data to do their jobs. So while we have really great discussions about speeds and feeds, the guy in the picture below just wants the app. From the hypervisor down we need to design with the application in mind or we will risk becoming like that goth dude locked in the server room on IT Crowd.

 

2 Honey badger don’t care about FCoE

My next post will get into what I have been researching regarding what is out there and hopefully help us (infra. peeps) understand our App/Dev brothers better.

You are probably an Infrastructure person if:

  1. You read this blog.
  2. You work mainly with Virtualization
  3. Storage Admin
  4. Network Admin
  5. You like to make fun of DBA’s

 

Its About the Apps – The Need for Application Modernization Webcast

As we migrate to Cloud models for Enterprise IT one big need that gets overlooked is how the applications are architected. Modernizing existing apps can be a very scary but a necessary step to taking advantage of what the cloud can offer.

Just look at this crazy puzzle. As a VMware/Network/Storage geek I spend so much time focusing on the bottom of this picture the “infrastructure” part. I have to admit though without the Applications no one cares about all my infrastructure.

So what can we do with that middle layer? The legacy apps, Analytics and Cloud applications. Expect more to come from me on this. Don’t worry they won’t be “coding” posts but rather enablement of applications in the world of Private Cloud.

So where to start?
I want to create some awareness for this upcoming webcast. Details are here:

http://www.emc.com/events/2012/q1/01-25-12-application-modernization.htm

Jan 25, 2012

Time:
11:00 AM – 12:00 PM EST (Set Time Zone)

Event Type:
EMC Live Webcast

Location:
Online

Details: In this session, EMC Consulting will discuss Application Modernization on the road to Platform as a Service.

Our expertise and experience will help you understand Cloud Application Platform technologies, architectural patterns and practical approaches to a modernization strategy that maximizes long-term benefits.

Attend this webcast and learn:

About next generation Application Architectures
How other organizations have successfully tackled an Application Modernization initiative
How to develop a strategy for Application Modernization

vSphere Metro Stretched Clusters – Some Info/Links

A lot of questions lately about vSphere Clusters across distance. I really need to learn for myself so I collected some good links.

Make sure you understand what “Only Non-uniform host access configuration is supported” means. Someone correct me if I have this wrong but your device that enables the distributed virtual storage needs to be sure that hosts in site A are writing to their preferred volumes in site A and vice versa in Site B. Probably way over simplifying it.


LINKS

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2007545

http://virtualgeek.typepad.com/virtual_geek/2011/10/new-vmware-hcl-category-vsphere-metro-stretched-cluster.html

http://www.yellow-bricks.com/2011/10/07/vsphere-metro-storage-cluster-solutions-what-is-supported-and-what-not/

http://www.yellow-bricks.com/2011/10/05/vsphere-5-0-ha-and-metro-stretched-cluster-solutions/

Big thanks to Scott Lowe for clearing the details on this topic.

An Idea for vCloud Director and View

Sometimes I am sitting up late at night and I have a thought of something I think would be cool, like if x and y worked together to get z. This time I thought this was good enough to blog about. Now I want to stress that I do not have any special insight into what is coming. This is just how I wish things would be.

Today there are two end user portals from VMware. The vCloud Director for self-service cloud interface and the View Manager access point for end-users to access Virtual Desktops. Each interface interacts with one or more vCenter instances to deploy, manage, and destroy virtual machines. Below is a way over simplified representation of how View, vCloud Director (plus Request Manager) relate to the user experience. I think maybe there is a divide when there does not need to be (someday).

 

 

My idea

What if vCloud director could be used in the future to be the one stop user interface portal. Leveraging vCloud Request Manager, vCD could deploy cloud resources, Desktops or Servers or both. vCloud Director would be the orchestration piece for VMware View. Once the Request for a desktop is approved the entitlement to the correct pool is automatically given. If extra desktops are needed the cloning begins. vCloud Director will learn to speak the View Composer’s language, providing the ever elusive ability to use linked clones with vCD. vCloud Director with this feature could be great for lab and test/dev environments. The best part is operationally there is one place to request, deploy, manage all virtual resources from the end-user perspective. This could eliminate the ambiguity for a user (and service providers) on how to consume (and deliver) resources. This has implications on how IaaS and DaaS would be architected.

 

Now some drawbacks

You might say, hey, Jon you are going to make me buy and run vCD just to get VDI? No. The beauty of the API’s is each product could stand alone or work together (in my Vision of how they should work). Maybe even leverage Composer with vCD without View or Request Manager with View without vCD.

One Cloud Portal to rule them all.