Example #1
0
 def power_on(self, system_id, context):
     """Power on host."""
     cur_state = yield self.power_query(system_id, context)
     uri = self.get_uri(context, HOST_STATE + "RequestedHostTransition")
     # power off host if it is currently on.
     if cur_state == "on":
         data = FileBodyProducer(
             BytesIO(json.dumps(HOST_OFF).encode("utf-8"))
         )
         off_state = yield self.command(context, b"PUT", uri, data)
         status = off_state.get("status")
         if status.lower() != "ok":
             raise PowerFatalError(
                 "OpenBMC power driver received unexpected response"
                 " to power off command"
             )
     # set one-time boot to PXE boot.
     yield self.set_pxe_boot(context)
     # power on host.
     data = FileBodyProducer(BytesIO(json.dumps(HOST_ON).encode("utf-8")))
     on_state = yield self.command(context, b"PUT", uri, data)
     status = on_state.get("status")
     if status.lower() != "ok":
         raise PowerFatalError(
             "OpenBMC power driver received unexpected response"
             " to power on command"
         )
Example #2
0
 def command(self, context, method, uri, data=None):
     """Current deployments of OpenBMC in the field do not
     support header based authentication. To issue RESTful commands,
     we need to login, issue RESTful command and logout.
     """
     # login to BMC
     login_uri = self.get_uri(context, "/login")
     login_creds = {
         "data": [context.get("power_user"),
                  context.get("power_pass")]
     }
     login_data = FileBodyProducer(
         BytesIO(json.dumps(login_creds).encode("utf-8")))
     login = yield self.openbmc_request(b"POST", login_uri, login_data)
     login_status = login.get("status")
     if login_status.lower() != "ok":
         raise PowerFatalError(
             "OpenBMC power driver received unexpected response"
             " to login command")
     # issue command
     cmd_out = yield self.openbmc_request(method, uri, data)
     # logout of BMC
     logout_uri = self.get_uri(context, "/logout")
     logout_creds = {"data": []}
     logout_data = FileBodyProducer(
         BytesIO(json.dumps(logout_creds).encode("utf-8")))
     logout = yield self.openbmc_request(b"POST", logout_uri, logout_data)
     logout_status = logout.get("status")
     if logout_status.lower() != "ok":
         raise PowerFatalError(
             "OpenBMC power driver received unexpected response"
             " to logout command")
     return cmd_out
Example #3
0
def probe_and_enlist_msftocs(
    user: str,
    ip: str,
    port: Optional[int],
    username: Optional[str],
    password: Optional[str],
    accept_all: bool = False,
    domain: str = None,
):
    """Extracts all of nodes from msftocs, sets all of them to boot via
    HDD by, default, sets them to bootonce via PXE, and then enlists them
    into MAAS.
    """
    # The default port for a MicrosoftOCS chassis is 8000. We expect an
    # integer from the AddChassis RPC call.
    port = 8000 if port is None or port == 0 else port

    msftocs_driver = MicrosoftOCSPowerDriver()
    context = {
        "power_address": ip,
        "power_port": str(port),
        "power_user": username,
        "power_pass": password,
    }
    try:
        # if get_blades works, we have access to the system
        blades = msftocs_driver.get_blades(context)
    except urllib.error.HTTPError as e:
        raise PowerFatalError(
            "Failed to probe nodes for Microsoft OCS with ip=%s "
            "port=%s, username=%s, password=%s. HTTP error code: %s" %
            (ip, port, username, password, e.code))
    except urllib.error.URLError as e:
        raise PowerFatalError(
            "Failed to probe nodes for Microsoft OCS with ip=%s "
            "port=%s, username=%s, password=%s. "
            "Server could not be reached: %s" %
            (ip, port, username, password, e.reason))
    else:
        for blade_id, macs in blades.items():
            context["blade_id"] = blade_id
            # Set default (persistent) boot to HDD
            msftocs_driver.set_next_boot_device(context, persistent=True)
            # Set next boot to PXE
            msftocs_driver.set_next_boot_device(context, pxe=True)
            system_id = create_node(macs, "amd64", "msftocs", context,
                                    domain).wait(30)

            if accept_all:
                commission_node(system_id, user).wait(30)
