|
13 | 13 | # limitations under the License.
|
14 | 14 | """A custom Spawner that creates notebooks backed by Dataproc clusters."""
|
15 | 15 |
|
| 16 | +import asyncio |
16 | 17 | import json
|
17 |
| -import re |
| 18 | +import math |
18 | 19 | import os
|
19 | 20 | import random
|
| 21 | +import re |
20 | 22 | import string
|
21 |
| -import proto |
22 |
| -import yaml |
23 |
| -import math |
24 |
| -import asyncio |
25 | 23 | from datetime import datetime as dt
|
26 | 24 | from types import SimpleNamespace
|
27 | 25 |
|
28 |
| -from google.protobuf.json_format import MessageToDict |
| 26 | +import proto |
| 27 | +import requests |
| 28 | +import yaml |
| 29 | +from async_generator import aclosing, async_generator, yield_ |
| 30 | +from dataprocspawner.customize_cluster import (get_base_cluster_html_form, |
| 31 | + get_custom_cluster_html_form) |
| 32 | +from dataprocspawner.spawnable import DataprocHubServer |
29 | 33 | from google.api_core import exceptions
|
30 |
| -from google.cloud import storage, logging_v2 |
31 |
| -from google.cloud.dataproc_v1beta2 import ( |
32 |
| - ClusterControllerClient, Cluster, ClusterStatus) |
| 34 | +from google.cloud import logging_v2, storage |
| 35 | +from google.cloud.dataproc_v1beta2 import (Cluster, ClusterControllerClient, |
| 36 | + ClusterStatus) |
| 37 | +from google.cloud.dataproc_v1beta2.services.cluster_controller.transports import \ |
| 38 | + ClusterControllerGrpcTransport |
33 | 39 | from google.cloud.dataproc_v1beta2.types.shared import Component
|
34 |
| - |
35 |
| -from google.cloud.dataproc_v1beta2.services.cluster_controller.transports import ClusterControllerGrpcTransport |
36 |
| -from traitlets import List, Unicode, Dict, Bool |
37 |
| - |
38 |
| -from dataprocspawner.spawnable import DataprocHubServer |
39 |
| -from dataprocspawner.customize_cluster import ( |
40 |
| - get_base_cluster_html_form, get_custom_cluster_html_form) |
41 |
| - |
42 |
| -from async_generator import async_generator, yield_, aclosing |
43 |
| - |
| 40 | +from google.protobuf.json_format import MessageToDict |
44 | 41 | from jupyterhub import orm
|
45 | 42 | from jupyterhub.spawner import Spawner
|
| 43 | +from traitlets import Bool, Dict, List, Unicode |
| 44 | + |
46 | 45 |
|
47 | 46 | def url_path_join(*pieces):
|
48 | 47 | """Join components of url into a relative url.
|
@@ -329,6 +328,21 @@ def __init__(self, *args, **kwargs):
|
329 | 328 | self.component_gateway_url = None
|
330 | 329 | self.progressor = SimpleNamespace(bar=0, logging=set(), start='')
|
331 | 330 |
|
| 331 | + # Check if we have a notebooks proxy URL |
| 332 | + self.hub_host = '' |
| 333 | + if 'hub_host' in kwargs: |
| 334 | + self.hub_host = kwargs.get('hub_host') |
| 335 | + else: |
| 336 | + try: |
| 337 | + r = requests.get( |
| 338 | + 'http://metadata.google.internal/computeMetadata/v1/instance/attributes/proxy-url', |
| 339 | + headers={'Metadata-Flavor': 'Google'}) |
| 340 | + r.raise_for_status() |
| 341 | + self.hub_host = f'https://{r.text}/' |
| 342 | + self.log.info(f'Got proxy url {r.text} from metadata') |
| 343 | + except Exception as e: ## pylint: disable=broad-except |
| 344 | + self.log.info(f'Failed to get proxy url from metadata: {e}') |
| 345 | + |
332 | 346 | if mock:
|
333 | 347 | # Mock the API
|
334 | 348 | self.dataproc_client = kwargs.get('dataproc')
|
@@ -646,6 +660,21 @@ def get_env(self):
|
646 | 660 | self.log.debug(f'env is {env}')
|
647 | 661 | return env
|
648 | 662 |
|
| 663 | + def get_args(self): |
| 664 | + """Set arguments to pass to Jupyterhub-singleuser on the cluster. |
| 665 | +
|
| 666 | + Note that we don't call the superclass method, as we don't want to |
| 667 | + set default args like port and ip. |
| 668 | + """ |
| 669 | + args = [] |
| 670 | + |
| 671 | + if self.debug: |
| 672 | + args.append('--debug') |
| 673 | + args.append('--NotebookApp.hub_activity_interval=0') |
| 674 | + args.append('--NotebookApp.hub_host={}'.format(self.hub_host)) |
| 675 | + args.extend(self.args) |
| 676 | + return args |
| 677 | + |
649 | 678 | ################################################################################
|
650 | 679 | # Custom Functions
|
651 | 680 | ################################################################################
|
@@ -1265,6 +1294,8 @@ def _build_cluster_config(self, cluster_data=None):
|
1265 | 1294 | ['dataproc:jupyter.hub.args']) = self.args_str
|
1266 | 1295 | (cluster_data['config']['software_config']['properties']
|
1267 | 1296 | ['dataproc:jupyter.hub.env']) = self.env_str
|
| 1297 | + (cluster_data['config']['software_config']['properties'] |
| 1298 | + ['dataproc:jupyter.hub.menu.enabled']) = 'true' |
1268 | 1299 |
|
1269 | 1300 | if self.gcs_user_folder:
|
1270 | 1301 | (cluster_data['config']['software_config']['properties']
|
|
0 commit comments