@@ -68,10 +68,6 @@ def CreateDiskCopy(
6868 ValueError: If both instance_name and disk_name are missing.
6969 """
7070
71- if not instance_name and not disk_name :
72- raise ValueError (
73- 'You must specify at least one of [instance_name, disk_name].' )
74-
7571 src_project = gcp_project .GoogleCloudProject (src_proj )
7672 dst_project = gcp_project .GoogleCloudProject (dst_proj , default_zone = zone )
7773
@@ -81,6 +77,9 @@ def CreateDiskCopy(
8177 elif instance_name :
8278 instance = src_project .compute .GetInstance (instance_name )
8379 disk_to_copy = instance .GetBootDisk ()
80+ else :
81+ raise ValueError (
82+ 'You must specify at least one of [instance_name, disk_name].' )
8483
8584 if not disk_type :
8685 disk_type = disk_to_copy .GetDiskType ()
@@ -252,6 +251,50 @@ def CreateDiskFromGCSImage(
252251 return result
253252
254253
254+ def CopyDisksToGCS (source_project : str ,
255+ source_disk : str ,
256+ destination_bucket : str ,
257+ destination_directory : str ,
258+ image_format : str ) -> str :
259+ """Given a VM, copy the disks to a GCS bucket.
260+
261+ Args:
262+ source_project: The project containing the disk to copy
263+ source_disk: The name of the disk to copy
264+ destination_bucket: The destination bucket to store the disk copy
265+ destination_directory: The directory in the bucket in which to store the
266+ disk image
267+ image_format: The image format to use. Supported formats documented at
268+ https://github.com/GoogleCloudPlatform/compute-image-import/blob/edee48bddbe159100da9ad961131a4beb0f12158/cli_tools/gce_vm_image_export/README.md?plain=1#L3
269+ """
270+ try :
271+ src_project = gcp_project .GoogleCloudProject (source_project )
272+ disk_to_copy = src_project .compute .GetDisk (source_disk )
273+ copied_image = src_project .compute .CreateImageFromDisk (disk_to_copy )
274+ return copied_image .ExportImage (
275+ gcs_output_folder = f'gs://{ destination_bucket } /{ destination_directory } ' ,
276+ image_format = image_format ,
277+ output_name = disk_to_copy .name )
278+ except (RefreshError , DefaultCredentialsError ) as exception :
279+ raise errors .CredentialsConfigurationError (
280+ 'Something is wrong with your Application Default Credentials. Try '
281+ 'running: $ gcloud auth application-default login: {0!s}' .format (
282+ exception ),
283+ __name__ ) from exception
284+ except HttpError as exception :
285+ if exception .resp .status == 403 :
286+ raise errors .CredentialsConfigurationError (
287+ 'Make sure you have the appropriate permissions on the project: '
288+ '{0!s}' .format (exception ),
289+ __name__ ) from exception
290+ if exception .resp .status == 404 :
291+ raise errors .ResourceNotFoundError (
292+ 'GCP resource not found. Maybe a typo in the project / instance / '
293+ 'disk name?' ,
294+ __name__ ) from exception
295+ raise RuntimeError (exception ) from exception
296+
297+
255298def AddDenyAllFirewallRules (
256299 project_id : str ,
257300 network : str ,
@@ -669,19 +712,13 @@ def TriageInstance(project_id: str, instance_name: str) -> Dict[str, Any]:
669712
670713 cpu_usage = project .monitoring .GetCpuUsage (
671714 instance_ids = [instance_info ['id' ]], aggregation_minutes = 1 )
672- if cpu_usage :
673- parsed_cpu = cpu_usage [0 ].get ('cpu_usage' , [])
715+ parsed_cpu = cpu_usage [0 ].get ('cpu_usage' , []) if cpu_usage else None
674716
675717
676718 gce_gpu_usage = project .monitoring .GetInstanceGPUUsage (
677- instance_ids = [instance_info ['id' ]])
678- if gce_gpu_usage :
679- parsed_gce_gpu = gce_gpu_usage
680-
719+ instance_ids = [instance_info ['id' ]])
681720
682721 gke_gpu_usage = project .monitoring .GetNodeAccelUsage ()
683- if gke_gpu_usage :
684- parsed_gke_gpu = gke_gpu_usage
685722
686723 instance_triage = {
687724 'instance_info' : {
@@ -697,25 +734,25 @@ def TriageInstance(project_id: str, instance_name: str) -> Dict[str, Any]:
697734 'data_type' : 'service_accounts' ,
698735 'values' : instance_info ['serviceAccounts' ]
699736 },
700- {
701- 'data_type' : 'firewalls' ,
702- 'values' : instance .GetNormalisedFirewalls ()
703- }, {
704- 'data_type' : 'cpu_usage' , 'values' : parsed_cpu
705- }, {
706- 'data_type' : 'gce_gpu_usage' , 'values' : parsed_gce_gpu
707- }, {
708- 'data_type' : 'gke_gpu_usage' , 'values' : parsed_gke_gpu
709- }, {
710- 'data_type' :
711- 'ssh_auth' ,
712- 'values' :
713- CheckInstanceSSHAuth (
714- project_id , instance_info ['name' ])
715- }, {
716- 'data_type' : 'active_services' ,
717- 'values' : parsed_services
718- }]
737+ {
738+ 'data_type' : 'firewalls' ,
739+ 'values' : instance .GetNormalisedFirewalls ()
740+ }, {
741+ 'data_type' : 'cpu_usage' , 'values' : parsed_cpu
742+ }, {
743+ 'data_type' : 'gce_gpu_usage' , 'values' : gce_gpu_usage
744+ }, {
745+ 'data_type' : 'gke_gpu_usage' , 'values' : gke_gpu_usage
746+ }, {
747+ 'data_type' :
748+ 'ssh_auth' ,
749+ 'values' :
750+ CheckInstanceSSHAuth (
751+ project_id , instance_info ['name' ])
752+ }, {
753+ 'data_type' : 'active_services' ,
754+ 'values' : parsed_services
755+ }]
719756 }
720757
721758 return instance_triage
0 commit comments