Example #4
0
 def power_query(self, system_id, context):
     """Power query MSCM node."""
     try:
         # Retreive node power state
         #
         # Example of output from running "show node power <node_id>":
         # "show node power c1n1\r\r\n\r\nCartridge #1\r\n  Node #1\r\n
         # Power State: On\r\n"
         output = self.run_mscm_command(
             "show node power %s" % context["node_id"], **context)
     except PowerConnError as e:
         raise PowerActionError(
             "MSCM Power Driver unable to power query node %s: %s" %
             (context["node_id"], e))
     match = re.search(r"Power State:\s*((O[\w]+|U[\w]+))", output)
     if match is None:
         raise PowerFatalError(
             "MSCM Power Driver unable to extract node power state from: %s"
             % output)
     else:
         power_state = match.group(1)
         if power_state in MSCMState.OFF:
             return "off"
         elif power_state == MSCMState.ON:
             return "on"
Example #5
0
    def power_control_nova(self,
                           power_change,
                           nova_id=None,
                           os_tenantname=None,
                           os_username=None,
                           os_password=None,
                           os_authurl=None,
                           **extra):
        """Control power of nova instances."""
        if not self.try_novaapi_import():
            raise PowerToolError("Missing the python3-novaclient package.")
        if user_domain_name != "" and project_domain_name != "":
            nova = self.nova_api.Client(
                2,
                username=os_username,
                password=os_password,
                project_name=os_tenantname,
                auth_url=os_authurl,
                user_domain_name=user_domain_name,
                project_domain_name=project_domain_name)
        else:
            nova = self.nova_api.Client(2, os_username, os_password,
                                        os_tenantname, os_authurl)

        try:
            urllib.request.urlopen(os_authurl)
        except urllib.error.URLError:
            raise PowerError('%s: URL error' % os_authurl)
        try:
            nova.authenticate()
        except self.nova_api.exceptions.Unauthorized:
            raise PowerAuthError('Failed to authenticate with OpenStack')
        try:
            pwr_stateStr = "OS-EXT-STS:power_state"
            tsk_stateStr = "OS-EXT-STS:task_state"
            vm_stateStr = "OS-EXT-STS:vm_state"
            power_state = getattr(nova.servers.get(nova_id), pwr_stateStr)
            task_state = getattr(nova.servers.get(nova_id), tsk_stateStr)
            vm_state = getattr(nova.servers.get(nova_id), vm_stateStr)
        except self.nova_api.exceptions.NotFound:
            raise PowerError('%s: Instance id not found' % nova_id)

        if power_state == NovaPowerState.NOSTATE:
            raise PowerFatalError('%s: Failed to get power state' % nova_id)
        if power_state == NovaPowerState.RUNNING:
            if (power_change == 'off' and task_state != 'powering-off'
                    and vm_state != 'stopped'):
                nova.servers.get(nova_id).stop()
            elif power_change == 'query':
                return 'on'
        if power_state == NovaPowerState.SHUTDOWN:
            if (power_change == 'on' and task_state != 'powering-on'
                    and vm_state != 'active'):
                nova.servers.get(nova_id).start()
            elif power_change == 'query':
                return 'off'
Example #6
0
 def power_query(self, system_id, context):
     """Power query host."""
     uri = self.get_uri(context, HOST_STATE + "CurrentHostState")
     power_state = yield self.command(context, b"GET", uri, None)
     status = power_state.get("data").split(".")[-1].lower()
     if all(status not in state for state in ("running", "off")):
         raise PowerFatalError(
             "OpenBMC power driver received unexpected response"
             "to power query command")
     return {"running": "on", "off": "off"}.get(status)
