2

I am writing a subordinate charm that will open a specific port by using the Charmhelpers.core.hookenv.open_port. Now I want to deploy the same subordinate charm to another charm that is on the same machine. The problem I'm having is that my port I want to open is already opened by the other subordinate charm so My charmhelpers are giving me an error:

subprocess.CalledProcessError: Command '['open-port', '8080/TCP']' returned non-zero exit status 1

I can't open the same port twice on the same machine which makes sense but in the Charmhelpers.core.hookenv I can't find any method that would make it possible to list all the open ports. Is there a way how I can check in my charm if my port is already opened or not?

2

To answer the question that's asked in the title: yes!

Charms written in Python

The charmhelpers library includes the functionality that you're after:

from charmhelpers.core.hookenv import opened_ports

opened_ports() will provide you with a list of port ranges and protocols that are open:

>>> opened_ports()
['80/tcp', '8081-8083/tcp', 'icmp']

The icmp protocol is special, as there are no port numbers.

Non-Python charms

If you wish to do this outside of Python, your script should execute a shell command:

open-ports

You'll need to interpret its output from within your hook handler. So, what does open-ports command actually provide? You can experiment by logging in to the unit with secure shell and running the command yourself.

First we set up the default model with the ubuntu charm:

$ juju bootstrap localhost c-testing
$ juju deploy ubuntu

Now we can ask Juju to grant us direct access to the machine running the ubuntu charm in the context of the ubuntu/0 unit:

$ juju run --unit ubuntu/0 -- opened-ports --help
Usage: opened-ports [options]

Summary:
lists all ports or ranges opened by the unit

Options:
--format  (= smart)
    Specify output format (json|smart|yaml)
-o, --output (= "")
    Specify an output file

Details:
Each list entry has format <port>/<protocol> (e.g. "80/tcp") or
<from>-<to>/<protocol> (e.g. "8080-8088/udp").

Just to confirm, we can run opened-ports from the context of the unit that we care about in the cloud, directly from the laptop that we're sitting at:

$ juju run --unit ubuntu/0 -- opened-ports --format=smart
80/tcp
8081-8083/tcp
icmp

Or if you prefer machine-readable output:

$ juju run --unit ubuntu/0 -- opened-ports --format=json
["icmp","80/tcp","8081-8083/tcp"]

Can we check open ports of a parent charm from its subordinate?

Not without some pain... I will try to flesh out an answer once I've figured something that's relatively simple.

3
  • Thank you for this answer, I look forward to the update on the last part of your answer since that is really the one that could help me May 21 '19 at 9:46
  • 1
    I've added a question on the official Juju forum for visibility. May 21 '19 at 20:40
  • thank you for that! May 22 '19 at 8:40
1

From the docs it looks like you can use the opened-ports hook tool:

https://jujucharms.com/docs/stable/reference-hook-tools#opened-ports

It looks like it's in charm-helpers here:

https://github.com/juju/charm-helpers/blob/dfd42251406f4f45dc4a2317ee4e02171239979f/charmhelpers/core/hookenv.py#L689

Another possible path would be to close the port you want to open one step before you open it so that it'd be technically closed and ok to reopen. I'm sure that'll be confusing though with multiple subordinates managing the same ports.

2
  • The problem is that the opened_ports will only return a list of ports that are opened in that charm. since the ports are opened in a completely different charm this method has no access to these ports and the list is empty. I also noticed that this method is not yet available in the charmhelpers: module 'charmhelpers.core.hookenv' has no attribute 'opened_ports' . I could always close the port before opening it since, closing a port that is not open, will not give any errors. Dec 5 '17 at 15:28
  • 1
    Yes, this is tricky as you're only allowed to know what you know via your state or relation data in the case of charms. If you want global details you have to reach outside of the charm context. There's a thread looking into this in the mailing list this week you might find interesting. lists.ubuntu.com/archives/juju/2017-December/009748.html
    – Rick
    Dec 6 '17 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.