Example #7
0
    def power_control_nova(
        self,
        power_change,
        nova_id=None,
        os_tenantname=None,
        os_username=None,
        os_password=None,
        os_authurl=None,
        **extra
    ):
        """Control power of nova instances."""
        if not self.try_novaapi_import():
            raise PowerToolError("Missing the python3-novaclient package.")
        nova = self.nova_api.Client(
            2, os_username, os_password, os_tenantname, os_authurl
        )

        try:
            urllib.request.urlopen(os_authurl)
        except urllib.error.URLError:
            raise PowerError("%s: URL error" % os_authurl)
        try:
            nova.authenticate()
        except self.nova_api.exceptions.Unauthorized:
            raise PowerAuthError("Failed to authenticate with OpenStack")
        try:
            pwr_stateStr = "OS-EXT-STS:power_state"
            tsk_stateStr = "OS-EXT-STS:task_state"
            vm_stateStr = "OS-EXT-STS:vm_state"
            power_state = getattr(nova.servers.get(nova_id), pwr_stateStr)
            task_state = getattr(nova.servers.get(nova_id), tsk_stateStr)
            vm_state = getattr(nova.servers.get(nova_id), vm_stateStr)
        except self.nova_api.exceptions.NotFound:
            raise PowerError("%s: Instance id not found" % nova_id)

        if power_state == NovaPowerState.NOSTATE:
            raise PowerFatalError("%s: Failed to get power state" % nova_id)
        if power_state == NovaPowerState.RUNNING:
            if (
                power_change == "off"
                and task_state != "powering-off"
                and vm_state != "stopped"
            ):
                nova.servers.get(nova_id).stop()
            elif power_change == "query":
                return "on"
        if power_state == NovaPowerState.SHUTDOWN:
            if (
                power_change == "on"
                and task_state != "powering-on"
                and vm_state != "active"
            ):
                nova.servers.get(nova_id).start()
            elif power_change == "query":
                return "off"
Example #8
0
 def test_handles_fatal_error_on_first_call(self):
     system_id = factory.make_name("system_id")
     context = {"context": factory.make_name("context")}
     driver = make_power_driver(wait_time=[0, 0])
     mock_on = self.patch(driver, self.action_func)
     mock_on.side_effect = [PowerFatalError(), None]
     mock_query = self.patch(driver, "power_query")
     mock_query.return_value = self.action
     method = getattr(driver, self.action)
     with ExpectedException(PowerFatalError):
         yield method(system_id, context)
     self.expectThat(mock_query, MockNotCalled())
Example #9
0
 def power_query(self, system_id, context):
     """Power query host."""
     uri = self.get_uri(context, HOST_STATE + 'CurrentHostState')
     power_state = yield self.command(context, b'GET', uri, None)
     status = power_state.get('data').split('.')[-1].lower()
     if all(status not in state for state in ('running', 'off')):
         raise PowerFatalError(
             "OpenBMC power driver received unexpected response"
             "to power query command")
     return {
         'running': 'on',
         'off': 'off'
     }.get(status)
Example #10
0
 def power_off(self, system_id, context):
     """Power off host."""
     uri = self.get_uri(
         context, HOST_STATE + 'RequestedHostTransition')
     data = FileBodyProducer(BytesIO(
         json.dumps(HOST_OFF).encode('utf-8')))
     # set next one-time boot to PXE boot.
     yield self.set_pxe_boot(context)
     # power off host.
     power_state = yield self.command(context, b'PUT', uri, data)
     status = power_state.get('status')
     if status.lower() != 'ok':
         raise PowerFatalError(
             "OpenBMC power driver received unexpected response"
             " to power off command")
Example #11
0
 def power_query(self, system_id, context):
     """Power query Wedge."""
     try:
         power_state = self.run_wedge_command(
             "/usr/local/bin/wedge_power.sh status", **context)
     except PowerConnError:
         raise PowerActionError("Wedge Power Driver unable to power query")
     else:
         if power_state in WedgeState.OFF:
             return "off"
         elif power_state in WedgeState.ON:
             return "on"
         else:
             raise PowerFatalError(
                 "Wedge Power Driver retrieved unknown power response %s" %
                 power_state)
Example #12
0
 def power_query(self, system_id, context):
     """Power query MicrosoftOCS blade."""
     try:
         power_state = self.extract_from_response(
             self.get('GetBladeState', context,
                      ["bladeid=%s" % context['blade_id']]), 'bladeState')
     except PowerConnError as e:
         raise PowerActionError(
             "MicrosoftOCS Power Driver unable to power query blade_id %s:"
             " %r" % (context['blade_id'], e))
     else:
         if power_state == MicrosoftOCSState.OFF:
             return 'off'
         elif power_state == MicrosoftOCSState.ON:
             return 'on'
         else:
             raise PowerFatalError(
                 "MicrosoftOCS Power Driver retrieved unknown power state"
                 " %s for blade_id %s" % (power_state, context['blade_id']))
Example #13
0
File: hmc.py Project: zhangrb/maas
 def power_query(self, system_id, context):
     """Power query HMC lpar."""
     try:
         # Power query lpar
         power_state = self.run_hmc_command(
             "lssyscfg -m %s -r lpar -F state --filter lpar_names=%s" %
             (context['server_name'], context['lpar']), **context)
     except PowerConnError as e:
         raise PowerActionError(
             "HMC Power Driver unable to power query lpar %s: %s" %
             (context['lpar'], e))
     else:
         if power_state in HMCState.OFF:
             return 'off'
         elif power_state in HMCState.ON:
             return 'on'
         else:
             raise PowerFatalError(
                 "HMC Power Driver retrieved unknown power state %s"
                 " for lpar %s" % (power_state, context['lpar']))
Example #14
0
def probe_and_enlist_mscm(
    user: str,
    host: str,
    username: Optional[str],
    password: Optional[str],
    accept_all: bool = False,
    domain: str = None,
):
    """ Extracts all of nodes from the MSCM, sets all of them to boot via M.2
    by, default, sets them to bootonce via PXE, and then enlists them into
    MAAS.  If accept_all is True, it will also commission them.
    """
    mscm_driver = MSCMPowerDriver()
    # Discover all available nodes
    #
    # Example of output from running "show node list":
    # "show node list\r\r\nSlot ID    Proc Manufacturer
    # Architecture         Memory Power Health\r\n----
    # ----- ---------------------- --------------------
    # ------ ----- ------\r\n 01  c1n1  Intel Corporation
    # x86 Architecture     32 GB  On    OK \r\n 02  c2n1
    # N/A                    No Asset Information \r\n\r\n'"
    node_list = mscm_driver.run_mscm_command(
        "show node list",
        power_address=host,
        power_user=username,
        power_pass=password,
    )
    nodes = re.findall(r"c\d+n\d", node_list)
    for node_id in nodes:
        params = {
            "power_address": host,
            "power_user": username,
            "power_pass": password,
            "node_id": node_id,
        }
        # Set default boot to M.2
        mscm_driver.run_mscm_command("set node boot M.2 %s" % node_id,
                                     **params)
        # Retrieve node architecture
        #
        # Example of output from running "show node info <node_id>":
        # "show node info c1n1\r\r\n\r\nCartridge #1 \r\n
        # Type: Compute\r\n Manufacturer: HP\r\n
        # Product Name: ProLiant m500 Server Cartridge\r\n"
        node_info = mscm_driver.run_mscm_command("show node info %s" % node_id,
                                                 **params)
        match = re.search(r"Product Name:\s*([A-Za-z0-9 ]+)", node_info)
        if match is None:
            raise PowerFatalError(
                "MSCM Power Driver unable to extract node architecture"
                " from: %s" % node_info)
        else:
            cartridge = match.group(1)
        if cartridge in cartridge_mapping:
            arch = cartridge_mapping[cartridge]
        else:
            arch = cartridge_mapping["Default"]
        # Retrieve node MACs
        #
        # Example of output from running "show node macaddr <node_id>":
        # "show node macaddr c1n1\r\r\nSlot ID    NIC 1 (Switch A)
        # NIC 2 (Switch B)  NIC 3 (Switch A)  NIC 4 (Switch B)\r\n
        # ---- ----- ----------------- ----------------- -----------------
        # -----------------\r\n  1  c1n1  a0:1d:48:b5:04:34 a0:1d:48:b5:04:35
        # a0:1d:48:b5:04:36 a0:1d:48:b5:04:37\r\n\r\n\r\n"
        node_macaddr = mscm_driver.run_mscm_command(
            "show node macaddr %s" % node_id, **params)
        macs = re.findall(r":".join(["[0-9a-f]{2}"] * 6), node_macaddr)
        # Create node
        system_id = create_node(macs, arch, "mscm", params, domain).wait(30)

        if accept_all:
            commission_node(system_id, user).wait(30)